likec4 1.59.4 → 1.61.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.
Files changed (186) hide show
  1. package/README.md +2 -0
  2. package/__app__/codegen/react.mjs +4 -10
  3. package/__app__/codegen/webcomponent.mjs +6 -131
  4. package/__app__/index.html +15 -15
  5. package/__app__/src/aichat/index.mjs +11 -7
  6. package/__app__/src/chunks/AIChat.mjs +1355 -739
  7. package/__app__/src/chunks/ErrorComponent.mjs +444 -0
  8. package/__app__/src/chunks/Header.mjs +269 -0
  9. package/__app__/src/chunks/ViewReact.mjs +438 -0
  10. package/__app__/src/chunks/find.mjs +38 -0
  11. package/__app__/src/chunks/hooks.mjs +158 -472
  12. package/__app__/src/chunks/libs/@tabler/icons-react.mjs +340 -0
  13. package/__app__/src/chunks/libs/@tanstack-ai.mjs +11841 -1417
  14. package/__app__/src/chunks/libs/@tanstack.mjs +5110 -2404
  15. package/__app__/src/chunks/libs/fast-equals.mjs +507 -214
  16. package/__app__/src/chunks/libs/html-to-image.mjs +613 -0
  17. package/__app__/src/chunks/libs/nanostores.mjs +170 -0
  18. package/__app__/src/chunks/libs/react-resizable-panels.mjs +2792 -0
  19. package/__app__/src/chunks/react.mjs +22 -0
  20. package/__app__/src/chunks/rolldown-runtime.mjs +16 -29
  21. package/__app__/src/chunks/router.mjs +106 -0
  22. package/__app__/src/chunks/scope.mjs +106 -0
  23. package/__app__/src/chunks/searchParams.mjs +29 -0
  24. package/__app__/src/chunks/single-index.mjs +465 -0
  25. package/__app__/src/chunks/styled-system.mjs +1826 -2528
  26. package/__app__/src/chunks/useAsync.mjs +69 -0
  27. package/__app__/src/chunks/useSyncedRef.mjs +16 -0
  28. package/__app__/src/components/ColorSchemeToggle.mjs +124 -0
  29. package/__app__/src/components/CopyToClipboard.mjs +53 -0
  30. package/__app__/src/components/ErrorComponent.mjs +1 -0
  31. package/__app__/src/components/NavigationPanel.mjs +63 -0
  32. package/__app__/src/components/NotFound.mjs +155 -0
  33. package/__app__/src/components/ViewOutlet.mjs +9 -0
  34. package/__app__/src/components/model-diff/CompareModelProvider.mjs +44 -0
  35. package/__app__/src/components/model-diff/ModelDiffPanel.mjs +179 -0
  36. package/__app__/src/components/model-diff/compare-model.mjs +76 -0
  37. package/__app__/src/components/model-diff/state.mjs +45 -0
  38. package/__app__/src/components/search/OverviewSearch.mjs +92 -0
  39. package/__app__/src/components/search/OverviewSearchAdapter.mjs +94 -0
  40. package/__app__/src/components/sidebar/DiagramTree.css.mjs +48 -0
  41. package/__app__/src/components/sidebar/DiagramsTree.mjs +304 -0
  42. package/__app__/src/components/sidebar/Drawer.mjs +178 -0
  43. package/__app__/src/components/sidebar/SidebarBurger.mjs +28 -0
  44. package/__app__/src/components/sidebar/data.mjs +94 -0
  45. package/__app__/src/components/sidebar/state.mjs +16 -0
  46. package/__app__/src/components/view-page/Header.mjs +1 -0
  47. package/__app__/src/components/view-page/SelectProject.mjs +258 -0
  48. package/__app__/src/components/view-page/ShareModal.mjs +111 -0
  49. package/__app__/src/components/view-page/share-modal/AlertLocalhost.mjs +31 -0
  50. package/__app__/src/components/view-page/share-modal/CopyButtonChild.mjs +36 -0
  51. package/__app__/src/components/view-page/share-modal/EmbedPanel.mjs +100 -0
  52. package/__app__/src/components/view-page/share-modal/WebcomponentsPanel.mjs +264 -0
  53. package/__app__/src/components/view-page/state.mjs +17 -0
  54. package/__app__/src/context/LikeC4CustomizationContext.mjs +26 -0
  55. package/__app__/src/context/LikeC4IconRendererContext.mjs +29 -0
  56. package/__app__/src/context/LikeC4ModelContext.mjs +34 -0
  57. package/__app__/src/context/LikeC4ProjectsContext.mjs +40 -0
  58. package/__app__/src/context/ModelDiffsContext.mjs +33 -0
  59. package/__app__/src/context/safeCtx.mjs +14 -0
  60. package/__app__/src/fonts.css +112 -1
  61. package/__app__/src/hooks.mjs +1 -0
  62. package/__app__/src/main.mjs +6 -29151
  63. package/__app__/src/pages/EmbedPage.mjs +93 -0
  64. package/__app__/src/pages/ExportPage.mjs +691 -0
  65. package/__app__/src/pages/ProjectsOverview.mjs +23 -0
  66. package/__app__/src/pages/ViewAsD2.mjs +105 -0
  67. package/__app__/src/pages/ViewAsDot.mjs +65 -0
  68. package/__app__/src/pages/ViewAsMmd.mjs +109 -0
  69. package/__app__/src/pages/ViewAsPuml.mjs +105 -0
  70. package/__app__/src/pages/ViewEditor.mjs +220 -0
  71. package/__app__/src/pages/ViewReact.mjs +1 -0
  72. package/__app__/src/pages/export-layout.mjs +95 -0
  73. package/__app__/src/pages/export-page-params.mjs +9 -0
  74. package/__app__/src/pages/styles.css.mjs +23 -0
  75. package/__app__/src/routeTree.gen.mjs +105 -0
  76. package/__app__/src/router.mjs +1 -0
  77. package/__app__/src/routes/__root.mjs +65 -0
  78. package/__app__/src/routes/index.css.mjs +29 -0
  79. package/__app__/src/routes/index.mjs +32 -0
  80. package/__app__/src/routes/project._projectId/-components.mjs +100 -0
  81. package/__app__/src/routes/project._projectId/embed._viewId.mjs +5 -0
  82. package/__app__/src/routes/project._projectId/export._viewId.mjs +24 -0
  83. package/__app__/src/routes/project._projectId/index.mjs +14 -0
  84. package/__app__/src/routes/project._projectId/route.mjs +93 -0
  85. package/__app__/src/routes/project._projectId/view._viewId.d2.mjs +34 -0
  86. package/__app__/src/routes/project._projectId/view._viewId.dot.mjs +41 -0
  87. package/__app__/src/routes/project._projectId/view._viewId.index.mjs +7 -0
  88. package/__app__/src/routes/project._projectId/view._viewId.mjs +23 -0
  89. package/__app__/src/routes/project._projectId/view._viewId.mmd.mjs +39 -0
  90. package/__app__/src/routes/project._projectId/view._viewId.puml.mjs +34 -0
  91. package/__app__/src/routes/projects.mjs +36 -0
  92. package/__app__/src/routes/single-index.mjs +1 -0
  93. package/__app__/src/routes/webcomponent._.mjs +94 -0
  94. package/__app__/src/style.css +18497 -1
  95. package/config/schema.json +146 -97
  96. package/dist/app/render-view-client.css +1 -1
  97. package/dist/app/render-view-client.js +394 -238
  98. package/dist/chunks/enableServer.mjs +1 -1
  99. package/dist/chunks/filenames.mjs +25 -17
  100. package/dist/chunks/generate-likec4.mjs +5 -0
  101. package/dist/chunks/index.d.mts +255 -194
  102. package/dist/chunks/index2.d.mts +8246 -3610
  103. package/dist/chunks/libs/@chenglou/pretext.mjs +9 -0
  104. package/dist/chunks/libs/@chevrotain/gast.mjs +27 -1
  105. package/dist/chunks/libs/@chevrotain/regexp-to-ast.mjs +81 -9
  106. package/dist/chunks/libs/@logtape/logtape.mjs +5 -4
  107. package/dist/chunks/libs/@lume/kiwi.mjs +1 -1
  108. package/dist/chunks/libs/@ts-graphviz/common.d.mts +2 -4
  109. package/dist/chunks/libs/@ts-graphviz/core.mjs +1 -1
  110. package/dist/chunks/libs/birpc.mjs +1 -1
  111. package/dist/chunks/libs/chevrotain-allstar.mjs +2 -2
  112. package/dist/chunks/libs/chevrotain.mjs +88 -36
  113. package/dist/chunks/libs/clone.mjs +1 -0
  114. package/dist/chunks/libs/eventemitter3.mjs +1 -1
  115. package/dist/chunks/libs/fast-equals.mjs +1 -0
  116. package/dist/chunks/libs/fontkit.mjs +1 -0
  117. package/dist/chunks/libs/json5.mjs +4 -4
  118. package/dist/chunks/libs/langium.d.mts +6707 -6715
  119. package/dist/chunks/libs/langium.mjs +16 -24
  120. package/dist/chunks/libs/merge-error-cause.mjs +1 -1
  121. package/dist/chunks/libs/p-limit.mjs +1 -0
  122. package/dist/chunks/libs/p-queue.mjs +1 -1
  123. package/dist/chunks/libs/package-manager-detector.mjs +1 -1
  124. package/dist/chunks/libs/pako.mjs +1 -1
  125. package/dist/chunks/libs/pathe.mjs +1 -1
  126. package/dist/chunks/libs/pretty-ms.mjs +1 -1
  127. package/dist/chunks/libs/remeda.mjs +1 -1
  128. package/dist/chunks/libs/ufo.mjs +1 -1
  129. package/dist/chunks/libs/unstorage.mjs +1 -1
  130. package/dist/chunks/libs/which.mjs +1 -1
  131. package/dist/chunks/node.mjs +111 -77
  132. package/dist/chunks/rolldown-runtime.mjs +1 -1
  133. package/dist/chunks/sequence-view.mjs +1 -1
  134. package/dist/chunks/vite-plugin.mjs +185 -166
  135. package/dist/cli/index.mjs +254 -1306
  136. package/dist/config/index.d.mts +66 -5
  137. package/dist/config/index.mjs +1 -1
  138. package/dist/generators/likec4.d.mts +6530 -0
  139. package/dist/generators/likec4.mjs +1 -0
  140. package/dist/index.d.mts +2 -4
  141. package/dist/model/index.d.mts +0 -7
  142. package/dist/vite-plugin/index.d.mts +83 -58
  143. package/dist/vite-plugin/index.mjs +1 -1
  144. package/dist/vite-plugin/internal/chunks/rolldown-runtime.mjs +8 -0
  145. package/dist/vite-plugin/internal/index.d.mts +92 -17
  146. package/dist/vite-plugin/internal/index.mjs +225 -126
  147. package/generators/likec4/package.json +4 -0
  148. package/package.json +134 -122
  149. package/react/index.d.mts +7496 -26659
  150. package/react/index.mjs +533 -63936
  151. package/react/rolldown-runtime-CfRud99p.js +1 -0
  152. package/skills/likec4-dsl/SKILL.md +474 -0
  153. package/skills/likec4-dsl/evals/evals-public.json +207 -0
  154. package/skills/likec4-dsl/evals/grading-spec.json +603 -0
  155. package/skills/likec4-dsl/references/bridge-leanix-drawio.md +42 -0
  156. package/skills/likec4-dsl/references/cli.md +168 -0
  157. package/skills/likec4-dsl/references/configuration.md +266 -0
  158. package/skills/likec4-dsl/references/deployment.md +160 -0
  159. package/skills/likec4-dsl/references/diffs.md +52 -0
  160. package/skills/likec4-dsl/references/dynamic-views.md +455 -0
  161. package/skills/likec4-dsl/references/examples.md +370 -0
  162. package/skills/likec4-dsl/references/identifier-validity.md +90 -0
  163. package/skills/likec4-dsl/references/include-predicates-wildcards.md +180 -0
  164. package/skills/likec4-dsl/references/model.md +182 -0
  165. package/skills/likec4-dsl/references/predicates.md +123 -0
  166. package/skills/likec4-dsl/references/relationships-bidirectional.md +176 -0
  167. package/skills/likec4-dsl/references/specification.md +79 -0
  168. package/skills/likec4-dsl/references/style-tokens-colors.md +150 -0
  169. package/skills/likec4-dsl/references/troubleshooting.md +101 -0
  170. package/skills/likec4-dsl/references/views.md +329 -0
  171. package/vite-plugin-modules.d.ts +126 -51
  172. package/__app__/src/chunks/LikeC4Styles.mjs +0 -2306
  173. package/__app__/src/chunks/ProjectsOverview.mjs +0 -537
  174. package/__app__/src/chunks/es.mjs +0 -439
  175. package/__app__/src/chunks/libs/@floating-ui.mjs +0 -2532
  176. package/__app__/src/chunks/libs/@mantine.mjs +0 -13868
  177. package/__app__/src/chunks/libs/@xstate/react.mjs +0 -2015
  178. package/__app__/src/chunks/libs/@xyflow/react.mjs +0 -5367
  179. package/__app__/src/chunks/libs/bezier-js.mjs +0 -1007
  180. package/__app__/src/chunks/libs/d3.mjs +0 -2817
  181. package/__app__/src/chunks/libs/framer.mjs +0 -5926
  182. package/__app__/src/chunks/libs/zod.mjs +0 -3176
  183. package/dist/chunks/libs/@chevrotain/types.d.mts +0 -108
  184. package/dist/chunks/libs/picomatch.mjs +0 -1
  185. package/dist/chunks/libs/zod.d.mts +0 -3840
  186. package/dist/chunks/libs/zod.mjs +0 -65
