← Blog

2026.10.26 · 3 min · docker · tooling · open source

Your Compose file is already a diagram.

compviz reads a compose.yaml and draws the architecture: services become nodes, depends_on becomes edges, and the customisation lives in the same file as standard Compose labels, so it still runs with docker compose. How it reads the file, what it matches, and what it deliberately doesn't do.

Hand-drawn architecture diagrams go stale the day the stack changes. Someone adds a queue, nobody opens the drawing tool, and the README now describes a system that no longer exists. But the stack is already described somewhere precise: the Compose file that runs it. compviz draws the picture from that file, so the diagram is as current as the code.

Watch the 60-second version on Instagram.

compviz is a web app at compviz.a2coder.dev, by @a2coder, MIT-licensed. It runs in the browser with no sign-up, no backend and no database. Paste a compose.yaml and the diagram appears.

How it reads the file

COMPOSE.YAMLservices: api: depends_on: [db] labels: compviz.edge.events.label: events compviz.edge.events.animated: "true" db: image: postgres:16-alpine events: image: rabbitmq:3-managementDEPENDS_ONLABELSAPIDBEVENTSDIAGRAMFIG. 01 / THE FILE IS THE DIAGRAM
  • Every entry under services: becomes a node.
  • depends_on and links become edges, drawn from the dependent service to the one it uses: api → db.
  • Volumes, networks and ports show as details on the node.
  • Edge annotations can add edges depends_on doesn't declare. In the figure, api never depends on events, but two compviz.edge.events.* labels draw an animated edge to it anyway.

Here is the full example from the README:

compose.yaml
x-compviz:
  title: Storefront
  direction: LR
 
services:
  api:
    build: ./api
    depends_on: [db]
    labels:
      compviz.name: Orders API
      compviz.highlight: "true"
      compviz.edge.db.label: SQL
      compviz.edge.events.label: events
      compviz.edge.events.animated: "true"
  db:
    image: postgres:16-alpine
  events:
    image: rabbitmq:3-management

The highlighted lines are the customisation, and they're the part I like most. A top-level x-compviz block sets the title and the direction (TB, LR, RL or BT). Per-service compviz.* labels rename a node, highlight it, or label, animate and hide edges (compviz.edge.<target>.label, .animated, .hidden). Both are standard Compose mechanisms: x- fields and labels. So there's no sidecar file to keep in sync, and the same file still runs with docker compose.

Known Apps are matched by image

compviz knows exactly 55 apps, among them Postgres, Redis, Kafka, NGINX, Grafana and Next.js. A Known App gets a logo and a category on its node. The match is made on the service's image, never on its service name.

db:image: postgres:16-alpineDBPOSTGRESpostgres:build: ./pgPOSTGRESNO MATCHMATCHED BY IMAGE · NEVER BY SERVICE NAMEFIG. 02 / MATCHED BY IMAGE

The second service in the figure is made up to show the rule: calling a service postgres doesn't make it Postgres to compviz. image: postgres:16-alpine does, whatever the service is called.

The editor and the exports

  • Autocomplete for keys, annotations and Known Apps.
  • A bad key shows a warning instead of breaking the diagram.
  • The cursor and the diagram are linked both ways.
  • Export as SVG, PNG or PDF, each stamped "Made with compviz · compviz.a2coder.dev".

That covers the places diagrams usually live: READMEs, onboarding docs, pull requests and design docs.

What compviz doesn't do

The usual assumption about a diagram tool is that it either wants its own diagram file or wants to run your stack. compviz does neither. It only reads the text you paste:

  • It runs nothing. It doesn't run, validate or deploy containers.
  • It doesn't follow includes, read .env, or interpolate variables. What's in the pasted text is what gets drawn.
  • The SVG API is self-hosted only. POST /api/svg exists when you run the Docker image a2coder/compviz with COMPVIZ_API=true, and it's off on compviz.a2coder.dev.
  • Edges come from the file. If neither depends_on, links nor an edge annotation mentions a connection, it isn't drawn. The compviz:convert agent skill helps there: it annotates an existing file and infers edges from URLs like DATABASE_URL=postgres://db:5432.

On a client project I'd put the labels straight into the real Compose file, so the diagram in the README changes in the same pull request as the stack it describes.

The short version

  1. Paste a compose.yaml: services become nodes, depends_on and links become edges.
  2. Customise in the same file with x-compviz and compviz.* labels; it still runs with docker compose.
  3. Edge annotations can draw connections depends_on never declares.
  4. 55 Known Apps get a logo and category, matched by image, never by service name.
  5. It only reads text: no containers, no .env, no includes, and the SVG API is self-hosted only.

Sources: compviz on GitHub (README) · compviz.a2coder.dev