Use case · Code screenshots

Programmatic code screenshots, not click-export-repeat.

Carbon.now, but as an API. Pick a theme, paste code, get a PNG. Batch from a script, generate on every commit in CI, or call from an agent — same /v1/render endpoint.

The problem

Carbon.now is a UI, not an API. To batch-render 50 code snapshots for a tutorial, you click-export 50 times. Worse: themes are fixed, sizes are limited, and you can't drop in your brand colors without forking the project.

And there's no programmatic access — no CI integration, no agent integration, no automation. The moment your code changes, every screenshot in your docs goes stale and someone has to re-shoot them by hand.

Three approaches, one API

1. Full HTML control

For pixel-perfect brand

Write your own template with highlight.js, Prism, or Shiki and custom CSS — window chrome, fonts, padding, background — exactly how you want it. POST it to /v1/render.

2. REST API in your blog pipeline

For docs and tutorials

Wire a templating service into your blog build. Each MDX file with a code-shot block hits the API and gets a fresh PNG written to /public/code/.

3. CLI in CI

For every commit

@codetoimage/cli runs in GitHub Actions, generates code screenshots from changed files, attaches them to the PR as visual previews. No more stale tutorial images.

Example — syntax-highlighted Python snippet

A complete dark-themed template with window chrome, traffic-light dots, and highlight.js via CDN. Drop in your code, POST it, get a PNG back:

HTML=$(cat <<'EOF'
<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet"
    href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.min.css">
  <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js"></script>
  <style>
    body { margin: 0; background: #1e293b; font-family: 'JetBrains Mono', monospace; }
    .card {
      width: 1080px; margin: 60px auto;
      background: #0f172a; border-radius: 14px;
      box-shadow: 0 30px 80px rgba(0,0,0,0.5);
      overflow: hidden;
    }
    .chrome {
      display: flex; gap: 8px; padding: 14px 18px;
      background: #1e293b; border-bottom: 1px solid #334155;
    }
    .dot { width: 12px; height: 12px; border-radius: 50%; }
    .red { background: #ef4444; } .yel { background: #f59e0b; } .grn { background: #10b981; }
    pre { margin: 0; padding: 28px 32px; font-size: 16px; line-height: 1.6; }
    code { background: transparent !important; }
  </style>
</head>
<body>
  <div class="card">
    <div class="chrome">
      <span class="dot red"></span><span class="dot yel"></span><span class="dot grn"></span>
    </div>
    <pre><code class="language-python">def fibonacci(n: int) -> list[int]:
    seq = [0, 1]
    while len(seq) < n:
        seq.append(seq[-1] + seq[-2])
    return seq[:n]

print(fibonacci(10))</code></pre>
  </div>
  <script>hljs.highlightAll();</script>
</body>
</html>
EOF
)

curl -X POST https://api.codetoimage.app/v1/render \
  -H "X-API-Key: cti_live_..." \
  -H "Content-Type: application/json" \
  -d "{\"html\": $(jq -Rs . <<< "$HTML"), \"width\": 1200, \"format\": \"png\"}" \
  --output code.png

Same flow from Node — wrap the body in a templating function and call it from a build script:

import { writeFile } from "node:fs/promises";

async function renderCode(code: string, lang = "python") {
  const html = buildTemplate(code, lang);
  const res = await fetch("https://api.codetoimage.app/v1/render", {
    method: "POST",
    headers: {
      "X-API-Key": process.env.CODETOIMAGE_API_KEY!,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      html,
      width: 1200,
      format: "png",
      output: "url",
    }),
  });
  const { url } = await res.json();
  return url;
}

const url = await renderCode(`def hello(): print("world")`);
console.log(url);

vs Carbon.now

AspectCarbon.nowcodetoimage
InterfaceWeb UI only✓ REST API, CLI, MCP
Theme customizationPreset list✓ Any CSS (VSCode, Shiki, custom)
Batch renderingManual, one at a time✓ Scriptable — 50, 500, whatever
Brand customizationNone✓ Full HTML — your fonts, your frame, your colors
Programmatic accessNo✓ Yes — REST + CLI + MCP
CI integrationNo✓ GitHub Actions, GitLab CI, anywhere npx runs
Output formatsPNG, SVG✓ PNG, JPEG, WebP
Free tier✓ Yes, unlimited UI useSandbox 50/mo

What you get

Any syntax highlighter

highlight.js, Prism, or Shiki via SSR — all of them are just CSS classes by the time they hit the renderer. Use whichever has the language and theme you want.

Custom themes

Your dark, your light, your brand palette. Export from VSCode, write from scratch, or fork an existing theme — it is just CSS.

Window chrome optional

With or without traffic-light dots, terminal frame, IDE-style sidebar, line numbers, file path header. Style it like your editor or strip it down to bare code.

Batch from gist or repo

Script reads a directory of .py / .ts / .rs files, renders all of them with consistent styling, drops PNGs into /public/code/. Tutorial-ready in one run.

Twitter/X automation

GitHub Action on push: extract the changed function, render to PNG, post to X with the commit message. Your repo announces itself.

Course and docs automation

Style change in your design system? Regenerate every code screenshot in your course or docs site in one CI run. No more stale visuals.

FAQ

Is this Carbon.now in a box?

Kind of, but you control everything: the highlighter, theme, window frame, fonts, padding, background. Carbon.now is a great UI for one-off shots. codetoimage is a programmable backend for the same job — so you can batch 50 snippets, regenerate when your brand changes, or render code screenshots from a GitHub Action on every commit.

Can I use my own VSCode theme?

Yes. Export the theme JSON from VSCode (or grab it from the marketplace), generate CSS rules from it — or use a converter like vscode-theme-css-converter — and drop the resulting CSS into your template. Every token color and background becomes part of your render. Same goes for Shiki themes (which already ship as TextMate JSON).

How do I do light + dark variants?

Render twice with two different stylesheets — once with your dark theme CSS, once with light. Save them as code-dark.png and code-light.png. On Twitter/X and LinkedIn, embed the one that matches your audience or use dark-mode meta hints. For docs sites, swap them via a CSS prefers-color-scheme media query around an HTML <picture> element.

Can I render really long code?

Yes, but watch output dimensions. At width 1200 with default font-size, about 80 lines fit in ~2048px height (the paid-tier ceiling). For longer snippets, split into two images, use horizontal layout (wider canvas, shorter height), or shrink the font. The render endpoint returns an error if you exceed the height limit so you can fall back gracefully.

Stop click-exporting code shots.

Free Sandbox tier — 50 renders/month, no credit card. Wire up in five minutes with the example above, or drop the CLI into CI.