Generator-Skeleton (Phase 1): static HTML + watchdog + HTTP server
Replaces obv-Fork. New architecture: - Python watchdog observes /home/admin/my-karpathy-wiki/ - On .md change → regenerate single HTML + update index - On startup → full regen + tree.json/graph.json/tags.json/backlinks.json - HTTP server on 127.0.0.1:8765 + tailscale proxy - 265 static HTML pages with full Markdown rendering - WikiLink resolution: [[entity]] → <a href='/path/entity.html'> - Frontmatter as styled card (type, status, updated, sources) - TOC auto-generated via markdown.extensions.toc - PWA manifest for native-feeling install - data.js with all metadata for offline use Touch-first design (CSS+JS for tree/graph/search) follows in Phase 2. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,117 +1,117 @@
|
||||
# Hermes Wiki Viewer
|
||||
# hermes-wiki-static
|
||||
|
||||
A customizable Obsidian-vault viewer with 3D Graph visualization, current-page highlighting, and responsive layout. Designed specifically for Lukas Huber's [Hermes Wiki](https://github.com/NousResearch/hermes-agent) workflow.
|
||||
Static HTML wiki generator for Lukas Huber's karpathy-style Obsidian-vault.
|
||||
|
||||
**This is a side-project fork of [DanielCheer/obsidian-web-viewer](https://github.com/DanielCheer/obsidian-web-viewer)** (MIT, 2026-04) with customizations layered on top via an additive `vault-custom.js`. Upstream patches merge cleanly because we touch exactly one line of `vault.html`.
|
||||
## What this is
|
||||
|
||||
## Features (in addition to upstream)
|
||||
A Python tool that watches `/home/admin/my-karpathy-wiki/` for changes and
|
||||
regenerates static HTML files on disk. A simple HTTP server serves them on
|
||||
loopback port 8765; Tailscale exposes it to the tailnet.
|
||||
|
||||
- **Current-page highlighting in 3D Graph** — the node representing the open file gets a brighter material and a glow outline; connected nodes (via `[[wikilinks]]`) are also highlighted; unrelated nodes dim to 20% opacity
|
||||
- **Click-to-navigate on 3D Graph** — Three.js raycaster triggers file navigation on node click
|
||||
- **Responsive layout** — graph collapses to a bottom panel below 1024px viewport; tree collapses to hamburger menu below 768px
|
||||
- **Backlinks panel** (planned) — see CHANGELOG.md
|
||||
## Why this exists
|
||||
|
||||
## Features (from upstream, unchanged)
|
||||
We previously used `DanielCheer/obsidian-web-viewer` (forked as
|
||||
`hermes-wiki-viewer`). It had three blockers:
|
||||
|
||||
- File tree sidebar (collapsible folder tree)
|
||||
- Markdown rendering with code blocks, tables, blockquotes, images
|
||||
- Wikilink navigation (`[[links]]` click-to-traverse)
|
||||
- YAML frontmatter rendered as styled card
|
||||
- Full-text search by note name and content with snippets
|
||||
- 3D graph visualization (Three.js) showing note connections
|
||||
- Catppuccin-inspired dark theme
|
||||
- Zero client-side setup — anyone with the URL can browse
|
||||
- **No touch support on iOS Safari** — click handlers don't work reliably
|
||||
- **3D-Graph auto-rotates** — prevents node selection via tap
|
||||
- **Fixed 260px Graph column** — wastes horizontal space
|
||||
|
||||
This tool replaces obv with our own renderer:
|
||||
|
||||
- **Touch-first design** — bottom-nav on mobile, hamburger-tree, FAB+modal graph
|
||||
- **Static HTML** — each page is a real URL, deep-linkable, PWA-installable
|
||||
- **No auto-rotation** — graph is static, click-to-rotate, click-to-navigate
|
||||
- **Native-feeling** — service worker, pull-to-refresh, swipe-back
|
||||
|
||||
## Architecture
|
||||
|
||||
See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for the design rationale (why `vault-custom.js`, why the minimal `vault.html` patch, why we don't fork aggressively).
|
||||
```
|
||||
my-karpathy-wiki/*.md (input)
|
||||
|
|
||||
v
|
||||
[watchdog observer] (auto-regen on .md change)
|
||||
|
|
||||
v
|
||||
generator.py (Python: markdown + frontmatter)
|
||||
|
|
||||
v
|
||||
~/.local/share/hermes-wiki/site/ (static HTML output)
|
||||
|
|
||||
v
|
||||
python3 http.server (loopback:8765)
|
||||
|
|
||||
v
|
||||
tailscale serve (https://openclaw.wholphin-musical.ts.net/)
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
## Files
|
||||
|
||||
- `generator.py` — daemon with watchdog + HTTP server
|
||||
- `requirements.txt` — markdown, pyyaml, watchdog, python-frontmatter
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
# Clone
|
||||
git clone https://github.com/LukasHuber/hermes-wiki-viewer.git
|
||||
cd hermes-wiki-viewer
|
||||
# Install deps (one-time, system Python)
|
||||
pip install --break-system-packages markdown pyyaml watchdog python-frontmatter
|
||||
|
||||
# Optional: PyYAML for frontmatter
|
||||
pip install -r requirements.txt
|
||||
# Start daemon
|
||||
python3 generator.py --start
|
||||
|
||||
# Point to your vault
|
||||
python3 server.py --vault /path/to/your/vault --host 127.0.0.1 --port 8765
|
||||
# Status / Stop
|
||||
python3 generator.py --status
|
||||
python3 generator.py --stop
|
||||
|
||||
# Open http://localhost:8765
|
||||
# One-shot regen (no watcher, no HTTP server)
|
||||
python3 generator.py --once
|
||||
```
|
||||
|
||||
For Tailscale access (Lukas' typical setup), pair with `tailscale serve`:
|
||||
## Output structure
|
||||
|
||||
```bash
|
||||
tailscale serve --bg --https=443 http://127.0.0.1:8765
|
||||
# Access via https://<hostname>.<tailnet>.ts.net/
|
||||
```
|
||||
site/
|
||||
├── index.html (redirect to first note)
|
||||
├── concepts/<slug>.html (one file per .md)
|
||||
├── entities/<slug>.html
|
||||
├── ...
|
||||
└── __/
|
||||
├── style.css
|
||||
├── app.js
|
||||
├── data.js (all metadata inlined for offline)
|
||||
├── tree.json
|
||||
├── graph.json
|
||||
├── tags.json
|
||||
├── backlinks.json
|
||||
└── manifest.json (PWA)
|
||||
```
|
||||
|
||||
### One-command setup via wrapper script
|
||||
## WikiLink syntax
|
||||
|
||||
The `scripts/hermes-wiki-serve.sh` wrapper handles start/stop/logs/status, PID-tracking, log-files, and Tailscale integration:
|
||||
`[[entity-name]]` or `[[entity-name|display text]]` resolves to a real
|
||||
`<a class="wikilink" href="/path/to/entity.html">` if the target exists,
|
||||
otherwise `<a class="wikilink-missing">` (greyed out).
|
||||
|
||||
```bash
|
||||
# Install: copy script to PATH
|
||||
cp scripts/hermes-wiki-serve.sh ~/.local/bin/
|
||||
chmod +x ~/.local/bin/hermes-wiki-serve.sh
|
||||
|
||||
# Use:
|
||||
hermes-wiki-serve.sh start # starts server, sets up tailscale serve
|
||||
hermes-wiki-serve.sh status # shows PID, Tailscale-URL, health
|
||||
hermes-wiki-serve.sh logs # tail all logs
|
||||
hermes-wiki-serve.sh stop # stops server (keeps tailscale running)
|
||||
hermes-wiki-serve.sh restart # stop + start
|
||||
```
|
||||
|
||||
The script defaults to using this repo at `~/repos/hermes-wiki-viewer/`. Override via `HERMES_WIKI_OWV_DIR`.
|
||||
|
||||
## Customization
|
||||
|
||||
`vault-custom.js` is Lukas' own code, organized into clear sections:
|
||||
|
||||
```js
|
||||
// Current-page highlighting
|
||||
window.HermesCustom = window.HermesCustom || {};
|
||||
HermesCustom.highlightCurrentNode = function() { ... };
|
||||
|
||||
// Graph click-to-navigate
|
||||
HermesCustom.setupGraphClickHandler = function() { ... };
|
||||
|
||||
// Responsive layout
|
||||
HermesCustom.responsiveLayout = function() { ... };
|
||||
```
|
||||
|
||||
To add a new customization, add a method to `HermesCustom` and call it from `HermesCustom.init()` at the bottom of the file.
|
||||
|
||||
## Updating from upstream
|
||||
|
||||
```bash
|
||||
git remote add upstream https://github.com/DanielCheer/obsidian-web-viewer.git
|
||||
git fetch upstream
|
||||
git merge upstream/master
|
||||
# Conflicts should only occur in vault.html — the one-line patch
|
||||
```
|
||||
|
||||
If `vault.html` has been heavily modified upstream, manually re-apply the single patch:
|
||||
|
||||
```html
|
||||
<!-- Add before </body>: -->
|
||||
<script src="vault-custom.js"></script>
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT — same as upstream. See [LICENSE](LICENSE).
|
||||
|
||||
## Author
|
||||
|
||||
Lukas Huber — see [Personal-Profile](https://github.com/LukasHuber) for context.
|
||||
This fork exists to make the agent-wiki viewing experience fit Lukas' specific needs (3D graph focus, responsive layout for mobile reading, current-page highlighting for fast cross-page navigation).
|
||||
## Frontmatter
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: My Note
|
||||
type: concept
|
||||
status: stable
|
||||
updated: 2026-07-15
|
||||
sources:
|
||||
- https://example.com
|
||||
tags:
|
||||
- hermes
|
||||
- architecture
|
||||
---
|
||||
```
|
||||
|
||||
Upstream: [DanielCheer/obsidian-web-viewer](https://github.com/DanielCheer/obsidian-web-viewer) © 2026 Daniel Cheer
|
||||
Hermes Wiki Viewer fork © 2026 Lukas Huber
|
||||
## Known limitations (Phase 1)
|
||||
|
||||
- CSS is placeholder — touch design comes in Phase 2
|
||||
- JS is placeholder — search/tree/graph render comes in Phase 2
|
||||
- Bottom-Nav template is there but not styled
|
||||
- 5 YAML files in the wiki have malformed frontmatter (parser warnings)
|
||||
- Graph only shows 27 edges — some WikiLinks not resolving due to those YAML issues
|
||||
|
||||
Reference in New Issue
Block a user