- Share a note as a live read-only page at /s/{token} with optional password and expiry
- Share page renders with the shared parser (TOC, footnotes, math, Mermaid, code highlighting)
and only serves images from the note's own .assets directory
- Shares follow renames made through the API or externally
- Manage shares and API tokens from the command palette and file tree
- Accept read/write API tokens as Bearer credentials; management endpoints require a session
- Serve a hand-written openapi.json, checked against the route table in tests
- Index notes in a separate, rebuildable SQLite database (index.db) using FTS5 trigram,
synced from watcher snapshots so external edits are picked up; terms under 3 characters
fall back to LIKE
- GET /api/v1/search?q= returns matching notes with the first matching line and a snippet;
path matches rank first
- Sidebar search panel (Ctrl+Shift+F) with highlighted terms and keyboard navigation;
opening a result jumps to and selects the match
- Restore scroll position on tab switch with scroll snapshots; restoring scrollTop drifted
by a few lines after line heights were re-estimated
scripts/dev.sh checks toolchains and ports, installs frontend deps when
the lockfile changes, starts the Go server and Vite with prefixed logs,
and stops both on Ctrl+C or when either exits. The Vite proxy reads the
same API_PORT so custom ports keep working.
- The dev build tag reads web/dist from disk instead of embedding it,
so the backend starts without building the frontend first; Vite
serves the UI and proxies /api and WebSocket to the Go server
- Document the two-terminal dev workflow and ignore .dev-data/
- Multi-stage build: frontend, static Go binary with embedded assets,
distroless nonroot runtime (~35 MB) with a built-in healthcheck
- Explain how to fix data directory permission errors on bind mounts