Ignite Element
Ignite Element is a thin, typed layer around modern state systems so you can ship platform-native custom elements without dragging along an app-framework runtime. Commands express intent, effects express consequences, and the same component contract runs in the DOM, in tests, or headlessly.
import { igniteCore } from 'ignite-element/xstate';import { toggleMachine } from './toggle-machine';
const toggle = igniteCore({ source: toggleMachine, view: ({ matches }) => ({ isOn: matches('on') }), commands: ({ actor }) => ({ toggle: () => actor.send({ type: 'TOGGLE' }) }),});
toggle('ignite-toggle', ({ isOn, toggle }) => ( <button onClick={toggle}>{isOn ? 'On' : 'Off'}</button>));That registration is both a <ignite-toggle> custom element and a headless runtime you can drive from tests or agents — no DOM required.
Pick your path
Section titled “Pick your path”- Build a UI — install, enable JSX once, and ship a component. Start with Installation → Your first component, then read The Ignite model.
- Build for agents — drive and inspect component behavior through the headless runtime before any DOM exists. Start with Build for agents and the Headless runtime reference.
New to the idea entirely? Read What is Ignite Element? for the why and how it compares to other tools.
Try it live
Section titled “Try it live”Try the counter directly in the docs, or open the full example in StackBlitz.
<ignite-counter>
Every press is a command — the buttons express intent, the state machine owns the transition, and the view re-renders from state. Here is the same counter with the real API:
import { igniteCore } from 'ignite-element/xstate';import { counterMachine } from './counter-machine';
const counter = igniteCore({ source: counterMachine, view: ({ context }) => ({ count: context.count }), commands: ({ actor }) => ({ increment: () => actor.send({ type: 'INC' }), decrement: () => actor.send({ type: 'DEC' }), reset: () => actor.send({ type: 'RESET' }), }),});
counter('ignite-counter', ({ count, increment, decrement, reset }) => ( <div> <button onClick={decrement}>−</button> <output>{count}</output> <button onClick={increment}>+</button> <button onClick={reset}>Reset</button> </div>));Want to edit and fork the full project?