NixieFX
Tutorial · Updated August 2026

PixiJS particle effects: juicing game UI with NixieFX

A crisp UI is table stakes; a juicy UI is what players remember. This hands-on tutorial builds HTML5 game UI in PixiJS v8 and wires real particle effects to it — a button press burst and a reward coin fountain — authored in the free, browser-based NixieFX editor.

TL;DR — what you'll build

To add particle effects to a PixiJS v8 game: install the runtime with npm install pixi.js nixie-fx, author your effects in the free NixieFX editor (it saves plain JSON into your own project folder), export them with npx nixie-fx export ./my-vfx into an out/vfx bundle, then load that bundle with loadVfxExportBundle, render it with PixiVfxRenderer parented to your stage, and call update() from app.ticker once per frame. This page walks through the whole path: a claim button that sparks on press and a coin fountain for the reward popup.

Why does UI juice matter in free-to-play games?

Free-to-play UI is not decoration — it is the reward loop made visible. The moments that decide whether an action feels worth repeating are almost all UI moments:

  • Button feedback. A press that flashes and throws a handful of sparks confirms the tap instantly, even before the server responds. Silent buttons read as broken buttons.
  • Reward bursts. Coins fountaining out of a chest, stars popping on a level-clear screen — the particle burst is the dopamine hit. Games A/B-test these because they measurably move retention.
  • Screen transitions. A drift of embers or a swoosh of motes carries the eye between screens and hides loading seams.

PixiJS is the natural home for this layer: it is the standard 2D web renderer, and its ParticleContainer is designed to draw thousands of lightweight sprites cheaply. What Pixi does not ship is an authoring tool — designing a burst by editing velocity numbers in code is miserable. That is the gap NixieFX fills: a full particle editor in the browser, exporting to a small runtime that renders through Pixi.

How do you set up PixiJS v8 with NixieFX?

Install both packages in your web game project:

npm install pixi.js nixie-fx

If you work with an AI coding agent (Claude Code, Cursor, Codex, Grok, Copilot, Gemini CLI…), also install the agent skills for both libraries so it writes correct Pixi v8 and NixieFX code instead of hallucinating old APIs:

npx skills add https://github.com/pixijs/pixijs-skills
npx skills add https://github.com/azakhary/nixie-fx

The NixieFX command installs two skills: nixie-fx-authoring (create, validate and export effects) and nixie-fx-runtime (integrate exported effects into a running game). Now the minimal Pixi v8 scene — an application and one claimable reward button:

import { Application, Assets, Sprite } from "pixi.js";

const app = new Application();
await app.init({ background: "#14110e", resizeTo: window });
document.body.appendChild(app.canvas);

const buttonTexture = await Assets.load("ui/claim-button.png");
const button = new Sprite(buttonTexture);
button.anchor.set(0.5);
button.position.set(app.screen.width / 2, app.screen.height - 120);
button.eventMode = "static";
button.cursor = "pointer";
app.stage.addChild(button);

Nothing NixieFX-specific yet — this is stock Pixi v8: Application with async init(), an eventMode: "static" sprite that receives pointer events.

How do you author a particle effect in the NixieFX editor?

The NixieFX editor is free and runs entirely in your browser — no account, no install. It opens a folder on your own disk (a NixieFX project is any folder containing a vfx-editor.prj file) and saves every effect as plain JSON inside it, so your VFX live in your game repo and diff like code. You can scaffold and round-trip a project from the terminal too:

npx nixie-fx effect create ./my-vfx --profile portable && npx nixie-fx validate ./my-vfx

For this tutorial, author two effects:

  • spark-burst — the button press. One emitter with a single burst of 15–25 particles, radial initial velocity, additive blending, a warm white-to-amber gradient that fades out, and size shrinking over each particle's lifetime. Total life under half a second — feedback, not fireworks.
  • coin-fountain — the reward popup. A looping emitter that sprays coin-textured particles upward against gravity, with slight rotation over lifetime and a spread cone wide enough to feel abundant.

When both look right in the live preview, export. The editor (or the CLI) compiles your authored effects into a out/vfx runtime bundle — a manifest.json, compiled effect JSON under effects/, and the texture assets they reference:

npx nixie-fx export ./my-vfx

Games consume only the generated out/vfx bundle — never the editor's source particle-data files. The manifest is the source of truth: it lists every effect, every asset path, and a per-backend support report, so a broken export fails loudly at load time instead of silently at runtime.

How do you load the exported effects in PixiJS?

Copy (or serve) out/vfx as static files in your app — here it is mounted at /vfx/. Loading is three steps: fetch the manifest and effect JSON, hand them to loadVfxExportBundle, and stand up a texture provider that maps the manifest's asset paths to Pixi textures:

import { Assets, Texture } from "pixi.js";
import { loadVfxExportBundle } from "nixie-fx/export";
import { PixiVfxRenderer } from "nixie-fx/pixi";

// 1. Read the export produced by the editor.
const manifest = await fetch("/vfx/manifest.json").then((r) => r.json());

const effectsByPath: Record<string, unknown> = {};
for (const entry of manifest.effects) {
  effectsByPath[entry.path] = await fetch(`/vfx/${entry.path}`).then(
    (r) => r.json(),
  );
}

