How to bulk css clip-path generation with the jad runner
- Step 1Pair the runner — Install and pair @jadapps/runner with your JAD account (Pro tier or above, since this tool is Pro-only). The runner is what actually executes SVG transforms locally; the cloud API only hands back the schema and routing info. Calling the API to upload a file will not work.
- Step 2Organise your shape SVGs — Put each shape in a
shapes/folder with a semantic file name —hero-diagonal.svg,card-skew.svg,divider-trapezoid.svg. Use the file stem as the constant name later. Keep each SVG to a single flattened straight-edged path for faithful conversion. - Step 3Flatten curves before the loop — The converter keeps only segment endpoints, so curved outlines flatten to chords. If a shape relies on curves, either accept the chord approximation or pre-process it. To thin a dense polyline first, run it through the Path Simplifier so the 32-vertex cap does not drop meaningful points.
- Step 4Dispatch each file through the runner — Read each SVG, send it to the runner for
svg-clip-path-gen(engine mode). The runner returns CSS text of the form.icon-clip { clip-path: polygon(...) }. There are no options to pass — any options object is ignored by this tool. - Step 5Extract the polygon and name it — Parse the
polygon(...)substring out of the returned CSS and key it by the file stem (camel-cased). The fixed.icon-clipclass from the server path is irrelevant when you only keep the polygon value. - Step 6Write a typed constants file — Emit
src/constants/clip-paths.tswith named exports, then importCLIP_PATHS.heroDiagonalin components and applystyle={{ clipPath: CLIP_PATHS.heroDiagonal }}. TypeScript autocompletes the names and catches typos at build time.
Cloud API vs local runner for bulk conversion
The most common automation mistake is expecting an upload-and-receive API. JAD's API is schema-and-routing only; the runner does the work locally.
| Concern | Public API (GET /api/v1/tools/...) | Local runner (@jadapps/runner) |
|---|---|---|
| Accepts file uploads | No — never receives uploads | Yes — reads local files in-process |
| Returns processed CSS | No — returns schema + execution shape | Yes — returns the polygon CSS |
| Where files live | Never leave your machine | Stay on your machine |
| Execution mode for this tool | Reports runnerMode: engine | Runs the engine transform in-process |
| Options accepted | Schema lists zero options | Ignores options (none exist) |
| Auth / tier | API key; Pro tier | Paired runner; Pro tier |
What the bulk conversion produces per file
Behaviour is identical to the web tool except the server path caps at 32 vertices (the browser caps at 20) and uses a fixed class name.
| Aspect | Value | Note |
|---|---|---|
| Output type | CSS text | text/css |
| Class name | .icon-clip | Fixed on the server path; strip it and keep the polygon |
| Max vertices | 32 | Evenly downsampled if the path has more |
| Path read | First d="..." only | Other paths in the file are ignored |
| No path found | /* No path found in SVG */ | Skip / log these files |
| No viewBox | Assumes 100x100 | Percentages can exceed 100% with pixel coords |
Cookbook
A minimal Node workflow that drives the runner over a shapes folder and writes a typed constants file. Adapt the dispatch call to your runner client.
Folder layout and naming
Each file stem becomes a constant name. Keep names semantic and the shapes flattened to single straight-edged paths.
shapes/ hero-diagonal.svg -> CLIP_PATHS.heroDiagonal card-skew.svg -> CLIP_PATHS.cardSkew divider-trapezoid.svg -> CLIP_PATHS.dividerTrapezoid
Loop and collect polygons (pseudocode)
Read each SVG, dispatch to the runner for svg-clip-path-gen, and extract the polygon() substring. No options are passed because the tool has none.
for (const file of readdir('shapes')) {
const svg = read(`shapes/${file}`);
const css = await runner.run('svg-clip-path-gen', { text: svg });
// css === '.icon-clip {\n clip-path: polygon(...);\n}\n'
const poly = css.match(/polygon\(([^)]*)\)/)?.[0];
if (!poly) { console.warn('no path:', file); continue; }
clips[camelCase(stem(file))] = poly;
}Emit a typed constants file
Write the collected polygons as named TS exports. Diffs are stable because the conversion is deterministic.
// src/constants/clip-paths.ts (generated)
export const CLIP_PATHS = {
heroDiagonal: 'polygon(0.0% 0.0%, 100.0% 0.0%, 100.0% 88.0%, 0.0% 100.0%)',
cardSkew: 'polygon(0.0% 6.0%, 100.0% 0.0%, 100.0% 100.0%, 0.0% 94.0%)',
} as const;Consume in a component
Import the constant and apply it inline or via a CSS variable. Autocomplete prevents name typos.
import { CLIP_PATHS } from '@/constants/clip-paths';
<div style={{ clipPath: CLIP_PATHS.heroDiagonal }} />
/* or expose as a CSS var: --hero-clip: <value> */Handle skipped files in the report
Files with no path, or shapes that flattened poorly, should be surfaced in your build log rather than silently producing broken CSS.
Build report: converted: 11 skipped (no path): 1 -> shapes/logo-mark.svg (only <circle>) warning (curves flattened): 2 -> rounded-card.svg, wave.svg Action: convert primitives to paths; accept or redraw flattened shapes.
Edge cases and what actually happens
Expecting the cloud API to process uploads
Not supportedThe public API never receives uploads. GET /api/v1/tools/svg-clip-path-gen returns the schema and runnerMode: engine; there is no endpoint that takes an SVG and returns a polygon over the wire. All processing happens through the locally-paired runner. Architect your script around the runner, not an upload API.
Passing a container-dimensions option
IgnoredOlder guides imply a 'target container dimensions' parameter. It does not exist. The schema lists zero options for this tool, and coordinates are normalised against the SVG's viewBox, not any container size. Percentages already make the clip resolution-independent.
Shape relies on curves
FlattenedAt scale this is the silent killer: curved outlines convert to chord polygons because only endpoints are kept. Audit your shapes folder for paths containing C/S/Q/T/A and flag them in the build report, or pre-flatten so the result is predictable.
Path has more than 32 points
DownsampledThe server path keeps at most 32 vertices (the browser keeps 20). Highly detailed silhouettes are reduced by even-index sampling, which can drop defining vertices. Simplify with the Path Simplifier before bulk conversion so the kept points are the meaningful ones.
File has multiple paths
First path onlyOnly the first d="..." is converted; additional <path> elements are ignored with no warning. In a batch, this means multi-path SVGs may convert the wrong shape. Pre-process so the intended path is first, or split the file.
SVG missing a viewBox
Assumes 100x100Without a viewBox, coordinates are divided by 100, so a path drawn at 0-512 pixel coordinates yields percentages up to 512%. Normalise every shape to an accurate viewBox before the loop, or your generated constants will clip outside their elements.
Primitive-only SVG in the folder
No path — invalid outputA file built only from <circle>/<rect>/<polygon> returns /* No path found in SVG */ and yields no clip-path. Detect this string and either skip the file or run an editor 'object to path' step in your pre-processing stage.
Free-tier API key
Pro requiredThis tool is Pro-tier. A free-tier key or runner pairing cannot run it. Ensure the account driving the runner is on Pro or higher before scheduling a batch.
Non-deterministic naming collisions
Watch closelyTwo files whose stems camel-case to the same key (card-skew.svg and card_skew.svg) overwrite each other in the constants object. Deduplicate stems before writing, and fail the build on a collision so a shape is not silently lost.
Frequently asked questions
Is there an API I can POST an SVG to and get a polygon back?
No. JAD's public API does not accept uploads. GET /api/v1/tools/svg-clip-path-gen returns the tool schema and tells you it runs via the runner in engine mode. The conversion itself happens through your locally-paired @jadapps/runner, which keeps files on your machine.
How do I convert many SVGs at once?
Loop your shape files through the runner. For each file, dispatch svg-clip-path-gen with the SVG text, take the returned CSS, extract the polygon(...) substring, and write all of them to a constants file. There are no options to pass.
Can I set the output dimensions or container size?
No — there is no such option. Output is always percentage coordinates relative to the SVG's viewBox, which is exactly what makes the clip scale to any element size. A container parameter would be redundant.
How many vertices will each generated polygon have?
At most 32 on the server/runner path (the in-browser tool caps at 20). Shapes with more points are evenly downsampled. Pre-simplify dense paths if you want control over which points survive.
Why did one file produce a comment instead of CSS?
It had no <path> with a d attribute — likely a primitive-only SVG (<circle>, <rect>). The tool emits /* No path found in SVG */. Convert primitives to paths in your pre-processing step, then re-run that file.
Does the runner upload my files to JAD?
No. The runner executes the transform in-process on your machine. The whole point of the runner architecture is that files never touch JAD servers, which is also why there is no upload API.
What class name does the bulk output use?
The server path emits a fixed .icon-clip class. For automation you typically discard the wrapper and keep only the polygon(...) value keyed by your own constant name, so the class is irrelevant.
Is the conversion deterministic for version control?
Yes. The same SVG always yields the same polygon, so your generated constants file has stable diffs. Re-running the batch only changes a value when the source SVG changes.
Can I run this on the free tier in CI?
No. The tool is Pro-tier. Your CI's runner pairing or API key must belong to a Pro (or higher) account, otherwise the job is rejected before it runs.
How do I handle curved shapes in a batch?
Decide a policy: either accept the chord approximation (fine for subtly curved dividers) or flag any path containing C/S/Q/T/A and pre-flatten it. Surfacing these in the build report prevents shipping a silently mangled clip.
What if two shapes map to the same constant name?
They will collide in the output object and one will be lost. Normalise and deduplicate file stems before writing, and fail the build on a collision so the problem is caught rather than shipped.
Which other JAD tools fit a clip-path build pipeline?
Pair this with the Path Simplifier to thin dense paths before conversion, the Precision Tuner to round coordinates upstream, and the Responsive SVG Wrapper if you also ship the source SVGs.
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.