# Writing diagrams

> Page: https://docs.plotwork.dev/writing-diagrams. Index of every page: https://docs.plotwork.dev/llms.txt

How to write flow, sequence, and schema diagrams in the diagram language, with a pointer to the guide of each of the seventeen other kinds. There are twenty kinds in all. It is for anyone, human or AI agent, who writes diagram source. Every example on this page is a real diagram, rendered by the tool this guide teaches, so you can copy one and it works.

## TL;DR

| Rule | Yes | No |
|---|---|---|
| Statements | One per line | Two statements on one line |
| Labels | Quoted: `"Auth API"` | Bare words with spaces |
| Meaning | A node `type` (`database`) or a `tone=` (`violet`) | A color value such as `#7c3aed`; colors are not accepted |
| Ids | Short and stable: `api`, `user_db`, `as-jwks` | Spaces, or an id reused for two things |
| Icons | `icon=lucide:key`, `icon=simple:postgresql`, `icon=aws:lambda`, `icon=status:success` | A made-up name; it is rejected with suggestions |
| Groups | A name and a type for what the group is: `group vpc "Application VPC" type=network {` | A color, or a long sentence as the name |
| Size | About 15 nodes, 6 tables, or 6 actors at most | One diagram that tries to show everything |
| Labels | Short, in sentence case | A paragraph inside a node |
| Step numbers | `numbered=on` in the header, `step=off` on a line to skip one | A number typed into each label |

## 1. How a diagram starts

The first line names the kind, gives a quoted title, and may add options. The title becomes the accessible name of the picture.

