How to automate svg precision tuning across your icon library
- Step 1Decide your precision policy — Pick the
decimalPlacesvalue per asset type — typically 0–1 for geometric UI icons, 2 for logos and illustrations. The value must be an integer from 0 to 4; the API validates it and rejects anything outside that range or non-numeric. - Step 2Fetch the tool schema — Call
GET /api/v1/tools/svg-precision-tunerwith your API key in the auth header. The response describes the runner-backed execution shape and the input options (thedecimalPlacesschema), so your client knows exactly what to send. - Step 3Pair the @jadapps/runner — Install and pair the runner once (see /docs/runner). It listens on
127.0.0.1:9789. The runner executes SVG regex tools in-process locally — your SVGs are processed on your machine, not uploaded. - Step 4Dispatch each file to the local runner — POST your payload (the SVG plus
{ decimalPlaces: 1 }) tohttp://127.0.0.1:9789/v1/tools/svg-precision-tuner/run. Loop over your icon folder, sending one file per call, and write each*-tuned.svgresult back to disk. - Step 5Or run SVGO in the build instead — If you do not want the runner, add
convertPathDatawithfloatPrecisiontosvgo.config.jsand runnpx svgo --recursive --folder ./icons. This is the standard build-time path and covers precision plus structural minification in one pass. - Step 6Diff and visually regression-test — Run
git diffto confirm only coordinate values changed (the tuner never touches IDs, classes, or colours). For large sets, gate the change behind a visual regression suite (Chromatic, Percy, Playwright snapshots) before merging.
The decimalPlaces option schema
Returned by GET /api/v1/tools/svg-precision-tuner and enforced on dispatch. It is the only option this tool takes.
| Field | Type | Constraints | Default |
|---|---|---|---|
decimalPlaces | number (integer) | min 0, max 4, step 1; non-numeric or out-of-range is rejected | 2 |
| (file) | SVG text | single SVG per call; must be valid SVG XML | required |
| (no other options) | — | no per-element, viewBox, or transform toggles exist | — |
Runner/API vs SVGO convertPathData
Both round coordinates. They differ in scope and where the work runs. Pick by whether you want a precision-only pass or full path restructuring.
| Aspect | JAD Precision Tuner (runner/API) | SVGO convertPathData |
|---|---|---|
| Precision control | decimalPlaces 0–4 | floatPrecision (any integer) |
| Rounds path d | Yes | Yes |
| Rounds shape attrs (cx/cy/x/y/r/width/height/points) | Yes | Via convertShapeToPath / cleanupNumericValues |
| Restructures paths (command type, merging) | No — numeric-only | Yes (converts to relative, merges, etc.) |
| Touches viewBox / transform | No | Can, depending on enabled plugins |
| Where it runs | Your browser, or your paired local runner | Your build machine / CI |
| File leaves your network | No (runner-local; JAD API is upload-free) | No (local) |
Cookbook
Concrete commands. Replace JAD_API_KEY and adjust the precision to your policy.
Fetch the schema
Confirm the option shape before you build payloads. The response marks the tool runner-backed and upload-free, and includes the decimalPlaces option.
curl -H "Authorization: Bearer $JAD_API_KEY" \
https://jadapps.com/api/v1/tools/svg-precision-tuner
# → execution.runnerBacked: true, apiAvailable: false
# → input.options includes { name: "decimalPlaces",
# type: "number", min: 0, max: 4, default: 2 }POSTing content to JAD's API is rejected — on purpose
The /run endpoint never accepts uploads. It returns a 400 telling you to dispatch to your local runner instead. This is the privacy contract, not an error in your code.
POST /api/v1/tools/svg-precision-tuner/run (with file body)
400 Runner required
{
"reason": "JAD's API/MCP never accepts uploads...",
"runnerEndpoint": "http://127.0.0.1:9789/v1/tools/svg-precision-tuner/run",
"schemaEndpoint": ".../api/v1/tools/svg-precision-tuner"
}Loop a folder through the local runner
Pair the runner once, then send each SVG to localhost with your chosen precision. Files stay on your machine.
for f in ./icons/*.svg; do
curl -s -X POST \
http://127.0.0.1:9789/v1/tools/svg-precision-tuner/run \
-F "file=@$f" \
-F 'options={"decimalPlaces":1}' \
-o "./dist/$(basename "$f" .svg)-tuned.svg"
doneSVGO config alternative
If you would rather keep everything in the build, SVGO's floatPrecision covers the precision step. Note it also restructures paths unless you disable those passes.
// svgo.config.js
module.exports = {
plugins: [
{ name: 'convertPathData', params: { floatPrecision: 1 } },
],
};
// then:
npx svgo --recursive --folder ./iconsDifferent precision per folder
Geometric icons can take aggressive rounding; illustrations need more. Run two passes with different decimalPlaces targeting different folders.
# Geometric UI icons — round to whole units for f in ./icons/ui/*.svg; do ... decimalPlaces:0 ...; done # Illustrations — keep two decimals for f in ./icons/art/*.svg; do ... decimalPlaces:2 ...; done
Edge cases and what actually happens
POST file to JAD /run endpoint
400 Runner requiredJAD's API and MCP layer are upload-free. Posting an SVG body to /api/v1/tools/svg-precision-tuner/run returns a 400 with the runner endpoint and schema endpoint. Dispatch the same payload to your paired runner on 127.0.0.1:9789 instead. This is the intended privacy design, not a bug.
decimalPlaces outside 0–4
RejectedThe option validator enforces min 0 and max 4. A value like 6 or -1 is rejected with a message naming the bound. Pass an integer in range; SVGO's floatPrecision has no such cap if you need more digits, but for web display 0–4 covers every realistic case.
Non-numeric decimalPlaces
RejectedA non-finite or non-numeric value (e.g. "high") fails validation with Option "decimalPlaces" must be a number. Omit the option entirely to fall back to the default of 2 rather than sending a bad value.
Missing or invalid API key on schema fetch
401/403GET /api/v1/tools/... validates the API key first; an absent or invalid key returns an auth error before any schema is returned. Org-issued keys also carry per-tool scopes, so a key without SVG scope is rejected for this tool.
Rate limit hit during a large batch
429Schema fetches and run dispatches are rate-limited per key. A big loop can hit 429 Rate limit exceeded with a resetAt timestamp and X-RateLimit headers. Back off until reset, or fetch the schema once and cache it — you only need it a single time per batch.
Expecting parallel multi-file in one call
By designThe tuner processes one SVG per call — there is no built-in multi-file batch for this tool. Loop over your folder client-side, one dispatch per file. The runner handles each in-process locally, so a sequential loop is fast.
SVGO changed more than the numbers
ExpectedUnlike the tuner, SVGO's convertPathData also converts command types, switches to relative coordinates, and merges segments. Your diff will show structural changes, not just rounded numbers. If you want numeric-only diffs, use the runner-backed tuner; if you want full minification, that is SVGO working as intended.
Pipeline expects viewBox/transform cleanup too
Out of scopeThe tuner rounds path data and the listed shape attributes only — never viewBox or transform. If your automation needs those cleaned, add an SVGO pass or a dedicated step; do not assume the precision tuner handled them.
Frequently asked questions
Can I batch-tune hundreds of SVGs in one API call?
Not in a single call — the tuner processes one SVG per request. Loop over your folder client-side and dispatch each file to your paired runner on 127.0.0.1:9789. Because the runner executes in-process locally, a sequential loop over hundreds of icons completes quickly and nothing leaves your machine.
Why does JAD's /run endpoint reject my uploaded file?
By design. JAD's API and MCP layer never accept uploads — POSTing content returns a 400 with pairing instructions. Every tool executes through a paired @jadapps/runner on localhost, so source SVGs stay on your network. Send the same payload to the runner endpoint named in the 400 response.
What options does the precision API accept?
Exactly one: decimalPlaces, an integer from 0 to 4 (default 2). There are no per-element, viewBox, or transform toggles. Fetch GET /api/v1/tools/svg-precision-tuner to see the validated schema your client should build against.
Does SVGO's convertPathData do the same thing?
For the precision step, broadly yes — floatPrecision rounds coordinates much like the slider. The difference is scope: SVGO also restructures paths (command-type conversion, segment merging, relative coordinates), whereas the JAD tuner is numeric-only and never restructures. Choose SVGO for full minification, the tuner for clean numeric-only diffs.
Can I set different precision for different icon types?
Yes. Run two passes with different decimalPlaces values targeting different folders — for example 0 for geometric UI icons and 2 for illustrations. With SVGO, point separate config invocations (or glob patterns) at each subdirectory.
How do I wire this into a Vite or webpack build?
The simplest build-time route is SVGO: use vite-plugin-svgo (or svgo-loader for webpack) with convertPathData floatPrecision in the config, so every imported SVG is rounded at build with zero runtime cost. The JAD runner route is better when you want a separate, auditable step that keeps files local and matches the web tool exactly.
Will automated tuning preserve IDs, classes, and ARIA?
With the JAD tuner, yes — it only rewrites numeric coordinate values, so IDs, class names, ARIA attributes, colours, and element order are untouched. SVGO can rename or remove IDs depending on which plugins you enable, so review its config if ID stability matters.
Does the runner produce identical output to the web tool?
Yes. The runner calls the same in-process SVG engine the browser uses, and the precision-tuning code is the identical regex rounding pass in both. The same input and decimalPlaces value yield the same bytes whether you run it in the UI or via the runner.
How do I verify only coordinates changed?
Run git diff on the tuned files. Because the tuner is numeric-only, the diff should show changed numbers in d and the rounded shape attributes and nothing else. For visual confirmation across a large set, add a snapshot/visual-regression suite (Chromatic, Percy, Playwright) before merging.
What happens if I omit decimalPlaces?
It falls back to the default of 2. Omitting the option is the safe way to take the default; sending an empty or null value is treated the same way rather than as an error.
Is there a size limit per file in automation?
The same tier limits apply — 5 MB free, 50 MB Pro per file, with higher limits above. SVGs rarely approach these, but if an auto-traced file does, simplify it with the path simplifier or minify it first.
Can I chain tuning with other SVG steps in automation?
Yes — a common local pipeline is simplify, then tune precision, then minify, then check the compressed size. Dispatch each step to the runner in sequence, or fold the precision step into an SVGO config alongside structural plugins if you prefer one build pass.
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.