A desktop reader for markdown documents with PDF-style annotations — highlight, leave a re.mark, and doodle on top of your docs. Annotations save as a human-readable JSON sidecar next to the source file.
![]() |
![]() |
| Reading view — vertical watermark, syntax-highlighted article, right-gutter minimap, animated BETA pin under the wordmark. | Navigation, checkboxes & code — drag in the right-gutter minimap to jump anywhere in long documents; task-list - [ ] items render as live checkboxes; fenced code blocks pick up real per-language Shiki theming (Rust shown here). |
![]() |
![]() |
| Annotate freely — highlight passages in 5 preset colors, drop re.marks anchored to a single word with inline popovers, and doodle on top of the text with the freehand draw tool. | Settings panel — 18 preferences across appearance, reading, annotation, and updates. |
remarkdown 0.5.0-beta is the first public beta. It ships every v1 reader + annotation feature, the full error-recovery matrix, a hand-drawn welcome tutorial, the new re.marks side panel, and — for the first time — in-app auto-update so future betas land without you having to manually reinstall. Stable enough for daily reading; bug reports very welcome.
⚠️ If you're running a pre-beta build (0.4.x or earlier): auto-update wasn't shipped yet, so your installed copy can't pull this beta on its own. Download the 0.5.0-beta installer from the Releases page and run it once — every release after this one will arrive automatically via the in-app updater.
Pre-built Windows installers are published with each tagged release. Grab the latest from the Releases page:
remarkdown_<version>_x64-setup.exe — NSIS installer (recommended)-beta.Already installed? Open Hamburger menu → Check for updates… to grab the next release without leaving the app.
When you're reading a technical spec, a paper, or a book chapter in markdown, you often want to highlight key passages, scribble in the margins, and leave re.marks — the same mental model you'd use with a paper book or a PDF. Most markdown viewers are read-only, and most annotation tools require converting to PDF first.
remarkdown reads plain markdown from disk, renders it in a clean dark UI, and lets you annotate on top. Your annotations save alongside the source file as a plain-text JSON sidecar — so they stay with your notes, survive document edits where possible, and can be read back by any tool (including LLMs) without the original document loaded.
.md file from Explorer onto the window to open itCtrl + / Ctrl - / Ctrl 0 — scales the entire article (and minimap) via a single CSS variablere.md → remarkdown whenever you hover the menu button (same choreography as the splash)/releases/latest/download/latest.json is what your installed copy pollssettings.json in the OS app-data dirsvelte-check warnings| Tool | Activation | Behavior |
|---|---|---|
| 🎯 Cursor | Default | Normal text selection; copy works |
| 🖍 Highlight | Tool rail | Drag-select text → highlight in current color. Right-click an existing highlight → Delete |
| 📝 re.mark | Tool rail | Click a word → accent pin pinned to that word's end with an inline popover. Click the re.marks pill above the zoom controls to browse every annotation with surrounding sentence context. |
| ✏️ Draw | Tool rail | Freehand stroke capture. 3s idle or tool-change finalizes. Right-click an existing drawing → Delete |
| 🧹 Eraser | Tool rail | Click any annotation to delete it instantly — no confirmation |
Color strip appears above the rail when Highlight or Draw is active (5 presets each).
| Shortcut | Action |
|---|---|
Ctrl + / Ctrl = |
Zoom in |
Ctrl - |
Zoom out |
Ctrl 0 |
Reset zoom |
Esc |
Close popover / cancel selection / exit reader mode |
? |
Show or hide the welcome tutorial overlay |
1 / 2 / 3 / 4 / 5 |
Switch to Cursor / Highlight / re.mark / Draw / Eraser |
| Double-click title bar | Toggle maximize |
| Double-click bottom-right corner | Reset window to 1100×780 |
For every markdown file foo.md, remarkdown writes annotations to a sibling file foo.md.remarkdown.json:
{
"_comment": "remarkdown annotations for: foo.md",
"$schema": "remarkdown/v1",
"document": {
"path": "foo.md",
"sha256": "7ac1bc…",
"lastSeenBytes": 4821
},
"annotations": [
{
"id": "01HP8XYZ…",
"type": "highlight",
"color": "#ffd25a",
"anchor": {
"text": "must read slowly, and with care",
"prefix": "The reader who would truly understand ",
"suffix": ", turning the pages back when needed.",
"blockHint": "p:3"
},
"createdAt": "2026-04-21T14:32:00Z",
"updatedAt": "2026-04-21T14:32:00Z"
}
]
}
The file is git-friendly, human-editable, and semantically rich enough for an LLM to understand every annotation without the source document loaded.
git clone https://github.com/kaislate/remarkdown.git
cd remarkdown
npm install
npm run tauri dev
⏱ First cold build compiles the Rust toolchain + Tauri dependencies — expect 3–8 minutes. Subsequent launches are ~5 seconds.
npm run tauri build
Produces a signed NSIS installer in src-tauri/target/release/bundle/nsis/. Cutting a release with the in-app updater enabled requires the Ed25519 signing key — see RELEASING.md for the full process.
npm test # 320+ Vitest unit + component tests
npm run check # svelte-check (0 errors, 0 warnings)
npm run test:e2e # 6 Playwright end-to-end scenarios
cd src-tauri && cargo test # 6 Rust tests
| Layer | Choice | Reason |
|---|---|---|
| Shell | Tauri 2.x | ~5–10 MB installer, native file dialogs, Rust host, auto-updating WebView2 on Windows |
| Updater | tauri-plugin-updater + minisign Ed25519 | Signed installer verification against an in-app pubkey |
| UI framework | Svelte 5 (runes) + Vite | Compiled away, small runtime, clean reactive primitives |
| Markdown | markdown-it + footnote + task-lists + KaTeX | Mature, plugin-rich, easy to extend |
| Syntax highlight | Shiki 1.x (WASM, github-dark) | Real VS Code themes, dark-friendly |
| Math | KaTeX via @vscode/markdown-it-katex |
Fast, no server |
| Anchoring | W3C-style text-quote selector | Robust to edits, graceful orphaning |
| Hand-drawn UI | rough.js | Sketchy/jittery vector strokes for the tutorial arrows |
| Validation | Zod | Runtime-validated loads, typed TS output |
| Highlights rendering | CSS Custom Highlight API | No DOM mutation, browser-native overlap handling |
| Tests | Vitest + @testing-library/svelte + Playwright |
Unit / component / e2e |
remarkdown/
├── src/ # Svelte 5 frontend
│ ├── lib/ # Pure TS modules (anchoring, renderer, save, schema, …)
│ ├── components/ # Svelte components (Viewer, ToolRail, layers, modals, …)
│ ├── stores/ # Reactive state (doc, annots, tool, toasts, modals, …)
│ └── styles/ # Theme tokens (dark + light) + glass mixins + CSS highlight rules
├── src-tauri/ # Rust host
│ ├── capabilities/ # Tauri capability allowlists
│ └── src/ # Invoke commands, atomic sidecar writes, recent-files persistence
├── scripts/ # Build helpers (latest.json manifest generator)
├── tests/
│ ├── unit/ # Vitest unit tests
│ ├── component/ # @testing-library/svelte component tests
│ └── e2e/ # Playwright end-to-end + support/
├── RELEASING.md # End-to-end release/sign/publish process
└── README.md # This file
remarkdown is a personal project right now. If you find a bug or want a feature, please open an issue before opening a PR so we can talk about scope.
TBD. Will settle on a license before a stable v1.0 tag ships.
🖍 · 📝 · ✏️ · 🧹
Read well. Mark well. Keep your thoughts where your source lives.