Dieser Post setzt den zweiten Teil fort.
Dort wurde bausteinsicht init, sync und watch vorgestellt.
Hier geht es um das Herzstück: das JSONC-Datenmodell mit allen Feldern und Erweiterungspunkten.
Die Grundstruktur
Eine architecture.jsonc-Datei hat vier Pflichtfelder und mehrere optionale Abschnitte:
{
"$schema": "./node_modules/.bausteinsicht/bausteinsicht.schema.json",
"config": { ... },
"specification": { ... },
"model": { ... },
"relationships": [ ... ],
"views": { ... },
"asIs": { ... },
"toBe": { ... },
"dynamicViews": [ ... ],
"constraints": [ ... ]
}config
Globale Einstellungen für die Diagrammgenerierung:
"config": {
"author": "Paul Fleischmann",
"repo": "https://github.com/mein-org/mein-repo",
"metadata": true,
"legend": true
}specification
Die specification definiert die Sprache des Modells — welche Element-Typen und Beziehungsarten existieren.
Sie ist die einzige Stelle, die man einmal aufsetzen und dann selten ändern muss.
specification.elements
"specification": {
"elements": {
"actor": {
"notation": "Actor",
"description": "Ein Benutzer oder externes System",
"container": false
},
"system": {
"notation": "Software System",
"container": true
},
"container": {
"notation": "Container",
"container": true
},
"component": {
"notation": "Component",
"container": true
}
}
}Das container-Flag steuert, ob ein Element in der Hierarchie children haben darf.
Fehlt das Flag (oder ist false), lehnt bausteinsicht validate jedes Modell-Element dieses Typs mit children ab.
specification.relationships
"specification": {
"relationships": {
"uses": {
"notation": "uses",
"dashed": false
},
"reads": {
"notation": "reads",
"dashed": true
}
}
}specification.tags
Tags werden unter specification.tags definiert und können optionales draw.io-Styling mitbringen:
"specification": {
"tags": [
{
"id": "external",
"description": "Externes System außerhalb unserer Kontrolle",
"style": {
"fillColor": "#f5f5f5",
"fontColor": "#666666"
}
},
{
"id": "legacy",
"description": "Altsystem — keine aktive Weiterentwicklung"
}
]
}specification.patterns
Patterns sind wiederverwendbare Topologie-Vorlagen — z.B. ein Standard-Microservice-Muster mit Frontend, API und Datenbank:
"specification": {
"patterns": {
"microservice": {
"description": "Standardmuster: API + Datenbank",
"elements": [
{ "id": "api", "kind": "container", "title": "{{name}} API", "technology": "Go" },
{ "id": "db", "kind": "container", "title": "{{name}} Database", "technology": "PostgreSQL" }
],
"relationships": [
{ "id": "r1", "from": "api", "to": "db", "label": "reads/writes", "kind": "uses" }
]
}
}
}specification.decisions
ADR-Referenzen (Architecture Decision Records) können direkt in der Specification verwaltet werden:
"specification": {
"decisions": [
{
"id": "ADR-001",
"title": "PostgreSQL als primäre Datenbank",
"status": "active",
"date": "2025-01-15",
"file": "docs/adr/001-postgresql.md"
}
]
}model
Das model beschreibt die konkreten Elemente des Systems.
Jeder Schlüssel ist die Element-ID — sie muss innerhalb der Hierarchieebene eindeutig sein.
Element-Felder
"model": {
"onlineshop": {
"kind": "system",
"title": "Online Shop",
"description": "Der Kern des Systems",
"technology": "Go, PostgreSQL",
"tags": ["external", "legacy"],
"status": "deployed",
"decisions": ["ADR-001"],
"metadata": {
"owner": "Team Backend",
"cost": "€500/month"
},
"children": {
"frontend": { ... },
"api": { ... }
}
}
}Verschachtelte Hierarchie
Elemente lassen sich beliebig tief verschachteln, solange der jeweilige kind container: true hat:
"model": {
"shop": {
"kind": "system", "title": "Online Shop",
"children": {
"backend": {
"kind": "container", "title": "Backend",
"children": {
"orderservice": { "kind": "component", "title": "Order Service" },
"paymentservice": { "kind": "component", "title": "Payment Service" }
}
}
}
}
}Die Element-ID in Beziehungen und Views verwendet Punkt-Notation für den Pfad: shop.backend.orderservice.
status-Werte
| Status | Bedeutung | draw.io Farbe |
|---|---|---|
| Geplant, noch nicht begonnen | Gelb |
| Im Entwurf | Blau |
| In Entwicklung | Orange |
| Produktiv | Grün |
| Veraltet, wird abgelöst | Rot |
| Eingestellt | Grau |
relationships
Beziehungen werden als flaches Array auf Top-Level definiert, nicht innerhalb der Elemente. Das ermöglicht Beziehungen zwischen Elementen verschiedener Hierarchieebenen:
"relationships": [
{
"from": "shop.backend.orderservice",
"to": "shop.backend.paymentservice",
"label": "bestätigt Zahlung",
"kind": "uses",
"description": "Synchroner REST-Call",
"cardinality": "1:N",
"dataFlow": "sync",
"decisions": ["ADR-002"]
}
]views
Views definieren, welche Elemente in welchem Diagramm-Tab erscheinen.
Jeder Schlüssel wird ein Tab in architecture.drawio.
View-Felder
"views": {
"context": {
"title": "System Context",
"description": "Übersicht aller Systeme",
"scope": "shop",
"include": ["customer", "shop"],
"exclude": ["shop.backend.legacy"],
"filter-tags": ["external"],
"exclude-tags": ["archived"],
"layout": "auto"
}
}include mit Wildcards:
"include": [
"customer",
"shop.*",
"shop.**"
]Optionale Erweiterungen
asIs / toBe
Für As-Is/To-Be-Vergleiche kann die aktuelle und die Zielarchitektur direkt im Modell hinterlegt werden:
"asIs": {
"elements": {
"legacy-monolith": { "kind": "system", "title": "Legacy Monolith" }
},
"relationships": [
{ "from": "customer", "to": "legacy-monolith", "label": "uses" }
]
},
"toBe": {
"elements": {
"shop": { "kind": "system", "title": "Online Shop (Microservices)" }
},
"relationships": [
{ "from": "customer", "to": "shop", "label": "uses" }
]
}bausteinsicht diff visualisiert den Unterschied zwischen asIs und toBe als annotiertes Diagramm.
dynamicViews
Sequenzdiagramme beschreiben den zeitlichen Ablauf von Interaktionen:
"dynamicViews": [
{
"key": "checkout",
"title": "Checkout-Flow",
"steps": [
{ "index": 1, "from": "customer", "to": "frontend", "label": "klickt Kaufen", "type": "sync" },
{ "index": 2, "from": "frontend", "to": "orderservice", "label": "POST /orders", "type": "sync" },
{ "index": 3, "from": "orderservice", "to": "paymentservice", "label": "charge()", "type": "sync" },
{ "index": 4, "from": "paymentservice", "to": "orderservice", "label": "OK", "type": "return" }
]
}
]type-Werte: sync (durchgezogener Pfeil) | async (offener Pfeil) | return (gestrichelt zurück).
bausteinsicht export sequence generiert daraus PlantUML oder Mermaid.
constraints
Architekturregeln werden als maschinenprüfbare Constraints definiert und mit bausteinsicht lint ausgewertet:
"constraints": [
{
"id": "NO-DIRECT-DB-ACCESS",
"description": "Nur Services dürfen direkt auf die Datenbank zugreifen",
"rule": "no-relationship",
"from-kind": "component",
"to-kind": "database"
},
{
"id": "REQUIRE-DESCRIPTION",
"description": "Alle Systeme brauchen eine Beschreibung",
"rule": "required-field",
"element-kind": "system",
"field": "description"
}
]Verfügbare rule-Werte: no-relationship, allowed-relationship, required-field, max-depth, technology-allowed.
JSON Schema für IDE-Autovervollständigung
Ohne Plugin funktioniert die Autovervollständigung über das mitgelieferte JSON Schema.
Den $schema-Eintrag in architecture.jsonc setzen:
{
"$schema": "https://raw.githubusercontent.com/docToolchain/Bausteinsicht/main/schemas/bausteinsicht.schema.json"
}In VS Code (und jedem Editor mit JSON Schema Support) erscheint dann direkt Autovervollständigung für alle Felder — ohne Extension installieren zu müssen.
Beispiel-Modell
Das Beispiel für diesen Teil ist als ausführbare JSONC-Datei unter teil_3.jsonc abgelegt und zeigt specification, model, views und relationships mit allen optionalen Feldern.
So sieht das Ergebnis in draw.io aus (bausteinsicht sync):
Das draw.io-File dafür findest du hier: teil_3.drawio
Generierte PNG-Dateien via bausteinsicht export --image-format png:


Generierte PlantUML-Diagramme via bausteinsicht export-diagram:
Was als nächstes kommt
Teil 4: Bidirektionale Synchronisation — wie der Merge-Algorithmus funktioniert und was passiert wenn beide Seiten gleichzeitig geändert wurden
Teil 5: Multi-View — mehrere Diagrammperspektiven aus einem Modell
Offizielle Dokumentation: User Manual · Tutorial auf doctoolchain.org