For Architects

The diagram is generated. So it's never wrong.

Hand-drawn architecture is a snapshot that starts rotting the moment you save it. ClarifyDoc assembles a C4 model from the real link graph and derives deployment topology from your compose, Kubernetes, Dockerfile and Terraform files — a system view that regenerates from source every run.

Illustration
Context›Deployment›Projects›Components›Code
api-key web (SPA) Vue · Vite bff.api gateway order.api service license.api service postgres datastore auth issuer external

Your architecture docs are fiction

Not because anyone lied — because the code kept moving and the diagram didn't. The only complete, current description of the system is the source, spread across repos, languages and tiers.

  • The C4 diagram was drawn three rewrites ago
  • No single picture spans the frontend, the services and the database
  • Nobody can state the true deployment topology from memory
  • Coupling and blast radius are felt, not measured
  • “Which service owns this table?” has no authoritative answer
  • Every modernization estimate rests on a guess

C4 DRILL-DOWN

Five levels, aggregated from the real graph

Start at the system context and drill: Deployment topology, then project groups, then the components inside a project, down to the file-level graph — each level rolled up from the same linkGraph, symbolLinks and dataAccessGraph. Big estates stay legible: a monorepo with a hundred projects folds into a handful of groups.

  • Context → Deployment → Projects → Components → Code
  • Laid out deterministically with a layered (Sugiyama) engine
  • Components boxed by folder and role — controllers, services, data access, models — with the datastores outside
  • The file hairball is scoped to one component, never the whole system
Illustration
C4 LEVELS drill in / out
1 · Context1 system · 7 external
2 · Deployment29 services · 71 edges
3 · Projects179 → 8 groups
4 · Componentsgrouped by role
5 · Codefile graph

DEPLOYMENT TOPOLOGY

Read from your deployment files, not a whiteboard

ClarifyDoc reads your docker-compose stacks, Kubernetes manifests, Dockerfiles and Terraform modules and reconstructs services, externals and the edges between them — name-agnostic, from real evidence. An API-key handshake between a provider and a consumer becomes an edge; a literal connection string tells ownership from a cross-DB reference.

  • A compose build: reads its Dockerfile: the command it runs and the source file it starts
  • Terraform modules give Lambdas, API Gateway routes, queues, tables and databases
  • Helm charts, and the Argo CD and Flux releases that deploy them
  • A service’s outbound calls followed through its env and config files, dev proxies and gateways (YARP, Ocelot) to the service that answers
  • CI pipelines’ deploy steps — GitHub, GitLab, Azure, CircleCI, Bitbucket — with trigger and path
  • The environment variables each service reads, and which deployments set them (names only)
# docker-compose.yml — evidence
bff.api     AUTH__APIKEY=${IDP_KEY}
auth.idp    ApiKeys__0=${IDP_KEY}      ← handshake
order.api   Db=Host=postgres;Database=orders

# derived edges
bff.api   ──api-key──▶  auth.idp   (external)
order.api ──────────▶  postgres   (orders)

ENTITY-RELATIONSHIP MODEL

One data model, recovered from the ORM code

Entities, fields, enums and associations are lifted straight out of EF Core, Mongoose, Prisma, Eloquent, Hibernate, TypeORM and friends — plus raw CREATE TABLE DDL — with cardinality and foreign keys as crow's-foot relationships. Raw SQL files parse into the same model, so the picture holds even where there's no ORM.

  • Associations with cardinality, FK and join tables
  • SQL migration chains — Flyway, golang-migrate, Prisma — replayed in order into the schema they end with
  • MyBatis mapper methods joined to the SQL in their mapper XML, and the tables it names
  • Every entity ties back to the endpoints that touch it
Illustration

Customers

  • id uuid
  • name text
  • email text

Orders

  • id uuid
  • customer_id fk
  • total money
  • status enum

OrderLines

  • id uuid
  • order_id fk
  • product_id fk
  • qty int

Customers 1─* Orders 1─* OrderLines

ONE GRAPH, EVERY TIER

Cross-repo, cross-language, one model

ClarifyDoc detects project markers and assigns every file to its innermost sub-project — then keeps the links that cross those boundaries. A Delphi client, a .NET service and a React frontend become one analyzable system.

Sub-projects

Detected from package.json, *.csproj, *.dpr, go.mod, pom.xml and more.

Cross-tier

Frontend → backend → DB links survive across languages and repositories.

Confidence

Every link is graded EXTRACTED / INFERRED / AMBIGUOUS.

SHA-256

Versioned by content hash — diff the architecture between two runs.

YOUR ARCHITECTURE, ENFORCED

Write the rules down once — every breach is named

Say which parts of the system must not depend on which, in a file committed with the code. Each import that breaks a rule is reported with the rule’s name — in the report, in the editor’s Problems panel and in the pull-request gate, which fails only on breaches the change introduces.

  • from / to globs, except for the shared kernel, warn or error
  • Your own layer map, checked before the built-in heuristics
  • Cycles judged without type-only imports, so an interface file doesn’t count as a tangle
// .clarifydoc/config.json
{
  "rules": [
    { "name": "billing stays out of payroll",
      "from": "features/billing/**",
      "to":   "features/payroll/**",
      "except": ["**/shared/**"] },
    { "name": "domain is pure",
      "from": "src/Domain/**",
      "to":   "src/Infrastructure/**",
      "severity": "warn" }
  ]
}

Topology you can act on

Beyond the picture, the graph carries the structural signals you'd otherwise argue about from intuition.

Coupling & cohesion

Named communities, a module dependency matrix and cohesion scores show where the natural seams — and the tangles — actually are.

God-nodes

The files everything leans on, surfaced explicitly, so refactors start where they matter.

Layer violations

Imports that cross the boundaries your architecture — or your own rules file — says shouldn't be crossed.

Blast radius

Per-file and per-class change impact, so modernization is scoped from data.

Surprising connections

Edges between parts of the system that “shouldn't” know about each other.

Services and their contracts

Which service calls which, over HTTP, gRPC or a message queue — Kafka, AMQP, BullMQ, Celery — with the endpoints behind every edge.

Diagrams you can commit

clarifydoc export writes ARCHITECTURE.md, DATA-MODEL.md, FLOWS.md, Mermaid, GraphML, Cypher, CSV, an Obsidian vault, an OpenAPI document and a CycloneDX SBOM; in VS Code, Create Architecture Diagram does it in one command. The same code gives the same file, so the diff is the change — and facts --check fails a document whose cited facts no longer hold.

Deeper resolution, no Docker

In VS Code, the language servers you already run resolve the cross-file calls the text linker missed. In CI, the SCIP or LSIF index your pipeline already builds does the same.

Behaviour baselines

Commit every endpoint’s flow — calls, data, hops to other services — and fail the build when one changes. How it works →

IN THE REPORT

Where architects spend their time

Real screenshots of ClarifyDoc’s report on RealWorld’s open-source Conduit app. Each one opens that tab in the product tour.

GENERATE IT

From repos to a living architecture model

Run it on each repo from VS Code or in CI, and the model regenerates from the code every time — re-runs only re-read what changed. The report is one self-contained file, so the architecture travels with the change: attach it to the review, the ADR or the hand-over.