Vancetope Application — app: canvasbook
Folder container for multiple
kind: canvaspages — a “book” of Canvases, built on the doc-kind-application foundation. Intentionally named differently from the Kind (workbook⊃workpageas a model) to avoid confusing the app and the Kind. See also: doc-kind-canvas, app-workbook (model pattern), documents-channel (live update). Implementation track:planning/canvas.md.
1. Purpose
kind: canvas alone is sufficient for a single surface. As soon as multiple
related boards need to be managed and switched between, a Canvasbook bundles
them: a folder with _app.yaml (kind: application, app: canvasbook),
containing multiple *.canvas.* pages and an auto-generated _index.md.
For a single surface, create kind: canvas directly.
CanvasbookApplication is the only authoring interface for Canvases.
2. Folder Layout & Manifest
design-sketches/
├── _app.yaml ← kind: application, app: canvasbook
├── _index.md ← auto-generated (page list), only refresh() writes
├── ideas.canvas.yaml ← kind: canvas
├── architecture.canvas.yaml
└── assets/ ← files imported via Drag&Drop
$meta:
kind: application
app: canvasbook
title: "Design Sketches"
description: "Whiteboard Collection"
canvasbook:
landingPage: "ideas.canvas.yaml" # optional — default page on open
index:
outputPath: "_index.md"
Discovery: listByKind(..., "application") + Header app == "canvasbook". The
manifest is written via ApplicationDocument + ApplicationCodec (not manually).
For the web create dialog, the addon provides a bundled
Document Template canvasbook (resource under
vance-defaults/_vance/templates/, name: { mode: fixed, value: _app.yaml }) —
it only writes the manifest; pages are added afterwards via the editor /
canvasbook_page_create. Generated artifact: _index.md (kind: workpage, link list of all
Canvas pages), deterministically from the sources, only CanvasbookApplication.refresh
writes.
3. Tools
| Tool | Purpose |
|---|---|
canvasbook_app_create(folder, title?, description?, landingPage?, pages?) |
One-shot: Manifest + optional initial pages + index rebuild. Instead of manual _app.yaml. |
canvasbook_page_create(folder, title?, slug?) |
New Canvas page in Canvasbook + index refresh. |
app_rebuild(folder) |
Regenerates _index.md. |
The pages themselves are populated using the canvas_* tools (see
doc-kind-canvas §4) and validated with canvas_validate.
promptInject displays a short hint block with the tools as long as a Canvasbook
is open in Cortex.
4. Web UI
Kind registration application:canvasbook → CanvasbookAppKind.vue (immersive
app view). A single menu button at the top switches between the *.canvas.*
pages (intentionally no sidebar tree navigation); landing page leads. The active
Canvas is edited in the VueFlow editor, debounced auto-saved (status
indicator: saved/not saved/saving), plus “+ Canvas” and “↻ Index”.
Live Document Update: the app view subscribes to the
documents channel via folder prefix; an external save
of the active page reloads it. Own echoes are suppressed via a self-write window,
and local unsaved changes are not overwritten. No CRDT — for true
simultaneous editing, Last-Writer-Wins applies; awareness comes via the live
cursors of the pointers channel.
5. REST API
Under /brain/{tenant}/addon/canvas/... (permission-scoped, no direct
MongoTemplate access from the controller):
| Endpoint | Purpose |
|---|---|
GET /scan?projectId=&folder= |
Manifest title, landing, page list. |
POST /page?projectId=&folder= |
New Canvas page. |
POST /rebuild?projectId=&folder= |
Regenerate _index.md. |
GET /graph?projectId=&path= |
Parsed graph as JSON (server codec). |
PUT /graph?projectId=&path= |
Graph JSON → serialized + saved. |
GET /documents/search?projectId=&query= |
Project document search (Doc Picker). |
GET /document?projectId=&path= |
Doc meta (Embed Resolution). |
The client does not parse YAML — the Java CanvasCodec remains the Single Source of
Truth; graph GET/PUT transport typed JSON.
6. Anti-Patterns
- Manual edits to
_app.yaml→ usecanvasbook_app_create. - Canvasbook with a single page → bare
kind: canvasis sufficient. - Manual edits to
_index.md→ will be overwritten byapp_rebuild. - Sub-Canvasbook in a section folder → one Canvasbook per tree root.