stackpicks.dev
Back to gallery
statelyai/xstate preview
statelyai
statelyai/

xstate

State machines, statecharts, and actors for complex logic

Stars
29.6k
Forks
1.4k
Watchers
29.6k
Open issues
128
TypeScriptMIT main Updated 1 day ago~8 stars/day lifetime
Editor's take

Actor-based state machines. ~27k stars. Overkill for most apps but unbeatable for genuinely complex workflows — multi-step forms, async retries with rollback, real-time collaboration. Worth learning even if you do not adopt.

Use this if

You have a genuinely complex workflow with many states, transitions, and side effects.

Skip if

You have toggles and modals — useState is enough.

State Management
Topics
background-jobsfinite-state-machinefsmhacktoberfestinterpreterjavascriptorchestrationscxmlstatestate-machinestate-managementstatechartstatechartstypescriptvisualizerworkflow
Quick install
# Install via npm / pnpm / bun:
pnpm add xstate
# or
npm install xstate

Inferred from TypeScript · always double-check against the official README below.

README — rendered from statelyai/xstate(truncated)


XState logotype
Actor-based state management & orchestration for complex app logic. → Documentation

XState is a state management and orchestration solution for JavaScript and TypeScript apps. It has zero dependencies, and is useful for frontend and backend application logic.

It uses event-driven programming, state machines, statecharts, and the actor model to handle complex logic in predictable, robust, and visual ways. XState provides a powerful and flexible way to manage application and workflow state by allowing developers to model logic as actors and state machines.

✨ Create state machines visually in Stately Studio → state.new


📖 Read the documentation

➡️ Create state machines with the Stately Editor

🖥 Download our VS Code extension

📑 Inspired by the SCXML specification

💬 Chat on the Stately Discord Community

✍️ Browse through the many XState examples

Which package should I use?

Pick based on what you need:

  • @xstate/store: simple event-based state management. <1kb, great TypeScript inference, similar in spirit to Redux/Zustand. Start here if you just need a store.
  • xstate: state machines, statecharts, actors, effects, and orchestration for complex app logic.

They work great together, but you don't need one to use the other.

Sponsors

Special thanks to the sponsors who support this open-source project:

Templates

Get started by forking one of these templates on CodeSandbox:

Template

🤖 XState Template (CodeSandbox)

Open in StackBlitz

  • XState v5
  • TypeScript
  • No framework

⚛️ XState + React Template (CodeSandbox)

Open in StackBlitz

  • React
  • XState v5
  • TypeScript

💚 XState + Vue Template (CodeSandbox)

Open in StackBlitz

  • Vue
  • XState v5
  • TypeScript

🧡 XState + Svelte Template (CodeSandbox)

Open in StackBlitz

Super quick start

npm install xstate
import { createMachine, createActor, assign } from 'xstate';

// State machine
const toggleMachine = createMachine({
  id: 'toggle',
  initial: 'inactive',
  context: {
    count: 0
  },
  states: {
    inactive: {
      on: {
        TOGGLE: { target: 'active' }
      }
    },
    active: {
      entry: assign({ count: ({ context }) => context.count + 1 }),
      on: {
        TOGGLE: { target: 'inactive' }
      }
    }
  }
});

// Actor (instance of the machine logic, like a store)
const toggleActor = createActor(toggleMachine);
toggleActor.subscribe((state) => console.log(state.value, state.context));
toggleActor.start();
// => logs 'inactive', { count: 0 }

toggleActor.send({ type: 'TOGGLE' });
// => logs 'active', { count: 1 }

toggleActor.send({ type: 'TOGGLE' });
// => logs 'inactive', { count: 1 }

@xstate/store: simple state management

Not every app needs all the features of state machines and statecharts. @xstate/store is a separate, extremely small event-based store with first-class TypeScript inference; similar to Redux or Zustand, but with less boilerplate.

Use it on its own, or graduate to full XState machines when your logic gets more complex.

npm install @xstate/store
import { createStore } from '@xstate/store';

const donutStore = createStore({
  context: {
    donuts: 0,
    favoriteFlavor: 'chocolate'
  },
  on: {
    addDonut: (context) => ({ ...context, donuts: context.donuts + 1 }),
    changeFlavor: (context, event: { flavor: string }) => ({
      ...context,
      favoriteFlavor: event.flavor
    }),
    eatAllDonuts: (context) => ({ ...context, donuts: 0 })
  }
});

donutStore.subscribe((snapshot) => {
  console.log(snapshot.context);
});

donutStore.send({ type: 'addDonut' });
// => { donuts: 1, favoriteFlavor: 'chocolate' }

donutStore.send({ type: 'changeFlavor', flavor: 'strawberry' });
// => { donuts: 1, favoriteFlavor: 'strawberry' }

