Skip to content

Concept Colors

Koine’s promise is one ubiquitous language. Concept Colors extends that promise to color: one DDD concept, one color, everywhere. A value object is the same blue in the Studio explorer, on the domain canvas, in the code editor, in the website playground, and in VS Code — so the color association you build scanning a tree or a diagram carries straight into the source, which is where it pays off.

The rule of thumb is simple:

Structure stays neutral; names carry the concept color. Keywords, punctuation, strings, and numbers stay in the muted syntax palette. Only the names of DDD concepts — an aggregate, a value object, an enum, a domain event — take their concept hue, at both their declaration and every reference.

Every concept hue lives in exactly one place: design/concept-colors.json. Each surface consumes a generated artifact from it (CSS variables, a typed map, VS Code color rules), each guarded by a sync test — so nothing below can drift from the source. This very table is rendered from that palette at build time.

DarkLightConceptCSS variableLSP modifier
Aggregate--koi-ddd-aggregateaggregate
Entity--koi-ddd-entityentity
Value object--koi-ddd-valuevalueObject
Enumeration--koi-ddd-enumenumeration
Domain event--koi-ddd-eventdomainEvent
Integration event--koi-ddd-integration-eventintegrationEvent
Command--koi-ddd-commandcommand
Query--koi-ddd-queryquery
Read model--koi-ddd-read-modelreadModel
Service--koi-ddd-serviceservice
Repository--koi-ddd-repositoryrepository
Policy--koi-ddd-policypolicy
Factory--koi-ddd-factoryfactory
State machine--koi-ddd-state-machinestateMachine
Specification--koi-ddd-specspecification

The dark value is the canonical hue (the one Studio’s explorer and canvas have always used); the light value is a contrast-tuned variant that stays readable on a white background (≥ 4.5:1 against white). The CSS variable is what every web surface references (color: var(--koi-ddd-<slug>)); the LSP modifier is the signal the compiler puts on the wire (see below).

The compiler never emits a color — it emits a concept kind. The Koine language server’s semantic-token legend carries one modifier per concept kind (bits 1–15, after the declaration bit), advertised append-only so the base token types (type, enum, …) never shift:

  • A declaration name carries declaration | <kind>.
  • A reference resolves through the model index to its declaring kind and carries <kind> alone.
  • Primitives (Decimal, String, List<…>) carry no kind — they keep the neutral type color.

Each editor decodes the kind bit into a cm-st-k-<slug> class themed color: var(--koi-ddd-<slug>), applied after the base type color so the concept color wins. The full rationale, alternatives, and the append-only legend contract are recorded in ADR 0004.

SurfaceDeclarationsReferencesMechanism
Studio explorer / inspector--koi-ddd-* CSS vars
Studio domain canvas / event flowCONCEPT_COLORS (same hex)
Studio code editorLSP kind modifiers → cm-st-k-<slug>
Website playgroundLSP kind modifiers → cm-st-k-<slug>
VS CodeLSP + semanticTokenColorCustomizations
Rider (LSP4IJ)inherits the base type/enum color (graceful fallback)

A client that doesn’t understand the kind modifiers simply ignores them and renders domain names with the base type/enum color — exactly as before. Concept Colors is an upgrade, never a regression.

The domain canvas’s Event Flow view used to speak the classic Event Storming sticky palette (a yellow aggregate, a blue command). That separate palette is retired — the flow now uses the same concept colors as everything else. For orientation, here’s how the Event Storming vocabulary maps onto Koine’s concepts:

Event Storming stickyKoine conceptConcept color
Command (blue)commandcommand red
Aggregate (yellow)aggregateaggregate indigo
Domain Event (orange)event (domain event)domain-event pink
Policy / Process (lilac)policypolicy magenta
External system / Integrationintegration eventintegration-event teal
Read Model (green)readmodelread-model lime

Deliberately deferred (follow-ups, not part of this pass): a distinct hue for bounded contexts (today they stay structural / neutral), Rider-side custom coloring beyond the LSP fallback, a Shiki theme for the static code blocks in these docs, and user-customizable palettes.

See also: Editor tooling for the language server and the VS Code / Rider extensions that carry these colors.