A full-feature Markdown editor that runs entirely in your browser. Live preview · Mermaid diagrams · LaTeX math · syntax highlighting · works offline.
MarkdownLab is a client-side Markdown workspace. Paste any content, watch it render live, export to HTML or PDF. The app is a static single page — your documents never touch a server, and after the first load it works without a connection.
- Live split preview with content-aware scroll sync (block-by-block, not ratio)
- Full GFM — tables, task lists, footnotes, heading anchors,
[!NOTE]/[!WARNING]alerts - Mermaid diagrams — flowchart, sequence, class, state, ER, Gantt, pie, mindmap, gitGraph, journey
- KaTeX math — inline
$x$and display$$…$$with MathML output for screen readers - Syntax highlighting across 190+ languages via highlight.js
- Multi-file projects with sidebar, draggable tabs, fuzzy search, and
⌘Pcommand palette - Load from any public GitHub URL — paste a blob, raw, or repo URL; relative links and images resolve back to the repo
- Export to self-contained HTML, vector PDF (native print), or Markdown source
- Zero backend — IndexedDB on your device, DOMPurify on untrusted HTML, no analytics or cookies
Use the hosted version at markdownlab.vercel.app, or run locally:
git clone https://github.com/invincible04/markdownlab.git
cd markdownlab
python3 -m http.server 8000No build step, no package manager. index.html is the entry point and pulls pinned runtime dependencies from jsdelivr on demand.
GitHub's README renderer supports Mermaid and LaTeX natively — so the examples below are the same output MarkdownLab produces in the editor.
A Mermaid flowchart:
flowchart LR
Src[Markdown source] --> Math[extractMath]
Math --> Parse[marked + GFM]
Parse --> Reinject[reinject KaTeX]
Reinject --> Clean[DOMPurify]
Clean --> DOM[Preview DOM]
DOM --> M[mermaid.run]
DOM --> Post[postProcess]
LaTeX math:
Syntax-highlighted code:
async function render(src: string): Promise<string> {
const { body, math } = extractMath(src);
const html = marked.parse(body);
return DOMPurify.sanitize(reinjectMath(html, math));
}GitHub-style alerts:
Note
MarkdownLab uses the same alert syntax GitHub does — > [!NOTE], [!TIP], [!IMPORTANT], [!WARNING], [!CAUTION].
| Area | What you get |
|---|---|
| Content | GFM, footnotes, alerts, Mermaid (10 diagram types), KaTeX (inline + block), 190+ highlighted languages |
| Editing | Live split preview with end-to-end latency under 40 ms, content-aware scroll sync, soft-wrapped editor with accurate line numbers, focus mode, reading mode |
| Projects | Sidebar with projects + files, draggable tabs, fuzzy search, command palette (⌘P), dual-pane find-and-replace with regex, folder import, GitHub URL import, undoable delete |
| Diagrams | Pinch, wheel, and keyboard-zoomable lightbox, in-viewer theme toggle, 2× PNG export with inlined computed styles, redraws on theme change, WCAG AA palette, structured parse-error card for Mermaid |
| Exports | Self-contained HTML, vector PDF (native window.print()), Markdown source, clipboard copy of rendered HTML or source |
| UX | Dark + light themes (WCAG AA in both), keyboard-first navigation, responsive drawer on mobile |
| Offline | Service worker caches the app shell and pinned CDN deps on first visit; installable as a PWA |
| Privacy | 100% client-side; documents in IndexedDB (origin-isolated), DOMPurify sanitization, strict Mermaid security level, no analytics, no cookies |
| A11y | Semantic HTML, ARIA roles on dialogs, visible focus rings, MathML alongside visual math, respects prefers-reduced-motion |
Full capability list (click to expand)
- Debounced 120 ms render loop, typical end-to-end latency under 40 ms
- Soft-wrapped editor with a hidden mirror that keeps line math correct
- Line numbers track soft-wrapped lines exactly
- Per-file autosave — cursor position, scroll, and dirty indicator
Tabinserts two spaces;Ctrl+F/Ctrl+Hopen find / find-and-replace with regex, matching in both the editor and the rendered preview
- IndexedDB storage (localStorage fallback for private browsing)
- Drag-reorder files within or across projects
- Middle-click or
⌘Wto close tabs;⌘Tabto cycle - Fuzzy search across every project and file from the sidebar or palette
⌘P+⌘Entercreates a new file from the current query- 7-second undo toast on deletes — no accidental permanent loss
- Load any public GitHub markdown by URL —
blob/,raw/, or bare repo (default branch + README auto-resolved); relative.mdlinks lazy-fetch on click, images resolve toraw.githubusercontent.com
- Interactive lightbox with drag-to-pan and two-finger pinch zoom on touch
- Wheel zoom calibrated for both mouse wheels and trackpad pinch;
+/−/0/ arrow-key zoom and pan from the keyboard - Attribute-based SVG zoom — vectors re-rasterize crisply at every level, including
<foreignObject>HTML labels - In-viewer theme toggle re-themes diagrams without leaving the lightbox, preserving scale and pan
- 2× PNG export with inlined computed styles — colors match on-screen output exactly
- Auto theme — diagrams redraw on theme toggle without re-parsing the document
- Mermaid parse errors render as a structured card with the offending line highlighted and a Copy source action
- HTML export inlines KaTeX + highlight.js CSS when the network is reachable; falls back to CDN
<link>tags otherwise - PDF export uses
window.print()inside a hidden light-themed iframe — true vector output with selectable text and working hyperlinks - Markdown export, rendered-HTML copy, and source copy from the same menu
- Three view modes (editor / split / preview), resizable divider
- Focus mode hides all chrome; floating glass dock keeps theme, outline, reading, and exit accessible
- Reading mode — opt-in serif typography with a narrower column
- Sidebar collapses to a swipe-dismissible drawer on small screens
|
Architecture RFCs with inline Mermaid, incident post-mortems with Gantt timelines, runbook fragments with GFM alerts and highlighted code, preview of raw GitHub issue/PR bodies before posting. |
Academic notes with inline and block equations that render identically on any device. Prototype data-science notebooks' narrative sections. Long-form drafts in reading mode with serif typography. |
Runbook fragments with syntax-highlighted code and GitHub-style callouts. Chart documentation previews. Self-contained HTML exports for reports. 2× PNG diagram exports for slide decks. |
| Shortcut | Action |
|---|---|
| Ctrl/Cmd + 1 / 2 / 3 | Editor / Split / Preview view |
| Ctrl/Cmd + P | Command palette / quick open |
| Ctrl/Cmd + F | Find in file (editor and preview) |
| Ctrl/Cmd + H or Ctrl/Cmd + Shift + F | Find and replace |
| F3 or Ctrl/Cmd + G | Next match (add Shift for previous) |
| Alt + C / W / R | Toggle case-sensitive, whole-word, regex |
| Ctrl/Cmd + B | Toggle sidebar |
| Ctrl/Cmd + N | New file in active project |
| Ctrl/Cmd + W | Close current tab |
| Ctrl/Cmd + Tab | Next tab (add Shift for previous) |
| Ctrl/Cmd + K | Toggle theme |
| Ctrl/Cmd + . | Toggle focus mode |
| Ctrl/Cmd + L | Toggle outline |
| Ctrl/Cmd + O | Open file(s) |
| Ctrl/Cmd + S | Download Markdown |
| F2 | Rename file (in sidebar) |
| / | Focus sidebar search |
| ? or Ctrl/Cmd + / | Show all shortcuts |
| Esc | Exit focus / close dialog |
| + / − / 0 / arrow keys | Zoom in / out / fit / pan (diagram viewer) |
| Tab | Insert two spaces (editor) |
sequenceDiagram
participant E as Editor
participant P as Pipeline
participant DOM as Preview
E->>P: keystroke (debounced 120ms)
P->>P: extractMath — pull out $...$ and $$...$$
P->>P: marked.parse (GFM + heading IDs + footnotes)
P->>P: reinject KaTeX HTML
P->>P: DOMPurify.sanitize (SVG + MathML allowlisted)
P->>DOM: innerHTML
DOM->>DOM: mermaid.run on .mermaid nodes
DOM->>DOM: postProcess (copy buttons, link targets, TOC, diagram controls)
-
extractMath pulls
$…$and$$…$$out of the source (skipping fenced and inline code) and renders each with KaTeX, leaving placeholders. -
marked parses the placeholder-substituted source. A custom renderer emits Mermaid fences as
<div class="mermaid">so they survive sanitization. - reinjectMath swaps the placeholders back with the pre-rendered KaTeX HTML.
- DOMPurify sanitizes with SVG and MathML allowlisted.
-
mermaid.run replaces each
.mermaiddiv with an SVG. - postProcess attaches copy buttons to code blocks, opens external links in new tabs, wires smooth scroll on anchor links, and attaches the zoom control to each diagram.
The app is a static single page — no backend, no analytics, no cookies, no tracking pixels. Documents are stored in the browser's IndexedDB (origin-isolated, never uploaded). You can inspect or delete them via DevTools → Application → IndexedDB → mdlab.
Every piece of rendered HTML passes through DOMPurify with a conservative allowlist. Mermaid runs with securityLevel: 'strict' (inline event handlers and external references blocked). A strict Content Security Policy in vercel.json whitelists only the pinned CDN origins and the site's own assets.
After the first load, a service worker serves the app shell and pinned CDN dependencies from cache, so the editor works without a connection. Offline-only edits still persist to IndexedDB.
Drop the repo onto any static host (GitHub Pages, Netlify, Cloudflare Pages, S3, Vercel, plain nginx). The app is 100% static — no build step, no env vars, no secrets.
If you're publishing a fork under your own domain, update these in one pass:
-
Canonical URL — find-and-replace
markdownlab.vercel.appacrossindex.html,robots.txt,sitemap.xml,llms.txt, anddesign/og-image.svg -
Repo link — find-and-replace
github.com/invincible04/markdownlabinindex.html(sameAs, footer, About modal) andllms.txt -
OG image — regenerate
og-image.pngfrom the editeddesign/og-image.svg. The steps are indesign/README.md -
Host headers —
vercel.jsonis Vercel-specific. For Netlify or Cloudflare Pages, drop-in replacements are already committed as_headersandnetlify.toml. For nginx or Apache, copy the directives into your server block. -
CSP hash — if you edit the inline async-CSS script in
<head>, recompute its SHA-256 and updatescript-srcinvercel.json,_headers, andnetlify.toml:python3 -c " import base64, hashlib, re html = open('index.html').read() body = re.search(r'<script(?![^>]*\ssrc\s*=)[^>]*>([\s\S]*?)</script>', html).group(1) print('sha256-' + base64.b64encode(hashlib.sha256(body.encode()).digest()).decode()) "
Is MarkdownLab really free?
Yes — free and open source under the MIT license. Every feature is available without payment, sign-up, or email capture.
Does it work offline?
Yes. After the first page load, the app runs entirely in your browser. Documents persist in IndexedDB and survive reloads and browser restarts. CDN assets are cached by the service worker on first visit.
Which markdown flavor is supported?
GitHub Flavored Markdown (GFM) via the marked parser, plus heading-ID and footnote extensions.
Can I render Mermaid diagrams?
Yes — any fenced block tagged mermaid renders as an interactive diagram. The viewer supports pinch (touch), wheel, and keyboard zoom, drag-to-pan, an in-viewer theme toggle, and 2× PNG export. All 10 Mermaid diagram types: flowchart, sequence, class, state, ER, Gantt, pie, mindmap, gitGraph, journey.
Can I open a README directly from GitHub?
Yes. Use Import → Load from GitHub URL and paste any of:
- A blob URL —
https://github.com/{owner}/{repo}/blob/{ref}/{path}.md - A raw URL —
https://raw.githubusercontent.com/{owner}/{repo}/{ref}/{path}.md - A bare repo —
https://github.com/{owner}/{repo}(default branch + README auto-resolved)
Relative .md links inside the loaded file lazy-fetch on click. Images, video, and audio with relative src resolve to raw.githubusercontent.com. Non-markdown links open on github.com in a new tab. Public repos only.
How do I export to PDF?
Export → Download PDF uses the browser's native print engine for crisp vector output with real pagination and working hyperlinks. No rasterization library needed.
Is my markdown private?
Completely. No backend, no analytics, no cookies. Documents never leave your device; you can inspect or delete them via DevTools → Application → IndexedDB → mdlab. The source is on GitHub — audit it yourself.
What browsers are supported?
Any modern browser with ES Modules support — Chrome, Firefox, Safari, Edge, Brave, Arc — on desktop and mobile. The last two stable versions of each are tested.
All runtime dependencies are public, version-pinned, and loaded from jsdelivr on demand. No package manager, no lockfile, no bundler.
| Library | Version |
|---|---|
| marked | 12.0.2 |
| marked-gfm-heading-id | 3.1.3 |
| marked-footnote | 1.2.4 |
| mermaid | 11.4.1 |
| KaTeX | 0.16.11 |
| highlight.js | 11.10.0 |
| DOMPurify | 3.2.7 |
PDF export uses the browser's native window.print() API against a hidden, light-themed iframe — no rasterization library. SVG diagram export is a pure-browser canvas.toBlob('image/png') with inlined computed styles. Both are zero-dependency.
PRs are welcome. Please read CONTRIBUTING.md first — it covers the zero-build invariant, the CSP-hash footgun, the code style, and the PR checklist. For anything non-trivial, open an issue before writing code.
Participation in this project is governed by the Code of Conduct. Security issues should be reported privately per the Security Policy, never in public issues.
MIT — use it, fork it, build on it, ship your own version.