📖 See the @xstate/store README for React/Solid bindings, selectors, and more.


  • Visually create, edit, and collaborate on state machines
  • Export to many formats, including XState v5
  • Test path & documentation autogeneration
  • Deploy to Stately Sky
  • Generate & modify machines with Stately AI
XState Viz

state.new

Why?

Statecharts are a formalism for modeling stateful, reactive systems. This is useful for declaratively describing the behavior of your application, from the individual components to the overall application logic.

Read 📽 the slides (🎥 video) or check out these resources for learning about the importance of finite state machines and statecharts in user interfaces:

Packages

Package Description
🤖 xstate Core finite state machine and statecharts library + interpreter, including graph traversal and model-based testing utilities
🏪 @xstate/store Simple event-based state management (<1kb) — standalone, works with or without xstate
⚛️ @xstate/react React hooks and utilities for using XState in React applications
💚 @xstate/vue Vue composition functions and utilities for using XState in Vue applications
🎷 @xstate/svelte Svelte utilities for using XState in Svelte applications
🥏 @xstate/solid Solid hooks and utilities for using XState in Solid applications
🔍 @statelyai/inspect Inspection utilities for XState

Finite State Machines

CodeStatechart
import { createMachine, createActor } from 'xstate';

const lightMachine = createMachine({
  id: 'light',
  initial: 'green',
  states: {
    green: {
      on: {
        TIMER: 'yellow'
      }
    },
    yellow: {
      on: {
        TIMER: 'red'
      }
    },
    red: {
      on: {
        TIMER: 'green'
      }
    }
  }
});

const actor = createActor(lightMachine);

actor.subscribe((state) => {
  console.log(state.value);
});

actor.start();
// logs 'green'

actor.send({ type: 'TIMER' });
// logs 'yellow'
Finite states
Open in Stately Studio

Hierarchical (Nested) State Machines

CodeStatechart
import { createMachine, createActor } from 'xstate';

const pedestrianStates = {
  initial: 'walk',
  states: {
    walk: {
      on: {
        PED_TIMER: 'wait'
      }
    },
    wait: {
      on: {
        PED_TIMER: 'stop'
      }
    },
    stop: {}
  }
};

const lightMachine = createMachine({
  id: 'light',
  initial: 'green',
  states: {
    green: {
      on: {
        TIMER: 'yellow'
      }
    },
    yellow: {
      on: {
        TIMER: 'red'
      }
    },
    red: {
      on: {
        TIMER: 'green'
      },
      ...pedestrianStates
    }
  }
});

const actor = createActor(lightMachine);

actor.subscribe((state) => {
  console.log(state.value);
});

actor.start();
// logs 'green'

actor.send({ type: 'TIMER' });
// logs 'yellow'

actor.send({ type: 'TIMER' });
// logs { red: 'walk' }

actor.send({ type: 'PED_TIMER' });
// logs { red: 'wait' }
Hierarchical states
Open in Stately Studio

Parallel State Machines

CodeStatechart
import { createMachine, createActor } from 'xstate';

const wordMachine = createMachine({
  id: 'word',
  type: 'parallel',
  states: {
    bold: {
      initial: 'off',
      states: {
        on: {
          on: { TOGGLE_BOLD: 'off' }
        },
        off: {
          on: { TOGGLE_BOLD: 'on' }
        }
      }
    },
    underline: {
      initial: 'off',
      states: {
        on: {
          on: { TOGGLE_UNDERLINE: 'off' }
        },
        off: {
          on: { TOGGLE_UNDERLINE: 'on' }
        }
      }
    },
    italics: {
      initial: 'off',
      states: {
        on: {
          on: { TOGGLE_ITALICS: 'off' }
        },
        off: {
          on: { TOGGLE_ITALICS: 'on' }
        }
      }
    },
    list: {
      initial: 'none',
      states: {
        none: {
          on: {
            BULLETS: 'bullets',
            NUMBERS: 'numbers'
          }
        },
        bullets: {
          on: {
            NONE: 'none',
            NUMBERS: 'numbers'
          }
        },
        numbers: {
          on: {
            BULLETS: 'bullets',
            NONE: 'none'
          }
        }
      }
    }
  }
});

const actor = createActor(wordMachine);

actor.subscribe((state) => {
  console.log(state.value);
});

actor.start();
// logs {
//   bold: 'off',
//   italics: 'off',
//   underline: 'off',
//   list: 'none'
// }

actor.send({ type: 'TOGGLE_BOLD' });
// logs {
//   bold: 'on',
//   italics: 'off',
//   underline: 'off',
//   list: 'none'
// }

actor.send({ type: 'TOGGLE_ITALICS' });
// logs {
//   bold: 'on',
//   italics: 'on',
//   underline: 'off',
//   list: 'none'
// }
Parallel states
Open in Stately Studio

History States

CodeStatechart
import { createMachine, createActor } from 'xstate';

const 
Live data via GitHub REST API · Cached 30 min · Created 14 Sept 2015
statelyai/xstate — Live preview — StackPicks