How to automating svg-to-canvas code export in a build pipeline
- Step 1Confirm the tool's schema and execution mode —
GET /api/v1/tools/svg-canvas-exporterreturns the tool metadata and its options array — which is empty for this tool (there are no knobs to set). The same metadata marks it as headless-browser execution, telling the runner it needs a browser session rather than the pure-text engine. - Step 2Install and pair the @jadapps/runner — Follow the runner docs to install
@jadapps/runnerand pair it with your account/API key. The runner listens on127.0.0.1:9789and executes tools locally. For this tool it launches a headless browser under the hood; make sure that environment is available on your build agent. - Step 3Send each SVG to the local runner — POST your payload to
http://127.0.0.1:9789/v1/tools/svg-canvas-exporter/runwith the SVG content and an emptyoptions: {}. The runner returns the generated.jsmodule. Do not POST content to JAD's hosted/api/v1/.../run— that endpoint is upload-free and replies 400 with pairing instructions by design. - Step 4Loop over your asset directory — Because the tool is single-file, iterate: for each
*.svg, call the runner once and write the returned module togenerated/<name>-canvas.js. A simple shell or Node loop is enough; there's no array-batch endpoint for this specific tool. - Step 5Name and wire up the modules — The export name comes from the file stem (
arrow-left.svg→drawArrowLeft). Re-export them from a barrel file if you want a single import:export * from './arrow-left-canvas.js'. Each function takes onlyctx; position withctx.translate/ctx.scaleat the call site. - Step 6Validate the output before committing — Scan generated files for
// arc approximated as linecomments (arcs degraded to straight lines) and for missing shapes (non-path elements are skipped). Gate your build on a quick check so a silently-empty module doesn't ship.
Automation surface for svg-canvas-exporter
What's real for driving this tool from code. The hosted API is deliberately upload-free; execution happens on your machine via the runner.
| Concern | Reality |
|---|---|
| Schema endpoint | GET /api/v1/tools/svg-canvas-exporter — returns metadata + an empty options array (no configurable options) |
| Hosted run endpoint | POST /api/v1/tools/svg-canvas-exporter/run — upload-free; returns 400 with runner pairing instructions, never processes content |
| Local runner endpoint | POST http://127.0.0.1:9789/v1/tools/svg-canvas-exporter/run — accepts the payload, executes locally, returns the .js |
| Execution mode | Headless browser (relies on the DOM parser) — not the pure-text engine used by tools like svg-pro-minifier |
| Options to send | {} — the tool has no options; sending extra keys has no effect |
| Output per file | One ES module: export function draw<Name>(ctx) { … }, filename <name>-canvas.js, MIME text/javascript |
| UI batch support | None — the in-browser tool is single-file; scripted batching = one runner call per SVG |
Tier limits that affect a pipeline
From the tier-limits config for the SVG family. The Canvas Exporter additionally requires the Developer plan to run at all. Batch-file counts apply to multi-file SVG tools generally; this tool is single-file regardless.
| Tier | SVG file-size cap | SVG batch-file cap | Can run svg-canvas-exporter? |
|---|---|---|---|
| Free | 5 MB | 1 | No — gated to Developer (upgrade overlay shown) |
| Pro | 50 MB | 20 | No — gated to Developer |
| Pro Media | 200 MB | (media-focused) | No — gated to Developer |
| Developer | 2 GB | Unlimited | Yes |
Cookbook
Pipeline recipes using the real upload-free API + local runner flow. Replace the API key and paths with yours.
Fetch the schema (source of truth, no options)
Before scripting anything, confirm the contract. The options array comes back empty — there is nothing to configure for this tool.
$ curl -s -H "Authorization: Bearer $JAD_KEY" \
https://jadapps.com/api/v1/tools/svg-canvas-exporter
{
"slug": "svg-canvas-exporter",
"category": "svg",
"minTier": "developer",
"options": [],
"execution": { "runnerMode": "headless-browser" }
}What the hosted /run endpoint returns (by design)
POSTing content to the hosted endpoint does not process it — it tells you to use the runner. This is the privacy guarantee, not an error in your script.
$ curl -s -X POST -H "Authorization: Bearer $JAD_KEY" \
https://jadapps.com/api/v1/tools/svg-canvas-exporter/run -d '{}'
HTTP 400
{
"error": "Runner required",
"reason": "JAD's API/MCP never accepts uploads. Pair an @jadapps/runner …",
"runnerEndpoint": "http://127.0.0.1:9789/v1/tools/svg-canvas-exporter/run",
"schemaEndpoint": "https://jadapps.com/api/v1/tools/svg-canvas-exporter"
}Convert one SVG through the local runner
The runner accepts the same payload on localhost and returns the generated module. Send an empty options object.
$ curl -s -X POST http://127.0.0.1:9789/v1/tools/svg-canvas-exporter/run \
-H 'Content-Type: application/json' \
-d '{"files":[{"name":"badge.svg","content":"<svg…><path d=\"M10 90L50 10L90 90Z\" fill=\"#6366f1\"/></svg>"}],"options":{}}' \
> badge-canvas.js
# badge-canvas.js now contains:
# export function drawBadge(ctx) { ctx.save(); … ctx.restore(); }Loop a whole icon folder (single-file tool, scripted batch)
Since the tool is single-file, batching is a loop. This Node snippet converts every SVG in ./icons into ./generated.
import { readdir, readFile, writeFile } from 'node:fs/promises';
const files = (await readdir('./icons')).filter(f => f.endsWith('.svg'));
for (const name of files) {
const content = await readFile(`./icons/${name}`, 'utf8');
const res = await fetch('http://127.0.0.1:9789/v1/tools/svg-canvas-exporter/run', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ files: [{ name, content }], options: {} }),
});
const js = await res.text();
await writeFile(`./generated/${name.replace(/\.svg$/, '-canvas.js')}`, js);
}Make a barrel + sanity-check the output
Re-export everything from one module and fail the build if any file came back with degraded arcs or an empty body.
# generated/index.js (barrel) export * from './arrow-left-canvas.js'; export * from './badge-canvas.js'; # CI guard: warn on approximated arcs, fail on empty draw bodies grep -l 'arc approximated as line' generated/*.js # review these grep -L 'ctx.beginPath' generated/*.js && exit 1 # empty → no <path> found
Edge cases and what actually happens
POSTing SVG content to the hosted /run endpoint
400 by designThe hosted endpoint is upload-free; it never processes file content. Sending an SVG returns HTTP 400 with error: "Runner required" and the localhost runner endpoint to use. This is the intended privacy behaviour — point your script at 127.0.0.1:9789, not the hosted URL.
Runner can't launch a headless browser on the build agent
Execution failsThis tool runs in headless-browser mode (it needs the DOM parser). On a minimal CI image without the browser dependencies the runner can't execute it. Provision the browser the runner expects on your agent, or run the conversion on a machine that has it. Pure-text SVG tools don't have this requirement, but the Canvas Exporter does.
Expecting an array-batch endpoint
Single-fileThere is no 'send an array of SVGs, get a bundle' call for this tool — the UI is single-file and the runner processes one SVG per request. Batch by looping in your script and writing one module per file. The 20-file SVG batch cap on Pro applies to multi-file SVG tools, not to this one.
Running on Free or Pro via the API
Developer tierThe Canvas Exporter is gated to the Developer plan. An API key without Developer entitlement won't be able to run it (and org keys are additionally scoped per tool). Ensure the key/account has Developer access before wiring it into a pipeline.
Source uses non-path primitives or text
Skipped silentlyOnly <path> elements are translated. SVGs built from <rect>/<circle>/<text> produce a module with an empty (or partial) draw body and no error. Add a build guard (e.g. fail if ctx.beginPath is absent) and pre-flatten primitives to paths in your asset export step.
Arcs in the geometry
Degraded to lineEvery A/a arc is exported as a ctx.lineTo() with an // arc approximated as line comment. In an automated run nothing fails, but rounded shapes silently straighten. Grep for the comment as a review gate, or convert arcs to cubic Béziers in your export pipeline before conversion.
Two SVGs share the same file stem
Name collisionThe export name derives from the file stem, so icons/a/star.svg and icons/b/star.svg both yield drawStar. Re-exporting both from one barrel collides. Namespace your filenames (or rename functions after generation) before bundling.
Colours set via CSS/style, not fill/stroke attributes
Colour droppedThe exporter reads literal fill/stroke attributes only. If your asset pipeline styles paths through a stylesheet or style= attribute, the generated module has no colour calls. Bake colours onto the path attributes during export, or set ctx.fillStyle in a post-processing step.
Frequently asked questions
Is there a hosted endpoint that converts my SVG to Canvas code directly?
No. JAD's API is upload-free for privacy: POST /api/v1/tools/svg-canvas-exporter/run returns 400 with pairing instructions and never processes content. Conversion happens on your machine through the paired @jadapps/runner at http://127.0.0.1:9789/v1/tools/svg-canvas-exporter/run.
Can I batch-convert a folder of SVGs in one API call?
Not in a single call — this tool is single-file. Batch by looping: for each *.svg, call the local runner once and write the returned module. The 20-file batch cap you may see for SVG tools on Pro applies to multi-file tools (like the sprite builder), not the Canvas Exporter.
What options can I pass to the runner for this tool?
None. The schema's options array is empty, so send options: {}. There are no decimal-precision, scale, format, or naming options — the export name is derived from the file stem and the geometry is translated with fixed rules.
Why does the runner need a headless browser for this tool?
The conversion uses the DOM parser to read the SVG, so it's classified as a headless-browser tool rather than a pure-text engine tool. The runner launches a short-lived browser session to execute it. Make sure your build agent has the browser dependencies the runner needs.
Does my SVG ever leave my machine in this flow?
No. The hosted API rejects uploads; the runner executes locally on 127.0.0.1. Your asset files and the generated code stay on your network. Only schema metadata is fetched from the hosted API, which contains no file content.
What does each generated file look like?
One ES module per SVG: export function draw<Name>(ctx) { ctx.save(); /* paths */ ctx.restore(); }, filename <name>-canvas.js, MIME text/javascript. The name is PascalCase of the file stem. Import it directly — import { drawBadge } from './badge-canvas.js' — in any bundler.
How do I get TypeScript types for the generated functions?
The tool doesn't emit .d.ts files. Since every function has the same signature (ctx: CanvasRenderingContext2D) => void, you can generate a tiny declaration in your build (one export declare function drawX(ctx: CanvasRenderingContext2D): void; per file) or simply annotate at the call site. There is no built-in TypeScript output option.
What tier do I need to automate this?
Developer. The tool is gated to the Developer plan in both the UI and the API, and the SVG file-size cap at that tier is 2 GB. Free (5 MB) and Pro (50 MB) caps exist for the SVG family generally, but they can't run this particular tool because of the tier gate.
Can I plug this into Webpack/Vite/Rollup?
Yes — run the runner loop as a pre-build step that writes *-canvas.js modules into your source tree (or a generated folder), then import them normally. Because the output is standard ESM, no special loader is required; treat the generated files like any other JS module.
How do I detect conversions that lost geometry?
Two checks: grep generated files for // arc approximated as line to find arcs that were straightened, and fail the build on any file missing ctx.beginPath (which means no <path> was found — likely a primitives-only or text-only SVG). Both run cheaply in CI.
Can I run this through MCP instead of curl?
Yes — the same contract applies. An MCP/SDK client fetches the schema from GET /api/v1/tools/svg-canvas-exporter, builds the payload, and dispatches it to the local runner. The hosted layer still never accepts uploads; the runner does the work on your machine.
What if I need rect/circle/text converted too?
Pre-process. Flatten primitives to paths and outline text (e.g. with svg-font-to-path) in your asset export step, so by the time the SVG reaches the Canvas Exporter it's path-only. The exporter won't add ctx.fillText or primitive shapes for you.
Privacy first
Every JAD SVG tool runs entirely in your browser using the DOM API and Canvas. Your SVG files never leave your device — verified by zero outbound network requests during processing.