Turn Markdown into typeset, print-ready documents — in the browser, with no account and no server.
Write on one side, watch a paginated document build itself on the other. Themes, charts, headers and footers, page numbers, a cover page, and a PDF that matches the preview exactly, because it is the preview.
- Real typography. Font pairings, per-element sizes and colours, an accent — no CSS required. Page size, orientation and margins in millimetres.
- Charts you edit by clicking. Charts are fenced
```chartblocks. Click one and edit it in a panel; the block updates as you go. - Diagrams you can style. Mermaid flowcharts render natively. Click a node to recolour, relabel or reshape it; drag to reorder.
- Pages that behave. Explicit page breaks, repeating table headers, keep-together rules, orphan and widow control.
- Nothing leaves your browser. Documents live in IndexedDB. No upload, no account, no watermark.
The parser is stock GitHub-Flavored Markdown. Everything mdstudio adds is an ordinary Markdown construct that other renderers already handle:
| Feature | Syntax | Elsewhere |
|---|---|---|
| Styling | mdstudio: key in YAML frontmatter |
Ignored as an unknown key |
| Charts | ```chart fence |
Renders as a code block |
| Diagrams | ```mermaid fence |
Renders on GitHub, GitLab, Obsidian |
| Contents | [[toc]] or <!-- toc --> |
Literal text, or invisible |
| Page break | \pagebreak or <!-- pagebreak --> |
Literal text, or invisible |
| Math | $…$, $$…$$ |
Renders on GitHub |
Use the HTML-comment forms and the file looks completely ordinary everywhere
else while still driving mdstudio. Any existing .md opens unchanged.
npm install
npm run devpredev and prebuild stage the vendor assets (Paged.js, KaTeX and the
self-hosted document fonts) into public/vendor/, so the render frame can load
them as plain static files.
npm run build # production build
npm run lint # eslintSee ARCHITECTURE.md — itself written as an mdstudio document, so you can open it in the app.
The short version: the Markdown string is the only source of truth. Every GUI control is a text editor in disguise, rewriting frontmatter or a fenced block. The document renders inside an isolated iframe that paginates itself with Paged.js, and "Export PDF" prints that same frame — which is what makes WYSIWYG true by construction rather than by agreement.
Next.js (App Router) · Tailwind v4 · CodeMirror 6 · unified/remark/rehype · Shiki · KaTeX · Mermaid · Paged.js · IndexedDB. No backend.
MIT