@vpxa/aikit 0.1.58 → 0.1.59
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/package.json +1 -1
- package/packages/present/dist/index.html +1 -1
- package/packages/server/dist/tools/present/tool.js +1 -1
- package/scaffold/general/skills/c4-architecture/SKILL.md +87 -1
- package/scaffold/general/skills/c4-architecture/references/html-design-system.md +337 -0
- package/scaffold/general/skills/c4-architecture/references/html-template.html +627 -0
- package/scaffold/general/skills/present/SKILL.md +180 -0
package/package.json
CHANGED
|
@@ -36,4 +36,4 @@ IMPORTANT: For charts, use the ChartValue format above. Do NOT use Chart.js form
|
|
|
36
36
|
- "browser": Serves a themed dashboard on a local URL. Use ONLY when you need user interaction back (confirmations, selections, form input). The tool blocks until user clicks an action button, then returns their selection.
|
|
37
37
|
FORMAT RULE: If no user interaction is needed → use "html". If you need user input back → use "browser".
|
|
38
38
|
CONTENT GUIDE: Pass typed blocks [{ type, title?, value }] for structured content. See the \`content\` parameter description for all supported block types and their value shapes. For charts: use {chartType, data:Record[], xKey, yKeys} — NOT Chart.js format.
|
|
39
|
-
BROWSER WORKFLOW: After calling present with format "browser", you MUST extract the URL from the response and call openBrowserPage({ url }) tool - PlayWright MCP to open it in VS Code Simple Browser. A system browser fallback also opens automatically, but always call openBrowserPage tool - PlayWright MCP yourself.`,o=async({format:e,title:t,content:r,actions:i,template:a})=>(e??`html`)===`browser`||Array.isArray(i)&&i.length>0?await T(t,r,i,n,a):E(t,r,i,a);if(i){b||=(u(t,`AI Kit Present App`,g,{description:`Rich interactive content viewer for AI Kit tools`},async()=>({contents:[{uri:g,mimeType:l,text:i}]})),!0),d(t,`present`,{title:r.title,description:a,annotations:r.annotations,inputSchema:v,_meta:{ui:{resourceUri:g}}},o);return}t.tool(`present`,a,v,r.annotations,o)}async function T(e,t,i,a,o){let s=r(e,t,{compactTables:!0}),c=n(e,t,i,o),l=m({uri:`ui://aikit/present-browser.html`,content:{type:`rawHtml`,htmlString:c},encoding:`text`,adapters:{mcpApps:{enabled:!0}}}),u,d,h=Array.isArray(i)?i:[],g=``,_;try{x&&=(x.close(),null),h.length>0&&(u=new Promise(e=>{d=e}));let e=!1;g=await new Promise((t,n)=>{let r=p((t,n)=>{if(e||(e=!0,_&&clearTimeout(_)),t.method===`POST`&&t.url===`/callback`){let e=``;t.on(`data`,t=>{e+=t.toString()}),t.on(`end`,()=>{n.writeHead(200,{"Content-Type":`application/json`,"Access-Control-Allow-Origin":`*`}),n.end(`{"ok":true}`);try{let t=JSON.parse(e);d?.(t)}catch{}});return}if(t.method===`OPTIONS`){n.writeHead(204,{"Access-Control-Allow-Origin":`*`,"Access-Control-Allow-Methods":`POST`,"Access-Control-Allow-Headers":`Content-Type`}),n.end();return}n.writeHead(200,{"Content-Type":`text/html; charset=utf-8`}),n.end(c)});r.listen(0,`127.0.0.1`,()=>{let i=r.address();if(typeof i==`object`&&i){x=r;let n=`http://127.0.0.1:${i.port}`;_=setTimeout(()=>{if(!e)try{f(process.platform===`win32`?`start "" "${n}"`:process.platform===`darwin`?`open "${n}"`:`xdg-open "${n}"`)}catch{}},8e3),_.unref(),t(n)}else n(Error(`Failed to start present server`))}),setTimeout(()=>{r.close(),x===r&&(x=null)},300*1e3).unref()})}catch{}let v=g?`${s}\n\n---\n🌐 **Dashboard opened in browser:** ${g}\n\n**IMPORTANT:** You MUST now open this URL using the \`openBrowserPage\` tool - PlayWright MCP. If that tool is unavailable, open the URL in the system browser as a fallback. If neither works, ask the user to open the URL manually.`:s;if(h.length>0&&a?.available&&u)try{let e=await Promise.race([u,new Promise((e,t)=>setTimeout(()=>t(Error(`timeout`)),300*1e3))]);return{content:[{type:`text`,text:`${v}\n\n✅ **Selected:** ${e.actionId} = \`${e.value}\``},l]}}catch{return{content:[{type:`text`,text:`${v}\n\n⚠️ *No selection received (timed out).*`},l]}}return{content:[{type:`text`,text:v},l]}}function E(e,
|
|
39
|
+
BROWSER WORKFLOW: After calling present with format "browser", you MUST extract the URL from the response and call openBrowserPage({ url }) tool - PlayWright MCP to open it in VS Code Simple Browser. A system browser fallback also opens automatically, but always call openBrowserPage tool - PlayWright MCP yourself.`,o=async({format:e,title:t,content:r,actions:i,template:a})=>(e??`html`)===`browser`||Array.isArray(i)&&i.length>0?await T(t,r,i,n,a):E(t,r,i,a);if(i){b||=(u(t,`AI Kit Present App`,g,{description:`Rich interactive content viewer for AI Kit tools`},async()=>({contents:[{uri:g,mimeType:l,text:i}]})),!0),d(t,`present`,{title:r.title,description:a,annotations:r.annotations,inputSchema:v,_meta:{ui:{resourceUri:g}}},o);return}t.tool(`present`,a,v,r.annotations,o)}async function T(e,t,i,a,o){let s=r(e,t,{compactTables:!0}),c=n(e,t,i,o),l=m({uri:`ui://aikit/present-browser.html`,content:{type:`rawHtml`,htmlString:c},encoding:`text`,adapters:{mcpApps:{enabled:!0}}}),u,d,h=Array.isArray(i)?i:[],g=``,_;try{x&&=(x.close(),null),h.length>0&&(u=new Promise(e=>{d=e}));let e=!1;g=await new Promise((t,n)=>{let r=p((t,n)=>{if(e||(e=!0,_&&clearTimeout(_)),t.method===`POST`&&t.url===`/callback`){let e=``;t.on(`data`,t=>{e+=t.toString()}),t.on(`end`,()=>{n.writeHead(200,{"Content-Type":`application/json`,"Access-Control-Allow-Origin":`*`}),n.end(`{"ok":true}`);try{let t=JSON.parse(e);d?.(t)}catch{}});return}if(t.method===`OPTIONS`){n.writeHead(204,{"Access-Control-Allow-Origin":`*`,"Access-Control-Allow-Methods":`POST`,"Access-Control-Allow-Headers":`Content-Type`}),n.end();return}n.writeHead(200,{"Content-Type":`text/html; charset=utf-8`}),n.end(c)});r.listen(0,`127.0.0.1`,()=>{let i=r.address();if(typeof i==`object`&&i){x=r;let n=`http://127.0.0.1:${i.port}`;_=setTimeout(()=>{if(!e)try{f(process.platform===`win32`?`start "" "${n}"`:process.platform===`darwin`?`open "${n}"`:`xdg-open "${n}"`)}catch{}},8e3),_.unref(),t(n)}else n(Error(`Failed to start present server`))}),setTimeout(()=>{r.close(),x===r&&(x=null)},300*1e3).unref()})}catch{}let v=g?`${s}\n\n---\n🌐 **Dashboard opened in browser:** ${g}\n\n**IMPORTANT:** You MUST now open this URL using the \`openBrowserPage\` tool - PlayWright MCP. If that tool is unavailable, open the URL in the system browser as a fallback. If neither works, ask the user to open the URL manually.`:s;if(h.length>0&&a?.available&&u)try{let e=await Promise.race([u,new Promise((e,t)=>setTimeout(()=>t(Error(`timeout`)),300*1e3))]);return{content:[{type:`text`,text:`${v}\n\n✅ **Selected:** ${e.actionId} = \`${e.value}\``},l]}}catch{return{content:[{type:`text`,text:`${v}\n\n⚠️ *No selection received (timed out).*`},l]}}return{content:[{type:`text`,text:v},l]}}function E(e,i,a,o){let s=Array.isArray(a)?a:[],c=r(e,i,{compactTables:!0}),l=m({uri:`ui://aikit/present-static.html`,content:{type:`rawHtml`,htmlString:n(e,i,a,o)},encoding:`text`,adapters:{mcpApps:{enabled:!0}}});return{content:[{type:`text`,text:c},l],structuredContent:{title:e,content:t(i),actions:s}}}export{T as formatAsBrowser,E as formatAsHtml,C as getPresentHtml,w as registerPresentTool,S as resolvePresentHtml};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: c4-architecture
|
|
3
|
-
description: Generate architecture documentation using C4 model Mermaid
|
|
3
|
+
description: Generate architecture documentation using C4 model diagrams. Supports two output formats: Mermaid (md) for documentation and HTML/SVG for presentations. Use when asked to create architecture diagrams, document system architecture, visualize software structure, create C4 diagrams, or generate context/container/component/deployment diagrams.
|
|
4
4
|
metadata:
|
|
5
5
|
category: cross-cutting
|
|
6
6
|
domain: general
|
|
@@ -22,6 +22,56 @@ Generate software architecture documentation using C4 model diagrams in Mermaid
|
|
|
22
22
|
> **Tip:** Use `present({ format: "html" })` to render diagrams as interactive visual output, rather than raw Mermaid code blocks. This provides a better viewing experience for stakeholders.
|
|
23
23
|
4. **Document** - Write diagrams to markdown files with explanatory context
|
|
24
24
|
|
|
25
|
+
## Format Selection
|
|
26
|
+
|
|
27
|
+
This skill supports two output formats. Choose based on the audience and delivery method:
|
|
28
|
+
|
|
29
|
+
> **Default rule:** When using the `present` tool to display architecture, **always use HTML/SVG format** (Method 2). It produces professional dark-themed diagrams with SVG icons, category colors, and summary cards. Use Mermaid only for saving to markdown docs or when the user explicitly requests it.
|
|
30
|
+
|
|
31
|
+
| Format | Output | Best For | Delivery |
|
|
32
|
+
|--------|--------|----------|----------|
|
|
33
|
+
| **Mermaid (md)** | `.md` files with Mermaid code blocks | Developer docs, GitHub rendering, version control | Save to `docs/architecture/*.md` |
|
|
34
|
+
| **HTML/SVG (html)** | Self-contained `.html` files | Stakeholder presentations, visual reviews, browser viewing | Save as `.html` or render via `present` tool |
|
|
35
|
+
|
|
36
|
+
### Format Decision Tree
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
What is the goal?
|
|
40
|
+
├── Save to docs / version control → Mermaid (md)
|
|
41
|
+
├── Present via `present` tool → HTML/SVG (html) ← DEFAULT for present
|
|
42
|
+
├── User says "Mermaid" or "markdown" → Mermaid (md)
|
|
43
|
+
└── User says "show", "visualize", "present" → HTML/SVG (html)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Present Tool Integration
|
|
47
|
+
|
|
48
|
+
Both formats work with the `present` tool:
|
|
49
|
+
|
|
50
|
+
**Mermaid format** - Use a `mermaid` content block:
|
|
51
|
+
```js
|
|
52
|
+
present({
|
|
53
|
+
format: "html", // or "browser"
|
|
54
|
+
title: "System Architecture",
|
|
55
|
+
content: [
|
|
56
|
+
{ type: "mermaid", title: "C4 Container Diagram", value: "C4Container\n title Container Diagram\n ..." }
|
|
57
|
+
]
|
|
58
|
+
})
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**HTML/SVG format** - Use a `markdown` block with the full HTML structure. Pair with `metrics` and `cards` blocks for a complete dashboard. See [references/html-design-system.md](references/html-design-system.md#present-tool-integration) for the full composition pattern.
|
|
62
|
+
|
|
63
|
+
```js
|
|
64
|
+
present({
|
|
65
|
+
format: "html", // or "browser" - both work
|
|
66
|
+
title: "System Architecture",
|
|
67
|
+
content: [
|
|
68
|
+
{ type: "metrics", title: "Overview", value: [{ label: "Services", value: "6" }, ...] },
|
|
69
|
+
{ type: "markdown", title: "Architecture Diagram", value: "<div class='arch-diagram'>...(inline SVG + CSS)...</div>" },
|
|
70
|
+
{ type: "cards", title: "Summary", value: [{ title: "Frontend", body: "React SPA" }, ...] }
|
|
71
|
+
]
|
|
72
|
+
})
|
|
73
|
+
```
|
|
74
|
+
|
|
25
75
|
## C4 Diagram Levels
|
|
26
76
|
|
|
27
77
|
Select the appropriate level based on the documentation need:
|
|
@@ -129,6 +179,40 @@ C4Deployment
|
|
|
129
179
|
Rel(api, db, "Reads/writes", "JDBC")
|
|
130
180
|
```
|
|
131
181
|
|
|
182
|
+
## HTML/SVG Format
|
|
183
|
+
|
|
184
|
+
For HTML/SVG output, use the design system and template from the references.
|
|
185
|
+
|
|
186
|
+
The component type registry, color palette, typography, and layout rules are defined in [references/html-design-system.md](references/html-design-system.md). This is the single source of truth - update colors, types, and icons there.
|
|
187
|
+
|
|
188
|
+
Copy and customize [references/html-template.html](references/html-template.html) for each diagram. The template is self-contained and opens directly in any browser.
|
|
189
|
+
|
|
190
|
+
### Component Categories
|
|
191
|
+
|
|
192
|
+
See the design system for the full sub-type registry and icon slots.
|
|
193
|
+
|
|
194
|
+
- Frontend - stroke `#22d3ee`
|
|
195
|
+
- Backend - stroke `#34d399`
|
|
196
|
+
- Data - stroke `#a78bfa`
|
|
197
|
+
- Infrastructure - stroke `#fbbf24`
|
|
198
|
+
- Messaging - stroke `#fb923c`
|
|
199
|
+
- Security - stroke `#fb7185`
|
|
200
|
+
- External - stroke `#94a3b8`
|
|
201
|
+
- Monitoring - stroke `#38bdf8`
|
|
202
|
+
|
|
203
|
+
### Minimal Component Box Example
|
|
204
|
+
|
|
205
|
+
Use the design system's inline SVG component pattern inside the HTML template's main `<svg>`:
|
|
206
|
+
|
|
207
|
+
```svg
|
|
208
|
+
<g class="node backend">
|
|
209
|
+
<rect x="280" y="210" width="190" height="60" rx="6" />
|
|
210
|
+
<text class="c4-tag" x="294" y="226"><<Container>></text>
|
|
211
|
+
<text class="node-title" x="294" y="243">API Service</text>
|
|
212
|
+
<text class="node-subtitle" x="294" y="257">Backend / HTTPS JSON</text>
|
|
213
|
+
</g>
|
|
214
|
+
```
|
|
215
|
+
|
|
132
216
|
## Element Syntax
|
|
133
217
|
|
|
134
218
|
### People and Systems
|
|
@@ -301,3 +385,5 @@ Write architecture documentation to `docs/architecture/` with naming convention:
|
|
|
301
385
|
- [references/c4-syntax.md](references/c4-syntax.md) - Complete Mermaid C4 syntax
|
|
302
386
|
- [references/common-mistakes.md](references/common-mistakes.md) - Anti-patterns to avoid
|
|
303
387
|
- [references/advanced-patterns.md](references/advanced-patterns.md) - Microservices, event-driven, deployment
|
|
388
|
+
- [references/html-design-system.md](references/html-design-system.md) - Centralized HTML/SVG design system (types, colors, icons, present integration)
|
|
389
|
+
- [references/html-template.html](references/html-template.html) - Self-contained HTML template for C4 diagrams
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
# HTML/SVG Architecture Diagram Design System
|
|
2
|
+
|
|
3
|
+
This file is the centralized design system for HTML and SVG architecture diagrams.
|
|
4
|
+
|
|
5
|
+
It is the single source of truth for visual tokens, component categories, layout rules, and `present` tool composition guidance used by the `c4-architecture` skill and the `present` skill. Update component types, colors, layout rules, and icon slots here only.
|
|
6
|
+
|
|
7
|
+
## Purpose
|
|
8
|
+
|
|
9
|
+
- Define a reusable visual language for C4-style architecture diagrams rendered as HTML and inline SVG.
|
|
10
|
+
- Keep category styling extensible through a registry instead of hardcoded component types.
|
|
11
|
+
- Standardize diagram composition for both skill-authored documentation and `present` output.
|
|
12
|
+
|
|
13
|
+
## Core Design Tokens
|
|
14
|
+
|
|
15
|
+
### Typography
|
|
16
|
+
|
|
17
|
+
- Font family: `"JetBrains Mono", monospace`
|
|
18
|
+
- Font source: Google Fonts (`https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700;800&display=swap`)
|
|
19
|
+
- Component names: `12px`
|
|
20
|
+
- Sublabels: `9px`
|
|
21
|
+
- Annotations: `8px`
|
|
22
|
+
- Tiny labels: `7px`
|
|
23
|
+
- Legend: `10px`
|
|
24
|
+
- Icon area labels: `11px`
|
|
25
|
+
|
|
26
|
+
### Background
|
|
27
|
+
|
|
28
|
+
- Page background: `#020617` (`slate-950`)
|
|
29
|
+
- Background pattern: inline SVG grid pattern over the page background
|
|
30
|
+
- Recommended grid line colors:
|
|
31
|
+
- Major grid: `rgba(148, 163, 184, 0.08)`
|
|
32
|
+
- Minor grid: `rgba(148, 163, 184, 0.04)`
|
|
33
|
+
|
|
34
|
+
### Component Box Defaults
|
|
35
|
+
|
|
36
|
+
- Shape: rounded rectangle
|
|
37
|
+
- Border radius: `rx="6"`
|
|
38
|
+
- Stroke width: `1.5px`
|
|
39
|
+
- Fill: category-specific semi-transparent RGBA fill
|
|
40
|
+
- Stroke: category-specific hex stroke
|
|
41
|
+
- Label stack:
|
|
42
|
+
- Line 1: C4 label such as `<<Container>>`
|
|
43
|
+
- Line 2: component name
|
|
44
|
+
- Line 3: subtype or technology summary
|
|
45
|
+
|
|
46
|
+
## Category Registry
|
|
47
|
+
|
|
48
|
+
The registry is hierarchical: categories define shared tokens and C4 intent, while sub-types inherit the category styling and reserve an icon slot for future SVG glyphs.
|
|
49
|
+
|
|
50
|
+
| Category | Stroke Color | Fill Color | C4 Mapping | Sub-types |
|
|
51
|
+
|---|---|---|---|---|
|
|
52
|
+
| Frontend | `#22d3ee` | `rgba(8, 51, 68, 0.4)` | Container (SPA, web) | SPA, Mobile App, Static Site, Micro-frontend, PWA, Desktop App |
|
|
53
|
+
| Backend | `#34d399` | `rgba(6, 78, 59, 0.4)` | Container (service) | API Service, Worker/Job, BFF, Microservice, Serverless Function, gRPC Service |
|
|
54
|
+
| Data | `#a78bfa` | `rgba(76, 29, 149, 0.4)` | ContainerDb | Relational DB, Document DB, Key-Value Store, Cache, Search Engine, Data Warehouse, Graph DB, Time-Series DB |
|
|
55
|
+
| Infrastructure | `#fbbf24` | `rgba(120, 53, 15, 0.3)` | Deployment_Node | CDN, Load Balancer, DNS, Object Storage, Container Registry, Reverse Proxy, Service Mesh |
|
|
56
|
+
| Messaging | `#fb923c` | `rgba(251, 146, 60, 0.3)` | ContainerQueue | Message Queue, Event Bus, Stream, Pub/Sub, Webhook |
|
|
57
|
+
| Security | `#fb7185` | `rgba(136, 19, 55, 0.4)` | System_Ext / boundary | Auth Provider, API Gateway, WAF, Secret Manager, Certificate Manager, Identity Provider |
|
|
58
|
+
| External | `#94a3b8` | `rgba(30, 41, 59, 0.5)` | System_Ext | Third-party API, SaaS, Legacy System, Partner Service, Payment Provider |
|
|
59
|
+
| Monitoring | `#38bdf8` | `rgba(12, 74, 110, 0.4)` | Container | Logging, Metrics, Tracing, Alerting, APM |
|
|
60
|
+
|
|
61
|
+
## Sub-type Registry
|
|
62
|
+
|
|
63
|
+
Each sub-type inherits its category tokens and keeps a placeholder slot for an inline SVG icon.
|
|
64
|
+
|
|
65
|
+
| Category | Sub-type | C4 Label | Icon Slot |
|
|
66
|
+
|---|---|---|---|
|
|
67
|
+
| Frontend | SPA | `<<Container>>` | `icon-spa` |
|
|
68
|
+
| Frontend | Mobile App | `<<Container>>` | `icon-mobile-app` |
|
|
69
|
+
| Frontend | Static Site | `<<Container>>` | `icon-static-site` |
|
|
70
|
+
| Frontend | Micro-frontend | `<<Container>>` | `icon-micro-frontend` |
|
|
71
|
+
| Frontend | PWA | `<<Container>>` | `icon-pwa` |
|
|
72
|
+
| Frontend | Desktop App | `<<Container>>` | `icon-desktop-app` |
|
|
73
|
+
| Backend | API Service | `<<Container>>` | `icon-api-service` |
|
|
74
|
+
| Backend | Worker/Job | `<<Container>>` | `icon-worker-job` |
|
|
75
|
+
| Backend | BFF | `<<Container>>` | `icon-bff` |
|
|
76
|
+
| Backend | Microservice | `<<Container>>` | `icon-microservice` |
|
|
77
|
+
| Backend | Serverless Function | `<<Container>>` | `icon-serverless-function` |
|
|
78
|
+
| Backend | gRPC Service | `<<Container>>` | `icon-grpc-service` |
|
|
79
|
+
| Data | Relational DB | `<<ContainerDb>>` | `icon-relational-db` |
|
|
80
|
+
| Data | Document DB | `<<ContainerDb>>` | `icon-document-db` |
|
|
81
|
+
| Data | Key-Value Store | `<<ContainerDb>>` | `icon-key-value-store` |
|
|
82
|
+
| Data | Cache | `<<ContainerDb>>` | `icon-cache` |
|
|
83
|
+
| Data | Search Engine | `<<ContainerDb>>` | `icon-search-engine` |
|
|
84
|
+
| Data | Data Warehouse | `<<ContainerDb>>` | `icon-data-warehouse` |
|
|
85
|
+
| Data | Graph DB | `<<ContainerDb>>` | `icon-graph-db` |
|
|
86
|
+
| Data | Time-Series DB | `<<ContainerDb>>` | `icon-time-series-db` |
|
|
87
|
+
| Infrastructure | CDN | `<<Deployment_Node>>` | `icon-cdn` |
|
|
88
|
+
| Infrastructure | Load Balancer | `<<Deployment_Node>>` | `icon-load-balancer` |
|
|
89
|
+
| Infrastructure | DNS | `<<Deployment_Node>>` | `icon-dns` |
|
|
90
|
+
| Infrastructure | Object Storage | `<<Deployment_Node>>` | `icon-object-storage` |
|
|
91
|
+
| Infrastructure | Container Registry | `<<Deployment_Node>>` | `icon-container-registry` |
|
|
92
|
+
| Infrastructure | Reverse Proxy | `<<Deployment_Node>>` | `icon-reverse-proxy` |
|
|
93
|
+
| Infrastructure | Service Mesh | `<<Deployment_Node>>` | `icon-service-mesh` |
|
|
94
|
+
| Messaging | Message Queue | `<<ContainerQueue>>` | `icon-message-queue` |
|
|
95
|
+
| Messaging | Event Bus | `<<ContainerQueue>>` | `icon-event-bus` |
|
|
96
|
+
| Messaging | Stream | `<<ContainerQueue>>` | `icon-stream` |
|
|
97
|
+
| Messaging | Pub/Sub | `<<ContainerQueue>>` | `icon-pub-sub` |
|
|
98
|
+
| Messaging | Webhook | `<<ContainerQueue>>` | `icon-webhook` |
|
|
99
|
+
| Security | Auth Provider | `<<System_Ext>>` | `icon-auth-provider` |
|
|
100
|
+
| Security | API Gateway | `<<System_Ext>>` | `icon-api-gateway` |
|
|
101
|
+
| Security | WAF | `<<System_Ext>>` | `icon-waf` |
|
|
102
|
+
| Security | Secret Manager | `<<System_Ext>>` | `icon-secret-manager` |
|
|
103
|
+
| Security | Certificate Manager | `<<System_Ext>>` | `icon-certificate-manager` |
|
|
104
|
+
| Security | Identity Provider | `<<System_Ext>>` | `icon-identity-provider` |
|
|
105
|
+
| External | Third-party API | `<<System_Ext>>` | `icon-third-party-api` |
|
|
106
|
+
| External | SaaS | `<<System_Ext>>` | `icon-saas` |
|
|
107
|
+
| External | Legacy System | `<<System_Ext>>` | `icon-legacy-system` |
|
|
108
|
+
| External | Partner Service | `<<System_Ext>>` | `icon-partner-service` |
|
|
109
|
+
| External | Payment Provider | `<<System_Ext>>` | `icon-payment-provider` |
|
|
110
|
+
| Monitoring | Logging | `<<Container>>` | `icon-logging` |
|
|
111
|
+
| Monitoring | Metrics | `<<Container>>` | `icon-metrics` |
|
|
112
|
+
| Monitoring | Tracing | `<<Container>>` | `icon-tracing` |
|
|
113
|
+
| Monitoring | Alerting | `<<Container>>` | `icon-alerting` |
|
|
114
|
+
| Monitoring | APM | `<<Container>>` | `icon-apm` |
|
|
115
|
+
|
|
116
|
+
## Icon Registry
|
|
117
|
+
|
|
118
|
+
Icons are inline SVG `<symbol>` elements with a 16x16 viewBox, rendered via `<use>` at `(x+W-22, y+4)` inside the component box. They use `currentColor` to inherit the category stroke color.
|
|
119
|
+
|
|
120
|
+
### Category-Level Icons (active)
|
|
121
|
+
|
|
122
|
+
Each category has a shared icon defined in `html-template.html` `<defs>`. All sub-types within a category use their category icon by default. Sub-type-specific icons can override these in the future.
|
|
123
|
+
|
|
124
|
+
| Category | Symbol ID | Shape | Status |
|
|
125
|
+
|---|---|---|---|
|
|
126
|
+
| Frontend | `icon-frontend` | Monitor with stand | **active** |
|
|
127
|
+
| Backend | `icon-backend` | Server rack (3 units) | **active** |
|
|
128
|
+
| Data | `icon-data` | Database cylinder | **active** |
|
|
129
|
+
| Infrastructure | `icon-infrastructure` | Cloud | **active** |
|
|
130
|
+
| Messaging | `icon-messaging` | Envelope | **active** |
|
|
131
|
+
| Security | `icon-security` | Shield with checkmark | **active** |
|
|
132
|
+
| External | `icon-external` | Globe with meridians | **active** |
|
|
133
|
+
| Monitoring | `icon-monitoring` | Line chart with axes | **active** |
|
|
134
|
+
|
|
135
|
+
Usage pattern:
|
|
136
|
+
```svg
|
|
137
|
+
<use href="#icon-frontend" class="icon-use" x="448" y="154" width="16" height="16"/>
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Sub-type Icons (planned)
|
|
141
|
+
|
|
142
|
+
When a sub-type icon is added, it overrides the category icon for that specific component. Until implemented, all sub-types use their category icon.
|
|
143
|
+
|
|
144
|
+
| Sub-type | Icon | Status |
|
|
145
|
+
|---|---|---|
|
|
146
|
+
| SPA | `icon-spa` | planned |
|
|
147
|
+
| Mobile App | `icon-mobile-app` | planned |
|
|
148
|
+
| Static Site | `icon-static-site` | planned |
|
|
149
|
+
| Micro-frontend | `icon-micro-frontend` | planned |
|
|
150
|
+
| PWA | `icon-pwa` | planned |
|
|
151
|
+
| Desktop App | `icon-desktop-app` | planned |
|
|
152
|
+
| API Service | `icon-api-service` | planned |
|
|
153
|
+
| Worker/Job | `icon-worker-job` | planned |
|
|
154
|
+
| BFF | `icon-bff` | planned |
|
|
155
|
+
| Microservice | `icon-microservice` | planned |
|
|
156
|
+
| Serverless Function | `icon-serverless-function` | planned |
|
|
157
|
+
| gRPC Service | `icon-grpc-service` | planned |
|
|
158
|
+
| Relational DB | `icon-relational-db` | planned |
|
|
159
|
+
| Document DB | `icon-document-db` | planned |
|
|
160
|
+
| Key-Value Store | `icon-key-value-store` | planned |
|
|
161
|
+
| Cache | `icon-cache` | planned |
|
|
162
|
+
| Search Engine | `icon-search-engine` | planned |
|
|
163
|
+
| Data Warehouse | `icon-data-warehouse` | planned |
|
|
164
|
+
| Graph DB | `icon-graph-db` | planned |
|
|
165
|
+
| Time-Series DB | `icon-time-series-db` | planned |
|
|
166
|
+
| CDN | `icon-cdn` | planned |
|
|
167
|
+
| Load Balancer | `icon-load-balancer` | planned |
|
|
168
|
+
| DNS | `icon-dns` | planned |
|
|
169
|
+
| Object Storage | `icon-object-storage` | planned |
|
|
170
|
+
| Container Registry | `icon-container-registry` | planned |
|
|
171
|
+
| Reverse Proxy | `icon-reverse-proxy` | planned |
|
|
172
|
+
| Service Mesh | `icon-service-mesh` | planned |
|
|
173
|
+
| Message Queue | `icon-message-queue` | planned |
|
|
174
|
+
| Event Bus | `icon-event-bus` | planned |
|
|
175
|
+
| Stream | `icon-stream` | planned |
|
|
176
|
+
| Pub/Sub | `icon-pub-sub` | planned |
|
|
177
|
+
| Webhook | `icon-webhook` | planned |
|
|
178
|
+
| Auth Provider | `icon-auth-provider` | planned |
|
|
179
|
+
| API Gateway | `icon-api-gateway` | planned |
|
|
180
|
+
| WAF | `icon-waf` | planned |
|
|
181
|
+
| Secret Manager | `icon-secret-manager` | planned |
|
|
182
|
+
| Certificate Manager | `icon-certificate-manager` | planned |
|
|
183
|
+
| Identity Provider | `icon-identity-provider` | planned |
|
|
184
|
+
| Third-party API | `icon-third-party-api` | planned |
|
|
185
|
+
| SaaS | `icon-saas` | planned |
|
|
186
|
+
| Legacy System | `icon-legacy-system` | planned |
|
|
187
|
+
| Partner Service | `icon-partner-service` | planned |
|
|
188
|
+
| Payment Provider | `icon-payment-provider` | planned |
|
|
189
|
+
| Logging | `icon-logging` | planned |
|
|
190
|
+
| Metrics | `icon-metrics` | planned |
|
|
191
|
+
| Tracing | `icon-tracing` | planned |
|
|
192
|
+
| Alerting | `icon-alerting` | planned |
|
|
193
|
+
| APM | `icon-apm` | planned |
|
|
194
|
+
|
|
195
|
+
## Visual Elements
|
|
196
|
+
|
|
197
|
+
### Component Box Pattern
|
|
198
|
+
|
|
199
|
+
Use a rounded component box with semi-transparent fill and category stroke.
|
|
200
|
+
|
|
201
|
+
```svg
|
|
202
|
+
<g class="node backend">
|
|
203
|
+
<rect x="280" y="210" width="190" height="60" rx="6" />
|
|
204
|
+
<text class="c4-tag" x="294" y="226"><<Container>></text>
|
|
205
|
+
<text class="node-title" x="294" y="243">API Service</text>
|
|
206
|
+
<text class="node-subtitle" x="294" y="257">Backend / HTTPS JSON</text>
|
|
207
|
+
</g>
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Arrow Masking Technique
|
|
211
|
+
|
|
212
|
+
Use an opaque background rectangle below the box content to visually hide arrows beneath components without breaking the component fill style.
|
|
213
|
+
|
|
214
|
+
```svg
|
|
215
|
+
<g class="node-mask-layer">
|
|
216
|
+
<rect x="280" y="210" width="190" height="60" rx="6" fill="#020617" />
|
|
217
|
+
<rect x="280" y="210" width="190" height="60" rx="6"
|
|
218
|
+
fill="rgba(6, 78, 59, 0.4)" stroke="#34d399" stroke-width="1.5" />
|
|
219
|
+
</g>
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Security Group Boundary
|
|
223
|
+
|
|
224
|
+
- Purpose: show auth, gateway, WAF, or identity zones
|
|
225
|
+
- Stroke color: rose (`#fb7185`)
|
|
226
|
+
- Pattern: `stroke-dasharray="4,4"`
|
|
227
|
+
- Suggested label: `Security Boundary`
|
|
228
|
+
|
|
229
|
+
```svg
|
|
230
|
+
<rect x="700" y="140" width="220" height="180" rx="12"
|
|
231
|
+
fill="transparent" stroke="#fb7185" stroke-width="1.5"
|
|
232
|
+
stroke-dasharray="4,4" />
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Region Boundary
|
|
236
|
+
|
|
237
|
+
- Purpose: group a deployment region, platform segment, or domain slice
|
|
238
|
+
- Stroke color: amber (`#fbbf24`)
|
|
239
|
+
- Pattern: `stroke-dasharray="8,4"`
|
|
240
|
+
- Radius: `rx="12"`
|
|
241
|
+
|
|
242
|
+
```svg
|
|
243
|
+
<rect x="70" y="120" width="600" height="430" rx="12"
|
|
244
|
+
fill="transparent" stroke="#fbbf24" stroke-width="1.5"
|
|
245
|
+
stroke-dasharray="8,4" />
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Arrow Marker SVG Definition
|
|
249
|
+
|
|
250
|
+
```svg
|
|
251
|
+
<defs>
|
|
252
|
+
<marker id="arrowhead" markerWidth="8" markerHeight="8" refX="7" refY="4" orient="auto">
|
|
253
|
+
<path d="M0,0 L8,4 L0,8 Z" fill="#cbd5e1" />
|
|
254
|
+
</marker>
|
|
255
|
+
</defs>
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Arrow Z-order Rule
|
|
259
|
+
|
|
260
|
+
Draw arrows early in the SVG so component boxes and masking layers paint over them. This keeps connectors readable in dense diagrams and avoids arrow overlap across component interiors.
|
|
261
|
+
|
|
262
|
+
## Spacing Rules
|
|
263
|
+
|
|
264
|
+
- Standard component height: `60px`
|
|
265
|
+
- Minimum vertical gap between stacked components: `40px`
|
|
266
|
+
- Inline connectors should route through gaps rather than through component interiors
|
|
267
|
+
- Keep labels inside the top `28px` of the box and the subtype line inside the lower third
|
|
268
|
+
- Place legends outside boundaries to prevent classification noise inside the diagram area
|
|
269
|
+
|
|
270
|
+
## Layout Structure
|
|
271
|
+
|
|
272
|
+
The canonical page composition is:
|
|
273
|
+
|
|
274
|
+
1. Header: title, pulse dot, subtitle
|
|
275
|
+
2. Main SVG diagram: embedded inside a rounded border card
|
|
276
|
+
3. Summary cards: grid of 3 cards beneath the diagram
|
|
277
|
+
4. Footer metadata: generator, scope, rendering notes, last-updated stamp
|
|
278
|
+
|
|
279
|
+
## Present Tool Integration
|
|
280
|
+
|
|
281
|
+
Compose architecture diagrams with the `present` tool by embedding the full HTML/SVG diagram in a markdown block and pairing it with metrics or cards blocks as needed.
|
|
282
|
+
|
|
283
|
+
### `format: "html"`
|
|
284
|
+
|
|
285
|
+
Use a `markdown` block with embedded `<div>`, inline SVG, and a `<style>` tag containing the full CSS. The `present` html format renders raw HTML in markdown blocks.
|
|
286
|
+
|
|
287
|
+
### `format: "browser"`
|
|
288
|
+
|
|
289
|
+
Use the same composition: a `markdown` block containing the full HTML structure. Summary content can also be added with `cards` and `metrics` blocks alongside the SVG diagram block.
|
|
290
|
+
|
|
291
|
+
### Example `present` Call Structure
|
|
292
|
+
|
|
293
|
+
```js
|
|
294
|
+
present({
|
|
295
|
+
format: "html", // or "browser"
|
|
296
|
+
title: "System Architecture",
|
|
297
|
+
content: [
|
|
298
|
+
{
|
|
299
|
+
type: "metrics",
|
|
300
|
+
title: "Overview",
|
|
301
|
+
value: [
|
|
302
|
+
{ label: "Services", value: "6" },
|
|
303
|
+
{ label: "Data Stores", value: "2" },
|
|
304
|
+
{ label: "External Systems", value: "3" }
|
|
305
|
+
]
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
type: "markdown",
|
|
309
|
+
title: "Architecture Diagram",
|
|
310
|
+
value: "<div class='arch-diagram'>...(inline SVG)...</div><style>...(design system CSS)...</style>"
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
type: "cards",
|
|
314
|
+
title: "Summary",
|
|
315
|
+
value: [
|
|
316
|
+
{ title: "Frontend", body: "React SPA..." },
|
|
317
|
+
{ title: "Backend", body: "API + async workers..." },
|
|
318
|
+
{ title: "Security", body: "Gateway + IdP..." }
|
|
319
|
+
]
|
|
320
|
+
}
|
|
321
|
+
]
|
|
322
|
+
})
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
This design system is the single source of truth. The `c4-architecture` skill and `present` skill both reference this file. Update component types, colors, or layout rules here only.
|
|
326
|
+
|
|
327
|
+
## Adding New Categories
|
|
328
|
+
|
|
329
|
+
1. Add a new row to the Category Registry with the category name, colors, C4 mapping, and initial subtype set.
|
|
330
|
+
2. Add the new sub-types to the Sub-type Registry with a C4 label and icon slot name.
|
|
331
|
+
3. Add icon placeholders to the Icon Registry.
|
|
332
|
+
4. Update [html-template.html](html-template.html) legend content so the new category appears in the rendered template.
|
|
333
|
+
5. Update summary card accent colors in [html-template.html](html-template.html) if the new category needs a dedicated card treatment.
|
|
334
|
+
|
|
335
|
+
## Template Pairing
|
|
336
|
+
|
|
337
|
+
See [html-template.html](html-template.html) for the complete self-contained reference implementation of this design system.
|
|
@@ -0,0 +1,627 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>C4 Architecture HTML/SVG Template - AIKIT</title>
|
|
7
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
8
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
9
|
+
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700;800&display=swap" rel="stylesheet" />
|
|
10
|
+
<style>
|
|
11
|
+
:root {
|
|
12
|
+
--bg: #020617;
|
|
13
|
+
--panel: rgba(15, 23, 42, 0.86);
|
|
14
|
+
--panel-border: rgba(148, 163, 184, 0.2);
|
|
15
|
+
--panel-shadow: 0 24px 60px rgba(2, 6, 23, 0.55);
|
|
16
|
+
--text: #e2e8f0;
|
|
17
|
+
--muted: #94a3b8;
|
|
18
|
+
--soft: #cbd5e1;
|
|
19
|
+
--cyan-stroke: #22d3ee;
|
|
20
|
+
--cyan-fill: rgba(8, 51, 68, 0.4);
|
|
21
|
+
--emerald-stroke: #34d399;
|
|
22
|
+
--emerald-fill: rgba(6, 78, 59, 0.4);
|
|
23
|
+
--violet-stroke: #a78bfa;
|
|
24
|
+
--violet-fill: rgba(76, 29, 149, 0.4);
|
|
25
|
+
--amber-stroke: #fbbf24;
|
|
26
|
+
--amber-fill: rgba(120, 53, 15, 0.3);
|
|
27
|
+
--orange-stroke: #fb923c;
|
|
28
|
+
--orange-fill: rgba(251, 146, 60, 0.3);
|
|
29
|
+
--rose-stroke: #fb7185;
|
|
30
|
+
--rose-fill: rgba(136, 19, 55, 0.4);
|
|
31
|
+
--slate-stroke: #94a3b8;
|
|
32
|
+
--slate-fill: rgba(30, 41, 59, 0.5);
|
|
33
|
+
--sky-stroke: #38bdf8;
|
|
34
|
+
--sky-fill: rgba(12, 74, 110, 0.4);
|
|
35
|
+
--major-grid: rgba(148, 163, 184, 0.08);
|
|
36
|
+
--minor-grid: rgba(148, 163, 184, 0.04);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
* {
|
|
40
|
+
box-sizing: border-box;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
body {
|
|
44
|
+
margin: 0;
|
|
45
|
+
min-height: 100vh;
|
|
46
|
+
font-family: "JetBrains Mono", monospace;
|
|
47
|
+
color: var(--text);
|
|
48
|
+
background-color: var(--bg);
|
|
49
|
+
background-image:
|
|
50
|
+
linear-gradient(var(--major-grid) 1px, transparent 1px),
|
|
51
|
+
linear-gradient(90deg, var(--major-grid) 1px, transparent 1px),
|
|
52
|
+
linear-gradient(var(--minor-grid) 1px, transparent 1px),
|
|
53
|
+
linear-gradient(90deg, var(--minor-grid) 1px, transparent 1px);
|
|
54
|
+
background-size: 120px 120px, 120px 120px, 30px 30px, 30px 30px;
|
|
55
|
+
background-position: 0 0, 0 0, 0 0, 0 0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.page {
|
|
59
|
+
width: min(100%, 1200px);
|
|
60
|
+
margin: 0 auto;
|
|
61
|
+
padding: 32px 20px 24px;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.header {
|
|
65
|
+
display: flex;
|
|
66
|
+
align-items: center;
|
|
67
|
+
justify-content: space-between;
|
|
68
|
+
gap: 16px;
|
|
69
|
+
margin-bottom: 20px;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.header-copy {
|
|
73
|
+
display: flex;
|
|
74
|
+
flex-direction: column;
|
|
75
|
+
gap: 8px;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.eyebrow {
|
|
79
|
+
display: inline-flex;
|
|
80
|
+
align-items: center;
|
|
81
|
+
gap: 10px;
|
|
82
|
+
font-size: 10px;
|
|
83
|
+
color: var(--soft);
|
|
84
|
+
letter-spacing: 0.12em;
|
|
85
|
+
text-transform: uppercase;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.pulse-dot {
|
|
89
|
+
width: 10px;
|
|
90
|
+
height: 10px;
|
|
91
|
+
border-radius: 999px;
|
|
92
|
+
background: var(--cyan-stroke);
|
|
93
|
+
box-shadow: 0 0 0 0 rgba(34, 211, 238, 0.7);
|
|
94
|
+
animation: pulse 1.8s infinite;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
h1 {
|
|
98
|
+
margin: 0;
|
|
99
|
+
font-size: clamp(24px, 4vw, 34px);
|
|
100
|
+
font-weight: 800;
|
|
101
|
+
line-height: 1.1;
|
|
102
|
+
color: #f8fafc;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.subtitle {
|
|
106
|
+
margin: 0;
|
|
107
|
+
font-size: 11px;
|
|
108
|
+
line-height: 1.6;
|
|
109
|
+
color: var(--muted);
|
|
110
|
+
max-width: 76ch;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.meta-chip {
|
|
114
|
+
padding: 10px 12px;
|
|
115
|
+
border: 1px solid var(--panel-border);
|
|
116
|
+
border-radius: 14px;
|
|
117
|
+
background: rgba(15, 23, 42, 0.72);
|
|
118
|
+
color: var(--soft);
|
|
119
|
+
font-size: 10px;
|
|
120
|
+
line-height: 1.5;
|
|
121
|
+
white-space: nowrap;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.diagram-card,
|
|
125
|
+
.legend-card,
|
|
126
|
+
.summary-card,
|
|
127
|
+
.footer {
|
|
128
|
+
border: 1px solid var(--panel-border);
|
|
129
|
+
border-radius: 22px;
|
|
130
|
+
background: var(--panel);
|
|
131
|
+
box-shadow: var(--panel-shadow);
|
|
132
|
+
backdrop-filter: blur(10px);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.diagram-card {
|
|
136
|
+
padding: 18px;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.diagram-frame {
|
|
140
|
+
border: 1px solid rgba(148, 163, 184, 0.18);
|
|
141
|
+
border-radius: 18px;
|
|
142
|
+
padding: 14px;
|
|
143
|
+
background: rgba(2, 6, 23, 0.65);
|
|
144
|
+
overflow: hidden;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
svg {
|
|
148
|
+
display: block;
|
|
149
|
+
width: 100%;
|
|
150
|
+
height: auto;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.boundary-label {
|
|
154
|
+
fill: #f8fafc;
|
|
155
|
+
font-size: 8px;
|
|
156
|
+
font-weight: 700;
|
|
157
|
+
letter-spacing: 0.08em;
|
|
158
|
+
text-transform: uppercase;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.arrow,
|
|
162
|
+
.arrow-dashed {
|
|
163
|
+
fill: none;
|
|
164
|
+
stroke: #cbd5e1;
|
|
165
|
+
stroke-width: 1.6;
|
|
166
|
+
marker-end: url(#arrowhead);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.arrow-dashed {
|
|
170
|
+
stroke-dasharray: 6 4;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.arrow-label {
|
|
174
|
+
fill: #cbd5e1;
|
|
175
|
+
font-size: 8px;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.node rect {
|
|
179
|
+
rx: 6;
|
|
180
|
+
stroke-width: 1.5;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.node .c4-tag {
|
|
184
|
+
fill: #f8fafc;
|
|
185
|
+
font-size: 7px;
|
|
186
|
+
letter-spacing: 0.08em;
|
|
187
|
+
text-transform: uppercase;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.node .node-title {
|
|
191
|
+
fill: #f8fafc;
|
|
192
|
+
font-size: 12px;
|
|
193
|
+
font-weight: 700;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.node .node-subtitle {
|
|
197
|
+
fill: #cbd5e1;
|
|
198
|
+
font-size: 9px;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.node .icon-slot {
|
|
202
|
+
fill: #e2e8f0;
|
|
203
|
+
font-size: 11px;
|
|
204
|
+
font-weight: 700;
|
|
205
|
+
text-anchor: middle;
|
|
206
|
+
dominant-baseline: middle;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.icon-use {
|
|
210
|
+
color: var(--muted);
|
|
211
|
+
opacity: 0.7;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.frontend .icon-use { color: var(--cyan-stroke); }
|
|
215
|
+
.backend .icon-use { color: var(--emerald-stroke); }
|
|
216
|
+
.data .icon-use { color: var(--violet-stroke); }
|
|
217
|
+
.infrastructure .icon-use { color: var(--amber-stroke); }
|
|
218
|
+
.messaging .icon-use { color: var(--orange-stroke); }
|
|
219
|
+
.security .icon-use { color: var(--rose-stroke); }
|
|
220
|
+
.external .icon-use { color: var(--slate-stroke); }
|
|
221
|
+
.monitoring .icon-use { color: var(--sky-stroke); }
|
|
222
|
+
|
|
223
|
+
.frontend rect { fill: var(--cyan-fill); stroke: var(--cyan-stroke); }
|
|
224
|
+
.backend rect { fill: var(--emerald-fill); stroke: var(--emerald-stroke); }
|
|
225
|
+
.data rect { fill: var(--violet-fill); stroke: var(--violet-stroke); }
|
|
226
|
+
.infrastructure rect { fill: var(--amber-fill); stroke: var(--amber-stroke); }
|
|
227
|
+
.messaging rect { fill: var(--orange-fill); stroke: var(--orange-stroke); }
|
|
228
|
+
.security rect { fill: var(--rose-fill); stroke: var(--rose-stroke); }
|
|
229
|
+
.external rect { fill: var(--slate-fill); stroke: var(--slate-stroke); }
|
|
230
|
+
.monitoring rect { fill: var(--sky-fill); stroke: var(--sky-stroke); }
|
|
231
|
+
|
|
232
|
+
.legend-card {
|
|
233
|
+
margin-top: 16px;
|
|
234
|
+
padding: 18px;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.legend-title {
|
|
238
|
+
margin: 0 0 14px;
|
|
239
|
+
font-size: 10px;
|
|
240
|
+
text-transform: uppercase;
|
|
241
|
+
letter-spacing: 0.12em;
|
|
242
|
+
color: var(--soft);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.legend-grid {
|
|
246
|
+
display: grid;
|
|
247
|
+
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
|
248
|
+
gap: 12px;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.legend-item {
|
|
252
|
+
padding: 12px;
|
|
253
|
+
border-radius: 16px;
|
|
254
|
+
border: 1px solid rgba(148, 163, 184, 0.16);
|
|
255
|
+
background: rgba(2, 6, 23, 0.4);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.legend-item h3 {
|
|
259
|
+
margin: 0 0 8px;
|
|
260
|
+
font-size: 10px;
|
|
261
|
+
color: #f8fafc;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.legend-item p {
|
|
265
|
+
margin: 0;
|
|
266
|
+
font-size: 10px;
|
|
267
|
+
line-height: 1.5;
|
|
268
|
+
color: var(--muted);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.legend-item code {
|
|
272
|
+
color: var(--soft);
|
|
273
|
+
font-size: 10px;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.legend-swatch {
|
|
277
|
+
display: inline-block;
|
|
278
|
+
width: 10px;
|
|
279
|
+
height: 10px;
|
|
280
|
+
margin-right: 8px;
|
|
281
|
+
border-radius: 999px;
|
|
282
|
+
vertical-align: middle;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
.swatch-cyan { background: var(--cyan-stroke); }
|
|
286
|
+
.swatch-emerald { background: var(--emerald-stroke); }
|
|
287
|
+
.swatch-violet { background: var(--violet-stroke); }
|
|
288
|
+
.swatch-amber { background: var(--amber-stroke); }
|
|
289
|
+
.swatch-orange { background: var(--orange-stroke); }
|
|
290
|
+
.swatch-rose { background: var(--rose-stroke); }
|
|
291
|
+
.swatch-slate { background: var(--slate-stroke); }
|
|
292
|
+
.swatch-sky { background: var(--sky-stroke); }
|
|
293
|
+
|
|
294
|
+
.summary-grid {
|
|
295
|
+
display: grid;
|
|
296
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
297
|
+
gap: 16px;
|
|
298
|
+
margin-top: 18px;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
.summary-card {
|
|
302
|
+
padding: 16px;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
.summary-card h2 {
|
|
306
|
+
display: flex;
|
|
307
|
+
align-items: center;
|
|
308
|
+
gap: 10px;
|
|
309
|
+
margin: 0 0 10px;
|
|
310
|
+
font-size: 10px;
|
|
311
|
+
text-transform: uppercase;
|
|
312
|
+
letter-spacing: 0.12em;
|
|
313
|
+
color: var(--soft);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
.summary-card p {
|
|
317
|
+
margin: 0;
|
|
318
|
+
font-size: 10px;
|
|
319
|
+
line-height: 1.65;
|
|
320
|
+
color: var(--muted);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
.card-dot {
|
|
324
|
+
width: 10px;
|
|
325
|
+
height: 10px;
|
|
326
|
+
border-radius: 999px;
|
|
327
|
+
flex: 0 0 auto;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
.card-dot.cyan { background: var(--cyan-stroke); }
|
|
331
|
+
.card-dot.emerald { background: var(--emerald-stroke); }
|
|
332
|
+
.card-dot.violet { background: var(--violet-stroke); }
|
|
333
|
+
.card-dot.amber { background: var(--amber-stroke); }
|
|
334
|
+
.card-dot.orange { background: var(--orange-stroke); }
|
|
335
|
+
.card-dot.rose { background: var(--rose-stroke); }
|
|
336
|
+
.card-dot.slate { background: var(--slate-stroke); }
|
|
337
|
+
.card-dot.sky { background: var(--sky-stroke); }
|
|
338
|
+
|
|
339
|
+
.footer {
|
|
340
|
+
margin-top: 18px;
|
|
341
|
+
padding: 14px 16px;
|
|
342
|
+
display: flex;
|
|
343
|
+
flex-wrap: wrap;
|
|
344
|
+
gap: 10px 16px;
|
|
345
|
+
justify-content: space-between;
|
|
346
|
+
font-size: 9px;
|
|
347
|
+
color: var(--muted);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
@keyframes pulse {
|
|
351
|
+
0% {
|
|
352
|
+
box-shadow: 0 0 0 0 rgba(34, 211, 238, 0.7);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
70% {
|
|
356
|
+
box-shadow: 0 0 0 12px rgba(34, 211, 238, 0);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
100% {
|
|
360
|
+
box-shadow: 0 0 0 0 rgba(34, 211, 238, 0);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
@media (max-width: 900px) {
|
|
365
|
+
.header {
|
|
366
|
+
flex-direction: column;
|
|
367
|
+
align-items: flex-start;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
.meta-chip {
|
|
371
|
+
white-space: normal;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
.summary-grid {
|
|
375
|
+
grid-template-columns: 1fr;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
</style>
|
|
379
|
+
</head>
|
|
380
|
+
<body>
|
|
381
|
+
<main class="page">
|
|
382
|
+
<header class="header">
|
|
383
|
+
<div class="header-copy">
|
|
384
|
+
<div class="eyebrow">
|
|
385
|
+
<span class="pulse-dot"></span>
|
|
386
|
+
<span>C4 Architecture HTML/SVG Template</span>
|
|
387
|
+
</div>
|
|
388
|
+
<h1>System Architecture</h1>
|
|
389
|
+
<p class="subtitle">Self-contained architecture diagram template aligned to the centralized HTML/SVG design system for C4-style documentation, present blocks, and inline SVG rendering.</p>
|
|
390
|
+
</div>
|
|
391
|
+
<div class="meta-chip">viewBox 1000x680<br />JetBrains Mono<br />Single-source design tokens</div>
|
|
392
|
+
</header>
|
|
393
|
+
|
|
394
|
+
<section class="diagram-card" aria-labelledby="diagram-title">
|
|
395
|
+
<div class="diagram-frame">
|
|
396
|
+
<svg viewBox="0 0 1000 680" role="img" aria-labelledby="diagram-title diagram-desc">
|
|
397
|
+
<title id="diagram-title">C4 architecture diagram example</title>
|
|
398
|
+
<desc id="diagram-desc">Example architecture diagram with frontend, backend, data, infrastructure, messaging, security, external, and monitoring categories.</desc>
|
|
399
|
+
<defs>
|
|
400
|
+
<marker id="arrowhead" markerWidth="8" markerHeight="8" refX="7" refY="4" orient="auto">
|
|
401
|
+
<path d="M0,0 L8,4 L0,8 Z" fill="#cbd5e1"></path>
|
|
402
|
+
</marker>
|
|
403
|
+
|
|
404
|
+
<!-- Category Icons -->
|
|
405
|
+
<symbol id="icon-frontend" viewBox="0 0 16 16">
|
|
406
|
+
<rect x="1.5" y="1" width="13" height="10" rx="1.5" fill="none" stroke="currentColor" stroke-width="1.2"/>
|
|
407
|
+
<line x1="1.5" y1="4" x2="14.5" y2="4" stroke="currentColor" stroke-width="0.8"/>
|
|
408
|
+
<circle cx="3.5" cy="2.5" r="0.6" fill="currentColor"/>
|
|
409
|
+
<circle cx="5.5" cy="2.5" r="0.6" fill="currentColor"/>
|
|
410
|
+
<line x1="6" y1="11" x2="6" y2="14" stroke="currentColor" stroke-width="1.2"/>
|
|
411
|
+
<line x1="10" y1="11" x2="10" y2="14" stroke="currentColor" stroke-width="1.2"/>
|
|
412
|
+
<line x1="4" y1="14" x2="12" y2="14" stroke="currentColor" stroke-width="1.2"/>
|
|
413
|
+
</symbol>
|
|
414
|
+
|
|
415
|
+
<symbol id="icon-backend" viewBox="0 0 16 16">
|
|
416
|
+
<rect x="2" y="0.5" width="12" height="4" rx="1" fill="none" stroke="currentColor" stroke-width="1.2"/>
|
|
417
|
+
<rect x="2" y="6" width="12" height="4" rx="1" fill="none" stroke="currentColor" stroke-width="1.2"/>
|
|
418
|
+
<rect x="2" y="11.5" width="12" height="4" rx="1" fill="none" stroke="currentColor" stroke-width="1.2"/>
|
|
419
|
+
<circle cx="11.5" cy="2.5" r="0.8" fill="currentColor"/>
|
|
420
|
+
<circle cx="11.5" cy="8" r="0.8" fill="currentColor"/>
|
|
421
|
+
<circle cx="11.5" cy="13.5" r="0.8" fill="currentColor"/>
|
|
422
|
+
</symbol>
|
|
423
|
+
|
|
424
|
+
<symbol id="icon-data" viewBox="0 0 16 16">
|
|
425
|
+
<ellipse cx="8" cy="3" rx="5.5" ry="2.2" fill="none" stroke="currentColor" stroke-width="1.2"/>
|
|
426
|
+
<path d="M2.5 3 V12" fill="none" stroke="currentColor" stroke-width="1.2"/>
|
|
427
|
+
<path d="M13.5 3 V12" fill="none" stroke="currentColor" stroke-width="1.2"/>
|
|
428
|
+
<ellipse cx="8" cy="12" rx="5.5" ry="2.2" fill="none" stroke="currentColor" stroke-width="1.2"/>
|
|
429
|
+
<path d="M2.5 7.5 C2.5 9.7 5 10.2 8 10.2 C11 10.2 13.5 9.7 13.5 7.5" fill="none" stroke="currentColor" stroke-width="0.8"/>
|
|
430
|
+
</symbol>
|
|
431
|
+
|
|
432
|
+
<symbol id="icon-infrastructure" viewBox="0 0 16 16">
|
|
433
|
+
<path d="M3.5 13 C1.2 13 0 11.3 0 9.5 C0 7.8 1 6.3 2.8 6 C3 3.5 5.2 1.5 8 1.5 C10.8 1.5 13 3.5 13.2 6 C15 6.3 16 7.8 16 9.5 C16 11.3 14.8 13 12.5 13 Z" fill="none" stroke="currentColor" stroke-width="1.2"/>
|
|
434
|
+
</symbol>
|
|
435
|
+
|
|
436
|
+
<symbol id="icon-messaging" viewBox="0 0 16 16">
|
|
437
|
+
<path d="M1 3 L8 8.5 L15 3" fill="none" stroke="currentColor" stroke-width="1.2"/>
|
|
438
|
+
<rect x="1" y="3" width="14" height="10" rx="1.5" fill="none" stroke="currentColor" stroke-width="1.2"/>
|
|
439
|
+
</symbol>
|
|
440
|
+
|
|
441
|
+
<symbol id="icon-security" viewBox="0 0 16 16">
|
|
442
|
+
<path d="M8 0.8 L2 3.5 V7.5 C2 11.5 4.5 14 8 15.2 C11.5 14 14 11.5 14 7.5 V3.5 Z" fill="none" stroke="currentColor" stroke-width="1.2"/>
|
|
443
|
+
<polyline points="5.5 8 7.5 10 11 5.5" fill="none" stroke="currentColor" stroke-width="1.3"/>
|
|
444
|
+
</symbol>
|
|
445
|
+
|
|
446
|
+
<symbol id="icon-external" viewBox="0 0 16 16">
|
|
447
|
+
<circle cx="8" cy="8" r="6.5" fill="none" stroke="currentColor" stroke-width="1.2"/>
|
|
448
|
+
<ellipse cx="8" cy="8" rx="3" ry="6.5" fill="none" stroke="currentColor" stroke-width="0.8"/>
|
|
449
|
+
<line x1="1.5" y1="5.5" x2="14.5" y2="5.5" stroke="currentColor" stroke-width="0.8"/>
|
|
450
|
+
<line x1="1.5" y1="10.5" x2="14.5" y2="10.5" stroke="currentColor" stroke-width="0.8"/>
|
|
451
|
+
</symbol>
|
|
452
|
+
|
|
453
|
+
<symbol id="icon-monitoring" viewBox="0 0 16 16">
|
|
454
|
+
<polyline points="0.5 12 3.5 8 6 10 9 3 12 7 15.5 2" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/>
|
|
455
|
+
<line x1="0.5" y1="15" x2="15.5" y2="15" stroke="currentColor" stroke-width="1"/>
|
|
456
|
+
<line x1="0.5" y1="1" x2="0.5" y2="15" stroke="currentColor" stroke-width="1"/>
|
|
457
|
+
</symbol>
|
|
458
|
+
</defs>
|
|
459
|
+
|
|
460
|
+
<rect x="0" y="0" width="1000" height="680" rx="18" fill="rgba(2, 6, 23, 0.38)"></rect>
|
|
461
|
+
|
|
462
|
+
<rect x="54" y="86" width="612" height="472" rx="12" fill="transparent" stroke="#fbbf24" stroke-width="1.5" stroke-dasharray="8,4"></rect>
|
|
463
|
+
<text class="boundary-label" x="74" y="106">Application Region</text>
|
|
464
|
+
|
|
465
|
+
<rect x="708" y="118" width="228" height="194" rx="12" fill="transparent" stroke="#fb7185" stroke-width="1.5" stroke-dasharray="4,4"></rect>
|
|
466
|
+
<text class="boundary-label" x="728" y="138">Security Boundary</text>
|
|
467
|
+
|
|
468
|
+
<!-- CUSTOMIZATION: Add/remove arrows here -->
|
|
469
|
+
<path class="arrow" d="M190 182 H286"></path>
|
|
470
|
+
<text class="arrow-label" x="208" y="171">serves shell assets</text>
|
|
471
|
+
|
|
472
|
+
<path class="arrow" d="M470 208 H530"></path>
|
|
473
|
+
<text class="arrow-label" x="476" y="197">calls</text>
|
|
474
|
+
|
|
475
|
+
<path class="arrow-dashed" d="M655 210 H708"></path>
|
|
476
|
+
<text class="arrow-label" x="656" y="197">auth flow</text>
|
|
477
|
+
|
|
478
|
+
<path class="arrow" d="M615 270 V344"></path>
|
|
479
|
+
<text class="arrow-label" x="626" y="312">reads and writes</text>
|
|
480
|
+
|
|
481
|
+
<path class="arrow" d="M470 450 H530"></path>
|
|
482
|
+
<text class="arrow-label" x="482" y="439">publishes domain events</text>
|
|
483
|
+
|
|
484
|
+
<path class="arrow" d="M635 450 H730"></path>
|
|
485
|
+
<text class="arrow-label" x="650" y="439">exports metrics</text>
|
|
486
|
+
|
|
487
|
+
<path class="arrow" d="M850 250 V350"></path>
|
|
488
|
+
<text class="arrow-label" x="862" y="305">webhook callback</text>
|
|
489
|
+
|
|
490
|
+
<!-- CUSTOMIZATION: Add/remove component boxes here -->
|
|
491
|
+
<g class="node infrastructure">
|
|
492
|
+
<rect x="70" y="150" width="120" height="60"></rect>
|
|
493
|
+
<text class="c4-tag" x="84" y="166"><<Deployment_Node>></text>
|
|
494
|
+
<text class="node-title" x="84" y="184">CDN Edge</text>
|
|
495
|
+
<text class="node-subtitle" x="84" y="198">Infrastructure / CDN</text>
|
|
496
|
+
<use href="#icon-infrastructure" class="icon-use" x="168" y="154" width="16" height="16"/>
|
|
497
|
+
</g>
|
|
498
|
+
|
|
499
|
+
<g class="node frontend">
|
|
500
|
+
<rect x="286" y="150" width="184" height="60"></rect>
|
|
501
|
+
<text class="c4-tag" x="300" y="166"><<Container>></text>
|
|
502
|
+
<text class="node-title" x="300" y="184">Customer SPA</text>
|
|
503
|
+
<text class="node-subtitle" x="300" y="198">Frontend / React PWA</text>
|
|
504
|
+
<use href="#icon-frontend" class="icon-use" x="448" y="154" width="16" height="16"/>
|
|
505
|
+
</g>
|
|
506
|
+
|
|
507
|
+
<g class="node backend">
|
|
508
|
+
<rect x="530" y="180" width="186" height="60"></rect>
|
|
509
|
+
<text class="c4-tag" x="544" y="196"><<Container>></text>
|
|
510
|
+
<text class="node-title" x="544" y="214">Orders API</text>
|
|
511
|
+
<text class="node-subtitle" x="544" y="228">Backend / API Service</text>
|
|
512
|
+
<use href="#icon-backend" class="icon-use" x="694" y="184" width="16" height="16"/>
|
|
513
|
+
</g>
|
|
514
|
+
|
|
515
|
+
<g class="node security">
|
|
516
|
+
<rect x="730" y="164" width="184" height="60"></rect>
|
|
517
|
+
<text class="c4-tag" x="744" y="180"><<System_Ext>></text>
|
|
518
|
+
<text class="node-title" x="744" y="198">Identity Provider</text>
|
|
519
|
+
<text class="node-subtitle" x="744" y="212">Security / Auth Provider</text>
|
|
520
|
+
<use href="#icon-security" class="icon-use" x="892" y="168" width="16" height="16"/>
|
|
521
|
+
</g>
|
|
522
|
+
|
|
523
|
+
<g class="node security">
|
|
524
|
+
<rect x="730" y="240" width="184" height="60"></rect>
|
|
525
|
+
<text class="c4-tag" x="744" y="256"><<System_Ext>></text>
|
|
526
|
+
<text class="node-title" x="744" y="274">API Gateway</text>
|
|
527
|
+
<text class="node-subtitle" x="744" y="288">Security / Gateway</text>
|
|
528
|
+
<use href="#icon-security" class="icon-use" x="892" y="244" width="16" height="16"/>
|
|
529
|
+
</g>
|
|
530
|
+
|
|
531
|
+
<g class="node data">
|
|
532
|
+
<rect x="530" y="344" width="186" height="60"></rect>
|
|
533
|
+
<text class="c4-tag" x="544" y="360"><<ContainerDb>></text>
|
|
534
|
+
<text class="node-title" x="544" y="378">Orders DB</text>
|
|
535
|
+
<text class="node-subtitle" x="544" y="392">Data / Relational DB</text>
|
|
536
|
+
<use href="#icon-data" class="icon-use" x="694" y="348" width="16" height="16"/>
|
|
537
|
+
</g>
|
|
538
|
+
|
|
539
|
+
<g class="node messaging">
|
|
540
|
+
<rect x="530" y="420" width="186" height="60"></rect>
|
|
541
|
+
<text class="c4-tag" x="544" y="436"><<ContainerQueue>></text>
|
|
542
|
+
<text class="node-title" x="544" y="454">Event Bus</text>
|
|
543
|
+
<text class="node-subtitle" x="544" y="468">Messaging / Pub/Sub</text>
|
|
544
|
+
<use href="#icon-messaging" class="icon-use" x="694" y="424" width="16" height="16"/>
|
|
545
|
+
</g>
|
|
546
|
+
|
|
547
|
+
<g class="node external">
|
|
548
|
+
<rect x="760" y="350" width="154" height="60"></rect>
|
|
549
|
+
<text class="c4-tag" x="774" y="366"><<System_Ext>></text>
|
|
550
|
+
<text class="node-title" x="774" y="384">Payment SaaS</text>
|
|
551
|
+
<text class="node-subtitle" x="774" y="398">External / Provider</text>
|
|
552
|
+
<use href="#icon-external" class="icon-use" x="892" y="354" width="16" height="16"/>
|
|
553
|
+
</g>
|
|
554
|
+
|
|
555
|
+
<g class="node monitoring">
|
|
556
|
+
<rect x="760" y="420" width="154" height="60"></rect>
|
|
557
|
+
<text class="c4-tag" x="774" y="436"><<Container>></text>
|
|
558
|
+
<text class="node-title" x="774" y="454">Metrics Stack</text>
|
|
559
|
+
<text class="node-subtitle" x="774" y="468">Monitoring / Metrics</text>
|
|
560
|
+
<use href="#icon-monitoring" class="icon-use" x="892" y="424" width="16" height="16"/>
|
|
561
|
+
</g>
|
|
562
|
+
</svg>
|
|
563
|
+
</div>
|
|
564
|
+
</section>
|
|
565
|
+
|
|
566
|
+
<section class="legend-card" aria-labelledby="legend-title">
|
|
567
|
+
<h2 class="legend-title" id="legend-title">Legend</h2>
|
|
568
|
+
<div class="legend-grid">
|
|
569
|
+
<!-- CUSTOMIZATION: Update legend categories here -->
|
|
570
|
+
<article class="legend-item">
|
|
571
|
+
<h3><span class="legend-swatch swatch-cyan"></span>Frontend</h3>
|
|
572
|
+
<p><code><<Container>></code> for SPA, Mobile App, Static Site, Micro-frontend, PWA, and Desktop App.</p>
|
|
573
|
+
</article>
|
|
574
|
+
<article class="legend-item">
|
|
575
|
+
<h3><span class="legend-swatch swatch-emerald"></span>Backend</h3>
|
|
576
|
+
<p><code><<Container>></code> for API Service, Worker/Job, BFF, Microservice, Serverless Function, and gRPC Service.</p>
|
|
577
|
+
</article>
|
|
578
|
+
<article class="legend-item">
|
|
579
|
+
<h3><span class="legend-swatch swatch-violet"></span>Data</h3>
|
|
580
|
+
<p><code><<ContainerDb>></code> for Relational DB, Document DB, Key-Value Store, Cache, Search Engine, Data Warehouse, Graph DB, and Time-Series DB.</p>
|
|
581
|
+
</article>
|
|
582
|
+
<article class="legend-item">
|
|
583
|
+
<h3><span class="legend-swatch swatch-amber"></span>Infrastructure</h3>
|
|
584
|
+
<p><code><<Deployment_Node>></code> for CDN, Load Balancer, DNS, Object Storage, Container Registry, Reverse Proxy, and Service Mesh.</p>
|
|
585
|
+
</article>
|
|
586
|
+
<article class="legend-item">
|
|
587
|
+
<h3><span class="legend-swatch swatch-orange"></span>Messaging</h3>
|
|
588
|
+
<p><code><<ContainerQueue>></code> for Message Queue, Event Bus, Stream, Pub/Sub, and Webhook.</p>
|
|
589
|
+
</article>
|
|
590
|
+
<article class="legend-item">
|
|
591
|
+
<h3><span class="legend-swatch swatch-rose"></span>Security</h3>
|
|
592
|
+
<p><code><<System_Ext>></code> or boundary for Auth Provider, API Gateway, WAF, Secret Manager, Certificate Manager, and Identity Provider.</p>
|
|
593
|
+
</article>
|
|
594
|
+
<article class="legend-item">
|
|
595
|
+
<h3><span class="legend-swatch swatch-slate"></span>External</h3>
|
|
596
|
+
<p><code><<System_Ext>></code> for Third-party API, SaaS, Legacy System, Partner Service, and Payment Provider.</p>
|
|
597
|
+
</article>
|
|
598
|
+
<article class="legend-item">
|
|
599
|
+
<h3><span class="legend-swatch swatch-sky"></span>Monitoring</h3>
|
|
600
|
+
<p><code><<Container>></code> for Logging, Metrics, Tracing, Alerting, and APM.</p>
|
|
601
|
+
</article>
|
|
602
|
+
</div>
|
|
603
|
+
</section>
|
|
604
|
+
|
|
605
|
+
<section class="summary-grid" aria-label="Architecture summary cards">
|
|
606
|
+
<article class="summary-card">
|
|
607
|
+
<h2><span class="card-dot cyan"></span>Frontend Path</h2>
|
|
608
|
+
<p>The entry path routes through a CDN edge into a React PWA container, preserving a clear frontend classification with C4 container labeling and room for per-subtype icons in the top-right box area.</p>
|
|
609
|
+
</article>
|
|
610
|
+
<article class="summary-card">
|
|
611
|
+
<h2><span class="card-dot emerald"></span>Service Core</h2>
|
|
612
|
+
<p>The API service writes to a relational database and publishes events to the event bus, demonstrating standard, vertical, and labeled connectors while keeping arrows beneath component layers.</p>
|
|
613
|
+
</article>
|
|
614
|
+
<article class="summary-card">
|
|
615
|
+
<h2><span class="card-dot rose"></span>Security Edge</h2>
|
|
616
|
+
<p>A dashed rose boundary isolates identity and gateway capabilities, while an external payment provider and monitoring stack show how non-core systems stay visually distinct from platform containers.</p>
|
|
617
|
+
</article>
|
|
618
|
+
</section>
|
|
619
|
+
|
|
620
|
+
<footer class="footer">
|
|
621
|
+
<span>Generator: HTML/SVG C4 reference template</span>
|
|
622
|
+
<span>Layout: header, main SVG, legend, 3 summary cards, footer metadata</span>
|
|
623
|
+
<span>Colors and typography: synchronized with html-design-system.md</span>
|
|
624
|
+
</footer>
|
|
625
|
+
</main>
|
|
626
|
+
</body>
|
|
627
|
+
</html>
|
|
@@ -162,6 +162,154 @@ The dashboard uses a professional dark theme:
|
|
|
162
162
|
|
|
163
163
|
---
|
|
164
164
|
|
|
165
|
+
## Architecture Diagrams
|
|
166
|
+
|
|
167
|
+
> **Behavioral rule:** When asked to present, visualize, or display system architecture, infrastructure, or service topology — **always load the `c4-architecture` skill** and use its HTML/SVG format (Method 2 below) for rich visual output via `present`. The Mermaid method (Method 1) is acceptable only for quick in-chat previews or when the user explicitly asks for Mermaid. Default to HTML/SVG for all architecture presentations.
|
|
168
|
+
|
|
169
|
+
The `present` tool can render C4-style architecture diagrams in both `html` and `browser` formats. The visual design system is centralized in the `c4-architecture` skill's reference file — load that skill for the full type registry, color palette, and template.
|
|
170
|
+
|
|
171
|
+
**Design system source:** `c4-architecture/references/html-design-system.md` (single source of truth for all architecture diagram styling)
|
|
172
|
+
|
|
173
|
+
### When to Use (Auto-Trigger)
|
|
174
|
+
|
|
175
|
+
Load the `c4-architecture` skill and use HTML/SVG format when the user:
|
|
176
|
+
- Asks to "show architecture", "present the system design", "visualize infrastructure"
|
|
177
|
+
- Wants to display service topology, deployment layout, or component relationships
|
|
178
|
+
- Requests architecture review output, system overview dashboards, or technical presentations
|
|
179
|
+
- Uses words like "architecture diagram", "system diagram", "infrastructure diagram"
|
|
180
|
+
|
|
181
|
+
### Rendering Methods
|
|
182
|
+
|
|
183
|
+
| Method | Block Type | Format | When to Use |
|
|
184
|
+
|--------|-----------|--------|-------------|
|
|
185
|
+
| Mermaid C4 | `mermaid` | html / browser | Quick diagrams, developer-focused, version-controlled |
|
|
186
|
+
| HTML/SVG | `markdown` | html / browser | Rich visual presentations, stakeholder reviews, dark-themed dashboards |
|
|
187
|
+
|
|
188
|
+
### Method 1: Mermaid C4 Diagrams
|
|
189
|
+
|
|
190
|
+
Use a `mermaid` content block with standard C4 Mermaid syntax:
|
|
191
|
+
|
|
192
|
+
present({
|
|
193
|
+
format: "html", // or "browser"
|
|
194
|
+
title: "System Architecture",
|
|
195
|
+
content: [
|
|
196
|
+
{
|
|
197
|
+
type: "mermaid",
|
|
198
|
+
title: "C4 Container Diagram",
|
|
199
|
+
value: `C4Container
|
|
200
|
+
title Container Diagram - Payment System
|
|
201
|
+
|
|
202
|
+
Person(user, "Customer", "Places orders")
|
|
203
|
+
|
|
204
|
+
Container_Boundary(app, "Payment Platform") {
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Rendering Troubleshooting
|
|
209
|
+
|
|
210
|
+
### Why `html` format sometimes shows raw text
|
|
211
|
+
|
|
212
|
+
The `html` format renders content inside an MCP Apps companion iframe (UIResource). The chat text fallback is intentionally minimal (just the title). When the UIResource fails to load, the user sees only the title or raw JSON — NOT the rendered dashboard.
|
|
213
|
+
|
|
214
|
+
**Common causes of UIResource rendering failure:**
|
|
215
|
+
1. **MCP Apps not enabled** — The setting `chat.mcp.apps.enabled` must be `true` in VS Code settings
|
|
216
|
+
2. **Companion app build missing** — The `packages/present` companion app must be built (`npm run build`)
|
|
217
|
+
3. **Content too large** — Very large content arrays (20+ blocks or tables with 50+ rows) may cause the companion iframe to fail silently
|
|
218
|
+
4. **Iframe loading error** — Network issues, CSP restrictions, or extension conflicts can prevent the iframe from loading
|
|
219
|
+
|
|
220
|
+
### When to prefer `browser` over `html`
|
|
221
|
+
|
|
222
|
+
Use `format: "browser"` instead of `html` when:
|
|
223
|
+
- Content has **10+ blocks** or tables with **20+ rows** (large payloads are more reliable in browser)
|
|
224
|
+
- The output must be **guaranteed visible** (browser format always opens, no silent failures)
|
|
225
|
+
- You need **charts + tables + markdown** in the same view (browser renders all block types reliably)
|
|
226
|
+
- The user reports that `html` format "didn't show anything" or "showed raw text"
|
|
227
|
+
|
|
228
|
+
> **Reliability rule:** If content is complex (5+ blocks of mixed types), prefer `format: "browser"` for guaranteed rendering. The `html` format is best for simple, single-block content.
|
|
229
|
+
|
|
230
|
+
### Content formatting tips to avoid rendering issues
|
|
231
|
+
|
|
232
|
+
1. **Use `table` block type** instead of markdown tables inside `markdown` blocks — `table` blocks render natively; markdown pipe-tables may show as raw text in fallback
|
|
233
|
+
2. **Use `cards` and `metrics`** for summary data instead of embedding it in markdown text
|
|
234
|
+
3. **Keep `markdown` blocks for narrative text only** — don't embed HTML, tables, or complex formatting
|
|
235
|
+
4. **Split large content** into multiple smaller `present` calls rather than one massive content array
|
|
236
|
+
5. **For charts:** Always use ChartValue format (`chartType`, `data`, `xKey`, `yKeys`) — NOT Chart.js format (`labels`, `datasets`)
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
Container(api, "API Gateway", "Kong", "Routes requests")
|
|
241
|
+
Container(svc, "Payment Service", "Node.js", "Processes payments")
|
|
242
|
+
ContainerDb(db, "Payment DB", "PostgreSQL", "Transaction records")
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
System_Ext(stripe, "Stripe", "Payment processor")
|
|
246
|
+
|
|
247
|
+
Rel(user, api, "HTTPS")
|
|
248
|
+
Rel(api, svc, "gRPC")
|
|
249
|
+
Rel(svc, db, "SQL")
|
|
250
|
+
Rel(svc, stripe, "REST")`
|
|
251
|
+
}
|
|
252
|
+
]
|
|
253
|
+
})
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Method 2: HTML/SVG Architecture Diagrams
|
|
257
|
+
|
|
258
|
+
For rich visual output, embed the full HTML/SVG diagram in a `markdown` block. Compose with `metrics` and `cards` blocks for a complete dashboard.
|
|
259
|
+
|
|
260
|
+
**Both `format: "html"` and `format: "browser"` work with this approach.**
|
|
261
|
+
|
|
262
|
+
```js
|
|
263
|
+
present({
|
|
264
|
+
format: "html", // or "browser"
|
|
265
|
+
title: "System Architecture",
|
|
266
|
+
content: [
|
|
267
|
+
{
|
|
268
|
+
type: "metrics",
|
|
269
|
+
title: "Overview",
|
|
270
|
+
value: [
|
|
271
|
+
{ label: "Services", value: "6" },
|
|
272
|
+
{ label: "Data Stores", value: "2" },
|
|
273
|
+
{ label: "External Systems", value: "3" }
|
|
274
|
+
]
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
type: "markdown",
|
|
278
|
+
title: "Architecture Diagram",
|
|
279
|
+
value: "<div class='arch-diagram'><style>/* design system CSS from c4-architecture/references/html-design-system.md */</style><svg viewBox='0 0 1000 680'><!-- SVG components using category colors --></svg></div>"
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
type: "cards",
|
|
283
|
+
title: "Component Summary",
|
|
284
|
+
value: [
|
|
285
|
+
{ title: "Frontend", body: "React SPA + CDN delivery" },
|
|
286
|
+
{ title: "Backend", body: "3 microservices, gRPC mesh" },
|
|
287
|
+
{ title: "Data", body: "PostgreSQL + Redis cache" }
|
|
288
|
+
]
|
|
289
|
+
}
|
|
290
|
+
]
|
|
291
|
+
})
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Component Categories (Quick Reference)
|
|
295
|
+
|
|
296
|
+
The full type registry with sub-types and icon slots is in `c4-architecture/references/html-design-system.md`. Here is the category summary:
|
|
297
|
+
|
|
298
|
+
| Category | Stroke | CSS Class | Use For |
|
|
299
|
+
|----------|--------|-----------|---------|
|
|
300
|
+
| Frontend | `#22d3ee` | `.cyan` | SPAs, mobile apps, static sites, PWAs |
|
|
301
|
+
| Backend | `#34d399` | `.emerald` | API services, workers, microservices, serverless |
|
|
302
|
+
| Data | `#a78bfa` | `.violet` | Databases, caches, search engines, warehouses |
|
|
303
|
+
| Infrastructure | `#fbbf24` | `.amber` | CDNs, load balancers, DNS, storage |
|
|
304
|
+
| Messaging | `#fb923c` | `.orange` | Queues, event buses, streams, pub/sub |
|
|
305
|
+
| Security | `#fb7185` | `.rose` | Auth, API gateways, WAF, secret managers |
|
|
306
|
+
| External | `#94a3b8` | `.slate` | Third-party APIs, SaaS, legacy systems |
|
|
307
|
+
| Monitoring | `#38bdf8` | `.sky` | Logging, metrics, tracing, alerting |
|
|
308
|
+
|
|
309
|
+
> **Centralization note:** Do not duplicate colors or type definitions here. The `c4-architecture` skill's design system is the single source of truth. When categories or colors change, they are updated in one place.
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
165
313
|
## Best Practices
|
|
166
314
|
|
|
167
315
|
1. **Use `browser` format** for data-rich content — charts, tables, dashboards. **Always use `browser` in CLI mode** (the `html` UIResource doesn't render in terminal environments).
|
|
@@ -178,6 +326,38 @@ The dashboard uses a professional dark theme:
|
|
|
178
326
|
|
|
179
327
|
---
|
|
180
328
|
|
|
329
|
+
## Rendering Troubleshooting
|
|
330
|
+
|
|
331
|
+
### Why `html` format sometimes shows raw text
|
|
332
|
+
|
|
333
|
+
The `html` format renders content inside an MCP Apps companion iframe (UIResource). The chat text fallback is intentionally minimal (just the title). When the UIResource fails to load, the user sees only the title or raw JSON — NOT the rendered dashboard.
|
|
334
|
+
|
|
335
|
+
**Common causes of UIResource rendering failure:**
|
|
336
|
+
1. **MCP Apps not enabled** — The setting `chat.mcp.apps.enabled` must be `true` in VS Code settings
|
|
337
|
+
2. **Companion app build missing** — The `packages/present` companion app must be built (`npm run build`)
|
|
338
|
+
3. **Content too large** — Very large content arrays (20+ blocks or tables with 50+ rows) may cause the companion iframe to fail silently
|
|
339
|
+
4. **Iframe loading error** — Network issues, CSP restrictions, or extension conflicts can prevent the iframe from loading
|
|
340
|
+
|
|
341
|
+
### When to prefer `browser` over `html`
|
|
342
|
+
|
|
343
|
+
Use `format: "browser"` instead of `html` when:
|
|
344
|
+
- Content has **10+ blocks** or tables with **20+ rows** (large payloads are more reliable in browser)
|
|
345
|
+
- The output must be **guaranteed visible** (browser format always opens, no silent failures)
|
|
346
|
+
- You need **charts + tables + markdown** in the same view (browser renders all block types reliably)
|
|
347
|
+
- The user reports that `html` format "didn't show anything" or "showed raw text"
|
|
348
|
+
|
|
349
|
+
> **Reliability rule:** If content is complex (5+ blocks of mixed types), prefer `format: "browser"` for guaranteed rendering. The `html` format is best for simple, single-block content.
|
|
350
|
+
|
|
351
|
+
### Content formatting tips to avoid rendering issues
|
|
352
|
+
|
|
353
|
+
1. **Use `table` block type** instead of markdown tables inside `markdown` blocks — `table` blocks render natively; markdown pipe-tables may show as raw text in fallback
|
|
354
|
+
2. **Use `cards` and `metrics`** for summary data instead of embedding it in markdown text
|
|
355
|
+
3. **Keep `markdown` blocks for narrative text only** — don't embed HTML, tables, or complex formatting
|
|
356
|
+
4. **Split large content** into multiple smaller `present` calls rather than one massive content array
|
|
357
|
+
5. **For charts:** Always use ChartValue format (`chartType`, `data`, `xKey`, `yKeys`) — NOT Chart.js format (`labels`, `datasets`)
|
|
358
|
+
|
|
359
|
+
---
|
|
360
|
+
|
|
181
361
|
## MCP Apps Templates (VS Code Chat Widgets)
|
|
182
362
|
|
|
183
363
|
When `chat.mcp.apps.enabled` is true in VS Code settings, the `present` tool can render **interactive widgets directly in the chat panel** using the `template` parameter. These are distinct from the browser/html dashboard modes.
|