- 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
- Login and first-run setup screens
- File tree with inline create/rename, context menu, drag-and-drop
move and trash with undo; all operations update the UI first and roll
back on failure
- Tabs keep a CodeMirror state each; edits autosave after 500 ms with
If-Match revisions, unsent edits persist in IndexedDB, and conflicts
or remote deletions surface as banners with explicit choices
- WebSocket events sync external edits, moves and deletions into open
tabs; reconnects trigger a full resync
- Pasted or dropped images show instantly and upload to note.assets/
- Responsive layout with a swipe-in sidebar drawer on phones
- Switch to TypeScript 6: vue-tsc does not support TypeScript 7 yet
- vault: path validation (no traversal, hidden segments or symlink
escape), atomic writes with If-Match/If-None-Match revisions, moves
that carry the note's .assets folder and rewrite its image links,
trash with restore, content-addressed asset uploads
- auth: single-user Argon2id password, sliding sessions in SQLite,
login rate limiting, first-run setup gated by a one-time code written
to the data directory
- watch: fsnotify plus periodic rescans diffed against a snapshot, so
both RawMark and external edits are broadcast as tree/changed/moved/
deleted events over WebSocket
- api: stdlib router, SameSite=Strict cookies plus Origin checks,
sandboxed raw file serving, embedded SPA with gzip and CSP
- Copy button in the top-right of fenced code blocks, with execCommand
fallback when the Clipboard API is unavailable over plain HTTP
- Mod-A inside a code block selects the block content first; pressing
it again selects the whole document
- Paint code block backgrounds on a ::before layer below CodeMirror's
selection layer so selections inside code blocks are visible
- Table toolbar sits in reserved space above the table instead of
overlapping it, with grouped icon buttons
- Top-level GFM tables render as an editable widget: click a cell to
edit its Markdown source, Tab/Enter/arrows to navigate, toolbar to
insert/delete rows and columns or switch to source
- Structural table edits are isolated undo steps; focus is restored
after the widget is rebuilt
- Clicking an image moves the cursor to its syntax to reveal the source
- Renderer escapes raw HTML and filters dangerous URL schemes by default
- CodeMirror 6 editor with Obsidian/Typora-style live preview: block
markup revealed per line, inline markup revealed per element
- Fenced code highlighting via Shiki (github-dark, JS regex engine) in a
Web Worker, languages loaded on demand
- Lezer syntax tree to HTML renderer for share pages, checked against
the CommonMark 0.31.2 spec (640/652; 12 known parser deviations)
- Use markdownLanguage directly to avoid bundling lang-html/css/js