likec4 1.60.0 → 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 (157) hide show
  1. package/README.md +2 -0
  2. package/__app__/codegen/react.mjs +4 -10
  3. package/__app__/codegen/webcomponent.mjs +5 -208
  4. package/__app__/index.html +15 -15
  5. package/__app__/src/aichat/index.mjs +1 -2
  6. package/__app__/src/chunks/AIChat.mjs +292 -117
  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 +18 -541
  12. package/__app__/src/chunks/libs/@tabler/icons-react.mjs +340 -0
  13. package/__app__/src/chunks/libs/@tanstack-ai.mjs +11101 -1797
  14. package/__app__/src/chunks/libs/@tanstack.mjs +4563 -3083
  15. package/__app__/src/chunks/libs/fast-equals.mjs +140 -71
  16. package/__app__/src/chunks/{es.mjs → libs/html-to-image.mjs} +16 -22
  17. package/__app__/src/chunks/libs/nanostores.mjs +4 -8
  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 +3 -32
  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 +1916 -2946
  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/hooks.mjs +1 -0
  61. package/__app__/src/main.mjs +4 -48126
  62. package/__app__/src/pages/EmbedPage.mjs +93 -0
  63. package/__app__/src/pages/ExportPage.mjs +691 -0
  64. package/__app__/src/pages/ProjectsOverview.mjs +23 -0
  65. package/__app__/src/pages/ViewAsD2.mjs +105 -0
  66. package/__app__/src/pages/ViewAsDot.mjs +65 -0
  67. package/__app__/src/pages/ViewAsMmd.mjs +109 -0
  68. package/__app__/src/pages/ViewAsPuml.mjs +105 -0
  69. package/__app__/src/pages/ViewEditor.mjs +220 -0
  70. package/__app__/src/pages/ViewReact.mjs +1 -0
  71. package/__app__/src/pages/export-layout.mjs +95 -0
  72. package/__app__/src/pages/export-page-params.mjs +9 -0
  73. package/__app__/src/pages/styles.css.mjs +23 -0
  74. package/__app__/src/routeTree.gen.mjs +105 -0
  75. package/__app__/src/router.mjs +1 -0
  76. package/__app__/src/routes/__root.mjs +65 -0
  77. package/__app__/src/routes/index.css.mjs +29 -0
  78. package/__app__/src/routes/index.mjs +32 -0
  79. package/__app__/src/routes/project._projectId/-components.mjs +100 -0
  80. package/__app__/src/routes/project._projectId/embed._viewId.mjs +5 -0
  81. package/__app__/src/routes/project._projectId/export._viewId.mjs +24 -0
  82. package/__app__/src/routes/project._projectId/index.mjs +14 -0
  83. package/__app__/src/routes/project._projectId/route.mjs +93 -0
  84. package/__app__/src/routes/project._projectId/view._viewId.d2.mjs +34 -0
  85. package/__app__/src/routes/project._projectId/view._viewId.dot.mjs +41 -0
  86. package/__app__/src/routes/project._projectId/view._viewId.index.mjs +7 -0
  87. package/__app__/src/routes/project._projectId/view._viewId.mjs +23 -0
  88. package/__app__/src/routes/project._projectId/view._viewId.mmd.mjs +39 -0
  89. package/__app__/src/routes/project._projectId/view._viewId.puml.mjs +34 -0
  90. package/__app__/src/routes/projects.mjs +36 -0
  91. package/__app__/src/routes/single-index.mjs +1 -0
  92. package/__app__/src/routes/webcomponent._.mjs +94 -0
  93. package/__app__/src/style.css +1156 -1147
  94. package/config/schema.json +26 -2
  95. package/dist/app/render-view-client.css +1 -1
  96. package/dist/app/render-view-client.js +375 -393
  97. package/dist/chunks/filenames.mjs +26 -20
  98. package/dist/chunks/generate-likec4.mjs +4 -4
  99. package/dist/chunks/index.d.mts +16 -15
  100. package/dist/chunks/index2.d.mts +7041 -3293
  101. package/dist/chunks/libs/@chenglou/pretext.mjs +9 -0
  102. package/dist/chunks/libs/@logtape/logtape.mjs +5 -5
  103. package/dist/chunks/libs/@ts-graphviz/common.d.mts +2 -4
  104. package/dist/chunks/libs/chevrotain.mjs +19 -19
  105. package/dist/chunks/libs/clone.mjs +1 -0
  106. package/dist/chunks/libs/eventemitter3.mjs +1 -1
  107. package/dist/chunks/libs/fast-equals.mjs +1 -0
  108. package/dist/chunks/libs/fontkit.mjs +1 -0
  109. package/dist/chunks/libs/langium.d.mts +80 -2933
  110. package/dist/chunks/libs/langium.mjs +6 -6
  111. package/dist/chunks/libs/pako.mjs +1 -1
  112. package/dist/chunks/libs/pathe.mjs +1 -1
  113. package/dist/chunks/libs/remeda.mjs +1 -1
  114. package/dist/chunks/node.mjs +110 -77
  115. package/dist/chunks/rolldown-runtime.mjs +1 -1
  116. package/dist/chunks/sequence-view.mjs +1 -1
  117. package/dist/chunks/vite-plugin.mjs +183 -164
  118. package/dist/cli/index.mjs +157 -101
  119. package/dist/config/index.d.mts +65 -4
  120. package/dist/config/index.mjs +1 -1
  121. package/dist/generators/likec4.d.mts +16 -64
  122. package/dist/index.d.mts +2 -4
  123. package/dist/model/index.d.mts +0 -10
  124. package/dist/vite-plugin/index.d.mts +83 -61
  125. package/dist/vite-plugin/internal/chunks/rolldown-runtime.mjs +1 -2
  126. package/dist/vite-plugin/internal/index.d.mts +91 -17
  127. package/dist/vite-plugin/internal/index.mjs +156 -110
  128. package/package.json +60 -55
  129. package/react/index.d.mts +3010 -4014
  130. package/react/index.mjs +170 -171
  131. package/react/rolldown-runtime-CfRud99p.js +1 -0
  132. package/skills/likec4-dsl/SKILL.md +71 -25
  133. package/skills/likec4-dsl/evals/evals-public.json +5 -0
  134. package/skills/likec4-dsl/evals/grading-spec.json +15 -1
  135. package/skills/likec4-dsl/references/cli.md +39 -10
  136. package/skills/likec4-dsl/references/configuration.md +5 -5
  137. package/skills/likec4-dsl/references/diffs.md +52 -0
  138. package/skills/likec4-dsl/references/examples.md +2 -2
  139. package/skills/likec4-dsl/references/identifier-validity.md +31 -31
  140. package/skills/likec4-dsl/references/include-predicates-wildcards.md +16 -15
  141. package/skills/likec4-dsl/references/model.md +42 -11
  142. package/skills/likec4-dsl/references/specification.md +11 -7
  143. package/skills/likec4-dsl/references/troubleshooting.md +47 -42
  144. package/skills/likec4-dsl/references/views.md +2 -2
  145. package/vite-plugin-modules.d.ts +126 -51
  146. package/__app__/src/chunks/LikeC4Styles.mjs +0 -4522
  147. package/__app__/src/chunks/ProjectsOverview.mjs +0 -827
  148. package/__app__/src/chunks/libs/@floating-ui.mjs +0 -3286
  149. package/__app__/src/chunks/libs/@mantine.mjs +0 -17731
  150. package/__app__/src/chunks/libs/@xstate/react.mjs +0 -3471
  151. package/__app__/src/chunks/libs/@xyflow/react.mjs +0 -7927
  152. package/__app__/src/chunks/libs/bezier-js.mjs +0 -1593
  153. package/__app__/src/chunks/libs/d3.mjs +0 -4531
  154. package/__app__/src/chunks/libs/framer.mjs +0 -11331
  155. package/__app__/src/chunks/libs/zod.mjs +0 -5404
  156. package/dist/chunks/libs/@chevrotain/types.d.mts +0 -111
  157. package/react/rolldown-runtime-DnkiqaRY.js +0 -1
