INTRO
Particlr is a particle-effect editor that runs in the browser, paired with an MIT-licensed runtime that plays the effects back inside a game. You build an effect against emission rates, curves and gradients, velocity, gravity, drag, noise, blend modes, and collision, then export a single versioned `.prt` JSON file. `@particlr/runtime` on npm loads that file and renders it in PixiJS. It is a tool for game developers rather than a generative-art toy, and the output is meant to ship.
The thing I cared about most was parity. The editor doesn't approximate what your game will show, it previews through the same runtime your game links, so the preview and the shipped frame come from the same code path instead of two renderers that happen to agree. Golden-frame tests run in CI, headless through Playwright and SwiftShader, rendering each preset and comparing it against a committed baseline image to catch drift between the two. Everything else, the presets, the free and premium split, the Pixi v8 and v7 adapters, sits on top of that one choice.
SECTION
Same runtime, same frame
Game effects are unforgiving about small differences. A muzzle flash that is a few pixels brighter or a frame slower in-game than it looked in the tool is a defect that only shows up in the game, after the tool has already signed off on it. Particlr closes that gap by construction: the preview canvas is the runtime. What you scrub in the timeline is the code path your game executes.
A golden-frame suite backs that up in CI. It renders reference effects headless through Playwright and SwiftShader and compares the output against committed baseline images, pixel for pixel, so a divergence between the runtime and the preview shows up as a failing build instead of a bug report. The landing page is rendered live by the shipped runtime for the same reason: the ember field and the bursts on it are the same code that plays an exported file, not a recording of it.

SECTION
One JSON file between the editor and your game
The contract between the editor and the game is a single versioned `.prt` document, plain JSON. The editor writes it, the runtime reads it, and nothing else crosses the boundary. The runtime core is framework-agnostic; the Pixi integration sits on top as an adapter. PixiJS v8 is the first-class target, and there is a v7 adapter for projects that have not moved yet. Its entry mirrors the v8 entry's public shape so migrating is a one-line import change, but it is deliberately the narrower of the two: the trail internals v8 exposes are not re-exported, so the older adapter cannot quietly widen. Each adapter carries its own committed golden baselines at pixel tolerance zero, because v7 and v8 output is close but not byte-identical. The core is held to a budget of 25KB gzipped, a limit I set because a particle runtime that costs more than the effects are worth does not get adopted.
The bar I set for the whole thing is a time: a person with no prior context should be able to open the URL, tweak an explosion, and get it running in the sample game in under ten minutes. The sample is a small integration harness: click to spawn explosions, fire a projectile that sheds a trail, and watch a host parameter retune the ambient effect at runtime, all driven by exported `.prt` files. Effects run off a seeded PRNG, so a given seed reproduces the same run.

SECTION
The editor
The editor is a Preact and signals app, a static Vite build deployed on Vercel, held under 200KB gzipped without counting Pixi. The authoring surface covers the parts that actually shape an effect: emission rate and bursts, curves and gradients over a particle's life, velocity and gravity and drag, noise, blend modes, and collision. Each layer stacks into the effect, and a parameter can be exposed as a host knob so a game tunes it per instance without editing the file.
Nobody should start from an empty canvas, so there are 57 presets, and I release all of them as CC0. None is a screenshot or a locked demo: every one opens, plays and exports for a free user. 16 of the 57 use a premium module, and on those the one gated section's fields are read-only until a key is entered; the other 41 are editable end to end. Arc weld, ember field, blast anim, dissolving smoke, confetti, comet, and the rest are there to be pulled apart and reassembled into whatever you actually need.

SECTION
Premium forces without a hostage runtime
The runtime is MIT licensed; the editor is the commercial surface built on top of it, free to use during beta. Its free tier covers emission, curves and gradients, velocity, gravity, drag, noise, blend modes, collision, host parameters, and unlimited import and export, enough to build and ship real effects without paying anything. One optional lifetime key adds the heavier authoring tools: sub-emitters, trails and ribbons, attractors, texture masks, dissolve, a sheet packer, and baked-image export.
The part I was careful about is what buying the key actually gets you. A free user can open, play, and re-export an effect that was built with premium features, because the gate sits at the editor's UI layer, not in the format: five of the seven premium tools, sub-emitters, trails, attractors, texture masks, dissolve, are first-class `.prt` fields with real simulation and render code already inside the MIT runtime. Buying the key gets you the authoring tools, not a license to keep playing your own files.
OUTCOME
Live at particlr.com, with the runtime public on GitHub and published as `@particlr/runtime` on npm, and actively developed. The monorepo is TypeScript strict with Vitest and Playwright, and keeping the editor and the runtime in sync is what the golden-frame suite exists to protect. The short version of what I was building toward is the Slice One test: no context to a tweaked explosion running in a real game in under ten minutes.
