Get the FREE Ultimate OpenClaw Setup Guide →

creating-c4-diagrams

Scanned
npx machina-cli add skill msewell/agent-stuff/creating-c4-diagrams --openclaw
Files (1)
SKILL.md
8.7 KB

Creating C4 Diagrams

Workflow: Creating a C4 diagram

  1. Identify the audience and scope. Determine which diagram level is needed:

    • Level 1 — System Context: How the system fits into the world. Always create this first.
    • Level 2 — Container: Major technical building blocks and communication. Always create this second.
    • Level 3 — Component: Internal structure of a single container. Create only when it adds value.
    • Dynamic: Runtime behavior for a specific use case. Create for complex or non-obvious flows.
    • Deployment: How containers map to infrastructure. Create for production systems.
    • Skip Level 4 (Code) — auto-generate from IDE instead.
  2. Choose the tool.

    • Default: Structurizr DSL — model-first, single model with multiple views, supports all diagram types. Use for any long-lived architecture documentation.
    • Alternative: Mermaid — use only for quick diagrams in Markdown files (READMEs, PRs, wikis). Limited to Context and Container levels; no dynamic or deployment diagrams.
  3. Identify the elements. Map the system to C4 abstractions:

    • Person: A human user role.
    • Software System: A top-level system owned and deployed by one team.
    • Container: A separately deployable/runnable unit (app, database, queue, function). NOT a Docker container.
    • Component: A module/package within a container. Not separately deployable.
    • Apply the test: "Does this need to be running for the system to work?" → Yes = Container. No = Component.
  4. Define relationships. Every arrow must have:

    • A specific action verb label: "Submits purchase orders to", "Reads customer records from", "Publishes OrderCreated events to"
    • A technology annotation for inter-process communication: HTTPS/JSON, gRPC, SQL/TCP, AMQP
    • Unidirectional direction only — never use bidirectional arrows. Draw two separate arrows instead.
    • Use the pattern: [Action verb] + [what] + [preposition]
    • Avoid weak verbs: Uses, Calls, Connects, Talks, Accesses.
  5. Write the diagram code. Follow these rules:

    • Every element gets: name, type label, technology (containers/components), one-sentence responsibility.
    • Every diagram gets: title describing type and scope, key/legend, max ~20 elements.
    • Tag external systems with "External". Use tags for styling, not per-element styles.
    • In Structurizr DSL: always use !identifiers hierarchical.
    • In Mermaid: use C4Context or C4Container as diagram type.
  6. Validate against the review checklist. Check all items in references/08-checklists.md.

Workflow: Reviewing an existing C4 diagram

  1. Check abstraction correctness:

    • Are containers actually separately deployable? (shared libraries are components, not containers)
    • Are system boundaries aligned with team ownership?
    • Is the message broker modeled as individual topics/queues, not a single hub?
    • Are external systems shown as opaque boxes without internal details?
  2. Check notation quality:

    • Does every element have a name, type label, technology, and description?
    • Are all arrows unidirectional with specific action-verb labels?
    • Are communication protocols specified on inter-process arrows?
    • Is there a title, legend, and ≤20 elements?
  3. Check for common anti-patterns: vague "Uses"/"Calls" labels, bidirectional arrows, missing type metadata, color as only differentiator, 30+ elements in one diagram, invented abstraction levels. See references/03-anti-patterns.md for the full catalog.

  4. Propose specific fixes with corrected code.

Workflow: Using C4 diagrams as context

When C4 diagrams are available in the project (.dsl files or Mermaid blocks), use them as architectural context for:

  • Design decisions: Reference the container diagram to understand system boundaries and communication patterns before proposing changes.
  • Code generation: Use component diagrams to understand module responsibilities and interfaces when generating implementation code.
  • Risk analysis: Walk the container diagram to identify security boundaries, data flows, and single points of failure. See references/05-adr-and-risk-modeling.md.
  • Onboarding explanations: Start with Level 1 (context), then zoom into Level 2 (containers) to explain system architecture.
  • ADR context: Link architectural decisions to specific C4 elements. Reference ADRs in element descriptions.

Structurizr DSL quick reference