@@ -0,0 +1 @@
1
+ var e=Object.create,t=Object.defineProperty,__name=(e,n)=>t(e,`name`,{value:n,configurable:!0}),n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,__commonJSMin=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t,t.exports),e=null),t.exports),__copyProps=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},__toESM=(n,r,o)=>(o=n==null?{}:e(i(n)),__copyProps(r||!n||!n.__esModule||!a.call(n,`default`)?t(o,`default`,{value:n,enumerable:!0}):o,n));export{__name as n,__toESM as r,__commonJSMin as t};
@@ -10,10 +10,10 @@ Architecture-as-code tool. Describe systems in `.c4`/`.likec4` files and LikeC4
10
10
  ## Rules
11
11
 
12
12
  1. **Projects** - it is possible to have multiple likec4 projects in a workspace, project is determined by presence of a config file (`.likec4rc`, `likec4.config.{ts,js,json}`). LikeC4 files belong to the project of the nearest config file in the directory hierarchy.
13
- 2. **Top-level statements** — only `import`, `specification`, `model`, `deployment`, `views`, `global` are allowed. Blocks can repeat, but at least one per file must be present.
13
+ 2. **Top-level statements** — only `import`, `specification`, `model`, `deployment`, `views`, `global`, `diff` are allowed. Blocks can repeat, but at least one per file must be present.
14
14
  3. **Multi-file merge** — Top-level blocks across files are merged. For example, `model { ... }` blocks present in multiple files, parsed separately, and then merged into a single model.
15
15
  4. **Strings** — `'single'`, `"double"` — all support multi-line. Escape quotes with backslash: `\'` or `\"`. In a `title`, escape `\/` to include a literal `/` without it being read as a view-folder separator.
16
- 5. **Markdown** — properties like `summary`/`description`/`notes` can contain Markdown. Use triple quotes `'''` or `"""`. Begin a new line after opening quotes and indent Markdown content for better formatting and syntax highlighting.
16
+ 5. **Markdown** — properties like `summary`/`description`/`notes` can contain Markdown. Use triple quotes `'''` or `"""`. Begin a new line after opening quotes and indent Markdown content for better formatting and syntax highlighting. Markdown can link to elements and views: `[[cloud.api]]`, `[[cloud.api|API]]`, `[[view:index]]` (see "Element links in Markdown" below).
17
17
  6. **Comments** — `// single line` and `/* multi-line */` comments supported anywhere.
18
18
  7. **Identifier** — letters, digits, hyphens, underscores only. No dots (dots are FQN separators). Can't start with a digit. Examples: `customer`, `payment-service`, `frontendApp`, `queue-1`. **Critical:** `payment-api` is valid; `payment.api` is NOT an identifier (dots separate FQN hierarchy). See `references/identifier-validity.md`.
19
19
  8. **FQN** — Fully Qualified Name (FQN) is a dot-separated path to an element, MUST be unique within the project. Examples: `customer`, `saas.backend.payment-service.paymentsApi`, `infra.eu.zone1.node1`.
@@ -95,6 +95,7 @@ For strict command/snippet prompts, keep a compact loop:
95
95
  - deployment naming requirement satisfied
96
96
  - relationship matcher specificity (`kind`, `title` when needed)
97
97
  - dynamic view exactness: return arrows, chain form, single parallel block when requested, flow-control block placement (`alt` branches, no nested `parallel`, try/catch/finally order)
