Inkframe — Markdown to Image
Inkframe renders markdown content into polished, styled images via the inkframe.dev API. Run it via npx inkframe — no global install needed. The package includes a free shared API key, so it works out of the box.
Setup
No setup needed — always run the CLI via npx inkframe. The package ships with a free shared API key, so it works out of the box with no signup.
Quick Start
# Simplest render — just give it markdown
npx inkframe render --content "# Hello World\n\nThis is styled." --output out.png
# Render from a file
npx inkframe render --content @post.md --output out.png
# Use a template for instant styling
npx inkframe render --template tmpl_PWfUUDlVw --content @post.md --output out.png
# Preview in the browser (free, no API key needed)
npx inkframe open --content @post.md --design @design.json
CLI Commands
npx inkframe open
Opens the Inkframe playground in the browser with your content and design pre-loaded. Free, no API key needed — great for previewing and tweaking before rendering.
| Flag | Description | Default |
|---|---|---|
-c, --content <text> | Markdown string or @file.md to read from file | — |
-d, --design <json> | Inline JSON or @file.json | — |
--base-url <url> | Playground base URL | https://www.inkframe.dev |
npx inkframe open --content "# Hello World"
npx inkframe open --content @post.md --design @design.json
npx inkframe render
| Flag | Description | Default |
|---|---|---|
-c, --content <text> | Markdown string or @file.md to read from file | Required (unless --template provides content) |
-t, --template <id> | Template ID — applies its design (and content if --content omitted) | — |
-d, --design <json> | Inline JSON or @file.json — overrides template design | — |
-o, --output <path> | Save image to file (e.g. out.png). Prints URL if omitted | prints URL |
-s, --scale <n> | Scale factor: 1, 2, or 3 | 2 |
-f, --file-type <fmt> | Output format: png, jpeg, webp | png |
Content uses the @ prefix convention: --content @notes.md reads from notes.md, while --content "# Title" is inline markdown.
npx inkframe templates list
Lists all available templates with their IDs and names.
npx inkframe templates get <id>
Gets full template JSON. Add --design-only to get just the design object. Add -o file.json to save to file.
Available Templates
| ID | Name | Good for |
|---|---|---|
tmpl_650IbCa8k | Tweet (Dark) | Dark-themed tweet screenshots |
tmpl_vm9wHdOtU | Poem | Poetry, literary quotes |
tmpl_PWfUUDlVw | Quote | Inspirational/pull quotes |
tmpl_DAtOcPEQE | Business Poster | Professional announcements |
tmpl_W46vhIVoJ | Tweet | Tweet-style cards |
tmpl_4LNNIaHHO | DeepSeek问答 | Q&A format (Chinese) |
tmpl_vOv0UwIwl | Meme - Drake | Drake meme format |
tmpl_inxjqashV | Tweet (Bilingual) | Bilingual tweet cards |
tmpl_9PbGi7zcJ | Story (Bilingual) | Bilingual story format |
tmpl_qtYz45Xao | Quote Card (Classic) | Classic styled quotes |
tmpl_lVArmW0pP | Flowchart | Process/flow diagrams |
tmpl_pXED6toGN | Quote Card | Modern quote cards |
tmpl_ciwTrec6U | Tweet | Alternative tweet style |
tmpl_jKumMZX6E | Testimonial | Customer testimonials |
tmpl_hSlqk3U8h | Code Snippet | Code with syntax highlighting |
tmpl_KIHNN4CRg | Carousel | Multi-slide carousel |
tmpl_0fJUHUTWs | Listicle | Numbered/bulleted lists |
Templates are designed to look good out of the box — their fonts, colors, backgrounds, and layouts are already curated to work well together. Resist the urge to override a template's design unless the user specifically asks for customization. A template used as-is will almost always look more polished than a hastily assembled custom design.
Choosing the right template
Match the content to the template's purpose. When in doubt, inspect the template first with inkframe templates get <id> to see its content structure and design — then model your markdown after the template's content format for best results.
- Quotes/sayings:
tmpl_qtYz45Xao(Quote Card Classic) for elegant serif look,tmpl_PWfUUDlVw(Quote) for casual,tmpl_pXED6toGN(Quote Card) for modern - Code:
tmpl_hSlqk3U8h(Code Snippet) — dark theme, window controls, syntax highlighting - Tweets/social:
tmpl_W46vhIVoJ,tmpl_650IbCa8k(dark),tmpl_ciwTrec6U - Long-form content:
tmpl_DAtOcPEQE(Business Poster),tmpl_0fJUHUTWs(Listicle) - Testimonials:
tmpl_jKumMZX6E
Custom designs (when templates aren't enough)
Only reach for --design when the user wants something specific that no template provides — a particular aspect ratio, custom branding, or a specific color scheme. In that case, the best approach is:
- Find the closest template:
npx inkframe templates get <id> --design-only --output design.json - Modify only the fields that need to change
- Render with:
npx inkframe render --content @post.md --design @design.json --output out.png
For the full reference of all design fields (dimensions, backgrounds, color palettes, fonts, and more), read references/design-options.md in this skill's directory.
Interop With Prompt To Image
You can combine this skill with prompt-to-image when the user wants AI-generated art behind rendered markdown.
Important background fields:
backgroundImageUrl: full-canvas background imagecontentBoxImageUrl: background image inside the content box
These fields can use a normal hosted URL, and they can also use a base64 data URL such as data:image/png;base64,....
Recommended workflow:
- Use
prompt-to-imageto generate a background image - Convert the resulting file to a base64 data URL
- Put that data URL into
backgroundImageUrlorcontentBoxImageUrl - Render with
npx inkframe render
Example design:
{
"backgroundImageUrl": "data:image/png;base64,...",
"backgroundOverlayPresence": "dark",
"contentBoxVisibility": true,
"colorPaletteKey": "pure-white"
}
When the background is busy or high-contrast, use backgroundOverlayPresence and keep the content box visible so the text stays readable.
Multi-Page Content
Content can include \pagebreak to separate pages (e.g. for carousels or slideshows). The API renders one image per request — if your content has \pagebreak, only the first page is rendered. The inkframe.dev studio UI supports rendering all pages at once.
To render multi-page content, split it yourself and make one render call per page. Run them in parallel for speed:
# Split content and render each page in parallel
npx inkframe render --content @page1.md --design @design.json --output slide1.png &
npx inkframe render --content @page2.md --design @design.json --output slide2.png &
npx inkframe render --content @page3.md --design @design.json --output slide3.png &
wait
When building carousels or slideshows, write each page to a separate temp file, then render all pages in parallel using & and wait.
Design Pitfalls
When contentBoxVisibility is false, text renders directly on the background with no box behind it. Avoid these combinations — the text becomes unreadable:
- Dark
backgroundKey+ lightcolorPaletteKey(which has dark text) +contentBoxVisibility: false - Light
backgroundKey+ darkcolorPaletteKey(which has light text) +contentBoxVisibility: false
Either keep the content box visible, or match the palette theme to the background.
Workflow Tips
- Try a template as-is first — the curated designs are almost always better than custom ones. Use
npx inkframe templates listto browse, then render with--template. - Inspect before customizing —
npx inkframe templates get <id>shows the template's content and design. Model your markdown after the template's content structure. - Customize sparingly — if you must customize, start from a template's design and change only what's needed. Don't build designs from scratch.
- Preview with
npx inkframe open— usenpx inkframe open --content @post.md --design @design.jsonto open the playground in the browser for interactive previewing and tweaking. Free, no API key needed. - Write markdown to a temp file for anything longer than a line or two, then use
@file.md. This avoids shell escaping issues with inline content. - Always use
--outputto save the image locally rather than just printing a URL. - Content is standard markdown — headings, bold, italic, lists, code blocks, and blockquotes all render as expected.