| Kind | Header | Options |
|---|---|---|
| Flow | `flow "Title"` | `direction=` (`auto`, `right`, `down`, `left`, `up`), `desc="Summary"`, `animate=on`, `numbered=on`, `start=` |
| Sequence | `sequence "Title"` | `desc="Summary"`, `animate=on`, `numbered=on`, `start=` |
| Schema | `schema "Title"` | `desc="Summary"` |
| Git graph | `git "Title"` | `direction=`, `main=`, `desc=`. See [Git graphs](https://docs.plotwork.dev/git-graphs.md). |
| Gantt chart | `gantt "Title"` | `start=`, `unit=`, `today=`, `weekends=`, `holidays=`, `desc=`. See [Gantt charts](https://docs.plotwork.dev/gantt-charts.md). |
| Class diagram | `class "Title"` | `direction=`, `desc=`. See [Class diagrams](https://docs.plotwork.dev/class-diagrams.md). |
| State diagram | `state "Title"` | `direction=`, `desc=`. See [State diagrams](https://docs.plotwork.dev/state-diagrams.md). |
| Timeline | `timeline "Title"` | `direction=`, `side=`, `desc=`. See [Timelines](https://docs.plotwork.dev/timelines.md). |
| User journey | `journey "Title"` | `marks=`, `legend=`, `desc=`. See [User journeys](https://docs.plotwork.dev/user-journeys.md). |
| Mind map | `mindmap "Title"` | `layout=`, `desc=`. See [Mind maps](https://docs.plotwork.dev/mind-maps.md). |

`desc` is a one- or two-sentence summary. It is used as the picture's alt text, so write what the diagram says. `animate`, `numbered`, and `start` are explained in [Numbered steps](#7-numbered-steps) and [Animated lines](#8-animated-lines).

Lines that start with `#` are comments.

## 2. Flow diagrams

A flow diagram shows things and the connections between them. Use it for architecture and for processes.

| Statement | Form | Notes |
|---|---|---|
| Node | `node <id> <type> "Label" sub="Detail" tone=blue icon=lucide:key stack=simple:go` | `sub`, `tone`, `icon`, and `stack` are optional. `stack=` adds up to three technology marks under the text. |
| Group | `group <id> "Name" type=network provider=aws {`, then nodes, then `}` | `type`, `provider`, `icon`, and `tone` are optional. Groups nest. `type=` says what the group is and sets its icon, tone, and frame style. |
| Edge | `a -> b : "label" icon=status:yes role=data animate=off step=12` | The label, the icon, `role=`, `animate=`, and `step=` are optional. An icon needs a label. A label that names a relationship with a verb, such as `reads` or `publishes OrderPlaced`, draws its icon by itself. |

Arrows:

| Token | Meaning |
|---|---|
| `->` | Solid line, arrowhead at the end |
| `-->` | Dashed line, arrowhead at the end |
| `..>` | Dotted line, arrowhead at the end: an asynchronous call such as a webhook or an event |
| `<->` and `<-->` | Arrowheads at both ends |
| `--` | A line with no arrowhead |

Where one line crosses another at a right angle, the horizontal one hops over the other with a small arc, so a reader sees a crossing and not a join, in solid and dashed lines alike. Lines that meet or share a stretch are not crossings and do not hop. A bend right beside a hop tightens a little to make room, and a hop is left out where it would still land on a bend, an arrowhead, a node, or a label. There is nothing to write for it.

A node's type sets its default icon, tone, and look. The [flow node types](https://docs.plotwork.dev/reference/language/flow-nodes.md) page lists every type. These are the most used:

| Type | Use for |
|---|---|
| `person`, `agent`, `client` | Who or what starts things |
| `service`, `gateway`, `function` | Code that runs |
| `database`, `cache`, `queue`, `storage` | Where data lives |
| `identity`, `secret` | Trust and credentials |
| `external` | Systems you do not own (dashed outline) |
| `step`, `decision`, `terminal` | Process steps, branches, and end states |

A group draws a frame around its nodes and carries a corner tab: a small box fixed to the frame's top-left corner that holds the group's icon and its name on one line. The tab grows to fit the name, with the same padding on both sides. A name that is longer than the widest node card is cut with an ellipsis and warning `W203`, so keep a group's name to a few words and put detail in the nodes.

| Group option | Effect |
|---|---|
| `type=<type>` | What the group is, from a closed list such as `account`, `region`, `network`, `subnet`, `data-tier`, or `trust-boundary`. It sets the icon, the tone, and a solid, dashed, or dotted frame. |
| `provider=<provider>` | Whose resources the group holds (`aws`, `azure`, `gcp`), so a type draws that provider's icon. Nested groups inherit it. |
| `icon=<set>:<name>` | Overrides the icon in the tab. A group with no type has none unless you set one. |
| `tone=<tone>` | Overrides the tone. Without a type the group is neutral. |
| `sub="..."` | A short second line in the tab under the name, such as an address range. |
| `stack=<set>:<name>,...` | Up to three small marks in the tab, written like the marks of a node. |
| `icon=none` | Removes the icon. |
| `type=none` | Keeps the group plain: no type from its name and no suggestion. |

A group with no `type=` whose name gives its type for certain takes it by itself: `VPC`, `Production`, `CI pipeline`, `Kafka`, `Kubernetes`, `us-east-1`, `Data`, `Security`, and `Monitoring` are typed, while `Data science team` and `Data pipeline` stay plain. A name that only suggests a type gets warning `W205` with the `type=` to add. `icons=off` on the header turns this off along with the automatic icons.

An overlay draws a dashed frame around nodes or groups it does not own, wherever layout put them. It is one line after the members, `overlay set "Web machines" type=scale-group members=w1,w2,w3`, and it takes `type=`, `provider=`, `icon=`, `tone=`, `sub=`, and `stack=` like a group. Use it for a scaling group that spans two zones or a redundant set of machines inside a tier. When the members sit in different groups, the frame crosses the group frames on purpose, and warning `W206` says if it would also surround a node that is not a member.

A group nested in another is shaded one step stronger than the one around it, in light and in dark. The [group types page](https://docs.plotwork.dev/cloud-architecture/group-types.md) draws every group type and the icon each draws for each provider, the [cloud architecture guide](https://docs.plotwork.dev/cloud-architecture.md) has the recipe and the icon pages for every cloud product, and the [architecture patterns guide](https://docs.plotwork.dev/architecture-patterns.md) has ready-made diagrams for the common shapes.

An edge that would pass under a tab is moved to the side when the nodes it joins allow it, and otherwise passes behind the tab.

**Diagram source**

```diagram
flow "Nested groups and directions" desc="A request crosses a trust boundary into a private network containing an API and its data stores." direction=down

node client person "Client"

group edge "Public edge" type=edge {
  node gw gateway "API gateway" sub="TLS and rate limits"
}

group internal "Private network" type=trust-boundary tone=violet {
  node api service "Orders API"
  group data "Data stores" icon=lucide:database {
    node db    database "Orders DB"
    node cache cache    "Session cache"
  }
}

client -> gw  : "HTTPS"
gw     -> api : "forward"
api    -> db  : "read and write" role=data
api    --> cache : "lookup"
```

*Picture: Nested groups and directions: 5 nodes, 4 connections. A request crosses a trust boundary into a private network containing an API and its data stores.*

**Text description**

**Nodes:**

- Client, person
- Edge: Public edge
  - API gateway (TLS and rate limits), gateway
- Trust boundary: Private network
  - Orders API, service
  - Data tier: Data stores
    - Orders DB, database
    - Session cache, cache

**Connections:**

- Client to API gateway: HTTPS
- API gateway to Orders API: forward
- Orders API to Orders DB (stored data line): read and write
- Orders API to Session cache (dashed): lookup

### Make it look finished

Four habits make a flow diagram look finished without a single colour value:

| Habit | Write | What it draws |
|---|---|---|
| A verb on each arrow | `api -> db : "reads orders"` | The relationship's icon in the label: an eye for reads, a pen for writes, a paper plane for publishes, a rocket for deploys |
| A role on the lines that mean something | `role=data`, `role=async`, `role=identity`, `role=private` | The line in the role's colour, named in a legend. Warning `W500` lists the arrows to mark |
| A type on each group | `type=network`, or a name such as `"Production"` | The frame, tone, and icon of the kind |
| Product names on nodes | `"Postgres"`, `"Redis"`, `"Amazon S3"` | The product's mark |

`W204`, `W205`, and `W500` are style suggestions: `validate --strict` and the Action's `fail-on: warning` pass them.

**Diagram source**

```diagram
flow "Checkout" direction=right desc="A web app calls the checkout API, which writes orders to Postgres, reads sessions from Redis, and publishes an event that an email worker consumes."

node web    client   "Web app"
node api    service  "Checkout API"

group data "Data" {
  node db     database "Postgres"
  node cache  cache    "Redis"
}

group events "Event bus" {
  node bus    queue    "Kafka"
}

node mailer service  "Email worker"

web -> api    : "calls"
api -> db     : "writes orders"         role=data
api -> cache  : "reads sessions"        role=data
api -> bus    : "publishes OrderPlaced" role=async
bus -> mailer : "consumes"              role=async
```

*Picture: Checkout: 6 nodes, 5 connections. A web app calls the checkout API, which writes orders to Postgres, reads sessions from Redis, and publishes an event that an email worker consumes.*

**Text description**

**Nodes:**

- Web app, client
- Checkout API, service
- Email worker, service
- Data tier: Data
  - Postgres, database
  - Redis, cache
- Messaging: Event bus
  - Kafka, queue

**Connections:**

- Web app to Checkout API: calls
- Checkout API to Postgres (stored data line): writes orders
- Checkout API to Redis (stored data line): reads sessions
- Checkout API to Kafka (asynchronous line): publishes OrderPlaced
- Kafka to Email worker (asynchronous line): consumes

## 3. Sequence diagrams

A sequence diagram shows messages between actors over time. Use it for protocols, login flows, and code paths.

| Statement | Form | Notes |
|---|---|---|
| Actor | `actor <id> <type> "Label" sub="Detail" icon=lucide:key tone=blue` | Declared in column order, left to right. |
| Message | `a -> b : "label" animate=off step=off` | Use `-->` for a reply. `a -> a` is a message to itself. `animate=` and `step=` are optional. |
| Note | `note over a : "text"` or `note over a, b : "text"` | The second form spans several actors. |
| Frame | `alt "condition" {`, messages, `} else "other" {`, messages, `}` | Also `opt`, `loop`, and `par` (with `and` for the next branch). |

A message between two actors that are not neighbours crosses the lifelines of the actors between them. Each crossing is drawn as a small arc that the arrow hops over, so a reader sees a crossing and not a join, in solid and dashed arrows alike. There is nothing to write for it.

**Diagram source**

```diagram
sequence "Checkout with retries" desc="A client pays for an order. The payment is retried up to three times, and inventory is updated in parallel with the receipt."

actor app  client  "Shop app"
actor pay  service "Payments"
actor inv  service "Inventory"
actor mail service "Email"

app -> pay : "Charge order"

loop "up to 3 attempts" {
  pay -> pay : "Call card network"
  pay --> app : "Result"
}

note over app, pay : "A declined card stops the flow after the third attempt"

opt "payment accepted" {
  par "update stock" {
    pay -> inv : "Reserve items"
  } and "send receipt" {
    pay -> mail : "Receipt"
  }
}
```

*Picture: Checkout with retries: 4 participants. A client pays for an order. The payment is retried up to three times, and inventory is updated in parallel with the receipt.*

**Text description**

**Participants:**

- Shop app, client
- Payments, service
- Inventory, service
- Email, service

**Steps:**

- 1. Shop app to Payments: Charge order
- loop: up to 3 attempts
  - 2. Payments to Payments: Call card network
  - 3. Payments to Shop app (dashed): Result
- Note over Shop app and Payments: A declined card stops the flow after the third attempt
- opt: payment accepted
  - par: update stock
    - 4. Payments to Inventory: Reserve items
  - and: send receipt
    - 5. Payments to Email: Receipt

## 4. Schema diagrams

A schema diagram shows database tables, their columns, and the relations between them.

| Statement | Form | Notes |
|---|---|---|
| Table | `table <name> sub="Detail" icon=lucide:table tone=aqua {`, then columns, then `}` | `sub`, `icon`, and `tone` are optional. |
| Column | `<name> <type> pk fk unique nullable note="Why"` | Flags and `note` are optional and may be combined. |
| Relation | `child.column -> parent.column : "label"` | Written from the referencing column to the referenced one. The label is optional; leaving it out keeps wide schemas narrower. |

A relation draws a crow's foot at the many end. It draws a single tick at the one end, and at both ends when the referencing column is `unique`.

**Diagram source**

```diagram
schema "Orders" desc="Orders belong to customers; each order has one invoice and many items."

table customers sub="People who buy" {
  id     uuid  pk
  email  text  unique
}

table orders {
  id           uuid         pk
  customer_id  uuid         fk
  placed_at    timestamptz
  note         text         nullable
}

table invoices {
  id        uuid  pk
  order_id  uuid  fk unique  note="One invoice per order"
}

orders.customer_id -> customers.id
invoices.order_id  -> orders.id
```

*Picture: Orders: 3 tables, 2 relations. Orders belong to customers; each order has one invoice and many items.*

**Text description**

**Tables:**

- customers
  - id uuid (primary key)
  - email text (unique)
- orders
  - id uuid (primary key)
  - customer_id uuid (foreign key)
  - placed_at timestamptz
  - note text (nullable)
- invoices
  - id uuid (primary key)
  - order_id uuid (foreign key, unique): One invoice per order

**Relations:**

- orders.customer_id references customers.id (many to one)
- invoices.order_id references orders.id (one to one)

## 5. Icons

Every node, actor, table, and group can carry one icon, set with `icon=<set>:<name>`. A group shows its icon in its corner tab.

| Set | Contents | Example |
|---|---|---|
| `lucide` | General icons | `icon=lucide:key-round` |
| `simple` | Technology and brand logos | `icon=simple:postgresql` |
| `status` | Colored outcome icons | `icon=status:success` |
| `aws`, `gcp`, `azure`, `alibaba`, `oci`, `ibm`, `cloudflare`, `digitalocean`, `vercel` | A provider and its products | `icon=aws:lambda`, `icon=gcp:bigquery`, `icon=azure:functions`, `icon=alibaba:oss` |

Find a name with the `search_icons` tool, or ask your agent to choose icons for you. Search matches ideas as well as names: `token exchange`, `validate`, `revoke`, `timeout`, and `bug` each find suitable icons. It also knows products: `lambda`, `s3`, `gke`, `cosmos db`, `bigquery`, and `serverless function` find the right provider icon first. The [icon reference](https://docs.plotwork.dev/reference/icons.md) shows every icon. A name that does not exist is an error with a suggestion, so a typo never renders as a blank space, and a guessed provider such as `amazon:s3` is pointed at `aws:s3`.

Status icons keep their own color on any node: green for good, red for bad, amber for caution, blue for information, and neutral for waiting. The full list, with meanings, is in the [language reference](https://docs.plotwork.dev/reference/language/icon-sets.md#status-icons).

**Diagram source**

```diagram
flow "Deployment pipeline" desc="A change is built, tested, and deployed. A failed test stops the pipeline." direction=down

node build  step "Build"        icon=status:success
node test   step "Test"         icon=status:error sub="2 failures"
node deploy step "Deploy"       icon=status:skipped
node notify step "Notify team"  icon=status:warning

build  -> test
test   -> deploy : "blocked"
test   --> notify : "failed"
```

*Picture: Deployment pipeline: 4 nodes, 3 connections. A change is built, tested, and deployed. A failed test stops the pipeline.*

**Text description**

**Nodes:**

- Build, step
- Test (2 failures), step
- Deploy, step
- Notify team, step

**Connections:**

- Build to Test
- Test to Deploy: blocked
- Test to Notify team (dashed): failed

### Cloud architecture

Name a product with its provider and its own name: `aws:lambda`, `gcp:pubsub`, `azure:entra-id`. Give the group that holds a cloud's resources `type=account` and its `provider=`, which draws the provider's own icon (`<provider>:cloud`), and nest a `type=region` group for each region. The [cloud architecture guide](https://docs.plotwork.dev/cloud-architecture.md) covers the whole recipe, and the icon pages ([AWS](https://docs.plotwork.dev/cloud-icons/aws.md), [Azure](https://docs.plotwork.dev/cloud-icons/azure.md), [Google Cloud](https://docs.plotwork.dev/cloud-icons/google-cloud.md)) draw every product. Where a provider publishes an official icon for a product, or has a licensed brand mark, the icon draws it; every other product draws the glyph for its kind of service, so a function looks like a function whichever cloud it runs on. The label says whose it is.

**Diagram source**

```diagram
flow "Multi-cloud order platform" desc="Orders enter through AWS, are stored and queued in one region, replicated to Google Cloud for analytics, while customers sign in through Azure." direction=down

node users client "Customers" sub="Web and mobile"

group aws "AWS" type=account provider=aws tone=orange {
  node cdn gateway "CloudFront" icon=aws:cloudfront
  group eu "eu-west-1" type=region {
    node api   gateway  "API Gateway"   icon=aws:api-gateway
    node fn    function "Order handler" icon=aws:lambda sub="Validates and stores"
    node db    database "Orders table"  icon=aws:dynamodb
    node queue queue    "Order events"  icon=aws:sqs
  }
}

group gcp "Google Cloud" type=account provider=gcp tone=blue {
  node feed      queue    "Event feed" icon=gcp:pubsub
  node analytics database "Analytics"  icon=gcp:bigquery
}

group azure "Azure" type=account provider=azure tone=violet {
  node sso identity "Sign-in" icon=azure:entra-id
}

users -> cdn   : "HTTPS"
cdn   -> api
api   -> fn
fn    -> db
fn    -> queue
queue -> feed  : "replicate"
feed  -> analytics
users -> sso   : "SSO"
```

*Picture: Multi-cloud order platform: 9 nodes, 8 connections. Orders enter through AWS, are stored and queued in one region, replicated to Google Cloud for analytics, while customers sign in through Azure.*

**Text description**

**Nodes:**

- Customers (Web and mobile), client
- Account: AWS
  - CloudFront, gateway
  - Region: eu-west-1
    - API Gateway, gateway
    - Order handler (Validates and stores), function
    - Orders table, database
    - Order events, queue
- Account: Google Cloud
  - Event feed, queue
  - Analytics, database
- Account: Azure
  - Sign-in, identity

**Connections:**

- Customers to CloudFront: HTTPS
- CloudFront to API Gateway
- API Gateway to Order handler
- Order handler to Orders table
- Order handler to Order events
- Order events to Event feed: replicate
- Event feed to Analytics
- Customers to Sign-in: SSO

## 6. Decisions and outcomes

A `decision` node is a tinted card with a branch icon. Label the outgoing edges with the answers. A label that is exactly `yes` or `true` gets a green tick, and `no` or `false` gets a red cross, without any extra syntax. Add `icon=` to an edge for another icon, or `icon=none` to remove the automatic one. A `terminal` node is a pill, and it can carry a status icon for the outcome.

**Diagram source**

```diagram
flow "Review outcome" desc="A pull request is approved or sent back for changes." direction=down

node pr      step     "Pull request opened"
node review  decision "Does the change pass review?"
node merge   terminal "Merged"        icon=status:success
node changes terminal "Changes asked" icon=status:retry

pr     -> review
review -> merge   : "yes"
review -> changes : "no"
```

*Picture: Review outcome: 4 nodes, 3 connections. A pull request is approved or sent back for changes.*

**Text description**

**Nodes:**

- Pull request opened, step
- Does the change pass review?, decision
- Merged, terminal
- Changes asked, terminal

**Connections:**

- Pull request opened to Does the change pass review?
- Does the change pass review? to Merged: yes
- Does the change pass review? to Changes asked: no

## 7. Numbered steps

Add `numbered=on` to the header of a flow or a sequence diagram and every line gets a numbered badge, counting in the order the lines are written. In a sequence diagram the badge sits on the message, and the messages inside `alt`, `opt`, `loop`, and `par` blocks are numbered in the order they are read. In a flow diagram it sits on the connection. Use it for a procedure, a protocol, or a runbook, where a reader says "step 4" aloud.

| Where | Option | What it does |
|---|---|---|
| Header | `numbered=on` | Numbers every line, starting at 1. |
| Header | `start=5` | Starts at 5 instead. A whole number from 0 to 999, and it needs `numbered=on`. |
| One line | `step=off` | Draws no badge on this line, and uses up no number. |
| One line | `step=12` | Gives this line the number 12. The lines after it continue from 13. |

A `step=` on a line of a diagram that is not numbered is an error, and so is a count that runs past 999. A sequence diagram:

**Diagram source**

```diagram
sequence "Sign in with an emailed code" numbered=on desc="A user asks for a code, receives it by email, and trades it for a session. Each message carries its step number."

actor user person  "User"
actor web  client  "Web app"
actor api  service "Auth API"
actor mail service "Email"

user -> web  : "Enter email"
web  -> api  : "Request code"
api  -> mail : "Send the code"
mail --> user : "Email arrives"
user -> web  : "Type the code"
web  -> api  : "Verify code"
api  --> web : "Session cookie"
```

*Picture: Sign in with an emailed code: 4 participants. A user asks for a code, receives it by email, and trades it for a session. Each message carries its step number.*

**Text description**

**Participants:**

- User, person
- Web app, client
- Auth API, service
- Email, service

**Steps:**

- 1. User to Web app: Enter email
- 2. Web app to Auth API: Request code
- 3. Auth API to Email: Send the code
- 4. Email to User (dashed): Email arrives
- 5. User to Web app: Type the code
- 6. Web app to Auth API: Verify code
- 7. Auth API to Web app (dashed): Session cookie

A flow diagram, where the number sits on each connection:

**Diagram source**

```diagram
flow "Release steps" numbered=on direction=down desc="A change is pushed, built, published as an image, and deployed. Each connection carries its step number."

node dev  person   "Developer"
node git  service  "Git host"
node ci   service  "CI"
node reg  storage  "Registry"
node prod service  "Production"

dev -> git  : "Push"
git -> ci   : "Trigger build"
ci  -> reg  : "Publish image" icon=lucide:upload
ci  -> prod : "Deploy"
```

*Picture: Release steps: 5 nodes, 4 connections. A change is pushed, built, published as an image, and deployed. Each connection carries its step number.*

**Text description**

**Nodes:**

- Developer, person
- Git host, service
- CI, service
- Registry, storage
- Production, service

**Connections:**

- 1. Developer to Git host: Push
- 2. Git host to CI: Trigger build
- 3. CI to Registry: Publish image
- 4. CI to Production: Deploy

## 8. Animated lines

Add `animate=on` to the header of a flow or a sequence diagram and every line that has an arrowhead gets moving dashes that travel toward the head. It shows which way data or control goes, which suits a pipeline or a request path. To animate one line only, write `animate=on` on that line. To keep one line still while the header animates the rest, write `animate=off` on it.

| Rule | What happens |
|---|---|
| `animate=on` in the header | Every line with an arrowhead moves. A `--` line has no arrowhead, so it stays still. |
| `animate=off` on a line | That line stays still, whatever the header says. |
| `animate=on` on a `--` line | An error, because dashes travel toward an arrowhead and the line has none. Use `->`, or remove the option. |
| A line with two arrowheads (`<->`) | It moves from its first end to its second. |

The motion is part of the SVG, so it moves wherever a browser shows the SVG as an image, including a README on GitHub and this page. It stays still in a PNG and in a reader that flattens the SVG into a picture, and it is switched off when the reader asks for reduced motion in their system settings. The picture means the same thing without it, so never rely on motion to say something that the text does not.

**Diagram source**

```diagram
flow "Events into the warehouse" animate=on direction=down desc="Events flow from an app through an API and a queue to a processor, which stores them. The acknowledgement is drawn still."

node app    client   "Mobile app"
node api    gateway  "Events API"
node queue  queue    "Event queue"
node worker function "Processor"
node db     database "Warehouse"

app    -> api    : "POST /events"
api    -> queue  : "enqueue" role=async
queue  -> worker : "consume" role=async
worker -> db     : "store" role=data
worker --> api   : "ack" animate=off
```

*Picture: Events into the warehouse: 5 nodes, 5 connections. Events flow from an app through an API and a queue to a processor, which stores them. The acknowledgement is drawn still.*

**Text description**

**Nodes:**

- Mobile app, client
- Events API, gateway
- Event queue, queue
- Processor, function
- Warehouse, database

**Connections:**

- Mobile app to Events API: POST /events
- Events API to Event queue (asynchronous line): enqueue
- Event queue to Processor (asynchronous line): consume
- Processor to Warehouse (stored data line): store
- Processor to Events API (dashed): ack

## 9. Fitting text

Text never overflows its box, and padding stays the same on every box.

| Situation | What happens |
|---|---|
| A label is longer than a card | It wraps onto more lines, up to three, and the card grows taller. |
| One word is longer than a card | The card widens to hold it, up to 400px. |
| Text is still too long | It is cut with an ellipsis and the diagram gets warning `W203`. The full text stays in the text description. |
| A group name is long | The corner tab grows to fit it on one line, up to the width of the widest card (400px). Past that the name is cut with an ellipsis and warning `W203`. |
| A message label is long in a sequence diagram | The columns spread apart to make room, and `W202` appears if the diagram then becomes too wide. |

The fix for a warning is almost always shorter text. Move detail into `sub=`, a note, or the prose around the diagram.

## 10. Quality warnings

Warnings never stop rendering. They point at things a reader will notice.

| Code | Meaning | Fix |
|---|---|---|
| `W200` | Too many nodes, tables, or actors | Split along a group boundary or by domain. |
| `W201` | A node is not connected to anything | Connect it or remove it. |
| `W202` | The diagram is wider than a Markdown column and its text would shrink | Use `direction=down`, shorten labels, or split it. |
| `W203` | Text was cut with an ellipsis, in a node, an actor, or a group name | Shorten the text. |
| `W204` | A node has no `icon=`, and its label names one product | Add the `icon=` the warning gives, or write `icon=none`. |
| `W205` | A group has no `type=`, and its name matches one group type | Add the `type=` the warning gives. |

## See also

| Doc | Why |
|---|---|
| [Cloud architecture](https://docs.plotwork.dev/cloud-architecture.md) | Typed groups, provider icons, and how to map a product name to an icon |
| [Architecture patterns](https://docs.plotwork.dev/architecture-patterns.md) | Ready-made, checked diagrams to start from |
| [Language reference](https://docs.plotwork.dev/reference/language.md) | Every type, tone, icon, arrow, and diagnostic code |
| [Writing diagrams with an agent](https://docs.plotwork.dev/mcp/agent-loop.md) | The validate and fix loop |
| [Diagrams in Markdown and on GitHub](https://docs.plotwork.dev/markdown-and-github.md) | Putting diagrams in a document |
| [How a diagram is drawn](https://docs.plotwork.dev/how-it-works.md) | What happens between your text and the picture |