// 2. Validate and index the bundle for the Pixi backend.
const bundle = loadVfxExportBundle(
  { manifest, effectsByPath, assetPaths: manifest.assets.map((a) => a.path) },
  { requiredBackend: "pixi2d", requireEveryAsset: true },
);

// 3. Texture provider: manifest asset paths -> Pixi textures.
const textures = new Map<string, Texture>();
for (const asset of manifest.assets) {
  if (asset.type === "texture") {
    textures.set(asset.path, await Assets.load(`/vfx/${asset.path}`));
  }
}
const textureProvider = {
  getTexture: (ref) => textures.get(ref.path),
  release: () => textures.clear(),
};

const vfx = new PixiVfxRenderer({ parent: app.stage, textureProvider });

loadVfxExportBundle rejects a manifest whose validation failed and, with requiredBackend: "pixi2d", surfaces any effect the Pixi backend cannot fully render. The renderer parents itself to app.stage, so effects draw above your UI in normal stacking order — you can also parent it to any Container, for example a dedicated VFX layer.

How do you attach effects to UI events?

The runtime is deliberately boring: one update() per frame from the ticker, one createEffect() per spawned effect. Wire the spark burst to the button and reap finished instances:

import type { PixiVfxEffectInstance } from "nixie-fx/pixi";

const spark = bundle.effectsById.get("spark-burst");
const live = new Set<PixiVfxEffectInstance>();

button.on("pointerdown", () => {
  live.add(
    vfx.createEffect(spark, {
      position: [button.x, button.y, 0],
      seed: (Math.random() * 0xffffffff) >>> 0,
    }),
  );
});

app.ticker.add((ticker) => {
  vfx.update(ticker.deltaMS / 1000);
  for (const fx of live) {
    if (!fx.isActive) {
      vfx.removeEffect(fx, true); // done — destroy its containers
      live.delete(fx);
    }
  }
});

Two details matter here. The simulation is deterministic: the same effect with the same seed replays identically, which is why the example randomizes the seed per press — every burst should look a little different. And update() takes seconds, so Pixi's ticker.deltaMS is divided by 1000.

The looping coin fountain works better as one persistent instance you start and stop with the reward popup:

const fountain = vfx.createEffect(bundle.effectsById.get("coin-fountain"), {
  position: [app.screen.width / 2, 260, 0],
  autoStart: false,
});

function openRewardPopup() {
  fountain.spawn(); // start emitting coins
}

function closeRewardPopup() {
  fountain.stop();
}

An instance also supports reset() to rewind it and setPosition() to follow a moving UI element — handy for a fountain anchored to an animated chest. On teardown (leaving the scene, hot-reload), release everything:

vfx.destroy();          // removes and destroys all effect instances
textureProvider.release();

Performance note: each emitter renders through Pixi's ParticleContainer, built for thousands of lightweight sprites — a 20-particle button burst is nowhere near any budget. The usual mobile discipline still applies: keep effect textures in your atlas workflow, prefer a persistent looping instance over re-creating effects every frame, and let the reap loop above destroy finished one-shots. For your own UI around the effects: parent retained display objects once and toggle visible instead of addChild/removeChild per frame, and avoid runtime Graphics vector drawing for gameplay visuals — bake shapes into atlas textures.

The full discipline — allocation rules, pool prewarming, draw-call budgets, and how to profile a stutter — lives in our HTML5 game performance guide.

Frequently asked questions

How do I add particle effects to a PixiJS v8 game?

Install a particle runtime next to Pixi (npm install pixi.js nixie-fx), author effects in the free NixieFX editor, and export them to an out/vfx bundle. In your app, load the bundle with loadVfxExportBundle from nixie-fx/export, create a PixiVfxRenderer from nixie-fx/pixi parented to your stage, and call its update() from app.ticker once per frame.

Is the NixieFX particle editor free to use?

Yes. It runs entirely in your browser at nixiefx.com/editor with no account or install. It opens a folder on your own disk, saves effects as plain JSON in that folder, and exports the runtime bundle to out/vfx. The runtime is MIT-licensed and open source at github.com/azakhary/nixie-fx.

Can I reuse the same particle effects in Three.js?

Yes. NixieFX ships one deterministic simulation with two renderer adapters: PixiVfxRenderer (nixie-fx/pixi) for 2D and UI, and ThreeVfxRenderer (nixie-fx/three) for 3D scenes. The same exported effect JSON drives both — one VFX pipeline for UI juice and in-world effects. See the web-native mobile game stack for how the two layers fit together.

How many particles can a PixiJS UI effect afford on mobile?

Fewer than you'd think, and that's fine: a button burst reads well at 10–30 particles, a reward fountain at 50–150. Because emitters render through Pixi's ParticleContainer — designed for thousands of lightweight sprites — typical UI effects are cheap even on mid-range phones. Spend your budget on good gradients and timing, not raw particle count.

Can AI coding agents author and integrate NixieFX effects?

Yes — that is the point of the skills. npx skills add https://github.com/azakhary/nixie-fx installs nixie-fx-authoring (create, validate, export effects) and nixie-fx-runtime (load bundles, wire providers, per-frame updates). Combined with the official PixiJS skills, an agent can run this entire tutorial unattended.

Resources

This tutorial is maintained by the team behind NixieFX, the browser-based HTML5 particle editor for PixiJS and Three.js. A machine-readable version is available at /pixijs-particle-effects.md, and a site index for LLMs at /llms.txt.