Build SVGator
KINDAreplaces $24/mosaves $288/yrback to the verdict
A browser SVG animation editor whose hard problems are a preview that cannot disagree with the export, transform origins that every engine interprets the same way, and a project file that outlives the editor, rather than the timeline widgets people notice first.
Before step 1
Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.
- installfree
Why Runs the dev server, the build and the test suite.
Get it nodejs.org, or nvm install 22. open ↗
Verify
node --version prints v22 or higher - installfree
Why Transform origins and animation timing differ between engines, and an export checked in one engine is not a checked export.
Get it Install the browsers your test runner supports and run the engine suite in all three.
Verify
The engine suite runs in three engines and passes - have readyfree
Why Files from real vector editors contain defs, nested groups, clip paths and elements with no ids, and the round trip is only meaningful against those.
Get it Export a dozen files from the editors you actually use, including ones with gradients, masks and text.
Verify
Every file loads and round trips unchanged - have readyfree
Why The SVG defaults are not what anyone expects, and the export depends on writing both properties on every animated element.
Get it Read the two property definitions and note the initial values and the SVG rule. open ↗
Verify
A note records the initial values and why the export always sets both - decidefree
Why It is baked into every export and cannot change later without changing every existing animation.
Get it Decide translate, rotate, scale or another order, and write it into the interface.
Verify
The order is documented and asserted in the suite
Data model
Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.
- projects(id, name, format_version, svg_source, duration_ms, created_at, updated_at) · the source is kept verbatim - elements(project_id, element_id, tag, label, assigned_id) · assigned_id is set only where the file had none - tracks(id, project_id, element_id, property) · property is translateX, translateY, rotate, scale or opacity - keyframes(id, track_id, at_ms, value, easing) · easing belongs to the segment leaving this keyframe - origins(project_id, element_id, box, origin_x, origin_y) · written into the export on every animated element - exports(id, project_id, kind, at, bytes, engines_checked_json) · kind is animated_svg or css_only - The SVG source is stored as text and the DOM is rebuilt from it on load, so nothing the editor did not understand is ever lost between sessions.
Environment variables
These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.
| Variable | Needed | Example | Where the value comes from |
|---|---|---|---|
PROJECT_FORMAT_VERSION | required | 1 | Written into every project file. Migrations read it. |
DEFAULT_DURATION_MS | required | 3000 | New project duration. Editable per project. |
TRANSFORM_ORDER | required | translate,rotate,scale | Fixed and stated in the interface. Changing it changes every animation. |
DEFAULT_TRANSFORM_BOX | required | fill-box | Emitted on every animated element with an explicit origin. |
UNDO_DEPTH | required | 50 | Fast keyframe work produces mistakes and they should be cheap. |
REQUEST_PERSISTENT_STORAGE | required | true | Asked for at first save. Even when granted, the exported file is the real save. |
The build, in order
Loading a file without changing it
The editor understands the file's structure and does not alter what it does not touch.
A model of your own drops whatever it did not have a slot for.
Files
src/document.tsOnly where missing, and unique against what the file already has.
Files
src/ids.tssrc/ids.test.tsSemantic equality of the two DOMs, not string equality.
Files
tests/roundtrip.test.ts
done when · tick each as it passeswatch out- Building an internal model of shapes and re-serialising it for export drops every attribute, namespace and element the model did not have a slot for, and the user finds out when a gradient or a clip path disappears. Keep the original DOM as the document and only add attributes to it.
A preview that runs the export
Scrubbing the timeline shows exactly what the exported file will show.
One generator, used for preview and export alike.
Files
src/css/keyframes.tssrc/css/keyframes.test.tsThe browser does the interpolation, which is the point.
Files
src/preview.tsComputed transforms at three times, not a visual glance.
Files
tests/preview-equals-export.test.ts
done when · tick each as it passeswatch out- Interpolating in JavaScript for the preview while emitting CSS for the export produces two implementations that agree on the easy cases and diverge on easing, rotation past a half turn and overlapping keyframes, and the person only sees the difference after shipping. Make the preview run the generated stylesheet, so there is one implementation.
Origins every engine agrees on
A rotation spins around the point the user chose, in every browser.
The defaults for SVG are the viewport and its corner.
Files
src/css/origins.tstests/origins-present.test.tsTranslate, rotate, scale, and say so in the interface.
Files
src/css/compose.tsA rotation about the centre must land in the same place.
Files
tests/engines.spec.tsterminalnpx playwright test tests/engines.spec.ts --project=chromium --project=firefox --project=webkit
done when · tick each as it passeswatch out- The specification's initial transform-box is the nearest SVG viewport, and for SVG elements without a CSS layout box the used transform-origin is the top-left corner, so a rotation exported without both properties spins the element around the corner of the whole drawing rather than its own centre, and engines have historically differed on top of that. Emit both properties on every animated element and never rely on the default.
A timeline you can work in for an hour
Keyframes can be placed, moved, copied and undone without fighting the interface.
Zooming the timeline must not move a keyframe.
Files
src/timeline/snap.tssrc/timeline/snap.test.tsDeleting a track and pasting keyframes both undo cleanly.
Files
src/undo.tsSmoothness is a number, not an impression.
Files
tests/perf.spec.ts
done when · tick each as it passeswatch out- Snapping keyframes to pixels rather than to time means the same drag lands on a different millisecond at a different zoom, and the animation subtly changes when the user zooms the timeline. Snap in time units and derive pixels from them.
Projects that outlive the editorproduct builder
Nothing is trapped in browser storage and the export works where it will be used.
An old project must open after the format changes.
Files
src/project/format.tstests/format-migration.test.tsExport, reopen, compare every keyframe.
Files
tests/project-roundtrip.test.tsThat is where most animated SVGs end up, and scripts do not run there.
Files
tests/img-embed.spec.ts
done when · tick each as it passeswatch out- Treating browser storage as the filing system means a cleared site, a private window or storage pressure erases weeks of work with no warning, because the browser may evict it unless persistence was granted and sometimes even then. Version the format, export to a file, and make reopening the file identical to reopening the stored project, tested.
That is the whole plan for SVGator. What it deliberately does not cover is below · check the gaps before you call it a replacement.
- Path morphing, motion along a path and stroke draw-on.
- Shape and text editing.
- Script, SMIL, Lottie and video export.
- Collaboration and cloud projects.
- Path morphing, stroke draw-on, and motion-along-path, which are the effects people buy this for
- A polished easing curve editor with presets that look intentional instead of linear
- Export targets beyond CSS: SMIL, JS runtime, Lottie, video
- Cross-browser export sanity checks and the fixes for Safari's transform-origin quirks
- Built-in shape and text editing, so every asset change means a round trip to your vector editor
- Stroke draw-on through dash offset, which is the one effect that is a small addition to this design
- An easing preset library with visible curves, since linear is the tell of a home-made animation
- Motion along a path, which needs its own interpolation and is the first thing to charge for
Need the files? The project pack on the verdict page hands your agent the whole brief · more design.