Project Viewer
Mobile-readable, markdown-rendering server for the whole teaching project. Reads from disk on every request — in-flight changes show immediately, no rebuild step. Tailnet-only by default.
Run
python3 viewer/serve.py
Listens on http://100.83.250.41:8889/.
To run in the background and survive shell exit:
nohup python3 viewer/serve.py > /tmp/viewer.log 2>&1 &
To stop it: pkill -f "viewer/serve.py".
Override host/port
VIEWER_HOST=0.0.0.0 VIEWER_PORT=9000 python3 viewer/serve.py
What it does
/and any subdirectory → directory listing (folders first, then files)*.md→ rendered with markdown-it (CommonMark + tables + strikethrough + linkify + smart-quotes)*.txt,*.py,*.json,*.yaml,*.css,*.html,*.sh,*.gitignore→ preformatted text view- Anything else → raw bytes with guessed MIME (images, PDFs, etc.)
Skipped: .git/, __pycache__/, node_modules/, .qdrant/, .venv/, audio extensions (.mp3, .m4a, .wav, .flac, .ogg, .aac), video extensions (.mp4, .mov, .webm), .DS_Store, dotfiles other than .gitignore/.gitattributes/.env.example.
To extend the skip lists, edit SKIP_DIRS, SKIP_FILES, SKIP_EXTS near the top of serve.py.
Design tokens
tokens.json, variables.css, theme.css, DESIGN.md — The Browser Company design system extracted from https://thebrowser.company. The server inlines its own simplified CSS based on these tokens (sharp 0px radius, parchment background, midnight ink text, EB Garamond headings via Google Fonts, IBM Plex Mono substitute for ABCDiatypeMono via Google Fonts, system serif fallback for IvarText since IvarText isn't free).
Security
- Binds to the tailnet IP only — unreachable from outside your tailnet.
- Path-traversal protection: any resolved path outside
~/Projects/teaching/returns 403. - No write endpoints. Read-only.
Dependencies
markdown-it-py (already installed in this environment via the rag package). Standard library otherwise.