@@ -0,0 +1,182 @@
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; link other elements with `[[fqn]]`. If > 150 chars, 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
+
125
+ Elements have no `navigateTo` property. To set where a click on an element navigates, override it in a view: `include api with { navigateTo detail }`.
126
+
127
+ ## Relationship Properties
128
+
129
+ `title`, `description`, `technology`, `metadata`, `style`, `link`, `navigateTo`
130
+
131
+ ## Element Links in Markdown
132
+
133
+ Markdown values (`'''…'''` / `"""…"""`) can link to elements and views of the current project:
134
+
135
+ ```likec4
136
+ model {
137
+ cloud = system 'Cloud' {
138
+ ui = container 'Web UI'
139
+ api = container 'API' {
140
+ summary '''
141
+ Serves [[cloud.ui]]
142
+ '''
143
+ }
144
+ ui -> api 'calls' {
145
+ description '''
146
+ Requests go to [[cloud.api|the API]], see [[view:index]].
147
+ Not a link: \\[[cloud.api]] and `[[cloud.api]]`
148
+ '''
149
+ }
150
+ }
151
+ }
152
+ ```
153
+
154
+ - `[[fqn]]` renders the element title, `[[fqn|Label]]` a custom label, `[[view:id]]` the view title. In the diagram, links open the element details or navigate to the view.
155
+ - Works in every Markdown value: element, deployment, relationship and view `description`, `summary`, `title`, `technology`, `notes`, metadata values. Plain `'…'` strings and code (inline or fenced) are not scanned.
156
+ - FQN is absolute and resolved in the current project only: `[[cloud.backend.api]]`, never `[[api]]` or `[[this]]`. Imported elements are not supported.
157
+ - Escaping follows DSL strings: literal `[[` is `\\[[`; in a Markdown table cell write the separator as `\\|`, e.g. `[[cloud.api\\|API]]`.
158
+ - Unknown element, unknown view, or unknown `prefix:` is a **warning**: the model still builds and `likec4 validate` stays valid unless `--max-warnings` is given. In the editor, `[[` triggers completion and Go to Definition jumps to the target.
159
+ - Prefer `[[fqn]]` over repeating element names in descriptions; link only elements that exist.
160
+
161
+ ## Extend Patterns
162
+
163
+ ```likec4
164
+ // Add metadata and a link to an existing element from another file:
165
+ extend cloud.backend.api {
166
+ metadata { team "platform"; criticality "high" }
167
+ link ./adr-002.md "Scaling decision"
168
+ }
169
+
170
+ // Extend an untyped relationship:
171
+ extend cloud.ui.dashboard -> cloud.backend.api {
172
+ metadata { sla "99.9%" }
173
+ }
174
+
175
+ // Extend a typed relationship — include KIND to avoid ambiguous match:
176
+ extend cloud.ui.dashboard -[http]-> cloud.backend.api "calls" {
177
+ metadata { sla "99.9%" }
178
+ }
179
+
180
+ // Wrong: if a typed relationship exists, this silently targets the wrong relation
181
+ // extend cloud.ui.dashboard -> cloud.backend.api "calls" { ... }
182
+ ```
@@ -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,79 @@
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
+
7
+ - Specification is global across all files in the project.
8
+ - Duplicate identifiers (same kind, same tag, etc.) will cause a validation error.
9
+ - Multiple `specification` blocks (in one file or across files) are allowed, but not recommended.
10
+ - 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.
11
+
12
+ ## Syntax
13
+
14
+ ```likec4
15
+ specification {
16
+ // Define a tag; outside specification it is referenced as #IDENTIFIER
17
+ tag IDENTIFIER
18
+
19
+ // Define element kind for use in model
20
+ element IDENTIFIER {
21
+ #tag-1 #tag-2 // tags applied to all elements of this kind
22
+ title "default title for this kind"
23
+ technology "default tech for this kind"
24
+ description "default description for this kind"
25
+ notation "legend title for this kind"
26
+ style { ... } // see references/style-tokens-colors.md
27
+ }
28
+
29
+ // Define deployment node kind for use in deployment block
30
+ deploymentNode IDENTIFIER {
31
+ // same properties and styles as element kind
32
+ }
33
+
34
+ // Define relationship kind with default properties and styles
35
+ relationship IDENTIFIER {
36
+ technology "default tech for this relationship kind"
37
+ description "default description for this relationship kind"
38
+ // default style properties go directly in the body, not in a style block
39
+ color amber
40
+ line dashed
41
+ head diamond
42
+ }
43
+
44
+ // Define a custom named color token
45
+ color IDENTIFIER #FFFFFF // or rgba(255,255,255,1)
46
+ }
47
+ ```
48
+
49
+ ## Example
50
+
51
+ ```likec4
52
+ specification {
53
+ element actor { notation "Person"; style { shape person } }
54
+ element service { description "Same for all of the kind"; style { shape component } }
55
+ element webapp { style { shape browser } }
56
+ element queue { style { shape queue; color secondary } }
57
+ element database { style { shape storage } }
58
+ element system
59
+
60
+ relationship async { color amber; line dotted; head diamond; tail vee }
61
+ relationship sql { technology "SQL"; line dashed }
62
+
63
+ tag deprecated
64
+ tag critical
65
+
66
+ deploymentNode environment { notation "Environment"; style { color gray } }
67
+ deploymentNode zone { notation "Network Zone" }
68
+ deploymentNode vm
69
+ }
70
+ ```
71
+
72
+ ## Common Mistakes
73
+
74
+ | Mistake | Fix |
75
+ | -------------------------------- | --------------------------------------------------------------------------------------------- |
76
+ | Using a kind not defined here | Define `element KIND { }` or `deploymentNode KIND { }` in specification first |
77
+ | Duplicate tag or kind identifier | Each identifier must be unique within its type category |
78
+ | `#tag` in specification argument | Tags are defined without `#`; they are used with `#` elsewhere: `tag critical` → `#critical` |
79
+ | Raw hex color in style | Define a named color token first: `color my-blue #003366`, then use `color my-blue` in styles |