State Diagrams and Gantt Charts
stateDiagram-v2 for lifecycles and status machines: states, transitions, the [*] start/end markers, composite states, and forks. Then Gantt charts for project plans: the date format and axis, sections, task dependencies (after), milestones, and marking done/active/crit tasks. Two different shapes of thinking — flow over states vs. work over time.
State Diagrams and Gantt Charts
These two diagram types answer the same class of question: what happens over time? State diagrams track an entity moving through statuses — a request, an order, a user session. Gantt charts track work moving through a schedule. Same underlying question, completely different shapes of syntax.
stateDiagram-v2: the fundamentals
Always use stateDiagram-v2 — the older stateDiagram keyword still parses but uses a different renderer with limited layout control.
The most important symbol is [*], which marks entry and exit:
stateDiagram-v2
[*] --> Draft
Draft --> PendingReview : submit
PendingReview --> Published : approve
PendingReview --> Draft : reject
Published --> Archived : archive
Archived --> [*]A colon after a transition adds a label. [*] as the source means the lifecycle starts here; as the target, this is terminal. A diagram without a [*] entry technically renders, but the reader has no idea where the lifecycle begins — always include it.
State IDs can't contain spaces. If you need a multi-word display name, alias it:
state "Pending Review" as PendingReviewAfter that declaration, PendingReview is what you write in transition lines; "Pending Review" is what renders in the box.
Want a horizontal layout? Add direction LR on the line right after stateDiagram-v2 — this is a v2-only feature and one more reason to always use the modern keyword.
stateDiagram-v2
[*] --> Draft
Draft --> PendingReview : submit
PendingReview --> Published : approve
PendingReview --> Draft : reject
Published --> Archived : archive
Archived --> [*]Composite states
When a state has its own internal lifecycle, nest it with curly braces:
stateDiagram-v2
[*] --> Active
state Active {
[*] --> Idle
Idle --> Processing : request in
Processing --> Idle : response sent
Processing --> Failed : timeout
Failed --> Idle : retry
}
Active --> Terminated : shutdown
Terminated --> [*]The outer world sees Active as a single state — you enter and exit it as a unit. Internally it has its own [*] entry that fires when Active is entered. The outer Active --> Terminated transition fires regardless of which inner sub-state was active at the time. Nesting deeper than two levels usually signals the diagram should be split — same rule as with subgraphs in flowcharts.
stateDiagram-v2
[*] --> Active
state Active {
[*] --> Idle
Idle --> Processing : request in
Processing --> Idle : response sent
Processing --> Failed : timeout
Failed --> Idle : retry
}
Active --> Terminated : shutdown
Terminated --> [*]Concurrency: parallel regions and fork/join
Two ways to model activity that happens simultaneously:
Concurrent regions inside a composite state, separated by --:
stateDiagram-v2
state "Order Processing" as Proc {
[*] --> PaymentPending
PaymentPending --> PaymentConfirmed : paid
PaymentConfirmed --> [*]
--
[*] --> InventoryCheck
InventoryCheck --> Reserved : ok
Reserved --> [*]
}The -- line splits the composite state box into horizontal swim lanes that run independently.
Fork/join for branches that diverge and later reconverge:
stateDiagram-v2
[*] --> fork_state
state fork_state <<fork>>
fork_state --> RunTests
fork_state --> BuildDocs
RunTests --> join_state
BuildDocs --> join_state
state join_state <<join>>
join_state --> Deploy
Deploy --> [*]<<fork>> and <<join>> are state stereotypes — the rendered result is a solid horizontal bar, the standard UML convention. Use <<fork>> when multiple things must happen simultaneously; <<join>> when all must complete before the flow continues.
---
Gantt charts: the date/axis setup
Switch keyword to gantt. The lines to write every time:
gantt
dateFormat YYYY-MM-DD
axisFormat %b %d
title Website Launch PlandateFormat tells the parser how to read the dates you write in task lines. Skip it and any task with an absolute start date won't parse — you get a blank diagram with no error message whatsoever. YYYY-MM-DD is the safest choice and almost universal.
axisFormat controls how dates appear on the rendered timeline, using strftime notation: %b %d gives "Jan 06", %m/%d gives "01/06", %d gives just the day number. This affects display only, not parsing.
Task syntax and flags
Tasks live under section headers. The format:
Task label :flags, id, start, durationA realistic project plan:
gantt
dateFormat YYYY-MM-DD
axisFormat %b %d
title API v2 Launch
section Design
Define endpoints :done, des1, 2024-03-01, 5d
Review with team :done, des2, after des1, 2d
section Development
Implement auth :active, dev1, after des2, 7d
Write integration tests : dev2, after dev1, 4d
section Launch
Deploy to staging :crit, dep1, after dev2, 1d
Go live :milestone, live, after dep1, 0dFlag reference:
| Flag | Effect |
|---|---|
done | Filled/gray bar — task complete |
active | Highlighted (typically blue) — in progress |
crit | Red bar — on the critical path |
milestone | Diamond marker — duration must be 0d |
Flags combine freely: :crit, done marks a finished critical-path task. The parser recognizes those four keywords as flags; anything else in that position is treated as a task ID. So :dev2, after dev1, 4d assigns the id dev2 with no status flag.
Dependencies and milestones
after taskId as the start value makes a task begin the moment the referenced task ends. Chain multiple predecessors — after dev1 dev2 — and the task waits for both to finish before starting. This is the Gantt counterpart to <<join>> in state diagrams.
Milestones mark a point in time rather than a span of work. The 0d duration is what triggers the diamond rendering:
Go live :milestone, live, after dep1, 0dexcludes weekends at the top level removes those days from duration calculations — a 5-day task starting Thursday automatically extends into the following week.
gantt
dateFormat YYYY-MM-DD
axisFormat %b %d
title API v2 Launch
section Design
Define endpoints :done, des1, 2024-03-01, 5d
Review with team :done, des2, after des1, 2d
section Development
Implement auth :active, dev1, after des2, 7d
Write integration tests : dev2, after dev1, 4d
section Launch
Deploy to staging :crit, dep1, after dev2, 1d
Go live :milestone, live, after dep1, 0dQuick check
1. Draw a stateDiagram-v2 for a support ticket: Open → InProgress → PendingCustomer → Resolved → Closed → [*], with an edge from Closed back to Open labeled "re-open."
2. Add a composite state inside InProgress with two sub-states: Assigned and WorkingOnFix.
3. Write a five-task Gantt for a small feature rollout — at least one done task, one active, one crit, and a milestone at the end. Use after dependencies throughout.
The next submodule covers layout control, styling with classDef, theme variables, and clickable nodes — where your own-site rendering setup really starts to pay off.
Self-check
- You see a state diagram without any [*] markers. The diagram renders without errors. Why would you still add [*] to make it more correct?
- You need to display a state as 'Pending Review' in the diagram. Why write `state "Pending Review" as PendingReview` instead of just `state PendingReview`?
- Inside a composite state Auth with sub-states Login and TwoFactor, you define `Auth --> Logout`. What is the consequence of this transition firing?
- You're modeling a checkout process where payment validation and inventory checking must happen simultaneously. Which structure fits best?
- In a Gantt chart, you omit the `dateFormat` line and use task dates like '2024-03-01'. What is the result?
- What is the core difference between `dateFormat YYYY-MM-DD` and `axisFormat %b %d` in a Gantt diagram?
- You create a task `ship_date :milestone, m1, after deploy, 1d`. Why is this problematic?
- In a Gantt chart, you write `Integration :crit, int, after dev1 dev2, 3d`. When does Integration start?
Homework
Content Publishing Workflow State Diagramdocument
Create a state diagram that models how articles move through a publishing pipeline. Track these states: Draft (initial), Review, Revision, Approved, Published, and Archived (terminal). Include a transition from Review back to Revision when an article needs changes, and from Revision back to Review once the author resubmits. Label each transition with what triggers it (e.g., 'submit for review', 'reject', 'approve', 'publish', 'archive'). You can use multi-word state names—alias them if needed. Submit your work as a markdown file with the Mermaid code block.
Diagram uses stateDiagram-v2; [*] marks both entry and exit; all six required states are present with unique IDs; transitions connect states logically and each has a label; the feedback loop from Review to Revision is correctly implemented; diagram renders without syntax errors; code is properly indented and readable.
Sprint Development Gantt Chartdocument
Create a Gantt chart for a typical two-week development sprint. Include these phases: Sprint Planning, Development, Quality Assurance, and Release. Add 6–8 tasks spanning these phases (e.g., 'Review requirements', 'Implement feature X', 'Write unit tests', 'Run integration tests', 'Deploy to staging', 'Go live'). Use task dependencies so that testing doesn't start until development is complete, and the release happens only after QA signs off. Mark at least one task as critical (on the critical path), mark one or two as done (completed before this sprint), and create a 'Go live' milestone at the end. Use dateFormat YYYY-MM-DD and choose an axisFormat that's readable (e.g., %b %d). Submit as a markdown file with the Mermaid code block.
Diagram declares dateFormat YYYY-MM-DD and axisFormat; all tasks belong to clearly named sections; at least 6–8 tasks are defined with realistic start dates and durations; task IDs are unique; dependencies use 'after' correctly so testing waits for dev and release waits for QA; at least one :crit task, at least one :done task; a milestone is present with 0d duration and renders as a diamond; dates are sequential and realistic for a two-week sprint; diagram renders without parse errors.
Feature Request Lifecycle: State Diagram + Ganttdocument
Build a document that shows how a feature request moves through your organization's workflow. Include two parts: First, create a state diagram modeling the feature request lifecycle with states for Submitted, Under Review, Approved, In Development, Testing, Shipped, and Archived. Add transitions and feedback loops—for example, a path back to Under Review if a feature is rejected, and a path back to In Development if testing finds critical bugs. Second, create a Gantt chart showing the timeline for one specific feature request flowing through these stages. Include at least one task per major phase, dependencies that reflect the state flow, at least one milestone for 'Shipped', and a mix of task flags (done, active, crit). Finally, write 2–3 sentences explaining what the state diagram tells you that the Gantt chart doesn't—and vice versa. Submit as a single markdown file with both diagram code blocks, clear section headers, and your explanation.
State diagram uses stateDiagram-v2 with [*] entry and [*] exit; all required states present with no spaces in IDs (or properly aliased); transitions have labels; feedback loops for rejection and bugs are correctly implemented; Gantt has dateFormat and axisFormat declared; Gantt includes at least 6–7 tasks organized in sections aligned with the state diagram; tasks have dependencies (after) reflecting the state flow; Gantt includes a milestone with 0d duration, at least one :crit task, and at least one :done task; explanation clearly articulates what each diagram shows differently (e.g., state diagram shows branching logic and decision points, Gantt shows timing and sequence); both diagrams render cleanly without errors; markdown is well-organized with clear headers for each section.
Submit and get assignments reviewed in the Learn (Almost) Anything app.
