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:
2026-07-19 17:16:02 +00:00
co-authored by Claude
parent e57b0bc784
commit b5631986e6
11 changed files with 841 additions and 2148 deletions
+92 -92
View File
@@ -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