viteboard 0.1.0 → 0.1.2

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 (90) hide show
  1. package/README.md +110 -61
  2. package/content/docs/guide/boards-in-markdown.md +28 -26
  3. package/content/docs/guide/boards.md +44 -82
  4. package/content/docs/guide/getting-started.md +36 -48
  5. package/content/docs/index.md +21 -32
  6. package/content/docs/product-roadmap.board.json +4 -4
  7. package/content/machine/board-v1.schema.json +138 -0
  8. package/content/machine/example.board.json +217 -0
  9. package/content/machine/guide.md +270 -0
  10. package/content/machine/llms.txt +31 -0
  11. package/content/machine/viteboard.json +62 -0
  12. package/dist/assets/index-D2W76uu9.js +96 -0
  13. package/dist/assets/index-rMkUjGXP.css +1 -0
  14. package/dist/index.html +4 -2
  15. package/package.json +10 -12
  16. package/vite.config.ts +635 -48
  17. package/content/docs/capabilities.md +0 -89
  18. package/content/docs/docs.md +0 -84
  19. package/content/docs/guide/test.md +0 -6
  20. package/content/docs/test.md +0 -219
  21. package/content/docs/tetst-dir/test-board.board.json +0 -15
  22. package/content/docs/tetst-dir/test-test.md +0 -1
  23. package/content/docs/workspace.md +0 -73
  24. package/dist/assets/index-CEpxLM2o.css +0 -1
  25. package/dist/assets/index-D4xvJdEQ.js +0 -60
  26. package/index.html +0 -13
  27. package/src/app/AppController.ts +0 -955
  28. package/src/app/BoardState.ts +0 -130
  29. package/src/app/ClipboardService.ts +0 -159
  30. package/src/app/CommandManager.ts +0 -66
  31. package/src/app/ElementActions.ts +0 -152
  32. package/src/app/EmbedRegionSelector.ts +0 -103
  33. package/src/app/ExportPng.ts +0 -107
  34. package/src/app/ImageInsertService.ts +0 -141
  35. package/src/app/KeyboardShortcuts.ts +0 -124
  36. package/src/app/main.ts +0 -6
  37. package/src/board/BoardPreview.ts +0 -189
  38. package/src/board/BoardService.ts +0 -222
  39. package/src/canvas/CanvasRenderer.ts +0 -253
  40. package/src/canvas/CanvasSurface.ts +0 -70
  41. package/src/canvas/HitTester.ts +0 -110
  42. package/src/canvas/ImageCache.ts +0 -123
  43. package/src/canvas/PerformanceMonitor.ts +0 -31
  44. package/src/canvas/RenderScheduler.ts +0 -26
  45. package/src/canvas/Viewport.ts +0 -77
  46. package/src/content/ContentApi.ts +0 -258
  47. package/src/content/Markdown.ts +0 -431
  48. package/src/content/MarkdownView.ts +0 -70
  49. package/src/editor/DocEditor.ts +0 -799
  50. package/src/editor/htmlToMarkdown.ts +0 -333
  51. package/src/elements/renderElement.ts +0 -509
  52. package/src/elements/types.ts +0 -118
  53. package/src/shell/Shell.ts +0 -2950
  54. package/src/shell/Sidebar.ts +0 -1352
  55. package/src/storage/AssetStore.ts +0 -86
  56. package/src/storage/BoardSerializer.ts +0 -114
  57. package/src/storage/ImportExportService.ts +0 -153
  58. package/src/storage/IndexedDbStore.ts +0 -92
  59. package/src/storage/LocalBoardStore.ts +0 -104
  60. package/src/styles.css +0 -3257
  61. package/src/templates/helpers.ts +0 -124
  62. package/src/templates/index.ts +0 -65
  63. package/src/templates/journeyMapTemplate.ts +0 -52
  64. package/src/templates/opportunityTreeTemplate.ts +0 -45
  65. package/src/templates/personaTemplate.ts +0 -41
  66. package/src/templates/prioritizationMatrixTemplate.ts +0 -44
  67. package/src/templates/requirementsFlowTemplate.ts +0 -45
  68. package/src/templates/screenshotReviewTemplate.ts +0 -52
  69. package/src/templates/systemDiagramTemplate.ts +0 -41
  70. package/src/testing/StressTestGenerator.ts +0 -134
  71. package/src/testing/StressTestPanel.ts +0 -64
  72. package/src/tools/ArrowTool.ts +0 -87
  73. package/src/tools/ImageTool.ts +0 -39
  74. package/src/tools/PanTool.ts +0 -34
  75. package/src/tools/SelectTool.ts +0 -377
  76. package/src/tools/ShapeTool.ts +0 -106
  77. package/src/tools/StickyTool.ts +0 -69
  78. package/src/tools/TaskTool.ts +0 -52
  79. package/src/tools/TextTool.ts +0 -45
  80. package/src/tools/ToolContext.ts +0 -44
  81. package/src/tools/ToolController.ts +0 -178
  82. package/src/ui/Modal.ts +0 -58
  83. package/src/ui/PerformanceOverlay.ts +0 -75
  84. package/src/ui/StorageManager.ts +0 -94
  85. package/src/ui/TemplatePicker.ts +0 -67
  86. package/src/ui/TextEditorOverlay.ts +0 -137
  87. package/src/ui/Toolbar.ts +0 -151
  88. package/src/ui/TopControls.ts +0 -137
  89. package/src/ui/icons.ts +0 -50
  90. package/tsconfig.json +0 -19
