If you’ve ever built a “Markdown → image” pipeline, you’ve probably hit this wall:
TEXT
Markdown → HTML → Browser → Screenshot
Then you run into:
- Chromium is heavy (a pain to deploy)
- Pagination is unstable (every run may produce a different result)
- Batch rendering performance is poor
- It’s basically impossible to work with in serverless environments I was getting fed up with this pipeline, so I wrote my own: marknative ---
Core idea (completely different from the usual approach)
No HTML. No DOM. No browser.
Instead:
TEXT
Markdown → AST → Custom document model → Layout → Pagination → Canvas rendering
Put simply:
A stripped-down implementation of browser-style layout, built from scratch (just for Markdown).
---
What can it do?
1. Output PNGs and SVGs directly
TypeScript
import { renderMarkdown } from 'marknative'
const pages = await renderMarkdown('# Hello')
await Bun.write('page-1.png', pages[0].data)
No need for:
- Puppeteer
- Headless Chrome
- Screenshots ---
2. Pagination comes for free (and it’s deterministic)
Out of the box:
- 1080 × 1440
- A card-like aspect ratio And pagination is deterministic:
- The same Markdown input
- In any environment
- Identical rendering results --- ### 3. Great for generating content in bulk For example:
- Xiaohongshu cards
- Social images for technical articles
- AI-generated content images Compared with Puppeteer:
- Faster startup
- Lower memory usage
- Easier to scale horizontally --- ## Is this direction worth pursuing?
Ultimately, this kind of need boils down to:
“Structured text → Controlled layout → Image output” But browsers:
- Are too general-purpose (they’re designed for the web)
- Are hard to control (CSS + layout are too complex)
- Are too expensive For Markdown:
- The structure is fixed
- The constraints are clear
- It’s a perfect fit for a “purpose-built layout engine” --- ## Technical highlights (a few interesting ones)
- Use
micromark+mdastfor parsing- Implement block and inline layout from scratch
- Draw directly with
skia-canvas- Keep layout and rendering completely decoupled In theory, you can:
- Swap out the renderer (SVG / PDF / WebGL)
- Build a custom theming system
- Build a visual editor (in the future) --- ## Project repository
👉 https://github.com/liyown/marknative