If you've ever tried to visualize how an order moves from "placed" to "delivered," or how a user session changes between "active," "idle," and "expired," you know how messy these flows get in plain text. Mermaid JS state diagrams give you a way to map those states and transitions with a few lines of simple text-based syntax no design tools, no drag-and-drop, no exported image files to manage. This reference guide covers the exact syntax you need, with real examples, common pitfalls, and practical tips so you can write accurate state diagrams on the first try.

What Exactly Is a State Diagram in Mermaid JS?

A state diagram is a type of UML diagram that shows the different states an object or system can be in, and the transitions between those states. In Mermaid JS, you write these diagrams using a straightforward text syntax inside a stateDiagram-v2 block. Mermaid renders the output as an SVG diagram that works in documentation sites, GitHub READMEs, wikis, and any markdown renderer that supports Mermaid.

Unlike flowchart syntax in Mermaid, which focuses on decision paths and process steps, state diagrams focus specifically on the condition or status of something over time. You use them when the important thing is what states exist, not just what steps happen in order.

How Do You Define States in Mermaid?

Defining states is the starting point. You declare each state with a simple identifier. Mermaid will automatically render any state you reference in a transition, so you don't always need to list them upfront but you can define them explicitly for clarity.

stateDiagram-v2
 [] --> Idle
 Idle --> Processing
 Processing --> Complete
 Complete --> []

In this example:

  • [] represents the start state (initial state) and end state (final state).
  • Each named word like Idle, Processing, and Complete is a state.
  • The --> arrow defines a transition from one state to another.

You can also give states descriptions using the as keyword:

stateDiagram-v2
 s1 as "Waiting for payment"
 s2 as "Payment received"
 [] --> s1
 s1 --> s2
 s2 --> []

This is useful when your state name needs to be more descriptive than a short identifier.

How Do You Write Transitions Between States?

Transitions connect states and optionally include a label describing what triggers the change. The syntax is straightforward:

stateDiagram-v2
 Draft --> Submitted : submit for review
 Submitted --> Approved : reviewer approves
 Submitted --> Rejected : reviewer rejects
 Rejected --> Draft : revise and resubmit
 Approved --> Published

The text after the colon becomes the transition label. This is one of the most common parts of the Mermaid state diagram syntax, and it's where most of the meaning in your diagram comes from.

