Anyone who has tried "Markdown → image" has probably fallen into this trap:
Markdown → HTML → Browser → Screenshot
Then you run into:
- chromium is heavy (deployment is painful)
- pagination is unstable (results can differ every time)
- batch rendering performance is terrible
- serverless environments are basically unusable
I got fed up with this pipeline recently, so I wrote my own: marknative
Core Idea (Completely Different from Conventional Solutions)
No HTML, no DOM, no browser.
Instead:
Markdown → AST → Custom document model → layout → pagination → canvas drawing
Simple explanation:
I implemented a minimal version of "browser layout" myself (only for Markdown).
What Can It Do?
1. Direct PNG / SVG Output
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. Native Pagination Support (and It's Stable)
By default:
- 1080 × 1440
- Card-like aspect ratio
And pagination is deterministic:
- Same Markdown
- Any environment
- Consistent rendering results
3. Great for Batch Content Generation
For example:
- Xiaohongshu cards
- Technical article images
- AI-generated content images
Compared to puppeteer:
- Faster startup
- Lower memory
- Easier horizontal scaling
This Direction Is Worth Pursuing
Essentially, this type of need is:
"structured text → controllable layout → image output"
But browsers:
- Are too general (designed for web pages)
- Are uncontrollable (CSS + layout too complex)
- Have high costs
Markdown scenarios:
- Fixed structure
- Can be constrained
- Perfect for a "dedicated layout engine"
Technical Points (Briefly Mention a Few Interesting Ones)
- Use
micromark+mdastfor parsing - Implement my own block / inline layout
- Use
skia-canvasfor direct drawing - Layout and render are completely decoupled
So theoretically you can:
- Swap renderer (SVG / PDF / WebGL)
- Build custom theme system
- Build visual editor (future)
Project Address
👉 https://github.com/liyown/marknative