KimtuDocumentation

The kimtu.yaml file

One file at the repository root declares every component the repository contains and how it connects to the rest of the ecosystem.

repository rootkimtu/v1YAML

A complete file

One file describes one repository. A monorepo declares several components in the same file; a repository per service declares one.

kimtu.yaml
apiVersion: kimtu/v1

repository:
  id: invoice-service
  name: Invoice Service
  url: https://github.com/kimtu/invoice-service

docs: ./docs

components:
  - id: invoice
    name: Invoice Service
    type: service
    description: >-
      Manages the lifecycle of an invoice from draft through finalisation and
      settlement. The system of record for what a customer owes.
    owner: Billing Team
    language: TypeScript
    runtime: Node 20.x
    surface:
      endpoints: 14
      events: 4
    relationships:
      - to: pg-invoices
        interaction: postgres
        description: Persists invoices and their line items
        data:
          - Invoice
          - LineItem

      - to: event-bus
        interaction: amqp
        description: Publishes invoice lifecycle events
        data:
          - invoice.created
          - invoice.finalized

      - to: event-bus
        interaction: amqp
        direction: inbound
        description: >-
          Consumes settlement outcomes to move an invoice from finalised to
          paid. Finalisation is synchronous; settlement is not.
        data:
          - payment.settled
          - payment.failed

      - to: tax-rates
        interaction: https
        endpoint: POST /rates
        description: Resolves the regional rate at finalisation
        data:
          - TaxRate

  - id: pg-invoices
    name: Postgres · invoices
    type: database
    description: Primary Postgres instance for invoices and their line items.
    owner: Billing Team
    runtime: PostgreSQL 16

  - id: invoicing-job
    name: Invoicing Job
    type: job
    description: Nightly job that renders a PDF for every finalised invoice.
    owner: Billing Team
    docs: ./docs/invoicing-job
    relationships:
      - to: pg-invoices
        interaction: postgres
        description: Reads finalised invoices from a read replica
        data:
          - Invoice
          - LineItem

external:
  - id: event-bus
    name: Event Bus
    type: queue
    description: >-
      Fan-out broker carrying every billing event. Owned by the platform
      repository, not this one.

  - id: tax-rates
    name: Tax Rates
    type: external
    description: Third-party service returning the tax rate for a jurisdiction.

Top-level keys

FieldTypeDescription
apiVersion (required)stringThe manifest format. kimtu/v1 is the only accepted value.
repository (required)mapThe repository this file describes: id and name, plus an optional url linked from every page.
docsstringThe repository's documentation directory, e.g. ./docs.
components (required)listWhat this repository runs or owns. At least one.
externallistSystems outside this repository that its components talk to. Declared here so they are drawn with a name rather than a bare slug.

Fields marked * are required. Unknown keys are ignored, so you can annotate the file for your own tooling.

Component fields

Every entry under components becomes one page and one node on the architecture graph.

FieldTypeDescription
id (required)stringStable identifier, referenced by other components and used in URLs. Lowercase kebab-case. Renaming it creates a new component.
name (required)stringDisplay name, shown in the rail and on the graph.
type (required)enumWhat kind of thing it is. Picks the icon.
descriptionstringOne or two sentences, present tense. Shown under the title and in the system map's detail panel.
ownerstringThe team or person responsible, as the repository names them.
languagestringThe main programming language, e.g. TypeScript.
runtimestringWhat it runs on, with the version, e.g. Node 20.x or PostgreSQL 16.
surfacemapHow much it exposes, as counts: endpoints and events.
docsstringOverrides the repository documentation path for this component, and claims the markdown underneath it.
relationshipslistEverything this component calls, reads, publishes or consumes. Each entry is one edge on the graph.

surface is two counts rather than a list of routes. Numbers can be compared and summed across a system; a list of paths cannot.

FieldTypeDescription
endpointsnumberHTTP or RPC operations it serves, e.g. 14 for fourteen routes.
eventsnumberDistinct event types it publishes.
kimtu.yaml — surface
surface:
  endpoints: 14      # HTTP or RPC operations it serves
  events: 4          # distinct event types it publishes

Relationships

There is no separate depends_on, publishes or consumes. A call, a read and an event are the same thing — an edge between two components — and interaction and direction are what tell them apart.

FieldTypeDescription
to (required)stringThe id of the component on the other end. It may live in another repository, or be declared under external.
interactionstringProtocol or mechanism: http, postgres, amqp, grpc, sqs. Free-form on purpose — an enum breaks on the first team using something we did not think of.
directionenumWhich way the data moves. One of outbound, inbound. Defaults to outbound.
endpointstringThe specific operation, e.g. POST /v1/invoices. Shown as the contract when present.
descriptionstringWhat moves across this edge, and why, in one line.
datalistThe types or events that travel over this edge. This is what Data flow follows, so an edge without it is drawn but cannot be traced.
Without direction, publishing to a queue and consuming from one are the same edge between the same two components. It is the one field worth being deliberate about.
kimtu.yaml — relationships
relationships:
  # A call this component makes. The endpoint is the contract.
  - to: customer
    interaction: http
    endpoint: GET /v1/customers/{id}
    description: Reads billing details when composing an invoice
    data: [Customer]

  # Something it publishes. direction defaults to outbound.
  - to: event-bus
    interaction: amqp
    description: Publishes invoice lifecycle events
    data: [invoice.created, invoice.finalized]

  # Something it consumes. The same two components, opposite direction --
  # which is the only thing telling the two edges apart.
  - to: event-bus
    interaction: amqp
    direction: inbound
    description: Moves an invoice to paid once payment settles
    data: [payment.settled]

External systems

Anything your components talk to that this repository does not own: a payment provider, a queue run by the platform team, another team's service. Entries under external get a name and a description but no page of their own, and they declare no relationships — whoever talks to them does that, with direction: inbound for a call that comes the other way.

FieldTypeDescription
id (required)stringThe id your components point at in their relationships.
name (required)stringDisplay name, e.g. Stripe.
typeenumSet it when the kind is worth drawing — a queue owned by another repository, say. Defaults to external.
descriptionstringWhat it is, and whose it is.

Pointing at documentation

docs is one path, not a list. A component can override the repository's with a path of its own, which claims the markdown underneath it for that component.

kimtu.yaml
# the repository's documentation directory
docs: ./docs

components:
  # a component can override it with a path of its own,
  # which claims the markdown underneath it
  - id: invoicing-job
    name: Invoicing Job
    type: job
    docs: ./docs/invoicing-job

Validation

An error stops the import and nothing is stored; a warning is reported beside the architecture it produced.

Unknown targetswarning
A relationship pointing at an id nobody declares never fails the import. The target is drawn as an undeclared placeholder carrying only the slug the file gave it — which is usually how you find out something was missed.
Duplicate idserror
Ids are unique across every repository in the workspace, and the second declaration is dropped rather than merged.
Unknown typeserror
type is a closed list, so a value outside it is rejected with the offending line named, rather than quietly turned into a service.
Missing targeterror
A relationship with no to describes an edge with one end. There is nothing to draw and nothing to guess.
Relationships to selfwarning
The edge is counted, but no diagram draws a component calling itself.
Empty docs patherror
Raised when the file declares docs: and no markdown was found under it. A repository that never mentions documentation is allowed not to have any.
Cycles
Allowed and expected. Two components that call each other are two edges, and nothing tries to untangle them.
Unknown keys
Ignored, so the file can carry annotations for your own tooling.