A few rules to remember:

  • Use --> for every transition (single dash won't work).
  • Labels go on the same line, separated by a colon and a space.
  • You can have multiple transitions out of the same state (branching) and multiple transitions into the same state (merging).

How Do You Add Notes to States?

Sometimes a state name doesn't tell the full story. Mermaid supports state notes using the note keyword:

stateDiagram-v2
 [] --> Active
 Active --> Suspended
 note right of Active : User has logged in and session is valid
 note left of Suspended : Triggered after 30 min of inactivity

Notes render as small text boxes attached to the state. Use note right of or note left of to control placement. Keep notes short long text blocks will make the diagram hard to read.

How Do You Create Composite or Nested States?

Real systems often have states within states. A "Running" state might contain sub-states like "Initializing," "Processing," and "Shutting Down." Mermaid handles this with composite states:

stateDiagram-v2
 [] --> Server

 state Server {
 [] --> Booting
 Booting --> Running
 Running --> ShuttingDown
 ShuttingDown --> []

 state Running {
 [] --> Idle
 Idle --> HandlingRequest
 HandlingRequest --> Idle
 }
 }

 Server --> Offline
 Offline --> []

The outer state Server contains its own internal lifecycle, and inside Running, there's another nested set of sub-states. This nesting can go multiple levels deep, though two levels is usually enough for most diagrams.

Composite states are especially useful when modeling UML state machine diagrams for software systems, hardware controllers, or protocol designs.

How Do You Use Fork, Join, and Choice Nodes?

State diagrams in Mermaid support three special pseudo-states:

Fork and Join

A fork splits a single state into multiple concurrent states. A join merges concurrent states back into one. These are shown as thick horizontal bars in standard UML notation.

stateDiagram-v2
 [] --> Active
 Active --> Fork1

 state Fork1 <>
 Fork1 --> ProcessingA
 Fork1 --> ProcessingB

 ProcessingA --> Join1
 ProcessingB --> Join1

 state Join1 <>
 Join1 --> Done
 Done --> []

Use <> and <> as decorators after the state name.

Choice

A choice node lets you branch based on a condition similar to a decision diamond in a flowchart:

stateDiagram-v2
 [] --> Checking
 Checking --> State1
 Checking --> State2

 state Checking {
 [] --> Validate
 Validate --> Choice1

 state Choice1 <>
 Choice1 --> Pass : valid
 Choice1 --> Fail : invalid
 }

Choice nodes are declared with <>. They're useful when a transition depends on a condition being evaluated at runtime.

What Are the Most Common Mistakes?

Here are the errors people hit most often when writing Mermaid state diagram syntax:

  • Using stateDiagram instead of stateDiagram-v2. The v2 version has better layout and more features. Always use stateDiagram-v2.
  • Missing the colon before transition labels. Writing A --> B label instead of A --> B : label will cause a parse error.
  • Forgetting [] for start/end states. Without these, your diagram won't show entry or exit points.
  • Using special characters in state names without quotes. If your state name has spaces or symbols, wrap it in quotes or use the as alias syntax.
  • Overloading one diagram with too many states. State diagrams become unreadable past about 15-20 states. Split complex systems into multiple diagrams or use composite states.

If you're also working with other diagram types, the same kinds of syntax issues show up in class diagram Mermaid code and flowchart diagrams but the specific keywords and structure differ, so don't mix syntaxes.

When Should You Use a State Diagram Instead of a Flowchart?

Use a state diagram when the focus is on what states something can be in and how it moves between them. Use a flowchart when the focus is on sequential steps and decisions in a process.

Good candidates for state diagrams:

  • User account lifecycle (active, suspended, banned, deleted)
  • Order processing (placed, paid, shipped, delivered, returned)
  • Connection status (connecting, connected, reconnecting, disconnected)
  • UI component state (loading, loaded, error, empty)
  • Game entity behavior (idle, attacking, defending, stunned)

Good candidates for flowcharts:

  • Step-by-step procedures
  • Decision trees with yes/no branches
  • Approval workflows where the sequence matters more than the states

Quick Syntax Reference Table

ElementSyntax
Start state[] --> StateName
End stateStateName --> []
TransitionA --> B
Labeled transitionA --> B : label text
State descriptions1 as "Descriptive name"
Notenote right of StateName : note text
Forkstate ForkName <>
Joinstate JoinName <>
Choicestate ChoiceName <>
Composite statestate StateName { ... }
Directiondirection TB or direction LR

Practical Tips for Cleaner State Diagrams

  1. Start with the happy path. Map the normal flow first (e.g., draft → submitted → approved → published), then add error states and edge cases.
  2. Use meaningful state names. PaymentPending is clearer than S2.
  3. Label your transitions. Unlabeled arrows leave readers guessing what triggers each change.
  4. Set direction explicitly. Add direction LR at the top of your diagram if you prefer left-to-right layout instead of top-to-bottom.
  5. Keep one diagram per object. Don't mix the lifecycle of orders, users, and payments in a single diagram.
  6. Test your syntax in the Mermaid Live Editor before committing it to your docs.

Next Steps and Checklist

  • ✅ Open the Mermaid Live Editor and paste in a basic state diagram to verify your environment supports rendering.
  • ✅ List all states your system or object can be in don't think about transitions yet, just states.
  • ✅ Map the transitions with trigger labels between those states.
  • ✅ Add [] start and end points.
  • ✅ Use composite states if any state has its own internal lifecycle.
  • ✅ Check that you're using stateDiagram-v2 (not the older stateDiagram).
  • ✅ Test your diagram in the live editor, fix any syntax errors, then embed it in your documentation.