98
+ - Markdown links: `[[fqn]]` only inside `'''`/`"""`, full FQN that exists in the model, `\\|` as label separator inside tables
98
99
 
99
100
  3. **Finalize** by fixing in place (no extra alternatives unless explicitly requested).
100
101
 
@@ -119,6 +120,7 @@ pnpm dlx likec4 validate --json --no-layout --file <edited-file> <project-dir>
119
120
  - `--json` — structured output (stdout), logging goes to stderr
120
121
  - `--no-layout` — skip layout drift checks (faster, only syntax+semantic)
121
122
  - `--file <path>` — use with `--json` to scope results to the edited files. Without `--json`, text output still prints all diagnostics. Repeat once per edited source file.
123
+ - `--max-warnings <n>` — fail (`valid: false`, exit code 1) when there are more than `n` warnings; `0` fails on any warning. Without it, warnings never fail validation.
122
124
  - `<project-dir>` — path to the project directory
123
125
  - There is **no** `likec4 check` command; use `likec4 validate`.
124
126
 
@@ -139,11 +141,15 @@ Example output:
139
141
  "range": { "start": { "line": 5, "character": 2 }, "end": { "line": 5, "character": 20 } }
140
142
  }
141
143
  ],
144
+ "warnings": [], // same shape as errors
145
+ "maxWarnings": null, // value of --max-warnings, null when not given
142
146
  "stats": {
143
147
  "totalFiles": 100, // Total number of files in the project
144
148
  "totalErrors": 500, // Total number of errors in the project
149
+ "totalWarnings": 3, // Total number of warnings in the project
145
150
  "filteredFiles": 1, // Number of files that match the --file filter
146
- "filteredErrors": 1 // Number of errors in the filtered files
151
+ "filteredErrors": 1, // Number of errors in the filtered files
152
+ "filteredWarnings": 0 // Number of warnings in the filtered files
147
153
  }
148
154
  }
149
155
  ```
@@ -155,6 +161,7 @@ Field semantics (must be explicit in answers):
155
161
  - `filteredFiles`: count of files actually included by repeated `--file` filters
156
162
  - `filteredErrors`: errors in the filtered subset only
157
163
  - `totalErrors`: errors across the full project model
164
+ - `filteredWarnings`: warnings in the filtered subset only; `--max-warnings` limits this count
158
165
 
159
166
  Example edge case: if you pass 3 files but one is `likec4.config.json`, `filteredFiles` may be `2` because config JSON is not a `.c4`/`.likec4` source file for DSL validation.
160
167
 
@@ -241,6 +248,43 @@ For strict repair prompts about deployment views, the safe answer is **local `st
241
248
 
242
249
  Mini-reminder: in deployment views, treat `include ... with {}` and `global style ...` as unsupported repair patterns. Use a local `style ... {}` rule inside the deployment view instead.
243
250
 
