likec4 1.59.3 → 1.60.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/__app__/codegen/react.mjs +6 -6
- package/__app__/codegen/webcomponent.mjs +147 -69
- package/__app__/src/aichat/index.mjs +10 -5
- package/__app__/src/chunks/AIChat.mjs +1134 -693
- package/__app__/src/chunks/LikeC4Styles.mjs +4101 -1737
- package/__app__/src/chunks/ProjectsOverview.mjs +624 -334
- package/__app__/src/chunks/es.mjs +515 -335
- package/__app__/src/chunks/hooks.mjs +578 -366
- package/__app__/src/chunks/libs/@floating-ui.mjs +2720 -1966
- package/__app__/src/chunks/libs/@mantine.mjs +14067 -9487
- package/__app__/src/chunks/libs/@tanstack-ai.mjs +2266 -1146
- package/__app__/src/chunks/libs/@tanstack.mjs +3152 -1932
- package/__app__/src/chunks/libs/@xstate/react.mjs +2924 -1468
- package/__app__/src/chunks/libs/@xyflow/react.mjs +6627 -4067
- package/__app__/src/chunks/libs/bezier-js.mjs +1312 -726
- package/__app__/src/chunks/libs/d3.mjs +3218 -1509
- package/__app__/src/chunks/libs/fast-equals.mjs +437 -201
- package/__app__/src/chunks/libs/framer.mjs +9251 -3846
- package/__app__/src/chunks/libs/nanostores.mjs +174 -0
- package/__app__/src/chunks/libs/zod.mjs +4591 -2363
- package/__app__/src/chunks/rolldown-runtime.mjs +39 -23
- package/__app__/src/chunks/styled-system.mjs +3538 -756
- package/__app__/src/fonts.css +112 -1
- package/__app__/src/main.mjs +44398 -24039
- package/__app__/src/style.css +18488 -1
- package/config/schema.json +136 -97
- package/dist/app/render-view-client.css +1 -1
- package/dist/app/render-view-client.js +506 -338
- package/dist/chunks/enableServer.mjs +1 -1
- package/dist/chunks/filenames.mjs +16 -14
- package/dist/chunks/generate-likec4.mjs +5 -0
- package/dist/chunks/index.d.mts +246 -180
- package/dist/chunks/index2.d.mts +2882 -1977
- package/dist/chunks/libs/@chevrotain/gast.mjs +27 -1
- package/dist/chunks/libs/@chevrotain/regexp-to-ast.mjs +81 -9
- package/dist/chunks/libs/@chevrotain/types.d.mts +111 -0
- package/dist/chunks/libs/@logtape/logtape.mjs +5 -4
- package/dist/chunks/libs/@lume/kiwi.mjs +1 -1
- package/dist/chunks/libs/@ts-graphviz/core.mjs +1 -1
- package/dist/chunks/libs/birpc.mjs +1 -1
- package/dist/chunks/libs/chevrotain-allstar.mjs +2 -2
- package/dist/chunks/libs/chevrotain.mjs +87 -35
- package/dist/chunks/libs/eventemitter3.mjs +1 -1
- package/dist/chunks/libs/json5.mjs +4 -4
- package/dist/chunks/libs/langium.d.mts +9903 -5297
- package/dist/chunks/libs/langium.mjs +16 -24
- package/dist/chunks/libs/merge-error-cause.mjs +1 -1
- package/dist/chunks/libs/p-limit.mjs +1 -0
- package/dist/chunks/libs/p-queue.mjs +1 -1
- package/dist/chunks/libs/package-manager-detector.mjs +1 -1
- package/dist/chunks/libs/pako.mjs +2 -2
- package/dist/chunks/libs/pretty-ms.mjs +1 -1
- package/dist/chunks/libs/remeda.mjs +1 -1
- package/dist/chunks/libs/ufo.mjs +1 -1
- package/dist/chunks/libs/unstorage.mjs +1 -1
- package/dist/chunks/libs/which.mjs +1 -1
- package/dist/chunks/node.mjs +60 -60
- package/dist/chunks/rolldown-runtime.mjs +1 -1
- package/dist/chunks/sequence-view.mjs +1 -1
- package/dist/chunks/vite-plugin.mjs +55 -52
- package/dist/cli/index.d.mts +1 -1
- package/dist/cli/index.mjs +208 -1300
- package/dist/config/index.d.mts +2 -2
- package/dist/generators/likec4.d.mts +6578 -0
- package/dist/generators/likec4.mjs +1 -0
- package/dist/index.d.mts +3 -3
- package/dist/model/index.d.mts +8 -5
- package/dist/vite-plugin/index.d.mts +6 -3
- package/dist/vite-plugin/index.mjs +1 -1
- package/dist/vite-plugin/internal/chunks/rolldown-runtime.mjs +9 -0
- package/dist/vite-plugin/internal/index.d.mts +16 -15
- package/dist/vite-plugin/internal/index.mjs +144 -46
- package/generators/likec4/package.json +4 -0
- package/package.json +117 -110
- package/react/index.d.mts +8500 -5399
- package/react/index.mjs +534 -58617
- package/react/rolldown-runtime-DnkiqaRY.js +1 -0
- package/skills/likec4-dsl/SKILL.md +428 -0
- package/skills/likec4-dsl/evals/evals-public.json +202 -0
- package/skills/likec4-dsl/evals/grading-spec.json +589 -0
- package/skills/likec4-dsl/references/bridge-leanix-drawio.md +42 -0
- package/skills/likec4-dsl/references/cli.md +139 -0
- package/skills/likec4-dsl/references/configuration.md +266 -0
- package/skills/likec4-dsl/references/deployment.md +160 -0
- package/skills/likec4-dsl/references/dynamic-views.md +455 -0
- package/skills/likec4-dsl/references/examples.md +370 -0
- package/skills/likec4-dsl/references/identifier-validity.md +90 -0
- package/skills/likec4-dsl/references/include-predicates-wildcards.md +179 -0
- package/skills/likec4-dsl/references/model.md +151 -0
- package/skills/likec4-dsl/references/predicates.md +123 -0
- package/skills/likec4-dsl/references/relationships-bidirectional.md +176 -0
- package/skills/likec4-dsl/references/specification.md +75 -0
- package/skills/likec4-dsl/references/style-tokens-colors.md +150 -0
- package/skills/likec4-dsl/references/troubleshooting.md +96 -0
- package/skills/likec4-dsl/references/views.md +329 -0
- package/vite-plugin-modules.d.ts +4 -2
- package/dist/chunks/libs/picomatch.mjs +0 -1
- package/dist/chunks/libs/zod.d.mts +0 -2140
- package/dist/chunks/libs/zod.mjs +0 -65
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Model (LikeC4 DSL)
|
|
2
|
+
|
|
3
|
+
The `model` block defines the logical architecture: elements (systems, containers, components, actors) organized in a hierarchy, with relationships between them. Views project from this model.
|
|
4
|
+
|
|
5
|
+
**Key rules:**
|
|
6
|
+
|
|
7
|
+
- Elements MUST have a kind (from specification) and an identifier unique within their parent.
|
|
8
|
+
- Relationships cannot exist directly between parent and child — move them outside the parent element.
|
|
9
|
+
- `this` and `it` are aliases for the current element inside a nested relationship.
|
|
10
|
+
- Cross-file references require the full FQN (e.g. `cloud.backend.api`); short names are file-scoped.
|
|
11
|
+
- `extend FQN { }` adds tags, metadata, and links to an existing element without redefining it.
|
|
12
|
+
|
|
13
|
+
## Syntax
|
|
14
|
+
|
|
15
|
+
```likec4
|
|
16
|
+
model {
|
|
17
|
+
// Elements — top-level elements are global, referenceable by ID anywhere in the project
|
|
18
|
+
IDENTIFIER = KIND // no title, no body (title defaults to identifier)
|
|
19
|
+
IDENTIFIER = KIND "title" // with title, without body
|
|
20
|
+
KIND IDENTIFIER "title" // alternative: kind before identifier
|
|
21
|
+
|
|
22
|
+
IDENTIFIER = KIND {
|
|
23
|
+
TAGS // optional, must come first if present
|
|
24
|
+
PROPERTIES // optional, must come before nested elements/relationships
|
|
25
|
+
|
|
26
|
+
IDENTIFIER = KIND "Child Title" { ... } // nested element (unlimited depth)
|
|
27
|
+
KIND IDENTIFIER "Child Title" // nested, kind-first syntax
|
|
28
|
+
|
|
29
|
+
// Relationships inside element body (current element is implicitly SOURCE)
|
|
30
|
+
SOURCE -> TARGET // explicit, both sides named
|
|
31
|
+
-> TARGET "title" // implicit source (current element)
|
|
32
|
+
-> TARGET "title" { TAGS; PROPERTIES }
|
|
33
|
+
<-> TARGET "title" // bidirectional relationship
|
|
34
|
+
-[REL_KIND]-> TARGET "title" // typed directed relationship
|
|
35
|
+
-[REL_KIND]<-> TARGET "title" // typed bidirectional relationship
|
|
36
|
+
.REL_KIND TARGET "title" // alternative typed syntax
|
|
37
|
+
SOURCE -> it // TARGET = current element (alias)
|
|
38
|
+
this -> TARGET // SOURCE = current element (alias)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Top-level relationships (outside element body): SOURCE is required
|
|
42
|
+
SOURCE -> TARGET "title"
|
|
43
|
+
SOURCE <-> TARGET "title"
|
|
44
|
+
SOURCE -> TARGET "title" { TAGS; PROPERTIES }
|
|
45
|
+
SOURCE -[REL_KIND]-> TARGET
|
|
46
|
+
SOURCE -[REL_KIND]<-> TARGET
|
|
47
|
+
SOURCE .REL_KIND TARGET
|
|
48
|
+
|
|
49
|
+
// Extend existing element (by FQN, from any file)
|
|
50
|
+
extend FQN {
|
|
51
|
+
TAGS // additional tags to apply
|
|
52
|
+
PROPERTIES // only `metadata` and `link` are allowed
|
|
53
|
+
NESTED_ELEMENTS | RELATIONSHIPS // additional children or edges
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Extend existing relationship — matcher contract:
|
|
57
|
+
// 1) SOURCE and TARGET always required.
|
|
58
|
+
// 2) Include KIND when extending a typed relationship.
|
|
59
|
+
// 3) Include TITLE when extending a titled relationship.
|
|
60
|
+
// Omitting KIND is WRONG (not merely ambiguous) when a typed relation exists.
|
|
61
|
+
// Omitting TITLE is WRONG when the matched relation is titled.
|
|
62
|
+
extend SOURCE -> TARGET { TAGS; PROPERTIES } // untitled directed relationship
|
|
63
|
+
extend SOURCE -> TARGET "title" { TAGS; PROPERTIES } // titled directed relationship
|
|
64
|
+
extend SOURCE <-> TARGET { TAGS; PROPERTIES } // untitled bidirectional relationship
|
|
65
|
+
extend SOURCE <-> TARGET "title" { TAGS; PROPERTIES } // titled bidirectional relationship
|
|
66
|
+
extend SOURCE -[REL_KIND]-> TARGET "title" { TAGS; PROPERTIES } // typed titled relationship
|
|
67
|
+
extend SOURCE -[REL_KIND]<-> TARGET "title" { TAGS; PROPERTIES } // typed titled bidirectional
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Full Example
|
|
72
|
+
|
|
73
|
+
```likec4
|
|
74
|
+
model {
|
|
75
|
+
customer = actor {
|
|
76
|
+
title "Customer"
|
|
77
|
+
summary "Consumes Cloud Services"
|
|
78
|
+
description """
|
|
79
|
+
User with **active** subscription
|
|
80
|
+
... detailed description
|
|
81
|
+
"""
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
cloud = system "Cloud" {
|
|
85
|
+
ui = container "Frontend" {
|
|
86
|
+
technology "React"
|
|
87
|
+
style { shape browser }
|
|
88
|
+
metadata { version "1.0.0"; owners ["Name 1", "Name 2"] }
|
|
89
|
+
link https://github.com/likec4/likec4 "Repository"
|
|
90
|
+
link ../relative/adr1.md
|
|
91
|
+
|
|
92
|
+
dashboard = app "Dashboard" { icon tech:react }
|
|
93
|
+
}
|
|
94
|
+
backend = container "Backend" {
|
|
95
|
+
api = service "API" {
|
|
96
|
+
#critical
|
|
97
|
+
-[sql]-> db "reads/writes"
|
|
98
|
+
}
|
|
99
|
+
db = database "DB" {
|
|
100
|
+
style { icon tech:postgresql; shape storage }
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
ui.dashboard -> backend.api { title "calls"; technology "HTTPS" }
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
customer -> cloud.ui.dashboard "browses" {
|
|
107
|
+
metadata { protocol "HTTPS" }
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Element Properties
|
|
113
|
+
|
|
114
|
+
| Property | Values |
|
|
115
|
+
| --------------- | ---------------------------------------------------------------------------------------- |
|
|
116
|
+
| **title** | String, single line |
|
|
117
|
+
| **description** | String, prefer Markdown. If > 150 chars, also add `summary`. |
|
|
118
|
+
| **summary** | String, max 150 characters |
|
|
119
|
+
| **technology** | String, no multi-line |
|
|
120
|
+
| **style** | `style { ... }` — see `references/style-tokens-colors.md` |
|
|
121
|
+
| **icon** | Shortcut for `style { icon ... }`, takes precedence over the style block |
|
|
122
|
+
| **metadata** | `metadata { KEY VALUE }` — key is identifier format; value is string or array of strings |
|
|
123
|
+
| **link** | `link URL "Optional title"` — repeatable; URL can be relative to the document |
|
|
124
|
+
| **navigateTo** | ID of a dynamic view to navigate to on click |
|
|
125
|
+
|
|
126
|
+
## Relationship Properties
|
|
127
|
+
|
|
128
|
+
`title`, `description`, `technology`, `metadata`, `style`, `link`, `navigateTo`
|
|
129
|
+
|
|
130
|
+
## Extend Patterns
|
|
131
|
+
|
|
132
|
+
```likec4
|
|
133
|
+
// Add metadata and a link to an existing element from another file:
|
|
134
|
+
extend cloud.backend.api {
|
|
135
|
+
metadata { team "platform"; criticality "high" }
|
|
136
|
+
link ./adr-002.md "Scaling decision"
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Extend an untyped relationship:
|
|
140
|
+
extend cloud.ui.dashboard -> cloud.backend.api {
|
|
141
|
+
metadata { sla "99.9%" }
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Extend a typed relationship — include KIND to avoid ambiguous match:
|
|
145
|
+
extend cloud.ui.dashboard -[http]-> cloud.backend.api "calls" {
|
|
146
|
+
metadata { sla "99.9%" }
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Wrong: if a typed relationship exists, this silently targets the wrong relation
|
|
150
|
+
// extend cloud.ui.dashboard -> cloud.backend.api "calls" { ... }
|
|
151
|
+
```
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Predicates
|
|
2
|
+
|
|
3
|
+
Predicates are view rules that define what elements and relationships to include or exclude from a view. Predicate types:
|
|
4
|
+
|
|
5
|
+
- Wildcard predicate - used to select all elements/relationships, based on view scope
|
|
6
|
+
- Element predicates - used to select elements
|
|
7
|
+
- Relationship predicates - used to select relationships
|
|
8
|
+
- Filter predicates - used to apply filters to element and relationship predicates
|
|
9
|
+
- Custom predicates - used to override properties of elements/relationships (can be used with `include` only)
|
|
10
|
+
|
|
11
|
+
Syntax:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
EXPRESSION ::= WILDCARD | ELEMENT_EXPRESSION | RELATIONSHIP_EXPRESSION
|
|
15
|
+
FILTER_PREDICATE ::= EXPRESSION where FILTER_CONDITIONS
|
|
16
|
+
CUSTOMIZE_PREDICATE ::= (EXPRESSION | FILTER_PREDICATE) with { ... }
|
|
17
|
+
PREDICATE ::= EXPRESSION | FILTER_PREDICATE | CUSTOMIZE_PREDICATE
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Example:
|
|
21
|
+
|
|
22
|
+
```likec4
|
|
23
|
+
include * // WILDCARD
|
|
24
|
+
include some.element // ELEMENT_EXPRESSION
|
|
25
|
+
include some.from -> some.to // RELATIONSHIP_EXPRESSION
|
|
26
|
+
include * where tag is #production // FILTER_PREDICATE
|
|
27
|
+
include some.element with { color red } // CUSTOMIZE_PREDICATE on ELEMENT_EXPRESSION
|
|
28
|
+
include // CUSTOMIZE_PREDICATE on FILTER_PREDICATE
|
|
29
|
+
some.*
|
|
30
|
+
where
|
|
31
|
+
tag is #production and kind is component
|
|
32
|
+
with {
|
|
33
|
+
color red
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Expressions
|
|
38
|
+
|
|
39
|
+
Expressions inside `exclude` clause match against the accumulated result of previous predicates. Expressions inside `include` clause match against the accumulated result of previous predicates and the model. Element expressions select elements first, and then relationships connected to these elements. Relationship expressions select relationships first, and then elements that are connected by these relationships.
|
|
40
|
+
|
|
41
|
+
### Element expression
|
|
42
|
+
|
|
43
|
+
- `<element_ref>` - selects element by reference from the current file scope, or globally available if not found in the current file, together with all relationships between this element and accumulated result
|
|
44
|
+
- `<element_ref>.<child>` - selects unique child within `<element_ref>` together with all relationships between this child and accumulated result
|
|
45
|
+
- `<element_ref>.*` - selects **direct children only** of `<element_ref>`, together with all relationships between these children and accumulated result
|
|
46
|
+
- `<element_ref>._` - selects direct children of `<element_ref>` that have relationships with accumulated result
|
|
47
|
+
- `<element_ref>.**` - selects **all recursive descendants** of `<element_ref>` that have relationships with accumulated result
|
|
48
|
+
|
|
49
|
+
For detailed wildcard edge cases (`*` vs `_` vs `**`), load `references/include-predicates-wildcards.md`.
|
|
50
|
+
|
|
51
|
+
### Wildcard expression
|
|
52
|
+
|
|
53
|
+
Wildcard expression is a special element expression.
|
|
54
|
+
|
|
55
|
+
- If used inside a scoped view, it selects the scoped element, its direct children, and all relationships with them.
|
|
56
|
+
- If used inside an unscoped view, it selects top-level elements and all relationships between them.
|
|
57
|
+
|
|
58
|
+
### Relationship expression
|
|
59
|
+
|
|
60
|
+
Relationship expression uses element expressions as source and target.
|
|
61
|
+
If expression matches, predicate adds matched relationships together with matching source and target elements.
|
|
62
|
+
|
|
63
|
+
- `<expr1> -> <expr2>` - relationships from elements selected by `expr1` to elements selected by `expr2`
|
|
64
|
+
- `<expr1> -> <element_ref>.*` - relationships from elements selected by `expr1` to direct children of `element_ref`
|
|
65
|
+
- `<expr1> <-> <expr2>` - any relationships between elements selected by `expr1` and `expr2` (both directions)
|
|
66
|
+
- `-> <expr>` - any relationships, from accumulated result to the elements selected by `expr`
|
|
67
|
+
- `<expr> ->` - any relationships, from the elements selected by `expr` to accumulated result
|
|
68
|
+
- `-> <expr> ->` - any relationships, between the elements selected by `expr` and accumulated result
|
|
69
|
+
- `* -> *` - all relationships
|
|
70
|
+
|
|
71
|
+
## Filter Conditions
|
|
72
|
+
|
|
73
|
+
After expression is evaluated and selected elements/relationships, filter conditions are applied to refine the selection.
|
|
74
|
+
|
|
75
|
+
Core filters:
|
|
76
|
+
|
|
77
|
+
- Tags: `* where tag is #primary` / `* where tag is not #primary`
|
|
78
|
+
- Kind: `* where kind is component` / `* where kind is not component`
|
|
79
|
+
- Metadata value: `* where metadata.region is "eu"`
|
|
80
|
+
- Missing metadata key: `* where not metadata.owner`
|
|
81
|
+
- Arrays: `metadata.regions is "eu"` matches if the array contains `"eu"`
|
|
82
|
+
- Booleans: `metadata.critical is true`
|
|
83
|
+
- Combine with `and`, `or`, and parentheses
|
|
84
|
+
|
|
85
|
+
For relationship expressions:
|
|
86
|
+
|
|
87
|
+
- `* -> * where tag is #http` - relationship tag
|
|
88
|
+
- `* -> * where metadata.protocol is "grpc"` - relationship metadata
|
|
89
|
+
- `* -> * where source.tag is #primary` - source element tag
|
|
90
|
+
- `* -> * where target.kind is component` - target element kind
|
|
91
|
+
- `* -> * where source.metadata.zone is "public"` - source element metadata
|
|
92
|
+
- `* -> * where target.metadata.zone is "restricted"` - target element metadata
|
|
93
|
+
|
|
94
|
+
The same filters work in `exclude`, for example:
|
|
95
|
+
|
|
96
|
+
```likec4
|
|
97
|
+
exclude * where not metadata.owner
|
|
98
|
+
exclude * -> * where metadata.protocol is "http"
|
|
99
|
+
exclude * -> * where target.metadata.zone is "restricted"
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Use the same `where` forms with `include`.
|
|
103
|
+
|
|
104
|
+
In deployment views, instance tags are cumulative; instance metadata replaces logical metadata as a whole when present, otherwise logical metadata is the fallback.
|
|
105
|
+
|
|
106
|
+
## Customize Predicates
|
|
107
|
+
|
|
108
|
+
Customize predicates allow you to override properties of selected elements/relationships per view (for example, in different diagrams).
|
|
109
|
+
For example:
|
|
110
|
+
|
|
111
|
+
```likec4
|
|
112
|
+
include
|
|
113
|
+
* -> some.component.*
|
|
114
|
+
where
|
|
115
|
+
tag is #primary
|
|
116
|
+
with {
|
|
117
|
+
color red
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
- Selects all relationships incoming to the children of `some.component.*`
|
|
122
|
+
- Filters relationships by tag `#primary`
|
|
123
|
+
- Overrides color of selected relationships to red
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Bidirectional vs. Unidirectional Relationships
|
|
2
|
+
|
|
3
|
+
## Key distinction: model relationships vs. view predicates
|
|
4
|
+
|
|
5
|
+
LikeC4 supports `<->` in two places with related but different meanings:
|
|
6
|
+
|
|
7
|
+
- In `model { ... }`, `<->` declares one semantic bidirectional relationship.
|
|
8
|
+
- In `deployment { ... }`, `<->` declares one semantic bidirectional deployment relationship.
|
|
9
|
+
- In `views { ... }`, `A <-> B` is a binary predicate that includes relationships between two element sets in either direction.
|
|
10
|
+
|
|
11
|
+
## Declaring relationships in the model
|
|
12
|
+
|
|
13
|
+
The short snippets in this reference are fragments unless they include their own element declarations. Declare the
|
|
14
|
+
referenced elements in your model before using them.
|
|
15
|
+
|
|
16
|
+
Use `->` when one element initiates the relationship:
|
|
17
|
+
|
|
18
|
+
```likec4
|
|
19
|
+
model {
|
|
20
|
+
frontend -> api "REST call"
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Use `<->` when both elements actively communicate as one mutual interaction:
|
|
25
|
+
|
|
26
|
+
```likec4
|
|
27
|
+
model {
|
|
28
|
+
frontend <-> backend "synchronizes"
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Bidirectional model relationships render with arrows at both ends by default. Style can still override the rendered arrow tail, but the relationship remains semantically bidirectional for view predicates such as `include -> frontend`.
|
|
33
|
+
|
|
34
|
+
## Kinded bidirectional relationships
|
|
35
|
+
|
|
36
|
+
Use `-[kind]->` for a directed kinded relationship and `-[kind]<->` for a bidirectional kinded relationship:
|
|
37
|
+
|
|
38
|
+
```likec4
|
|
39
|
+
specification {
|
|
40
|
+
element component
|
|
41
|
+
relationship sync
|
|
42
|
+
relationship async
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
model {
|
|
46
|
+
component frontend
|
|
47
|
+
component backend
|
|
48
|
+
|
|
49
|
+
frontend -[async]-> backend "publishes events"
|
|
50
|
+
frontend -[sync]<-> backend "replicates state"
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The relationship kind participates in extension matching. When extending a kinded relationship, include the kind in `extend`; also include the title whenever the relationship is titled.
|
|
55
|
+
|
|
56
|
+
## Bidirectional deployment relationships
|
|
57
|
+
|
|
58
|
+
Deployment relationships use the same notation and semantics:
|
|
59
|
+
|
|
60
|
+
```likec4
|
|
61
|
+
specification {
|
|
62
|
+
element component
|
|
63
|
+
deploymentNode vm
|
|
64
|
+
relationship sync
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
model {
|
|
68
|
+
component database
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
deployment {
|
|
72
|
+
vm vm1 {
|
|
73
|
+
db = instanceOf database
|
|
74
|
+
}
|
|
75
|
+
vm vm2 {
|
|
76
|
+
db = instanceOf database
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
vm1.db <-> vm2.db "replicates"
|
|
80
|
+
vm1 -[sync]<-> vm2 "heartbeat"
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
There is no `extend` for deployment relationships, so extension matching does not apply here.
|
|
85
|
+
|
|
86
|
+
## Extending bidirectional relationships
|
|
87
|
+
|
|
88
|
+
Bidirectional relationship extensions are matched by source, target, kind, title, and bidirectionality. Endpoint order is normalized for bidirectional relationships, so these match the same relationship:
|
|
89
|
+
|
|
90
|
+
```likec4
|
|
91
|
+
model {
|
|
92
|
+
frontend <-> backend "sync"
|
|
93
|
+
|
|
94
|
+
extend backend <-> frontend "sync" {
|
|
95
|
+
metadata {
|
|
96
|
+
protocol "websocket"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Directed and bidirectional matchers are not interchangeable:
|
|
103
|
+
|
|
104
|
+
```likec4
|
|
105
|
+
model {
|
|
106
|
+
frontend -> backend "calls"
|
|
107
|
+
frontend <-> backend "sync"
|
|
108
|
+
|
|
109
|
+
// Matches only the directed relationship.
|
|
110
|
+
extend frontend -> backend "calls" { metadata { protocol "https" } }
|
|
111
|
+
|
|
112
|
+
// Matches only the bidirectional relationship.
|
|
113
|
+
extend frontend <-> backend "sync" { metadata { protocol "websocket" } }
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## When to use one bidirectional relation vs. two directed relations
|
|
118
|
+
|
|
119
|
+
Use one `<->` relationship when the model has one mutual interaction:
|
|
120
|
+
|
|
121
|
+
```likec4
|
|
122
|
+
model {
|
|
123
|
+
primaryDb <-> replicaDb "replicates"
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Use two directed relationships when each direction has separate meaning, labels, technology, or lifecycle:
|
|
128
|
+
|
|
129
|
+
```likec4
|
|
130
|
+
model {
|
|
131
|
+
frontend -> backend "request"
|
|
132
|
+
backend -> frontend "callback"
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
By default LikeC4 may merge opposite relationships into one bidirectional-looking edge. Set `multiple true` in the relationship kind or view style when each direction must render as a separate edge.
|
|
137
|
+
|
|
138
|
+
## Relationship predicates in views
|
|
139
|
+
|
|
140
|
+
Inside views, `<->` is the "any relationship between both sides" predicate. It is binary and matches relationships between the two sides in either direction:
|
|
141
|
+
|
|
142
|
+
```likec4
|
|
143
|
+
views {
|
|
144
|
+
view backend-detail of backend {
|
|
145
|
+
include *
|
|
146
|
+
include -> backend
|
|
147
|
+
include backend ->
|
|
148
|
+
include -> backend ->
|
|
149
|
+
include backend <-> frontend
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
- `-> X` includes incoming relationships to `X`; semantic bidirectional relationships involving `X` are also included.
|
|
155
|
+
- `X ->` includes outgoing relationships from `X`.
|
|
156
|
+
- `-> X ->` includes both incoming and outgoing relationships of `X`.
|
|
157
|
+
- `A <-> B` includes relationships between `A` and `B` in either direction.
|
|
158
|
+
|
|
159
|
+
There is no prefix `<-> X` predicate. Use `-> X ->` when you need both incoming and outgoing relationships around one scope.
|
|
160
|
+
|
|
161
|
+
## Summary
|
|
162
|
+
|
|
163
|
+
| Syntax | Where | Meaning |
|
|
164
|
+
| ------------------- | -------------- | ----------------------------------------------------------- |
|
|
165
|
+
| `A -> B` | model | Directed relationship: A initiates/calls/sends to B |
|
|
166
|
+
| `A <-> B` | model | One bidirectional relationship between A and B |
|
|
167
|
+
| `A <-> B` | deployment | One bidirectional deployment relationship between A and B |
|
|
168
|
+
| `A -[kind]-> B` | model | Directed relationship with relationship kind |
|
|
169
|
+
| `A -[kind]<-> B` | model | Bidirectional relationship with relationship kind |
|
|
170
|
+
| `A -> B` + `B -> A` | model | Two separate directed relationships |
|
|
171
|
+
| `-> X` | view predicate | Incoming relationships to X, plus bidirectional involving X |
|
|
172
|
+
| `X ->` | view predicate | Outgoing relationships from X |
|
|
173
|
+
| `-> X ->` | view predicate | Both incoming and outgoing relationships of X |
|
|
174
|
+
| `A <-> B` | view predicate | Relationships between A and B in either direction |
|
|
175
|
+
|
|
176
|
+
When in doubt, use `->` for request-response patterns where one side initiates. Use `<->` for one mutual interaction, and use two `->` relationships when each direction should be modeled independently.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Specification (LikeC4 DSL)
|
|
2
|
+
|
|
3
|
+
The `specification` block defines all named vocabularies for the project: element kinds, deployment node kinds, relationship kinds, tags, and custom color tokens. Every kind used in `model` or `deployment` blocks must be declared here first.
|
|
4
|
+
|
|
5
|
+
**Key rules:**
|
|
6
|
+
- Specification is global across all files in the project.
|
|
7
|
+
- Duplicate identifiers (same kind, same tag, etc.) will cause a validation error.
|
|
8
|
+
- Multiple `specification` blocks (in one file or across files) are allowed, but not recommended.
|
|
9
|
+
- Keep specification in a dedicated file, e.g. `specification.c4` — changes to specification trigger a full project re-parse, so isolating it reduces edit latency on model/view files.
|
|
10
|
+
|
|
11
|
+
## Syntax
|
|
12
|
+
|
|
13
|
+
```likec4
|
|
14
|
+
specification {
|
|
15
|
+
// Define a tag; outside specification it is referenced as #IDENTIFIER
|
|
16
|
+
tag IDENTIFIER
|
|
17
|
+
|
|
18
|
+
// Define element kind for use in model
|
|
19
|
+
element IDENTIFIER {
|
|
20
|
+
#tag-1 #tag-2 // tags applied to all elements of this kind
|
|
21
|
+
title "default title for this kind"
|
|
22
|
+
technology "default tech for this kind"
|
|
23
|
+
description "default description for this kind"
|
|
24
|
+
notation "legend title for this kind"
|
|
25
|
+
style { ... } // see references/style-tokens-colors.md
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Define deployment node kind for use in deployment block
|
|
29
|
+
deploymentNode IDENTIFIER {
|
|
30
|
+
// same properties and styles as element kind
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Define relationship kind with default properties and styles
|
|
34
|
+
relationship IDENTIFIER {
|
|
35
|
+
technology "default tech for this relationship kind"
|
|
36
|
+
description "default description for this relationship kind"
|
|
37
|
+
style { ... } // default style for this relationship kind
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Define a custom named color token
|
|
41
|
+
color IDENTIFIER #FFFFFF // or rgba(255,255,255,1)
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Example
|
|
46
|
+
|
|
47
|
+
```likec4
|
|
48
|
+
specification {
|
|
49
|
+
element actor { notation "Person"; style { shape person } }
|
|
50
|
+
element service { description "Same for all of the kind"; style { shape component } }
|
|
51
|
+
element webapp { style { shape browser } }
|
|
52
|
+
element queue { style { shape queue; color secondary } }
|
|
53
|
+
element database { style { shape storage } }
|
|
54
|
+
element system
|
|
55
|
+
|
|
56
|
+
relationship async { color amber; line dotted; head diamond; tail vee }
|
|
57
|
+
relationship sql { technology "SQL"; line dashed }
|
|
58
|
+
|
|
59
|
+
tag deprecated
|
|
60
|
+
tag critical
|
|
61
|
+
|
|
62
|
+
deploymentNode environment { notation "Environment"; style { color gray } }
|
|
63
|
+
deploymentNode zone { notation "Network Zone" }
|
|
64
|
+
deploymentNode vm
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Common Mistakes
|
|
69
|
+
|
|
70
|
+
| Mistake | Fix |
|
|
71
|
+
|---------|-----|
|
|
72
|
+
| Using a kind not defined here | Define `element KIND { }` or `deploymentNode KIND { }` in specification first |
|
|
73
|
+
| Duplicate tag or kind identifier | Each identifier must be unique within its type category |
|
|
74
|
+
| `#tag` in specification argument | Tags are defined without `#`; they are used with `#` elsewhere: `tag critical` → `#critical` |
|
|
75
|
+
| Raw hex color in style | Define a named color token first: `color my-blue #003366`, then use `color my-blue` in styles |
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Style Tokens and Colors (LikeC4 DSL)
|
|
2
|
+
|
|
3
|
+
## Canonical color tokens (semantic names)
|
|
4
|
+
|
|
5
|
+
LikeC4 provides a curated set of semantic color tokens. **Prefer these named tokens over raw hex colors** for consistency and automatic light/dark theme adaptation.
|
|
6
|
+
|
|
7
|
+
### Core semantic token palette
|
|
8
|
+
|
|
9
|
+
| Token | Usage | Light appearance | Dark appearance |
|
|
10
|
+
| ----------- | ---------------------------------- | ---------------- | --------------- |
|
|
11
|
+
| `primary` | Primary brand color, main emphasis | #2F80ED (blue) | lighter blue |
|
|
12
|
+
| `secondary` | Secondary accent, de-emphasis | #7C3AED (purple) | lighter purple |
|
|
13
|
+
| `muted` | Muted text, disabled states | #9CA3AF (gray) | lighter gray |
|
|
14
|
+
| `slate` | Neutral backgrounds, borders | #475569 | lighter slate |
|
|
15
|
+
| `blue` | Technical/IT systems | #3B82F6 | lighter blue |
|
|
16
|
+
| `indigo` | Data/analytics systems | #6366F1 | lighter indigo |
|
|
17
|
+
| `sky` | Cloud, external services | #0EA5E9 | lighter sky |
|
|
18
|
+
| `red` | Alerts, critical systems | #EF4444 | lighter red |
|
|
19
|
+
| `gray` | Infrastructure, generic | #6B7280 | lighter gray |
|
|
20
|
+
| `green` | Success, operational systems | #10B981 | lighter green |
|
|
21
|
+
| `amber` | Warnings, async/queue patterns | #F59E0B | lighter amber |
|
|
22
|
+
|
|
23
|
+
## Correct usage: semantic tokens
|
|
24
|
+
|
|
25
|
+
```likec4
|
|
26
|
+
specification {
|
|
27
|
+
element service {
|
|
28
|
+
style { color primary } // ✓ Correct: semantic token
|
|
29
|
+
}
|
|
30
|
+
element critical {
|
|
31
|
+
style { color red } // ✓ Correct: semantic token
|
|
32
|
+
}
|
|
33
|
+
element queue {
|
|
34
|
+
style { color amber } // ✓ Correct: semantic token
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## When hex colors are acceptable
|
|
40
|
+
|
|
41
|
+
Hex colors can be used if you define a custom named color in the specification:
|
|
42
|
+
|
|
43
|
+
```likec4
|
|
44
|
+
specification {
|
|
45
|
+
color my-brand-blue #003366 // Define a custom named token
|
|
46
|
+
|
|
47
|
+
element service {
|
|
48
|
+
style { color my-brand-blue } // Reference the custom token
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Do not use raw hex colors directly in styles without first defining them as named tokens in the specification.**
|
|
54
|
+
|
|
55
|
+
## What NOT to do
|
|
56
|
+
|
|
57
|
+
```likec4
|
|
58
|
+
style { color #FF5733 } // ✗ Wrong: raw hex color
|
|
59
|
+
style { color rgb(255,87,51) } // ✗ Wrong: rgb() notation
|
|
60
|
+
style { color "primary" } // ✗ Wrong: quoted string (remove quotes)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Style tokens vs. theme colors
|
|
64
|
+
|
|
65
|
+
- **Semantic tokens** (`primary`, `secondary`, `muted`, etc.) automatically adapt to light/dark mode.
|
|
66
|
+
- **Custom named colors** defined in specification are explicit hex values; use them sparingly for brand colors.
|
|
67
|
+
- **Raw hex** in a style property is not recommended — always register in specification first.
|
|
68
|
+
|
|
69
|
+
## Icon packs
|
|
70
|
+
|
|
71
|
+
Icons use the format `group:name` (e.g. `tech:react`, `aws:lambda`, `azure:app-service`). Five built-in groups are available:
|
|
72
|
+
|
|
73
|
+
| Group | Count | Examples |
|
|
74
|
+
| ----------- | ----- | ---------------------------------------------- |
|
|
75
|
+
| `aws` | ~307 | `aws:lambda`, `aws:s3`, `aws:dynamo-db` |
|
|
76
|
+
| `azure` | ~614 | `azure:app-service`, `azure:cosmos-db` |
|
|
77
|
+
| `gcp` | ~216 | `gcp:cloud-run`, `gcp:bigquery` |
|
|
78
|
+
| `tech` | ~2000 | `tech:react`, `tech:postgresql`, `tech:docker` |
|
|
79
|
+
| `bootstrap` | ~2051 | `bootstrap:gear`, `bootstrap:person` |
|
|
80
|
+
|
|
81
|
+
To get the full up-to-date list, run `likec4 list-icons` or `likec4 list-icons --group tech` (see `references/cli.md`)
|
|
82
|
+
|
|
83
|
+
## Complete style example
|
|
84
|
+
|
|
85
|
+
```likec4
|
|
86
|
+
specification {
|
|
87
|
+
color brand-orange #FF8C42 // Custom brand color
|
|
88
|
+
|
|
89
|
+
element actor {
|
|
90
|
+
style {
|
|
91
|
+
shape person
|
|
92
|
+
color primary
|
|
93
|
+
icon tech:user
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
element service {
|
|
98
|
+
style {
|
|
99
|
+
shape component
|
|
100
|
+
color primary
|
|
101
|
+
icon tech:gear
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
element critical-service {
|
|
106
|
+
style {
|
|
107
|
+
shape component
|
|
108
|
+
color red // Critical system
|
|
109
|
+
icon tech:alert
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
element queue {
|
|
114
|
+
style {
|
|
115
|
+
shape queue
|
|
116
|
+
color amber // Async/queue pattern
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
model {
|
|
122
|
+
customer = actor {
|
|
123
|
+
style { color primary }
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
api = service {
|
|
127
|
+
style { color primary }
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
alert-responder = critical-service {
|
|
131
|
+
style { color red }
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
job-queue = queue {
|
|
135
|
+
style { color amber }
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Summary
|
|
141
|
+
|
|
142
|
+
| Use case | Correct | Incorrect |
|
|
143
|
+
| --------------------- | ------------------------------------------------------------------------------------ | --------------------------- |
|
|
144
|
+
| Brand primary color | `style { color primary }` | `style { color "#2F80ED" }` |
|
|
145
|
+
| Critical system alert | `style { color red }` | `style { color "#FF0000" }` |
|
|
146
|
+
| Async/queue pattern | `style { color amber }` | `style { color "#FFC107" }` |
|
|
147
|
+
| Custom brand color | Define in spec + use token: `color my-brand #XXXXXX` then `style { color my-brand }` | Use raw hex in style |
|
|
148
|
+
| Theme-aware styling | Use semantic tokens (`primary`, `secondary`, etc.) | Use fixed hex values |
|
|
149
|
+
|
|
150
|
+
**Best practice:** Use semantic color tokens for all element and relationship coloring. Define custom named colors in specification only for brand compliance, never use raw hex in styles.
|