@@ -0,0 +1,138 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://viteboard.local/board-v1.schema.json",
4
+ "title": "ViteBoard Board v1",
5
+ "type": "object",
6
+ "required": [
7
+ "version",
8
+ "id",
9
+ "title",
10
+ "createdAt",
11
+ "updatedAt",
12
+ "viewport",
13
+ "theme",
14
+ "elements",
15
+ "assetIds"
16
+ ],
17
+ "properties": {
18
+ "$schema": {
19
+ "type": "string"
20
+ },
21
+ "version": {
22
+ "const": 1
23
+ },
24
+ "id": {
25
+ "type": "string",
26
+ "minLength": 1
27
+ },
28
+ "title": {
29
+ "type": "string"
30
+ },
31
+ "createdAt": {
32
+ "type": "number"
33
+ },
34
+ "updatedAt": {
35
+ "type": "number"
36
+ },
37
+ "viewport": {
38
+ "type": "object",
39
+ "required": ["offsetX", "offsetY", "scale"],
40
+ "properties": {
41
+ "offsetX": { "type": "number" },
42
+ "offsetY": { "type": "number" },
43
+ "scale": { "type": "number" }
44
+ },
45
+ "additionalProperties": false
46
+ },
47
+ "theme": {
48
+ "enum": ["light", "dark"]
49
+ },
50
+ "elements": {
51
+ "type": "array",
52
+ "items": { "$ref": "#/$defs/element" }
53
+ },
54
+ "assetIds": {
55
+ "type": "array",
56
+ "items": { "type": "string" }
57
+ }
58
+ },
59
+ "additionalProperties": false,
60
+ "$defs": {
61
+ "elementStyle": {
62
+ "type": "object",
63
+ "properties": {
64
+ "fill": { "type": "string" },
65
+ "stroke": { "type": "string" },
66
+ "strokeWidth": { "type": "number" },
67
+ "opacity": { "type": "number" },
68
+ "borderRadius": { "type": "number" },
69
+ "shadow": { "type": "boolean" },
70
+ "fontSize": { "type": "number" },
71
+ "fontFamily": { "type": "string" },
72
+ "fontWeight": { "type": "string" },
73
+ "textColor": { "type": "string" },
74
+ "arrowStart": { "type": "boolean" },
75
+ "arrowEnd": { "type": "boolean" },
76
+ "strokeDash": {
77
+ "type": "array",
78
+ "items": { "type": "number" }
79
+ }
80
+ },
81
+ "additionalProperties": true
82
+ },
83
+ "element": {
84
+ "type": "object",
85
+ "required": [
86
+ "id",
87
+ "type",
88
+ "x",
89
+ "y",
90
+ "width",
91
+ "height",
92
+ "rotation",
93
+ "zIndex",
94
+ "locked",
95
+ "hidden",
96
+ "createdAt",
97
+ "updatedAt",
98
+ "style",
99
+ "data"
100
+ ],
101
+ "properties": {
102
+ "id": { "type": "string", "minLength": 1 },
103
+ "type": {
104
+ "enum": [
105
+ "sticky",
106
+ "task",
107
+ "rectangle",
108
+ "ellipse",
109
+ "text",
110
+ "line",
111
+ "arrow",
112
+ "connector",
113
+ "image",
114
+ "screenshot",
115
+ "frame",
116
+ "templateGroup"
117
+ ]
118
+ },
119
+ "x": { "type": "number" },
120
+ "y": { "type": "number" },
121
+ "width": { "type": "number" },
122
+ "height": { "type": "number" },
123
+ "rotation": { "type": "number" },
124
+ "zIndex": { "type": "number" },
125
+ "locked": { "type": "boolean" },
126
+ "hidden": { "type": "boolean" },
127
+ "createdAt": { "type": "number" },
128
+ "updatedAt": { "type": "number" },
129
+ "style": { "$ref": "#/$defs/elementStyle" },
130
+ "data": {
131
+ "type": "object",
132
+ "additionalProperties": true
133
+ }
134
+ },
135
+ "additionalProperties": false
136
+ }
137
+ }
138
+ }
@@ -0,0 +1,217 @@
1
+ {
2
+ "$schema": "/board-v1.schema.json",
3
+ "version": 1,
4
+ "id": "examples/system-flow",
5
+ "title": "System Flow Example",
6
+ "createdAt": 1784635200000,
7
+ "updatedAt": 1784635200000,
8
+ "viewport": {
9
+ "offsetX": 80,
10
+ "offsetY": 80,
11
+ "scale": 0.58
12
+ },
13
+ "theme": "light",
14
+ "elements": [
15
+ {
16
+ "id": "frame-example",
17
+ "type": "frame",
18
+ "x": 0,
19
+ "y": 0,
20
+ "width": 1240,
21
+ "height": 840,
22
+ "rotation": 0,
23
+ "zIndex": 1,
24
+ "locked": false,
25
+ "hidden": false,
26
+ "createdAt": 1784635200000,
27
+ "updatedAt": 1784635200000,
28
+ "style": {
29
+ "fill": "#ffffff",
30
+ "stroke": "#e5e7eb",
31
+ "strokeWidth": 1.5,
32
+ "borderRadius": 20,
33
+ "shadow": true
34
+ },
35
+ "data": {
36
+ "text": "",
37
+ "shapeKind": "rectangle"
38
+ }
39
+ },
40
+ {
41
+ "id": "title-example",
42
+ "type": "text",
43
+ "x": 40,
44
+ "y": 50,
45
+ "width": 500,
46
+ "height": 40,
47
+ "rotation": 0,
48
+ "zIndex": 2,
49
+ "locked": false,
50
+ "hidden": false,
51
+ "createdAt": 1784635200000,
52
+ "updatedAt": 1784635200000,
53
+ "style": {
54
+ "fontSize": 24,
55
+ "fontWeight": "700",
56
+ "textColor": "#1f2933"
57
+ },
58
+ "data": {
59
+ "text": "System flow"
60
+ }
61
+ },
62
+ {
63
+ "id": "actor-user",
64
+ "type": "ellipse",
65
+ "x": 120,
66
+ "y": 320,
67
+ "width": 190,
68
+ "height": 110,
69
+ "rotation": 0,
70
+ "zIndex": 3,
71
+ "locked": false,
72
+ "hidden": false,
73
+ "createdAt": 1784635200000,
74
+ "updatedAt": 1784635200000,
75
+ "style": {
76
+ "fill": "#dcfce7",
77
+ "stroke": "#16a34a",
78
+ "strokeWidth": 1.5,
79
+ "shadow": true,
80
+ "fontSize": 14,
81
+ "fontWeight": "650",
82
+ "textColor": "#1f2933"
83
+ },
84
+ "data": {
85
+ "text": "User"
86
+ }
87
+ },
88
+ {
89
+ "id": "surface-ui",
90
+ "type": "rectangle",
91
+ "x": 430,
92
+ "y": 330,
93
+ "width": 220,
94
+ "height": 90,
95
+ "rotation": 0,
96
+ "zIndex": 4,
97
+ "locked": false,
98
+ "hidden": false,
99
+ "createdAt": 1784635200000,
100
+ "updatedAt": 1784635200000,
101
+ "style": {
102
+ "fill": "#4dabf7",
103
+ "stroke": "#1d4ed8",
104
+ "strokeWidth": 1.5,
105
+ "borderRadius": 999,
106
+ "shadow": true,
107
+ "fontSize": 14,
108
+ "fontWeight": "650",
109
+ "textColor": "#ffffff"
110
+ },
111
+ "data": {
112
+ "text": "ViteBoard UI",
113
+ "shapeKind": "pill"
114
+ }
115
+ },
116
+ {
117
+ "id": "store-docs",
118
+ "type": "rectangle",
119
+ "x": 840,
120
+ "y": 320,
121
+ "width": 220,
122
+ "height": 110,
123
+ "rotation": 0,
124
+ "zIndex": 5,
125
+ "locked": false,
126
+ "hidden": false,
127
+ "createdAt": 1784635200000,
128
+ "updatedAt": 1784635200000,
129
+ "style": {
130
+ "fill": "#86efac",
131
+ "stroke": "#15803d",
132
+ "strokeWidth": 1.5,
133
+ "shadow": true,
134
+ "fontSize": 14,
135
+ "fontWeight": "650",
136
+ "textColor": "#1f2933"
137
+ },
138
+ "data": {
139
+ "text": "Docs root\nfiles on disk",
140
+ "shapeKind": "cylinder"
141
+ }
142
+ },
143
+ {
144
+ "id": "edge-user-ui",
145
+ "type": "arrow",
146
+ "x": 310,
147
+ "y": 375,
148
+ "width": 120,
149
+ "height": 0,
150
+ "rotation": 0,
151
+ "zIndex": 6,
152
+ "locked": false,
153
+ "hidden": false,
154
+ "createdAt": 1784635200000,
155
+ "updatedAt": 1784635200000,
156
+ "style": {
157
+ "stroke": "#64748b",
158
+ "strokeWidth": 2,
159
+ "arrowEnd": true,
160
+ "arrowStart": false
161
+ },
162
+ "data": {
163
+ "text": "edits",
164
+ "labelPosition": "center"
165
+ }
166
+ },
167
+ {
168
+ "id": "edge-ui-store",
169
+ "type": "arrow",
170
+ "x": 650,
171
+ "y": 375,
172
+ "width": 190,
173
+ "height": 0,
174
+ "rotation": 0,
175
+ "zIndex": 7,
176
+ "locked": false,
177
+ "hidden": false,
178
+ "createdAt": 1784635200000,
179
+ "updatedAt": 1784635200000,
180
+ "style": {
181
+ "stroke": "#64748b",
182
+ "strokeWidth": 2,
183
+ "arrowEnd": true,
184
+ "arrowStart": false
185
+ },
186
+ "data": {
187
+ "text": "persists",
188
+ "labelPosition": "center"
189
+ }
190
+ },
191
+ {
192
+ "id": "note-example",
193
+ "type": "sticky",
194
+ "x": 140,
195
+ "y": 650,
196
+ "width": 360,
197
+ "height": 90,
198
+ "rotation": 0,
199
+ "zIndex": 8,
200
+ "locked": false,
201
+ "hidden": false,
202
+ "createdAt": 1784635200000,
203
+ "updatedAt": 1784635200000,
204
+ "style": {
205
+ "fill": "#fef3c7",
206
+ "borderRadius": 12,
207
+ "shadow": true,
208
+ "fontSize": 11,
209
+ "textColor": "#1f2933"
210
+ },
211
+ "data": {
212
+ "text": "Keep embed crops inside the frame and leave enough space around labeled arrows."
213
+ }
214
+ }
215
+ ],
216
+ "assetIds": []
217
+ }
@@ -0,0 +1,270 @@
1
+ # ViteBoard Authoring Guide
2
+
3
+ ViteBoard is a local-first documentation workspace. Humans browse it through the web UI. Machines can use the same origin to discover how the app is structured, then use normal filesystem tools to create and update the underlying files.
4
+
5
+ This guide is read-only. It explains how to work with ViteBoard content and how to cooperate with a human who may be using the app at the same time.
6
+
7
+ ## Connection rule
8
+
9
+ When a user gives you a ViteBoard URL, keep using that exact origin.
10
+
11
+ Example:
12
+
13
+ - if the user says `http://localhost:5173`, keep using `http://localhost:5173`
14
+ - do not replace it with `http://127.0.0.1:5173`
15
+
16
+ Some local ViteBoard sessions bind only one loopback interface, so `localhost` and `127.0.0.1` are not always equivalent.
17
+
18
+ ## 1. Workspace model
19
+
20
+ - Projects are registered in the local workspace.
21
+ - Every descendant directory named `docs` becomes a docs root.
22
+ - Markdown documents, capabilities, boards, and assets live inside a docs root.
23
+
24
+ Important discovery endpoints:
25
+
26
+ - `GET /__api/workspace`
27
+ - `GET /__api/project-tree?projectId={projectId}`
28
+ - `GET /__api/tree?rootId={rootId}`
29
+
30
+ The machine can navigate the same app surfaces a human uses:
31
+
32
+ - workspace home: `#/`
33
+ - project wiki: `#/project/{projectId}`
34
+ - project board index: `#/project/{projectId}/boards`
35
+ - document view: `#/root/{rootId}/docs/{path}`
36
+ - root board list: `#/root/{rootId}/boards`
37
+ - board editor: `#/root/{rootId}/boards/{boardId}`
38
+ - capability index: `#/root/{rootId}/capabilities`
39
+ - capability document: `#/root/{rootId}/capabilities/{path}`
40
+ - directory wiki: `#/root/{rootId}/directory/{path}`
41
+
42
+ Open these routes directly when you want the human UI to focus a specific page, document, board, or wiki surface.
43
+
44
+ If a target project is not in the workspace yet, register it with:
45
+
46
+ ```http
47
+ POST /__api/workspace/project
48
+ Content-Type: application/json
49
+
50
+ {
51
+ "rootPath": "/absolute/project/path",
52
+ "label": "optional label"
53
+ }
54
+ ```
55
+
56
+ If the project has no docs root yet, create one with:
57
+
58
+ ```http
59
+ POST /__api/workspace/project/docs-root
60
+ Content-Type: application/json
61
+
62
+ { "projectId": "project-..." }
63
+ ```
64
+
65
+ ## 2. Files and IDs
66
+
67
+ ### Markdown documents
68
+
69
+ - Stored as `*.md` beneath a docs root.
70
+ - Read and write them directly as normal Markdown files.
71
+
72
+ ### Boards
73
+
74
+ - Stored as `*.board.json` anywhere beneath a docs root.
75
+ - Board ID = path relative to the docs root, without `.board.json`.
76
+
77
+ Example:
78
+
79
+ ```text
80
+ docs/architecture/system-overview.board.json
81
+ ```
82
+
83
+ Board ID:
84
+
85
+ ```text
86
+ architecture/system-overview
87
+ ```
88
+
89
+ ### Capabilities
90
+
91
+ - Stored as managed directory branches beneath `capabilities/` inside a docs root.
92
+ - A capability branch is the unit, not just one markdown file.
93
+ - Human entrypoint: `index.md`
94
+ - Machine entrypoint: `llms.txt`
95
+
96
+ Example:
97
+
98
+ ```text
99
+ docs/capabilities/automation/docs-refresh/
100
+ index.md
101
+ llms.txt
102
+ scripts/
103
+ ```
104
+
105
+ Capability route path:
106
+
107
+ ```text
108
+ automation/docs-refresh
109
+ ```
110
+
111
+ Machines should treat the whole branch as the capability context and use `llms.txt` as the first machine-facing file when it exists.
112
+
113
+ ## 3. Markdown board embeds
114
+
115
+ Use fenced `board` blocks inside Markdown:
116
+
117
+ ````markdown
118
+ ```board
119
+ src: ./system-overview
120
+ region: 20, 20, 1200, 760
121
+ height: 500
122
+ title: System overview
123
+ ```
124
+ ````
125
+
126
+ Fields:
127
+
128
+ - `src` required
129
+ - `region` optional, `x, y, width, height`
130
+ - `height` optional, minimum `120`, default `360`
131
+ - `title` optional
132
+
133
+ Relative `src` paths resolve from the Markdown document directory.
134
+
135
+ ## 4. Board document model
136
+
137
+ Every board should contain:
138
+
139
+ - `version: 1`
140
+ - `id`
141
+ - `title`
142
+ - `createdAt`
143
+ - `updatedAt`
144
+ - `viewport`
145
+ - `theme`
146
+ - `elements`
147
+ - `assetIds`
148
+
149
+ Preferred form:
150
+
151
+ ```json
152
+ {
153
+ "$schema": "/board-v1.schema.json",
154
+ "version": 1,
155
+ "id": "architecture/system-overview",
156
+ "title": "System Overview",
157
+ "createdAt": 1784635200000,
158
+ "updatedAt": 1784635200000,
159
+ "viewport": { "offsetX": 80, "offsetY": 80, "scale": 0.24 },
160
+ "theme": "light",
161
+ "elements": [],
162
+ "assetIds": []
163
+ }
164
+ ```
165
+
166
+ Use the schema at `/board-v1.schema.json` for the full contract.
167
+
168
+ ## 5. Element families
169
+
170
+ Supported element types:
171
+
172
+ - `sticky`
173
+ - `task`
174
+ - `rectangle`
175
+ - `ellipse`
176
+ - `text`
177
+ - `line`
178
+ - `arrow`
179
+ - `connector`
180
+ - `image`
181
+ - `screenshot`
182
+ - `frame`
183
+ - `templateGroup`
184
+
185
+ Important shape semantics:
186
+
187
+ - Rectangle: general system or concept
188
+ - Ellipse: actor or user group
189
+ - Diamond: decision or routing question
190
+ - Pill: stable platform or product identity
191
+ - Parallelogram: interface or input/output boundary
192
+ - Hexagon: platform or partner capability
193
+ - Cylinder: authoritative data store
194
+ - Sticky: caveat or interpretation
195
+
196
+ Non-ellipse graphic shapes usually use:
197
+
198
+ ```json
199
+ {
200
+ "type": "rectangle",
201
+ "data": { "shapeKind": "diamond" }
202
+ }
203
+ ```
204
+
205
+ ## 6. Diagram composition
206
+
207
+ - One board should answer one coherent family of questions.
208
+ - One white frame should contain one diagram or visual cluster.
209
+ - Choose one dominant reading direction.
210
+ - Keep enough whitespace above and below the main node bounds.
211
+ - Use dashed arrows for optional or weaker relationships.
212
+ - Remove arrow labels when the relationship is already obvious.
213
+ - Keep Markdown embed crops fully inside a white frame.
214
+
215
+ ## 7. Updating existing content
216
+
217
+ When changing a hand-edited board:
218
+
219
+ 1. Preserve the board ID.
220
+ 2. Preserve unrelated elements.
221
+ 3. Preserve `createdAt`.
222
+ 4. Update `updatedAt`.
223
+ 5. Keep stable element IDs where possible.
224
+ 6. Recalculate arrow geometry if nodes moved.
225
+ 7. Adjust any embed crop if the layout changed.
226
+
227
+ When changing a Markdown document:
228
+
229
+ 1. Preserve unrelated sections.
230
+ 2. Preserve semantic frontmatter such as `title`, `summary`, and `tags`.
231
+ 3. Update fenced `board` embeds if board location or crop changes.
232
+
233
+ ## 8. Cooperative live use
234
+
235
+ If you want the app to reflect that an agent is connected and editing:
236
+
237
+ 1. Register an actor session.
238
+ 2. Heartbeat while active.
239
+ 3. Acquire a lock before writing a board or Markdown file.
240
+ 4. Write your file changes.
241
+ 5. Release the lock.
242
+
243
+ Actor sessions can include the current route, current doc or board target, and for boards the currently selected element IDs. That makes prompts like “update the section I have selected” possible when the actor and the app are cooperating on the same live session.
244
+
245
+ The lock protocol is cooperative. While your lock is active, the human UI becomes read-only for that target.
246
+
247
+ Session endpoints:
248
+
249
+ - `POST /__api/actors/session`
250
+ - `POST /__api/actors/heartbeat`
251
+ - `DELETE /__api/actors/session?actorId=...`
252
+
253
+ Lock endpoints:
254
+
255
+ - `POST /__api/locks/acquire`
256
+ - `POST /__api/locks/release`
257
+
258
+ Live events:
259
+
260
+ - `GET /__api/events`
261
+
262
+ ## 9. Completion checklist
263
+
264
+ - Board JSON parses.
265
+ - Board ID matches its path from the docs root.
266
+ - Element IDs are unique.
267
+ - Geometry is finite.
268
+ - Embeds resolve by relative path.
269
+ - Embed crops stay inside the intended frame.
270
+ - The resulting layout is readable to a human.
@@ -0,0 +1,31 @@
1
+ # ViteBoard
2
+
3
+ > Local-first documentation workspace and infinite-canvas board system. The source of truth is plain files on disk.
4
+
5
+ Use your normal filesystem tools to read and write project files. Use ViteBoard's HTTP surface to discover workspace roots, understand board/document grammar, and coordinate live editing with locks and presence.
6
+
7
+ Always reuse the exact origin the user gives you, for example `http://localhost:5173`. Do not silently swap it for `127.0.0.1`, another hostname, or another port because the running ViteBoard instance may only be bound on one loopback interface.
8
+
9
+ ## Core machine docs
10
+
11
+ - [ViteBoard authoring guide](/viteboard-guide.md): How docs roots, boards, embeds, visual layout, locks, and live coordination work.
12
+ - [Board schema v1](/board-v1.schema.json): JSON Schema for `.board.json` files.
13
+ - [Example board](/viteboard-example.board.json): One complete valid ViteBoard board.
14
+
15
+ ## Capability model
16
+
17
+ - Capabilities are managed directory branches under `capabilities/` inside a docs root.
18
+ - Human entrypoint: `index.md`
19
+ - Machine entrypoint: `llms.txt`
20
+ - The rest of the branch may contain markdown, scripts, helpers, assets, examples, and nested directories.
21
+
22
+ ## App discovery
23
+
24
+ - [Workspace listing](/__api/workspace): Registered projects and docs roots.
25
+ - [Machine manifest](/.well-known/viteboard.json): Route templates and coordination endpoints.
26
+
27
+ The machine can also open the same wiki, document, board, capability, and directory routes a human uses. See the guide for the exact route templates.
28
+
29
+ ## Optional
30
+
31
+ - [Machine guide source](https://gitlab.com/ajsib/viteboard): Project repository homepage.