How to automate vue and svelte svg component generation in bulk
- Step 1Pair the @jadapps/runner on the build machine — Install and pair the @jadapps/runner with your account. The runner executes tools locally; for svg-to-vue-svelte (a server-safe SVG tool) it calls the in-process engine — no headless browser needed. JAD's cloud only validates your API key and never sees file bytes.
- Step 2Fetch the option schema — Call
GET /api/v1/tools/svg-to-vue-sveltewith your API key. The response lists the three options:framework(enumvue/svelte, defaultvue),componentName(string, defaults to file stem), andtypescript(boolean, default true). Build payloads against this, not against assumptions. - Step 3Loop your SVG files — For each
.svg, dispatch a run to the local runner with the SVG content and your options. There is no array/batch payload — one file per call. Run the loop once withframework: 'vue'and again withframework: 'svelte'to populate both packages. - Step 4Set componentName per file — Derive
componentNamefrom the asset filename so output names are stable and predictable across both frameworks. For Vue the name also drives the suggested kebab-cased.vuefilename; keep your asset filenames kebab-case for consistency. - Step 5Post-process to wire props (optional) — The converter declares
size/color/classbut leaves your SVG's literal dimensions/colours in place. If you want reactive icons, add a regex/AST step that rewrites the root<svg>to:width="size"/:stroke="color"(Vue) orwidth={size}(Svelte). Run a clean/minify pass before generation so this rewrite has a predictable target. - Step 6Write outputs and commit — Save each result to
packages/icons-vue/src/<Name>.vueandpackages/icons-svelte/src/<Name>.svelte. Wire a barrel file of named exports for tree-shaking, then publish each package independently. Re-run on every icon change in CI so both frameworks stay in lockstep.
The real API surface for this tool
The /run endpoint is intentionally upload-free; file content executes through your paired @jadapps/runner. The schema endpoint is how clients build payloads.
| Step | Endpoint / mechanism | Returns / does |
|---|---|---|
| Discover options | GET /api/v1/tools/svg-to-vue-svelte | JSON schema: framework, componentName, typescript |
| List the catalogue | GET /api/v1/tools | All tools, categories, and tier requirements |
| Attempt direct run with content | POST /api/v1/tools/svg-to-vue-svelte/run | 400 with pairing instructions — content never accepted server-side |
| Actual execution | Paired @jadapps/runner (local) | Runs the in-process SVG engine; output stays on your machine |
| Auth | API key header | Validated by JAD cloud; rate-limited per key |
Per-file option payload for the runner
One object per SVG. There is no array form — your loop iterates files. Defaults apply when a key is omitted.
| Key | Example value | Notes |
|---|---|---|
framework | "vue" or "svelte" | Run the loop once per framework to build both packages |
componentName | "arrow-left" | Defaults to the file stem; Vue kebab-cases it for the filename |
typescript | true | On → lang="ts" typed props; off → plain JS (Vue gets runtime defaults) |
| (input) | raw SVG markup | The file content, supplied to the local runner — not posted to JAD cloud |
Cookbook
A real schema-then-loop flow. Pseudocode kept framework-neutral; adapt the runner-dispatch call to your client.
Fetch the schema before building payloads
Pin your automation to the tool's real contract so it never sends an option the tool ignores (e.g. there is no aria or batch option).
GET /api/v1/tools/svg-to-vue-svelte
Authorization: Bearer <API_KEY>
Response (shape):
{
"slug": "svg-to-vue-svelte",
"options": [
{ "name": "framework", "type": "enum",
"values": ["vue","svelte"], "default": "vue" },
{ "name": "componentName", "type": "string" },
{ "name": "typescript", "type": "boolean", "default": true }
]
}The upload-free 400 you get if you post content
Proof the loop must go through the local runner. Sending file content to /run is rejected with pairing instructions — by design, so icons never touch JAD's servers.
POST /api/v1/tools/svg-to-vue-svelte/run
Authorization: Bearer <API_KEY>
{ "content": "<svg>...</svg>", "options": { ... } }
400 Bad Request:
{ "error": "This endpoint is upload-free. Pair the
@jadapps/runner and dispatch the job locally." }Loop one set of SVGs into both frameworks
Iterate files; for each, dispatch to the local runner twice (vue, then svelte). This is what 'batch' means for this tool — a client-side loop.
for file in icons/*.svg:
name = kebab(basename(file))
svg = read(file)
for fw in ["vue", "svelte"]:
out = runner.run("svg-to-vue-svelte", svg, {
framework: fw,
componentName: name,
typescript: true,
})
ext = "vue" if fw == "vue" else "svelte"
write(f"packages/icons-{fw}/src/{name}.{ext}", out)Post-process to make size/color live
The converter declares props but doesn't bind them. If you want reactive icons, rewrite the root <svg> after generation. Minify first so the attribute set is predictable.
Pre-clean once (shared source):
runner.run("svg-pro-minifier", svg, {}) # collapse, shorten
runner.run("svg-metadata-scrubber", svg, {}) # drop editor cruft
After generation, rewrite the root element:
Vue: <svg ...> -> <svg :width="size" :height="size"
:stroke="color" ...>
Svelte: <svg ...> -> <svg width={size} height={size}
stroke={color} class={className} ...>Wire CI to keep both packages in sync
Run the loop on every change to the icon source so a new SVG produces a Vue and a Svelte component in the same commit.
# .github/workflows/icons.yml (sketch)
on: { push: { paths: [ "icons/**.svg" ] } }
jobs:
build:
steps:
- run: npx @jadapps/runner pair --key $JAD_KEY
- run: node scripts/generate-icons.mjs # the loop above
- run: git add packages/icons-*/src && \
git commit -m "chore: regenerate icon components"Edge cases and what actually happens
Posting an array of files to a batch endpoint
400 / no such endpointThere is no batch endpoint and no /api/svg/to-code. The only run path is POST /api/v1/tools/svg-to-vue-svelte/run, it is upload-free, and it processes the concept of one job. Iterate files in your own loop and dispatch each to the local runner.
Sending file content directly to /run
400 upload-freeThe endpoint rejects content with a 400 and pairing instructions. JAD's cloud never accepts file bytes — execution must happen through the paired @jadapps/runner on your machine. This is the privacy guarantee, not a bug; route the job through the runner.
Expecting size/color to be reactive in the output
Manual stepAutomating generation does not change what the tool emits: size/color are declared but unbound. If your icon package promises reactive sizing/recolouring, add the post-process rewrite step. Skipping it ships components whose props silently do nothing.
Passing an `aria`, `slots`, or `template` option
Ignored / unsupportedThe schema has exactly three options. Any extra keys (ARIA injection, slot generation, custom templates) are not part of the contract and won't take effect. Add accessibility attributes and wrappers in your post-process step instead.
Rate limit hit during a large run
429API keys are rate-limited per hour. A 1,000-icon × 2-framework loop is 2,000 dispatches — pace them or batch within your hourly budget. The runner does the work locally, but key validation still counts against the limit. Back off on 429 and respect X-RateLimit-Reset.
componentName collisions across the set
Overwrite riskIf two source files kebab-case to the same name (Arrow Left.svg and arrow-left.svg), your write step can clobber one output. De-duplicate names before the loop, or namespace by source folder, so each component file is unique.
Tier gating in CI
Developer requiredsvg-to-vue-svelte is a Developer-tier tool. A CI key on a lower plan is rejected for this tool. Use a Developer (or higher) key for the build, or the loop fails per-file with an authorization error.
Comments stripped from licensed icons
ExpectedThe converter removes <!-- --> comments before wrapping, so embedded SPDX/licence banners vanish in every generated file. Inject licence headers in your write step (outside the markup) rather than relying on comments surviving.
Huge generated SVG exceeds the tier cap
Tier-limitedPer-file caps still apply via the runner (Developer 2 GB). Typical icons are kilobytes, but a traced or generated mega-SVG can blow the limit. Pre-simplify with SVG Path Simplifier before the loop reaches it.
Vue and Svelte packages drift over time
AvoidableIf the two loops run from different sources or at different times, the packages diverge. Generate both from one cleaned source set in the same CI job so a new icon always appears in both, in the same commit.
Frequently asked questions
Is there a single batch endpoint that returns a ZIP of components?
No. There is no /api/svg/to-code and no batch payload. The API exposes a schema (GET /api/v1/tools/svg-to-vue-svelte) and an upload-free run endpoint (POST .../run) that executes through your paired @jadapps/runner. 'Batch' is a loop you write — iterate files and dispatch each one locally.
Why does posting my SVG content to /run return a 400?
By design. The endpoint is upload-free: JAD's cloud never accepts file bytes. Posting content returns a 400 with instructions to pair the @jadapps/runner, which runs the tool on your own machine. This keeps unreleased icon art entirely off JAD's servers.
How do I generate both Vue and Svelte from the same icons?
Run your file loop twice — once with framework: 'vue', once with framework: 'svelte' — from the same cleaned SVG source. Write the outputs to separate package folders. Doing both in one CI job keeps the packages in sync.
Do the generated components have working size/color props after the API run?
No more than the UI output does. The tool declares size, color, and class/className but does not bind them to your SVG markup. To ship reactive icons, add a post-process step that rewrites the root <svg> to consume the props. The cookbook shows the exact rewrite.
What options can I pass per file?
Exactly three: framework (vue/svelte), componentName (string, defaults to the file stem), and typescript (boolean, default true). There is no aria, slots, template, or props-schema option — fetch GET /api/v1/tools/svg-to-vue-svelte to confirm the live contract.
Can I add ARIA props or Storybook stories from the API?
Not from the tool itself — it has no ARIA or story option. Add them in your pipeline: a post-process step can inject aria-hidden/role and write a .stories.ts per component from the generated props. The converter only produces the base component.
What plan is required for the batch loop?
Developer. svg-to-vue-svelte is a Developer-tier tool, so the API key driving the loop must be on the Developer plan or higher. React JSX/TSX generation via SVG to JSX is available on Pro if that fits your stack better.
How do I keep component names consistent across both frameworks?
Set componentName explicitly per file, derived from the asset filename, and keep your source filenames kebab-case. Then both the Vue and Svelte outputs share the same base name, and Vue's kebab-cased filename matches your convention. De-dupe names first to avoid overwrite collisions.
Should I clean the SVGs before generating?
Yes. The converter inserts your markup verbatim (minus comments). Run SVG Metadata Scrubber and SVG Pro Minifier first so the committed components are small and your post-process prop-rewrite has a predictable attribute set to target.
How fast can I run a few hundred icons?
The runner executes the in-process SVG engine locally, so each conversion is near-instant; throughput is bounded mainly by your API key's per-hour rate limit (each dispatch validates the key). For thousands of files across two frameworks, pace the loop and honour X-RateLimit-Reset on 429.
Does the runner need a headless browser for this tool?
No. svg-to-vue-svelte is a server-safe SVG tool, so the runner calls the in-process engine directly (no DOM/Canvas/ZIP session). That makes it lightweight and reliable in CI compared to tools that must launch a headless browser.
Where do the generated files end up?
Wherever your loop writes them — the output is returned to your script by the local runner and never persisted by JAD. A common layout is packages/icons-vue/src/<Name>.vue and packages/icons-svelte/src/<Name>.svelte, with a barrel file of named exports for tree-shaking.
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.