Skip to content

Repository files navigation

Markdown With Diagrams

markdownwithdiagrams.com

Render GitHub-flavored Markdown with Mermaid diagrams in a clean, ChatGPT-style light theme. Type on the left, watch it render on the right, and export to PDF in one click.

split-view editor with a rendered Mermaid flowchart

Features

  • Split view: a CodeMirror editor beside a live preview.
  • GitHub-flavored Markdown: tables, task lists, fenced code with syntax highlighting.
  • Mermaid diagrams render to vector SVG inside a card that matches ChatGPT's.
  • Export to PDF through a server-side Puppeteer route. Text stays selectable and diagrams stay sharp.
  • A blog under /blog, written in markdown and rendered by the same pipeline, so posts can use mermaid blocks.
  • shadcn-style interface: neutral palette, Geist font, minimal chrome.

Run it

bun install
bunx puppeteer browsers install chrome   # one-time, for PDF export
bun run dev

Open http://localhost:3010.

How it works

One unified pipeline in lib/render-markdown.ts turns Markdown into HTML. The browser preview, the blog and the /api/pdf route all call it, so a diagram looks the same everywhere. The PDF route wraps that HTML in a print template, loads it in headless Chromium, waits for Mermaid to finish, and returns the printed page.

markdown ─▶ renderMarkdown() ─▶ HTML ─┬─▶ preview   (mermaid runs in the browser)
                                      ├─▶ /blog     (same browser renderer)
                                      └─▶ /api/pdf ─▶ Puppeteer ─▶ document.pdf

Two rules keep diagrams on screen, both learned from cards that came out empty:

  • DiagramHost is memoised. Without it, typing re-rendered the component on every keystroke, React re-applied the container's HTML, and every rendered SVG was destroyed and redrawn.
  • The print template inlines Mermaid from node_modules instead of fetching a CDN, and reveals a diagram's source if rendering fails. A card never prints blank.

Content

Blog posts live in content/blog/*.md with title, description and date frontmatter. Adding a file publishes a post, adds it to the sitemap, and generates its share image.

Deploying

Local development uses Chrome installed by puppeteer. On Vercel, the PDF route automatically uses the bundled @sparticuz/chromium browser through puppeteer-core. Keep their Chromium major versions aligned when upgrading. next.config.ts traces the browser binaries, mermaid.min.js, and shared stylesheets into the function.

Stack

Next.js 16 (App Router), React 19, TypeScript, Tailwind CSS 4, unified/remark/rehype, Mermaid 11, CodeMirror 6, Puppeteer.

Releases

Packages

Contributors

Languages