# yUML DSL Reference (v1) yUML is a text-based diagramming language. Each diagram type has its own syntax. Metadata lines (`@heading`, `@caption`, `@legend`, `@direction`, `@style`) can appear anywhere in any diagram type. This file is the **canonical source of truth** for the AI-friendly DSL reference. It is read by: - `/dsl/v1/spec` and `/dsl/v1/spec.txt` (public docs endpoint on app.yuml.me) - `Ai::FixDsl` service (Fix-with-AI system prompt in the Rails web app) - The MCP server's `render_diagram` / `render_story` tool descriptions Formal grammars live in `renderer/src/*.pegjs` and are the ultimate authority on what parses. This file is the human-and-LLM-friendly narrative — keep it in sync when grammar changes. Public URL: https://app.yuml.me/dsl/v1/spec.txt ## Styles Available styles: `clean`, `plain`, `boring`, `sketch`, `scruffy`, `napkin`, `midnight`, `blueprint`. Set via `@style ` in stories or as a render option. ## Layout direction Most diagram types lay out top-to-bottom by default. The **use case** diagram is the exception — it goes left-to-right. Override with `@direction` in the DSL: ``` @direction LR — left-to-right @direction TB — top-to-bottom (alias: TD, DOWN) [A]->[B] [B]->[C] ``` Accepted values (case-insensitive): `LR` / `RIGHT`, `TB` / `TD` / `DOWN`. Direction has no effect on types whose layout is intrinsic to the type — sequence, journey flow, timeline, roadmap, and the chart family (bar, column, line, pie). When rendering via the URL API you can also pass direction as a modifier on the style segment instead of editing the DSL: ``` /diagram/v1/class/clean;dir=LR/[A]->[B],[B]->[C].svg ``` `@direction` and `;dir=…` are equivalent. If both are present, the URL modifier wins. ## Forced line breaks A literal `\n` (backslash + the letter n) in the DSL becomes a forced line break in the rendered text. Soft-wrapping still applies to each segment, so `\n` is a *guaranteed* break, not a substitute for wrapping. Supported in: - `@heading` and `@caption` (any diagram type) - Class-diagram labels and notes — e.g. `[note: First line\nSecond line]` - Canvas titles, sub-titles, `>` help text, prose, and bullets Example: ``` @heading Quarterly Review\nSWOT [note: Recalculated\non every change]-[Order] ``` ## Class Diagrams ``` [ClassName] — class [ClassName|attr1;attr2] — with attributes [ClassName|attr1;attr2|method()] — with methods [<>;Name] — stereotype [note: text{bg:wheat}] — note [A]->[B] — directed association [A]<->[B] — bidirectional [Parent]^[Child] — inheritance — the side adjacent to ^ is the PARENT [A]<>[B] — aggregation [A]++->[B] — composition [A]-.->[B] — dependency (dashed) [A]^-.-[B] — implements (dashed inheritance) [A]label->[B] — labelled [A]1-0..*>[B] — cardinality // comment ``` Example: ``` [Customer|name;email]-orders>*[Order|date;total] [Order]->*[LineItem|qty;price] [LineItem]->[Product|name;sku;price] ``` Inheritance direction — the parent is on the **left** of `^`. So `[Animal]^[Duck]` means Duck inherits from Animal. Mirror this when translating from Mermaid (`Animal <|-- Duck` becomes `[Animal]^[Duck]`) or PlantUML (`Animal <|-- Duck` becomes `[Animal]^[Duck]`). ``` [Animal|age;gender|isMammal();mate()] [Animal]^[Duck|beakColor|swim();quack()] [Animal]^[Fish|sizeInFeet|canEat()] [Animal]^[Zebra|isWild|run()] ``` ## Sequence Diagrams ``` [Object] — participant (box) — on its own line declares; in a message it references (Actor) — participant (stick figure) — on its own line declares; in a message it references [A]message->[B] — sync message [A]message-->[B] — return message (dashed) [A]message->>[B] — async message {alt condition} ... {else} ... {end} — alt fragment {loop condition} ... {end} — loop fragment {opt condition} ... {end} — optional fragment [note: text]->[A] — note on participant ``` Example: ``` (User)Login->[Auth] [Auth]validate->[Auth] [Auth]checkCredentials->[DB] [DB]result-->[Auth] {alt valid} [Auth]token-->(User) {else} [Auth]error-->(User) {end} ``` ## Activity Diagrams ``` (Activity Name) — activity (rounded box) (start) — start node (end) — end node — decision diamond |Fork| — fork/join bar (A)->(B) — flow (A)label->(B) — labelled flow (A)[guard]->(B) — guarded flow (note: text) — note ``` Example: ``` (start)->(Receive Order) (Receive Order)-> [yes]->(Process) [no]->(Reject) (Process)->(end) (Reject)->(end) ``` ## Use Case Diagrams ``` [Actor Name] — actor (stick figure) (Use Case Name) — use case (ellipse) [A]-(B) — association (A)<(B) — extends (A)>(B) — includes (A)^(B) — inheritance ``` Example: ``` [Customer]-(Place Order) [Customer]-(Track Order) (Place Order)>(Validate Payment) (Track Order)<(Cancel Order) [Admin]-(Manage Inventory) ``` ## State Diagrams ``` [State Name] — state (rounded rect) (start) — initial state (end) — final state — choice diamond [A]->[B] — transition [A]-event->[B] — event transition [A]-event[guard]->[B] — guarded transition [A]-event[guard]/action->[B] — with action [note: text] — note ``` Example: ``` (start)->[Idle] [Idle]-login->[Active] [Active]-logout->[Idle] [Active]-timeout[inactive > 30m]->[Expired] [Expired]->[Idle] ``` ## C4 Architecture Diagrams A single `c4` diagram type covers Context, Container, Component and System Landscape views — they use the same notation. ``` [Name|Type|Description] — element with type + description [Name|Type] — element with type, no description [Name] — untyped element ``` Recognised element types (case-insensitive, with common aliases): - `Person` — also `User`, `Actor`, `Role`, `Customer`, `Admin` - `System` — also `Software System`, `Platform` - `Container` — also `Application`, `Web App`, `Service`, `Microservice`, `API`, `Database`, `Queue`, `Message Bus`, `Worker`, `Function` - `Component` — also `Module`, `Package`, `Library`, `Subsystem` - `External` — also `External System`, `External Service`, `Third Party`, `Vendor`, `SaaS` Edges: ``` [A]->[B] — solid arrow [A]-.->[B] — dashed arrow (any `.` in the dash run → dashed) [A]-Uses->[B] — middle label (solid) [A]-Sends mail via-.->[B] — middle label (dashed) [A]<->[B] — bidirectional [A]->[B] : Uses — colon label (alternative) ``` Boundaries group elements inside a dashed frame: ``` {Banking System [Web App|Container|Browser UI] [API|Container|REST endpoints] [DB|Container|Data store :database:] } ``` Decorator shortcodes inside descriptions trigger strip visuals on the card (database cylinder, browser chrome, mobile status bar, etc.): `:database:`, `:browser:`, `:mobile:`, `:queue:`, `:folder:`, `:document:`, `:console:`. Metadata: ``` @heading My Banking Architecture @caption System Context view @legend true @direction LR ``` Example: ``` @heading Banking System Context @legend true [Customer|Person|A user of the bank] [Banking System|System|Core system for accounts and payments] [Email Service|External|Third-party transactional email] [Customer]-Uses->[Banking System] [Banking System]-Sends mail via-.->[Email Service] ``` ## Journey Flow Diagrams Uses activity diagram syntax with emotions for customer journey mapping. ``` (Phase Name) — journey phase/section header [:emotion: Action text] — step with emotion [:emotion: "Quote text"] — speech bubble with emotion [Action text] — step without emotion -> — flow arrow (optional) ``` Emotions: `:elated:` `:happy:` `:relieved:` `:neutral:` `:uncertain:` `:frustrated:` `:angry:` Example: ``` (Discover)-> [:happy: Finds product online]-> [:happy: "This looks promising"]-> (Evaluate)-> [:neutral: Reads reviews]-> [:uncertain: "Is it worth the price?"]-> (Purchase)-> [:frustrated: Complex checkout form]-> [:elated: Order confirmed] ``` ## Timeline Diagrams Uses activity diagram syntax for milestones. ``` (Title|Subtitle|Details) — major milestone (3 parts) (Title|Subtitle) — major milestone (2 parts) (Title) — major milestone (title only) [Event text] — minor milestone -> — flow arrow (optional) ``` Example: ``` (Q1|Research|Interviewed 50 users)-> [Team assembled]-> (Q2|Beta launch)-> [First paying customer]-> (Q3|Public release) ``` ## Roadmap Diagrams ``` (Horizon Name) — horizon/column header [Card Title|Description] — feature card [Card Title] — card without description [Card{bg:color}] — coloured card ``` Example: ``` (Now) [Search improvements|Full-text search] [Bug fixes|Top 10 issues] (Next) [Mobile app|iOS and Android] [API v2|REST and GraphQL] (Future) [AI features{bg:green}] [Enterprise SSO] ``` ## Canvas Diagrams Canvases are structured 2D thinking grids — Strategy Choice Cascade, SWOT, retros, OKRs, post-mortems, or any custom frame. The DSL is markdown- flavoured. ``` @type canvas — required type metadata @cols N — top-level grid width (optional) # Region Title — top-level region ## Sub Region — sub-region of the most recent # > Custom help text — blockquote overrides canonical help Prose body… — body lines (prose or bullets) - bullet — `* ` or `- ` starts a bullet # Region {cols: 2} — sub-grid layout override # Region {span: 2} — width weight within its row # Region {bg: cream} — fill that cell # Region {!} — accent: tint title + body ``` A `#` section with at least one `##` child renders as a group containing sub-boxes; otherwise it renders as a single box with its body content. Bullets are content, not regions. Decorators chain with `;` — `{cols: 2; bg: cream; !}`. A literal `\n` forces a break inside any title, sub-title, `>` help line, prose paragraph, or bullet — see [Forced line breaks](#forced-line-breaks). ### Auto-detected templates When section names match a known framework, the renderer applies the template automatically: canonical help text appears under each heading (muted subtitle), missing canonical sections are inserted as dashed- inset placeholders, and the layout shape is hinted (e.g. SWOT → 2×2). Detection is fuzzy and case-insensitive. Aliases: ``` Strategy Choice Cascade — vertical stack of regions Aspiration / Winning Aspiration Where to Play — 4 sub-regions: Geography Customer / Customer Segments Channels Offering / Products How to Win Capabilities / Must-Have Capabilities Management Systems / Systems SWOT Analysis — 2×2 quadrant Strengths Weaknesses Opportunities Threats ``` ### Layout - `@cols N` (canvas-level): how many top-level cells per row. Default 1 (vertical stack), or template default, or heuristic (even-and-≥4 → N/2). - `{cols: N}` (on a heading with sub-regions): sub-grid width inside that group. - `{span: N}` (on any heading): weight within its row. Default 1; `{span: 2}` is twice as wide as a default sibling. - Empty cells (no body, no children) render as dashed-inset placeholders — same treatment whether auto-inserted or written empty by the user. ### Examples Strategy Choice Cascade — auto-detected, canonical help text supplied: ``` @type canvas # Aspiration Launch a successful startup that helps people build their face-to-face network and relationships without compromising privacy. # Where to Play ## Geography Initially focus on saturating specific events in a single town, then global product. ## Customer Anyone doing networking — hobbyist artists to business folks. ## Channels Organic makes most sense. ## Offering Privacy-first way of sharing always-up-to-date contact details at networking events. # How to Win ??? # Capabilities - Privacy-by-design contact format - Event partnerships # Management Systems - KPI: subscription revenue to £30K ARR - KPI: k-factor for card shares - KPI: after-event conversations ``` SWOT — 2×2 layout from the template: ``` @type canvas # Strengths Deep ML expertise; existing customer base of 200 SMBs. # Weaknesses - Limited marketing budget - Single-region presence # Opportunities > Where could we grow? (overrides canonical help) Enterprise demand for privacy-first tools is accelerating. # Threats Big-tech entrants with bundled offerings. ``` Custom canvas without a template — author supplies help via blockquote: ``` @type canvas @cols 2 # What worked > Highlights from this sprint - Shipped onboarding redesign - Cut p95 latency by 40% # What didn't > Rough edges - Demo broke in staging twice - Search relevance regression # Surprises - 3 enterprise leads from a tweet # Next sprint - Re-run onboarding A/B - Latency budgets per service ``` Guidelines for AI canvas generation: - Prefer canonical section names so templates auto-apply (Aspiration, Where to Play, Strengths, etc.) — gets help text and layout for free. - Use `>` blockquote help text only for *non-template* sections, or to override the canonical when a domain-specific framing is needed. - Reach for `{bg}` sparingly — it draws the eye; one or two cells max. - Use `{!}` to mark a single most-important region. - Leave a region empty (just heading + optional `>` help) when the user is mid-thinking — the dashed placeholder invites filling-in. ## Causal Loop Diagrams Causal loop diagrams (CLDs) show how variables in a system reinforce or balance one another. Polarity lives in the arrow. ``` @type causal-loop — required type metadata A -+> B — A increases B (positive / same-direction) A --> B — A increases B's *opposite* (negative) A -+> B --> C — chain: two links sharing node B Name (bad) — flag an undesirable variable Name (good) — default; rarely needed explicitly {Zone Name — group related variables Member 1 Member 2 } // comment ``` Conventions: - **Spaces around the operator are required**: write `A -+> B`, not `A-+>B`. Multi-word names with internal hyphens (`Tech-debt`) stay unambiguous because of the surrounding whitespace. - **`-+>` vs `-->`**: `-+>` means "as A goes up, B goes up" (or both down). `-->` means "as A goes up, B goes *down*". Never use a bare `->` — that is a syntax error. - **Value tags** `(good)` / `(bad)` are optional after any node name. `(good)` is the implicit default — only flag `(bad)` when a variable represents something undesirable (Burnout, Bugs shipped, Tech debt). - **Bare lines** declare or retag a variable without creating a link: `Churn (bad)` on its own line just marks Churn as bad. - **Zones** are visual groupings; a zone is opened with `{Name` on its own line and closed with `}`. Members listed on their own lines (or declared via links inside the zone) become part of it. - **Loop type is derived** at layout time from the parity of negative links around a cycle and any `(bad)` tags — you don't tag loops as reinforcing/balancing yourself. Example — burnout cycle: ``` @type causal-loop @heading Burnout cycle {People Burnout (bad) Decision quality Hours worked } {Output Bugs shipped (bad) Customer complaints (bad) } Hours worked -+> Burnout --> Decision quality --> Bugs shipped -+> Customer complaints -+> Hours worked ``` Example — SaaS referral with saturation: ``` @type causal-loop Happy customers -+> Referrals -+> New signups -+> Happy customers New signups -+> Market saturation --> New signups ``` Guidelines for AI causal-loop generation: - Aim for 4–8 variables and 1–3 loops. CLDs become unreadable past ~10 variables. - Name variables as nouns or short noun phrases ("Customer complaints", not "Customers complain"). - Mark only the genuinely undesirable variables with `(bad)`. Don't tag everything. - Use chains (`A -+> B --> C`) to keep loops on one line — easier to read than three separate `A -+> B` / `B --> C` / `C -+> A` lines. - Use zones when the user describes distinct sub-systems (People vs Output, Customer vs Internal, etc.). ## Chart Diagrams Charts render numeric data as visualisations. Five types share the same syntax shape: `bar`, `column`, `line`, `pie`, and `chart` (auto-pick — the renderer picks the best fit from the data). ``` @heading — optional title @caption <subtitle> — optional caption Label: value — value can be number, tally, or percentage Label: 100 — number Label: ||||| — tally marks (count = number of bars) Label: 72% — percentage Label{!}: value — accent / highlight Label{bg:wheat}: value — custom bar background tint // comment ``` Charts ignore `@direction` — bar is horizontal, column is vertical, line is left-to-right time series, pie is radial. ### Bar — horizontal bars Best for tally counts, survey responses, votes. Tally marks (`|||`) or numbers both work. Tally marks render as a count of glyphs. ``` @heading Fruit bowl census Apples: ||||| Pears: ||||||| Bananas: ||| Plums: |||||||||| ``` ### Column — vertical bars Best for category comparisons (quarters, months, products). ``` @heading Quarterly revenue Q1: 100 Q2: 120 Q3: 140{!} Q4: 160 ``` ### Line — time series Best for trends over time. Labels typically dates or sequential periods; values are numbers. ``` @heading Monthly active users 2025-01: 120 2025-02: 135 2025-03: 128 2025-04: 142 2025-05: 155 2025-06: 170 ``` ### Pie — proportions Best for parts-of-a-whole. Values can be percentages (must sum to ~100) or raw numbers (renderer normalises). ``` @heading Sprint status Done: 72% In progress: 18% Blocked: 10% ``` ### Chart — auto-picked type When the diagram type isn't specified, the renderer picks from the data shape: dated labels → line, percentages → pie, short numeric labels (Q1, Jan) → column, tally marks → bar. ``` // no @type — yUML picks bar/column/line/pie from the data shape Q1: 100 Q2: 120 Q3: 140 Q4: 160 ``` Guidelines for AI chart generation: - Pick a specific type (`bar`/`column`/`line`/`pie`) when the user's intent is clear; reach for `chart` only when ambiguous. - Tally marks suit small whole-number counts (≤ 12-ish). Use numbers for larger values. - Percentages should sum to ~100 in pies. If the user gives raw counts, leave them — the renderer handles the maths. - Use `{!}` on a single most-important bar/column to draw attention. ## Story Format Stories are markdown documents with embedded yUML diagrams. ```` @style blueprint — global style (applies to all diagrams) @direction LR — global direction # Slide Title — starts a section Prose text in **markdown**. — rendered as styled text ```yuml class — diagram block (type after "yuml") @heading Diagram Title — optional heading @caption Description — optional caption [A]->[B] ``` --- — slide separator # Next Slide ... ```` Guidelines for AI story generation: - Start with a high-level overview, then progressively reveal detail - Each slide should have a heading, 1-2 sentences of prose, and one diagram - Use different diagram types to show different perspectives (class for structure, sequence for behaviour, journey for UX, c4 for systems) - Keep individual diagrams focused — 3-7 elements each, not comprehensive - Use `@heading` on diagrams to label what aspect they show ## Common mistakes to avoid - Missing closing `]` or `)` on the last element - Unbalanced `{ }` boundary braces - Wrong arrow for the diagram type — respect the target type's arrow set - Extra or missing pipes in `[Name|Type|Desc]` (c4) or `[Name|attrs|methods]` (class) - Quoting names that don't need quotes — the grammar is liberal about names