workspace "Name" "Description" {
    !identifiers hierarchical

    model {
        user = person "User" "Description."
        system = softwareSystem "System" "Description." {
            webapp = container "Web App" "Description." "React"
            api = container "API" "Description." "Go"
            db = container "Database" "Description." "PostgreSQL" { tags "Database" }
        }
        ext = softwareSystem "External" "Description." { tags "External" }

        user -> system.webapp "Browses via" "HTTPS"
        system.webapp -> system.api "Makes API calls to" "HTTPS/JSON"
        system.api -> system.db "Reads from and writes to" "SQL/TCP"
        system.api -> ext "Sends requests to" "HTTPS/JSON"
    }

    views {
        systemContext system "Context" { include *; autoLayout }
        container system "Containers" { include *; autoLayout }
        styles {
            element "Person" { shape person }
            element "Database" { shape cylinder }
            element "External" { background #999999; color #ffffff }
        }
    }
}

Mermaid quick reference

C4Context
    title System Context Diagram for My System
    Person(user, "User", "Description.")
    System(system, "My System", "Description.")
    System_Ext(ext, "External System", "Description.")
    Rel(user, system, "Browses via", "HTTPS")
    Rel(system, ext, "Sends requests to", "HTTPS/JSON")
C4Container
    title Container Diagram for My System
    Person(user, "User", "Description.")
    Container_Boundary(system, "My System") {
        Container(webapp, "Web App", "React", "Serves the UI.")
        Container(api, "API", "Go", "Handles business logic.")
        ContainerDb(db, "Database", "PostgreSQL", "Stores data.")
    }
    Rel(user, webapp, "Browses via", "HTTPS")
    Rel(webapp, api, "Makes API calls to", "HTTPS/JSON")
    Rel(api, db, "Reads from and writes to", "SQL/TCP")

Key decisions

  • Microservices owned by one team → model as containers within one software system.
  • Microservices owned by separate teams → promote each to its own software system.
  • Event-driven → model individual topics/queues as containers, not the broker.
  • Serverless functions → model as containers (they are separately deployable).
  • Component diagrams → create only for complex containers; skip for simple microservices.

Reference material

Source

git clone https://github.com/msewell/agent-stuff/blob/main/skills/creating-c4-diagrams/SKILL.mdView on GitHub

Overview

This skill lets you create, review, and interpret C4 software architecture diagrams across System Context, Container, Component, Dynamic, and Deployment levels. It outputs diagram code in Structurizr DSL by default or Mermaid for quick Markdown diagrams, following formal C4 best practices. Use it to craft architecture docs, assess existing diagrams for correctness and anti-patterns, and provide context for design decisions, code generation, risk analysis, or onboarding.

How This Skill Works

Start by identifying the audience and the appropriate diagram level, then pick Structurizr DSL (default) or Mermaid (for quick READMEs). Map elements to C4 abstractions (Person, Software System, Container, Component), define unidirectional relationships with concrete action verbs and a technology annotation, and annotate every element with a concise responsibility. Generate the diagram code with a descriptive title and legend, keeping the total element count near 20.

When to Use It

  • Starting a new system architecture by documenting System Context and Container diagrams
  • Reviewing an existing C4 diagram for correctness and anti-patterns
  • Generating a Structurizr DSL workspace for long-lived architecture documentation
  • Producing Mermaid C4 diagrams for READMEs, PRs, or wikis
  • Using C4 diagrams as context for design decisions, code generation, risk analysis, or onboarding

Quick Start

  1. Step 1: Decide level and audience (System Context, Container, etc.) and choose Structurizr DSL by default or Mermaid for quick visuals
  2. Step 2: Map elements to C4 abstractions (Person, Software System, Container, Component) and define unidirectional relationships with action verbs and technology labels
  3. Step 3: Generate the code, add a descriptive title and legend, and review to keep ≤20 elements

Best Practices

  • Define audience and scope before diagramming
  • Prefer Structurizr DSL for long-lived documentation; use Mermaid for quick visuals
  • Map elements to C4 abstractions with a concise one-sentence responsibility
  • Use unidirectional arrows with specific action verbs and a technology annotation
  • Keep diagrams to around 20 elements and tag external systems with 'External'

Example Use Cases

  • System Context diagram for a fintech app showing user roles, the core system, and an external payment gateway
  • Container diagram for a microservices platform mapping services, data stores, and a message broker
  • Dynamic diagram illustrating a checkout flow with event-driven interactions between services
  • Deployment diagram mapping containers to cloud infrastructure (servers, networks, and runtimes)
  • Onboarding example: a generated Structurizr DSL workspace used to bring new engineers up to speed

Frequently Asked Questions

Add this skill to your agents

Related Skills

arazzo-specification

msewell/agent-stuff

Guides writing, reviewing, and modifying Arazzo workflow specifications (OpenAPI Initiative standard for multi-step API workflows). Use when creating Arazzo documents from scratch, adding steps or workflows to existing specs, reviewing Arazzo files for correctness, or generating API workflow definitions. Covers document structure, runtime expressions, success criteria, control flow, data threading, reusable components, workflow composition, AI agent integration, and validation.

kotlin-functional-programming

msewell/agent-stuff

Guides writing idiomatic, functional-style Kotlin code using built-in language features. Use when asked to write, review, or refactor Kotlin code for immutability, pure functions, sealed types, error handling, collections, coroutines, or functional architecture patterns.

property-based-testing-with-kotest

msewell/agent-stuff

Writes property-based tests using Kotest's kotest-property module. Identifies testable properties, designs generators, and configures PBT for Kotlin/JVM projects. Use when writing property-based tests, creating custom Arb generators, choosing property patterns (roundtrip, invariant, idempotence, oracle), debugging shrunk counterexamples, or integrating PBT into a Kotlin test suite alongside example-based tests.

reducing-coupling

msewell/agent-stuff

Analyzes a codebase scope for coupling issues, diagnoses coupling types using the Connascence framework, and proposes a comprehensive refactoring plan with concrete code changes. Use when asked to find coupling, reduce dependencies, decouple modules, or improve modularity in a codebase.

mermaid-sequence-diagrams

msewell/agent-stuff

Generates, reviews, and fixes Mermaid sequence diagrams following syntax rules and best practices. Use when creating sequence diagrams from system descriptions, reviewing existing Mermaid sequence diagrams for correctness, fixing parse errors, or refactoring large diagrams into focused sub-diagrams. Covers participants, arrows, activations, control flow, notes, styling, and common anti-patterns.

making-invalid-states-unrepresentable

msewell/agent-stuff

Analyzes existing code and guides new type design to make invalid states unrepresentable using type system techniques such as sum types, newtypes, typestate, branded types, and parse-don't-validate. Use when reviewing code for invalid-state bugs, refactoring types to eliminate impossible states, designing domain models, or applying compile-time correctness patterns. Language-agnostic.

Sponsor this space

Reach thousands of developers