251
+ ### Element links in Markdown (`[[fqn]]`)
252
+
253
+ ```likec4
254
+ model {
255
+ cloud = system 'Cloud' {
256
+ ui = container 'Web UI'
257
+ api = container 'API' {
258
+ description '''
259
+ Called by [[cloud.ui]] and [[cloud.ui|the frontend]].
260
+ See [[view:index]] for context.
261
+ Literal brackets: \\[[not a link]]
262
+
263
+ | Caller | Protocol |
264
+ | --------------------- | -------- |
265
+ | [[cloud.ui\\|Web UI]] | HTTPS |
266
+ '''
267
+ }
268
+ }
269
+ }
270
+ ```
271
+
272
+ - `[[cloud.ui]]` — element link, rendered with the element title
273
+ - `[[cloud.ui|UI]]` — element link with custom label `UI`
274
+ - `[[view:index]]` — view link, rendered with the view title
275
+ - `\\[[` — literal `[[`, not a link
276
+ - `[[cloud.ui\\|UI]]` — labelled link inside a Markdown table cell
277
+
278
+ Truth card:
279
+
280
+ - Only in Markdown values (`'''…'''` / `"""…"""`): `description`, `summary`, `notes`, `title`, `technology`, metadata values. Plain `'…'` / `"…"` strings, inline code and fenced code blocks are not scanned.
281
+ - Target is an **absolute FQN** in the **current project**: no short names, no `this`, no imported elements. `view:` is the only namespace; any other `prefix:` is reserved.
282
+ - Escaping follows DSL strings (`\\` → `\` before Markdown sees it): literal `[[` is `\\[[`; inside tables write `\\|`, a bare `|` splits the cell.
283
+ - Missing element/view or unknown `prefix:` → **warning**, not error. `likec4 validate` lists it under `warnings` but stays `valid: true` unless `--max-warnings` is given (`--max-warnings 0` fails on any warning); editors show it as an LSP diagnostic.
284
+ - Exports and MCP replace links with the title (or label); the DSL generator keeps `[[…]]`.
285
+
286
+ Agent guidance: in descriptions prefer `[[fqn]]` over retyping an element's name (title stays in sync, readers can click it); link only FQNs that exist in the model; use `\\|` in tables.
287
+
244
288
  ## LikeC4 Project Configuration
245
289
 
246
290
  Config file (`likec4.config.json`, `.likec4rc`, or `likec4.config.{ts,js}`) defines a project. Its location sets the project scope (LikeC4 files belong to the project of the nearest config file in the directory hierarchy).
@@ -384,12 +428,13 @@ Return-arrow precision:
384
428
 
385
429
  ## Anti-Patterns to Avoid in Strict Prompts
386
430
 
387
- | Anti-pattern | Why it fails | Correct behavior |
388
- | ------------------------------------------------------------------ | ---------------------------------------------- | --------------------------------------------------------- |
389
- | Substituting command families (`check`/`build`) for `validate` | Breaks exact command contract | Keep `likec4 validate` |
390
- | Inventing/guessing flags | Creates non-portable invalid commands | Use canonical documented flags only |
391
- | Multiple alternative snippets for one strict ask | Reduces precision; fails strict-output grading | Output one final answer unless alternatives are requested |
392
- | Extending typed relationship without kind/title in ambiguous graph | Can target wrong relationship | Match with source + target + kind (+ title when needed) |
431
+ | Anti-pattern | Why it fails | Correct behavior |
432
+ | ------------------------------------------------------------------ | ----------------------------------------------------------------------------- | --------------------------------------------------------- |
433
+ | Substituting command families (`check`/`build`) for `validate` | Breaks exact command contract | Keep `likec4 validate` |
434
+ | Inventing/guessing flags | Creates non-portable invalid commands | Use canonical documented flags only |
435
+ | Multiple alternative snippets for one strict ask | Reduces precision; fails strict-output grading | Output one final answer unless alternatives are requested |
436
+ | Extending typed relationship without kind/title in ambiguous graph | Can target wrong relationship | Match with source + target + kind (+ title when needed) |
437
+ | Short or guessed FQN in `[[…]]`, e.g. `[[api]]` | Broken link is only a warning; validate passes unless `--max-warnings` is set | Use an existing full FQN: `[[cloud.backend.api]]` |
393
438
 
394
439
  ## Common Mistakes & Debugging
395
440
 
@@ -409,20 +454,21 @@ When a model errors or an eval answer seems wrong, load `references/troubleshoot
409
454
 
410
455
  Load a reference file when the task involves the corresponding topic. Claude reads SKILL.md first; these files are loaded on demand only when needed.
411
456
 
412
- | File | Purpose — load when... |
413
- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
414
- | `references/specification.md` | Writing/editing `specification { }` blocks, defining element/deploymentNode/relationship/tag/color kinds |
415
- | `references/model.md` | Writing/editing `model { }` blocks, element hierarchy, relationships, `extend` patterns, property names |
416
- | `references/deployment.md` | Writing/editing `deployment { }` blocks, `instanceOf`, named instances, multi-environment topology, deployment metadata filters |
417
- | `references/style-tokens-colors.md` | Applying colors, shapes, icons, or relationship line styles; need exact token names |
418
- | `references/views.md` | Writing views, include/exclude rules, style rules in views, groups, autoLayout, global predicates |
419
- | `references/predicates.md` | Complex `where` conditions, metadata filters, `with` overrides, global predicate groups, reusable predicates |
420
- | `references/include-predicates-wildcards.md` | Wildcard confusion suspected (`*` vs `_` vs `**`); need exact scoped-view semantics |
457
+ | File | Purpose — load when... |
458
+ | -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
459
+ | `references/specification.md` | Writing/editing `specification { }` blocks, defining element/deploymentNode/relationship/tag/color kinds |
460
+ | `references/model.md` | Writing/editing `model { }` blocks, element hierarchy, relationships, `extend` patterns, property names, `[[fqn]]` links |
461
+ | `references/deployment.md` | Writing/editing `deployment { }` blocks, `instanceOf`, named instances, multi-environment topology, deployment metadata filters |
462
+ | `references/style-tokens-colors.md` | Applying colors, shapes, icons, or relationship line styles; need exact token names |
463
+ | `references/views.md` | Writing views, include/exclude rules, style rules in views, groups, autoLayout, global predicates |
464
+ | `references/predicates.md` | Complex `where` conditions, metadata filters, `with` overrides, global predicate groups, reusable predicates |
465
+ | `references/include-predicates-wildcards.md` | Wildcard confusion suspected (`*` vs `_` vs `**`); need exact scoped-view semantics |
421
466
  | `references/dynamic-views.md` | Writing dynamic views: steps, return arrows, chained steps, flow-control blocks (`parallel`/`opt`/`loop`/`alt`/`try`), `variant sequence` |
422
- | `references/identifier-validity.md` | Identifier vs FQN confusion; "dots in names" errors; understanding FQN construction |
423
- | `references/relationships-bidirectional.md` | Bidirectional relationship syntax and `<->` view predicate patterns |
424
- | `references/bridge-leanix-drawio.md` | LeanIX bridge · `drawio --profile leanix` · round-trip · mapping · MCP vs bridge · sync/artifacts/managed cells |
425
- | `references/cli.md` | Full CLI reference: serve, build, export, codegen, mcp, format; flag disambiguation |
426
- | `references/configuration.md` | Project config options, multi-project setup, include/exclude paths, generators |
427
- | `references/examples.md` | Compact real-world examples: extend, groups, globals, dynamic views, deployment, rank |
428
- | `references/troubleshooting.md` | Errors, unexpected output, eval failures — 6 error tables, 5-step debug workflow, 7 best practices |
467
+ | `references/identifier-validity.md` | Identifier vs FQN confusion; "dots in names" errors; understanding FQN construction |
468
+ | `references/relationships-bidirectional.md` | Bidirectional relationship syntax and `<->` view predicate patterns |
469
+ | `references/diffs.md` | Planned model changes (`diff` blocks), applying or discarding them, safe delete of elements |
470
+ | `references/bridge-leanix-drawio.md` | LeanIX bridge · `drawio --profile leanix` · round-trip · mapping · MCP vs bridge · sync/artifacts/managed cells |
471
+ | `references/cli.md` | Full CLI reference: serve, build, export, codegen, mcp, format; flag disambiguation |
472
+ | `references/configuration.md` | Project config options, multi-project setup, include/exclude paths, generators |
473
+ | `references/examples.md` | Compact real-world examples: extend, groups, globals, dynamic views, deployment, rank |
474
+ | `references/troubleshooting.md` | Errors, unexpected output, eval failures — 6 error tables, 5-step debug workflow, 7 best practices |
@@ -197,6 +197,11 @@
197
197
  "id": 38,
198
198
  "prompt": "Start your answer with exactly `Invalid.` or `Valid.` on the first line. Is this dynamic view valid?\n```likec4\ndynamic view flow {\n alt {\n loop {\n a -> b\n }\n }\n}\n```\nExplain in one sentence why, then give the corrected minimal snippet that keeps the `loop` but satisfies the `alt`-branch rule.",
199
199
  "files": []
200
+ },
201
+ {
202
+ "id": 39,
203
+ "prompt": "The model has `cloud.ui` (title \"Web UI\") and `cloud.api`, and a view `index`. Give me a minimal paste-ready `description` property for `cloud.api` that (1) links to `cloud.ui` in a sentence so the element title is shown, (2) links to the view `index`, and (3) has a Markdown table with one row whose first cell links to `cloud.ui` with the label `Frontend`. Snippet first, then one sentence on what happens if a linked FQN does not exist.",
204
+ "files": []
200
205
  }
201
206
  ]
202
207
  }
@@ -224,7 +224,7 @@
224
224
  "files": [],
225
225
  "expectations": [
226
226
  "The response identifies that `styles` is an invalid top-level statement.",
227
- "The response mentions allowed top-level statements (`import`, `specification`, `model`, `deployment`, `views`, `global`).",
227
+ "The response mentions allowed top-level statements (`import`, `specification`, `model`, `deployment`, `views`, `global`, `diff`).",
228
228
  "The corrected file uses only allowed top-level statements.",
229
229
  "The corrected DSL demonstrates styling intent via valid constructs (e.g., `global styleGroup` and applying in `views`).",
230
230
  "The output is a minimal valid LikeC4 file, not only prose."
@@ -543,6 +543,20 @@
543
543
  "The corrected snippet is minimal and syntactically valid LikeC4 DSL."
544
544
  ],
545
545
  "grading_guidance": "This is a contrastive placement-rule eval. The exact opening verdict `Invalid.` and the alt-branch rule are the primary signals. Reject answers that call the snippet valid, or that 'fix' it by removing the `loop` or by dropping the `alt` block entirely instead of nesting the loop inside a branch. `if` is an accepted alias for `when`."
546
+ },
547
+ {
548
+ "id": 39,
549
+ "expected_output": "The response starts with a `description '''…'''` snippet that uses `[[cloud.ui]]`, `[[view:index]]` and, inside the table, `[[cloud.ui\\\\|Frontend]]`, then states that a missing target is a validation warning, not an error.",
550
+ "files": [],
551
+ "expectations": [
552
+ "The response starts with the snippet (snippet-first), not prose.",
553
+ "The `description` uses a triple-quoted Markdown string (`'''` or `\"\"\"`), not a plain `'…'` string.",
554
+ "The sentence link is `[[cloud.ui]]` (full FQN, no label), so the element title is rendered.",
555
+ "The view link is `[[view:index]]`.",
556
+ "The table cell link escapes the label separator as `\\\\|`: `[[cloud.ui\\\\|Frontend]]`.",
557
+ "The response says a link to a missing element or view produces a warning (the model still builds; `likec4 validate` does not fail on it)."
558
+ ],
559
+ "grading_guidance": "Primary signals are the triple-quoted Markdown value, `[[view:index]]`, and the `\\\\|` escape inside the table. Reject a bare `|` inside the table cell, a single `\\|`, short names such as `[[ui]]`, `this`, or a Markdown `[text](url)` link instead of `[[…]]`. Do not require the `Frontend` label outside the table. Claiming that a broken link is a validation error is wrong."
546
560
  }
547
561
  ],
