A single-file Markdown workbench. Everything is stored locally in your browser (IndexedDB) — files, notes, ink and bookmarks never leave your machine.
Every document remembers its scroll position, cursor, mode, bookmarks, highlights, side notes and ink — keyed by its path. Reopening the file (or resuming a session) puts you right back where you left off.
Select text in the preview to highlight it or send a quote to the notes panel. The ✎ button enables the ink layer for a stylus (e.g. Wacom) or mouse — pressure is supported, and you get yellow/green/pink markers plus red, blue and ink pens, freehand smoothing, and box/circle/arrow shapes — outlined with pen colors or as solid translucent areas with marker colors. The ✥ tool selects a shape or stroke to move it (Del deletes, clicking a swatch recolors it). Each annotation is anchored to the picture or paragraph it sits on, so it follows that element precisely across Edit/Split/View modes and into the PDF.
Web images render directly; images with relative paths load when the project folder is open. Bare links to images are shown as pictures. The PDF button opens a print view — with or without highlights and ink — where “Save as PDF” produces the final document.
With a project folder open (write access), every annotated document gets a .mdesk file next to it — guide.md.mdesk holding its bookmarks, side notes, highlights and ink — written automatically and on every Save. The root .mdesk file remembers your open tabs, so opening the folder on another computer offers to restore the session. Sync or commit the folder and everything travels together. (Older .mdesk.json files are read once and upgraded automatically.) New files saved into the open project folder — and files opened individually from inside it — are recognized automatically and get the same treatment. A file saved outside any open project keeps its annotations in the browser only.
guide.md.mdesk
.mdesk
.mdesk.json
The PDF area button in the pen toolbar outlines exactly what PDF export includes: the text column, down to just past the last content — text or ink, whichever reaches lower, so a document with no text at all can still be drawn on and exported. On an empty document the frame offers at least a full screen to draw in and grows as your ink goes lower. The PNG button downloads the drawing alone as an image (white background; markdown text isn't rendered into it — use PDF export for text + ink together).
Export ZIP packs the entire project folder (documents, images, sidecars, settings) into one timestamped archive — handy as a portable backup or a simple version record. Import ZIP extracts an archive into a folder of your choice, or opens it read-only to review its documents with their annotations without touching your disk.
Everything stays on your machine: the tool talks to no server. The browser keeps only convenience data — the remembered folder, recents, sessions and annotation state. Press Ctrl+Shift+R or use the button below to erase all of it; .mdesk files on disk are yours and are never touched. Clear stored data…
When served from a website (https), Markdown Desk is installable: use the install icon in the address bar or the browser menu → Install Markdown Desk — it then opens in its own window with its own icon, like a native app. Install app…
Recommended server setup: Download PWA kit (zip) — it contains mdesk.webmanifest, two icon PNGs and mdesk-sw.js. Upload all four into the same folder as this HTML file. The tool detects them automatically; you get reliable installability and full offline support. Then reload and check the browser console for [mdesk pwa]. If no install icon appears in the address bar, use the browser menu: Cast, save and share → Install page as app (Chrome) or Apps → Install this site as an app (Edge).
mdesk.webmanifest
mdesk-sw.js
[mdesk pwa]
Without the kit, a built-in fallback manifest is used — installation may still be offered, but some browsers reject its embedded icons. The service worker file for offline support contains:
const C = "mdesk-v3.52"; self.addEventListener("install", e => { self.skipWaiting(); }); self.addEventListener("activate", e => e.waitUntil((async () => { for (const k of await caches.keys()) if (k !== C) await caches.delete(k); await clients.claim(); })())); /* network-first: the app updates the moment a deploy lands; the cache only serves when offline. (The old cache-first worker pinned users to stale versions forever - the v3.41..v3.51 "fix changed nothing" mystery.) */ self.addEventListener("fetch", e => { e.respondWith((async () => { try { const net = await fetch(e.request); const c = await caches.open(C); c.put(e.request, net.clone()); return net; } catch { const hit = await caches.match(e.request); return hit || caches.match(self.registration.scope); } })()); });
The tool registers it automatically when present; without it, installation still works and the app simply needs the network for its first load after a cache eviction.
Markdown Desk — a self-contained markdown reading, writing, annotation & snapshot tool. One HTML file, no installation, no external dependencies, fully offline-capable. Built by Andrew Michelis · KnackMentor — engineering consulting for automation, embedded & systems integration. More tools and articles at knackmentor.com.
Direct save-back into files and folder trees need Chrome/Edge (File System Access API) and https or localhost. In other browsers, saving downloads a copy.
Documents & references — all .md files, every image/file they actually link to, plus annotations & settings
Entire folder — everything inside the project, as-is
Opens a print view of the rendered document — choose “Save as PDF” in the print dialog.
Include text highlights Include pen & marker ink
Tip: with ink included, the page is laid out at your current on-screen width so the ink lines up exactly.