- Rename skill/ to skills/ for consistency with naming conventions - Rename agent/ to agents/ and command/ to commands/ - Update AGENTS.md with all directory references - Update scripts/test-skill.sh paths - Update prompts/athena.txt documentation This aligns with best practices of using plural directory names and updates all documentation to reflect the new structure.
211 lines
4.8 KiB
Markdown
211 lines
4.8 KiB
Markdown
# Excalidraw JSON Format Reference
|
|
|
|
Complete reference for Excalidraw JSON structure and element types.
|
|
|
|
---
|
|
|
|
## File Structure
|
|
|
|
```json
|
|
{
|
|
"type": "excalidraw",
|
|
"version": 2,
|
|
"source": "claude-code-excalidraw-skill",
|
|
"elements": [],
|
|
"appState": {
|
|
"gridSize": 20,
|
|
"viewBackgroundColor": "#ffffff"
|
|
},
|
|
"files": {}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Element Types
|
|
|
|
| Type | Use For | Arrow Reliability |
|
|
|------|---------|-------------------|
|
|
| `rectangle` | Services, components, databases, containers, orchestrators, decision points | Excellent |
|
|
| `ellipse` | Users, external systems, start/end points | Good |
|
|
| `text` | Labels inside shapes, titles, annotations | N/A |
|
|
| `arrow` | Data flow, connections, dependencies | N/A |
|
|
| `line` | Grouping boundaries, separators | N/A |
|
|
|
|
### BANNED: Diamond Shapes
|
|
|
|
**NEVER use `type: "diamond"` in generated diagrams.**
|
|
|
|
Diamond arrow connections are fundamentally broken in raw Excalidraw JSON:
|
|
- Excalidraw applies `roundness` to diamond vertices during rendering
|
|
- Visual edges appear offset from mathematical edge points
|
|
- No offset formula reliably compensates
|
|
- Arrows appear disconnected/floating
|
|
|
|
**Use styled rectangles instead** for visual distinction:
|
|
|
|
| Semantic Meaning | Rectangle Style |
|
|
|------------------|-----------------|
|
|
| Orchestrator/Hub | Coral (`#ffa8a8`/`#c92a2a`) + strokeWidth: 3 |
|
|
| Decision Point | Orange (`#ffd8a8`/`#e8590c`) + dashed stroke |
|
|
| Central Router | Larger size + bold color |
|
|
|
|
---
|
|
|
|
## Required Element Properties
|
|
|
|
Every element MUST have these properties:
|
|
|
|
```json
|
|
{
|
|
"id": "unique-id-string",
|
|
"type": "rectangle",
|
|
"x": 100,
|
|
"y": 100,
|
|
"width": 200,
|
|
"height": 80,
|
|
"angle": 0,
|
|
"strokeColor": "#1971c2",
|
|
"backgroundColor": "#a5d8ff",
|
|
"fillStyle": "solid",
|
|
"strokeWidth": 2,
|
|
"strokeStyle": "solid",
|
|
"roughness": 1,
|
|
"opacity": 100,
|
|
"groupIds": [],
|
|
"frameId": null,
|
|
"roundness": { "type": 3 },
|
|
"seed": 1,
|
|
"version": 1,
|
|
"versionNonce": 1,
|
|
"isDeleted": false,
|
|
"boundElements": null,
|
|
"updated": 1,
|
|
"link": null,
|
|
"locked": false
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Text Inside Shapes (Labels)
|
|
|
|
**Every labeled shape requires TWO elements:**
|
|
|
|
### Shape with boundElements
|
|
|
|
```json
|
|
{
|
|
"id": "{component-id}",
|
|
"type": "rectangle",
|
|
"x": 500,
|
|
"y": 200,
|
|
"width": 200,
|
|
"height": 90,
|
|
"strokeColor": "#1971c2",
|
|
"backgroundColor": "#a5d8ff",
|
|
"boundElements": [{ "type": "text", "id": "{component-id}-text" }],
|
|
// ... other required properties
|
|
}
|
|
```
|
|
|
|
### Text with containerId
|
|
|
|
```json
|
|
{
|
|
"id": "{component-id}-text",
|
|
"type": "text",
|
|
"x": 505, // shape.x + 5
|
|
"y": 220, // shape.y + (shape.height - text.height) / 2
|
|
"width": 190, // shape.width - 10
|
|
"height": 50,
|
|
"text": "{Component Name}\n{Subtitle}",
|
|
"fontSize": 16,
|
|
"fontFamily": 1,
|
|
"textAlign": "center",
|
|
"verticalAlign": "middle",
|
|
"containerId": "{component-id}",
|
|
"originalText": "{Component Name}\n{Subtitle}",
|
|
"lineHeight": 1.25,
|
|
// ... other required properties
|
|
}
|
|
```
|
|
|
|
### DO NOT Use the `label` Property
|
|
|
|
The `label` property is for the JavaScript API, NOT raw JSON files:
|
|
|
|
```json
|
|
// WRONG - will show empty boxes
|
|
{ "type": "rectangle", "label": { "text": "My Label" } }
|
|
|
|
// CORRECT - requires TWO elements
|
|
// 1. Shape with boundElements reference
|
|
// 2. Separate text element with containerId
|
|
```
|
|
|
|
### Text Positioning
|
|
|
|
- Text `x` = shape `x` + 5
|
|
- Text `y` = shape `y` + (shape.height - text.height) / 2
|
|
- Text `width` = shape `width` - 10
|
|
- Use `\n` for multi-line labels
|
|
- Always use `textAlign: "center"` and `verticalAlign: "middle"`
|
|
|
|
### ID Naming Convention
|
|
|
|
Always use pattern: `{shape-id}-text` for text element IDs.
|
|
|
|
---
|
|
|
|
## Dynamic ID Generation
|
|
|
|
IDs and labels are generated from codebase analysis:
|
|
|
|
| Discovered Component | Generated ID | Generated Label |
|
|
|---------------------|--------------|-----------------|
|
|
| Express API server | `express-api` | `"API Server\nExpress.js"` |
|
|
| PostgreSQL database | `postgres-db` | `"PostgreSQL\nDatabase"` |
|
|
| Redis cache | `redis-cache` | `"Redis\nCache Layer"` |
|
|
| S3 bucket for uploads | `s3-uploads` | `"S3 Bucket\nuploads/"` |
|
|
| Lambda function | `lambda-processor` | `"Lambda\nProcessor"` |
|
|
| React frontend | `react-frontend` | `"React App\nFrontend"` |
|
|
|
|
---
|
|
|
|
## Grouping with Dashed Rectangles
|
|
|
|
For logical groupings (namespaces, VPCs, pipelines):
|
|
|
|
```json
|
|
{
|
|
"id": "group-ai-pipeline",
|
|
"type": "rectangle",
|
|
"x": 100,
|
|
"y": 500,
|
|
"width": 1000,
|
|
"height": 280,
|
|
"strokeColor": "#9c36b5",
|
|
"backgroundColor": "transparent",
|
|
"strokeStyle": "dashed",
|
|
"roughness": 0,
|
|
"roundness": null,
|
|
"boundElements": null
|
|
}
|
|
```
|
|
|
|
Group labels are standalone text (no containerId) at top-left:
|
|
|
|
```json
|
|
{
|
|
"id": "group-ai-pipeline-label",
|
|
"type": "text",
|
|
"x": 120,
|
|
"y": 510,
|
|
"text": "AI Processing Pipeline (Cloud Run)",
|
|
"textAlign": "left",
|
|
"verticalAlign": "top",
|
|
"containerId": null
|
|
}
|
|
```
|