548
562
  "default_execution_checks": [
@@ -14,19 +14,22 @@ If workspace already has `likec4` as a dependency, check its version from packag
14
14
  | Task | Correct Command |
15
15
  | ----------------- | --------------------------------------------------------------------- |
16
16
  | Validate files | `bunx likec4 validate --json --no-layout --file <file> [project-dir]` |
17
+ | Fail on warnings | `bunx likec4 validate --max-warnings 0 [project-dir]` |
17
18
  | Start dev server | `bunx likec4 serve [project-dir]` |
18
19
  | Export PNG | `bunx likec4 export png -o ./images [project-dir]` |
19
20
  | Build static site | `bunx likec4 build -o ./dist [project-dir]` |
20
21
  | List icons | `bunx likec4 list-icons` or `bunx likec4 list-icons --group tech` |
22
+ | Apply a diff | `bunx likec4 diff apply <diff> [--dry-run] [project-dir]` |
23
+ | Safe delete | `bunx likec4 safe-delete <fqn> --dry-run [project-dir]` |
21
24
 
22
25
  ### ❌ Common mistakes (avoid these)
23
26
 
24
- | Incorrect | Why it fails | Correct |
25
- | ------------------------------------------ | ----------------------------------------- | ---------------------------------------- |
26
- | `bunx likec4 check ...` | Command doesn't exist | Use `bunx likec4 validate ...` |
27
- | `bunx likec4 lint ...` | Command doesn't exist | Use `bunx likec4 validate ...` |
28
- | `bunx likec4 verify ...` | Command doesn't exist | Use `bunx likec4 validate ...` |
29
- | `bunx likec4 export png --out-dir ./images` | Unknown flag (`--out-dir`) | Use `-o ./images` or `--outdir ./images` |
27
+ | Incorrect | Why it fails | Correct |
28
+ | ------------------------------------------- | -------------------------- | ---------------------------------------- |
29
+ | `bunx likec4 check ...` | Command doesn't exist | Use `bunx likec4 validate ...` |
30
+ | `bunx likec4 lint ...` | Command doesn't exist | Use `bunx likec4 validate ...` |
31
+ | `bunx likec4 verify ...` | Command doesn't exist | Use `bunx likec4 validate ...` |
32
+ | `bunx likec4 export png --out-dir ./images` | Unknown flag (`--out-dir`) | Use `-o ./images` or `--outdir ./images` |
30
33
 
31
34
  ## `serve` (aliases: `start`, `dev`)
32
35
 
@@ -48,6 +51,32 @@ Build a static website for deployment.
48
51
  bunx likec4 build -o ./dist [project-dir]
49
52
  ```
50
53
 
54
+ Preview the build with `bunx likec4 preview -o ./dist [project-dir]`.
55
+
56
+ ## App config (experimental)
57
+
58
+ Newer versions of the CLI read `likec4.app.config.ts` (also `.mts`, `.cts`, `.js`, `.mjs`, `.cjs`) from the project directory or the current directory.
59
+ Check that `likec4 build --help` lists `--app-config` before relying on it.
60
+
61
+ ```ts
62
+ // likec4.app.config.ts
63
+ import { defineAppConfig } from 'likec4/config'
64
+
65
+ export default defineAppConfig({
66
+ title: 'My Architecture',
67
+ theme: 'dark', // 'light' | 'dark'
68
+ base: '/pages/',
69
+ customization: './likec4.customization.tsx', // UI overrides, see docs
70
+ build: { outDir: './dist' },
71
+ server: { port: 3000 },
72
+ })
73
+ ```
74
+
75
+ - Read by `serve`, `build`, `preview`, `export png|jpg`, `codegen react`, `codegen webcomponent`.
76
+ - Flags win over the file. `--app-config <file>` points to another file, `--no-app-config` ignores it.
77
+ - Paths in the file are relative to the file; unknown options are errors.
78
+ - This is not `likec4.config.json` (the project configuration).
79
+
51
80
  ## `export`
52
81
 
53
82
  Export diagrams to various formats.
@@ -72,11 +101,11 @@ bunx likec4 export drawio --all-in-one -o ./diagrams [project-dir]
72
101
 
73
102
  Use these when the task is **LeanIX inventory**, **bridge artifacts**, or **Draw.io with stable bridge-managed ids** — not for generic DSL editing alone.
74
103
 
75
- | Task | Command |
76
- | ---------------------------------------------- | ------------------------------------------------------------------------ |
77
- | Manifest + LeanIX dry-run + report | `bunx likec4 gen leanix dry-run -o out/bridge [project-dir]` |
104
+ | Task | Command |
105
+ | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
106
+ | Manifest + LeanIX dry-run + report | `bunx likec4 gen leanix dry-run -o out/bridge [project-dir]` |
78
107
  | Sync workflow (review / apply) | `bunx likec4 sync leanix --dry-run -o out/bridge [project-dir]` / `bunx likec4 sync leanix --apply -o out/bridge [project-dir]` |
79
- | Draw.io with `likec4Id`, `bridgeManaged`, etc. | `bunx likec4 export drawio --profile leanix -o ./diagrams [project-dir]` |
108
+ | Draw.io with `likec4Id`, `bridgeManaged`, etc. | `bunx likec4 export drawio --profile leanix -o ./diagrams [project-dir]` |
80
109
 
81
110
  Full boundaries, round-trip notes, and MCP vs bridge: **`references/bridge-leanix-drawio.md`**.
82
111
 
@@ -6,11 +6,11 @@ LikeC4 projects are defined by a config file. The file's location determines pro
6
6
 
7
7
  LikeC4 recognizes (in any order):
8
8
 
9
- | Format | File names |
10
- | ---------- | -------------------------------------------------------- |
11
- | JSON/JSON5 | `.likec4rc`, `.likec4.config.json`, `likec4.config.json` |
12
- | JavaScript | `likec4.config.js`, `likec4.config.mjs` |
13
- | TypeScript | `likec4.config.ts`, `likec4.config.mts` |
9
+ | Format | File names |
10
+ | ---------- | ------------------------------------------------------------ |
11
+ | JSON/JSON5 | `.likec4rc`, `.likec4.config.json`, `likec4.config.json` |
12
+ | JavaScript | `likec4.config.js`, `likec4.config.cjs`, `likec4.config.mjs` |
13
+ | TypeScript | `likec4.config.ts`, `likec4.config.cts`, `likec4.config.mts` |
14
14
 
15
15
  ## JSON Config Schema
16
16
 
@@ -0,0 +1,52 @@
1
+ # Model diffs and safe delete
2
+
3
+ A `diff` is a named, planned change of the model (for example, an RFC).
4
+ The model does not change until the diff is applied.
5
+
6
+ ```likec4
7
+ diff rfc1 'RFC-1: Payments service' {
8
+ description 'Replace the SOAP gateway with a Payments service'
9
+
10
+ remove {
11
+ shop.legacyPayments // element, its descendants and their relationships
12
+ shop.orders -> bank 'checks fraud score' // relationship: source, target, kind, title and direction must match
13
+ }
14
+
15
+ add {
16
+ extend shop {
17
+ payments = container 'Payments Service'
18
+ }
19
+ shop.orders -> shop.payments 'requests payments'
20
+ extend shop.orders {
21
+ #next // tags, links and metadata for an existing element
22
+ }
23
+ }
24
+ }
25
+ ```
26
+
27
+ ## Rules
28
+
29
+ - `remove` lists elements and relationships that exist in the model. Use full FQNs.
30
+ - `add` has the syntax of a `model` block: elements, relationships, `extend` of elements.
31
+ - A diff cannot extend relationships, cannot remove elements added by a diff, and cannot add an element that exists.
32
+ - Diffs that change the same elements or relationships, or use what another diff adds, overlap:
33
+ both get a warning, and `diff apply` needs `--accept-overlaps` after the owners of the diffs agreed.
34
+ - Diffs with the same name in several files are merged.
35
+ - Views can reference elements added by a diff: the model "as is" ignores these references.
36
+
37
+ ## Apply, discard, safe delete
38
+
39
+ ```sh
40
+ bunx likec4 diff list [project-dir]
41
+ bunx likec4 diff apply rfc1 --dry-run [project-dir] # print the changes of each file
42
+ bunx likec4 diff apply rfc1 [project-dir] # merge `add` into the model, remove `remove` entries, delete the diff
43
+ bunx likec4 diff apply rfc1 --accept-overlaps [project-dir] # only after the owners of overlapping diffs agreed
44
+ bunx likec4 diff discard rfc1 [project-dir] # delete the diff, the model does not change
45
+ bunx likec4 safe-delete shop.legacyPayments --dry-run [project-dir]
46
+ bunx likec4 safe-delete shop.legacyPayments --orphans --scoped-views --dynamic-steps [project-dir]
47
+ ```
48
+
49
+ If `likec4 diff --help` fails, the installed version predates model diffs.
50
+ `apply` and `safe-delete` never edit other diffs: they report the diffs they break (exit code 1).
51
+ `apply` keeps only the model changes: the title, description and comments of the diff are deleted with it.
52
+ Comments inside the braces of an added element move with the element. Put lasting notes in an element `description`.
@@ -143,7 +143,7 @@ dynamic view checkout {
143
143
  api -> notifications "send confirmation"
144
144
  }
145
145
 
146
- payments <- api "payment result" {
146
+ api <- payments "payment result" {
147
147
  navigateTo payment-detail // link to another view
148
148
  }
149
149
 
@@ -262,7 +262,7 @@ views {
262
262
  exclude * -> * where target.metadata.zone is "restricted"
263
263
 
264
264
  // Wildcard with expansion
265
- include cloud._ // direct children only
265
+ include cloud._ // direct children that have relationships with the accumulated result
266
266
  include cloud.** // all descendants
267
267
  }
268
268
  }
@@ -12,24 +12,24 @@ identifier = /^[a-zA-Z_][a-zA-Z0-9_-]*$/
12
12
 
13
13
  ## Valid examples
14
14
 
15
- | Valid | Why |
16
- |---|---|
17
- | `payment-api` | hyphens allowed |
18
- | `paymentAPI` | camelCase allowed |
19
- | `payment_service` | underscores allowed |
20
- | `service1` | digits allowed (not at start) |
21
- | `_internal` | underscore at start allowed |
22
- | `PaymentService` | PascalCase allowed |
15
+ | Valid | Why |
16
+ | ----------------- | ----------------------------- |
17
+ | `payment-api` | hyphens allowed |
18
+ | `paymentAPI` | camelCase allowed |
19
+ | `payment_service` | underscores allowed |
20
+ | `service1` | digits allowed (not at start) |
21
+ | `_internal` | underscore at start allowed |
22
+ | `PaymentService` | PascalCase allowed |
23
23
 
24
24
  ## Invalid examples
25
25
 
26
- | Invalid | Why | Correct form |
27
- |---|---|---|
26
+ | Invalid | Why | Correct form |
27
+ | ------------- | ------------------------------------------------- | ----------------------------- |
28
28
  | `payment.api` | **dots are FQN separators**, not identifier chars | `payment-api` or `paymentApi` |
29
- | `payment api` | spaces not allowed | `payment-api` |
30
- | `1payment` | cannot start with digit | `payment1` |
31
- | `payment-` | cannot end with hyphen | `payment` |
32
- | `payment@api` | special chars not allowed | `payment-api` |
29
+ | `payment api` | spaces not allowed | `payment-api` |
30
+ | `1payment` | cannot start with digit | `payment1` |
31
+ | `payment-` | cannot end with hyphen | `payment` |
32
+ | `payment@api` | special chars not allowed | `payment-api` |
33
33
 
34
34
  ## Critical: dots vs. hyphens
35
35
 
@@ -43,23 +43,23 @@ model {
43
43
  }
44
44
  ```
45
45
 
46
- **Correct identifier:** `payment-api` (with hyphen)
46
+ **Correct identifier:** `payment-api` (with hyphen)\
47
47
  **Incorrect identifier:** `payment.api` (dots are FQN syntax, not part of the name)
48
48
 
49
49
  ## Use in different contexts
50
50
 
51
- | Context | Rule | Example |
52
- |---|---|---|
53
- | **Element name** | Must be valid identifier | `service name = api "payment api"` ✓ |
54
- | **Tag name** | Must be valid identifier | `tag critical` ✓, `tag #critical` ✗ |
55
- | **Relationship kind** | Must be valid identifier | `-[async]->` ✓, `-[async-queue]->` ✓ |
56
- | **Kind name** | Must be valid identifier | `element service`, `deploymentNode vm` ✓ |
57
- | **Metadata key** | Must be valid identifier | `metadata { api_version "1.0" }` ✓ |
58
- | **Color name** | Must be valid identifier (or hex) | `color primary`, `color custom-blue` ✓ |
51
+ | Context | Rule | Example |
52
+ | --------------------- | --------------------------------- | ---------------------------------------- |
53
+ | **Element name** | Must be valid identifier | `service name = api "payment api"` ✓ |
54
+ | **Tag name** | Must be valid identifier | `tag critical` ✓, `tag #critical` ✗ |
55
+ | **Relationship kind** | Must be valid identifier | `-[async]->` ✓, `-[async-queue]->` ✓ |
56
+ | **Kind name** | Must be valid identifier | `element service`, `deploymentNode vm` ✓ |
57
+ | **Metadata key** | Must be valid identifier | `metadata { api_version "1.0" }` ✓ |
58
+ | **Color name** | Must be valid identifier (or hex) | `color primary`, `color custom-blue` ✓ |
59
59
 
60
60
  ## When referencing by FQN
61
61
 
62
- Once defined, elements are referenced using their fully qualified names (FQNs), which *do* use dots:
62
+ Once defined, elements are referenced using their fully qualified names (FQNs), which _do_ use dots:
63
63
 
64
64
  ```likec4
65
65
  model {
@@ -81,10 +81,10 @@ deployment {
81
81
 
82
82
  ## Summary
83
83
 
84
- | Check | Valid | Invalid |
85
- |---|---|---|
86
- | Identifier rule | `[a-zA-Z_][a-zA-Z0-9_-]*` | Contains dots, spaces, or special chars |
87
- | Hyphens allowed? | **Yes** in identifiers | Not dots |
88
- | Dots allowed? | **Only in FQNs** (for scope separation) | Never in a single identifier name |
89
- | `payment-api` | ✓ identifier | — |
90
- | `payment.api` | ✗ identifier, but valid as FQN if `payment` and `api` are nested parents/children | — |
84
+ | Check | Valid | Invalid |
85
+ | ---------------- | --------------------------------------------------------------------------------- | --------------------------------------- |
86
+ | Identifier rule | `[a-zA-Z_][a-zA-Z0-9_-]*` | Contains dots, spaces, or special chars |
87
+ | Hyphens allowed? | **Yes** in identifiers | Not dots |
88
+ | Dots allowed? | **Only in FQNs** (for scope separation) | Never in a single identifier name |
89
+ | `payment-api` | ✓ identifier | — |
90
+ | `payment.api` | ✗ identifier, but valid as FQN if `payment` and `api` are nested parents/children | — |
@@ -63,6 +63,7 @@ views {
63
63
  ```
64
64
 
65
65
  **Key facts:**
66
+
66
67
  - `include *` in a scoped view = the scoped parent + **direct children only**
67
68
  - Grandchildren inside `*` context are **not** included (you'd need `include cloud.backend.**` or explicit FQN inclusion)
68
69
  - Relationship predicates like `->` and `<->` can further expand what neighbors appear
@@ -125,7 +126,7 @@ views {
125
126
  }
126
127
  ```
127
128
 
128
- This **does not change the base set of elements**; it only **includes relationships** that end in the visible elements. Neighbors of the scope that have incoming edges *do* appear because they are needed to render those edges visually.
129
+ This **does not change the base set of elements**; it only **includes relationships** that end in the visible elements. Neighbors of the scope that have incoming edges _do_ appear because they are needed to render those edges visually.
129
130
 
130
131
  ## Wildcard `**` vs. explicit include
131
132
 
@@ -158,22 +159,22 @@ views {
158
159
 
159
160
  ## Common mistakes
160
161
 
161
- | Wrong | Right | Why |
162
- |---|---|---|
163
- | Bare `include **` or `exclude _` | `include cloud.**`, `exclude * where tag is #deprecated` | `**` and `_` are suffixes on an element reference, not standalone wildcards |
164
- | `include cloud.**` expecting only immediate children | `include cloud.*` | `**` is recursive; use `*` for one level |
165
- | Forgetting to add relationship filters in scoped view | `include *` + `include -> parent` | Relationships may not auto-render without explicit inclusion |
166
- | Assuming `include *` includes grandchildren | Use `include cloud.**` instead | `*` is immediate children only |
162
+ | Wrong | Right | Why |
163
+ | ----------------------------------------------------- | -------------------------------------------------------- | --------------------------------------------------------------------------- |
164
+ | Bare `include **` or `exclude _` | `include cloud.**`, `exclude * where tag is #deprecated` | `**` and `_` are suffixes on an element reference, not standalone wildcards |
165
+ | `include cloud.**` expecting only immediate children | `include cloud.*` | `**` is recursive; use `*` for one level |
166
+ | Forgetting to add relationship filters in scoped view | `include *` + `include -> parent` | Relationships may not auto-render without explicit inclusion |
167
+ | Assuming `include *` includes grandchildren | Use `include cloud.**` instead | `*` is immediate children only |
167
168
 
168
169
  ## Summary table
169
170
 
170
- | Form | Matches | Scope context |
171
- |---|---|---|
172
- | `*` | Direct children + sibling relationships | One level down |
173
- | `parent._` | `parent` + direct children that have relationships with visible elements | One level down |
174
- | `parent.**` | All descendants recursively | Any depth |
175
- | `include -> element` | Inbound relationships to element | Shows external sources |
176
- | `include element ->` | Outbound relationships from element | Shows targets |
177
- | `include a <-> b` | Relationships between `a` and `b` in either direction | Shows symmetric dependencies |
171
+ | Form | Matches | Scope context |
172
+ | -------------------- | ------------------------------------------------------------------------ | ---------------------------- |
173
+ | `*` | Direct children + sibling relationships | One level down |
174
+ | `parent._` | `parent` + direct children that have relationships with visible elements | One level down |
175
+ | `parent.**` | All descendants recursively | Any depth |
176
+ | `include -> element` | Inbound relationships to element | Shows external sources |
177
+ | `include element ->` | Outbound relationships from element | Shows targets |
178
+ | `include a <-> b` | Relationships between `a` and `b` in either direction | Shows symmetric dependencies |
178
179
 
179
180
  **In scoped views:** `include *` establishes a base set of the scope parent + immediate children. Relationship predicates like `->` and `<->` can bring in neighboring elements needed to render those relationships.
@@ -111,22 +111,53 @@ model {
111
111
 
112
112
  ## Element Properties
113
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 |
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 }`.
125
126
 
126
127
  ## Relationship Properties
127
128
 
128
129
  `title`, `description`, `technology`, `metadata`, `style`, `link`, `navigateTo`
129
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
+
130
161
  ## Extend Patterns
131
162
 
132
163
  ```likec4