···11================================================================================
2233-Author intent:
43- Build a Svelte-native editor core (TS) + renderer + UI.
54- Keep the "engine" framework-agnostic so Web + Tauri share it.
65- Defer collaboration until single-player is correct.
···1110- Files shown are ideas, not requirements
12111312================================================================================
1414-1. Milestone A: Repo skeleton + dev loop *wb-A*
1313+Milestone P: Performance *wb-P*
1514================================================================================
16151717-Created a project monorepo/workspace.
1616+Goal: the editor stays responsive with many shapes.
18171919-================================================================================
2020-2. Milestone B: Math + coordinate systems *wb-B*
2121-================================================================================
1818+[ ] Add spatial index:
1919+ - rebuild index on doc changes
2020+ - query nearby shapes for hit testing
2121+[ ] Add view culling:
2222+ - compute viewport bounds in world space
2323+ - render only shapes whose bounds intersect viewport
2424+[ ] Reduce redraw frequency:
2525+ - rAF only while dirty
2626+ - optionally batch multiple store updates into one redraw
2727+[ ] Add microbench harness:
2828+ - generate 10k shapes doc
2929+ - measure hit test and render time
22302323-Camera math, matrix utilities, and transforms are fully implemented and verified
2424-so world and screen coordinates map precisely.
3131+(DoD):
3232+- 10k simple shapes pans/zooms smoothly on a typical machine.
25332634================================================================================
2727-3. Milestone C: Document model (records) *wb-C*
3535+Milestone A: Richer arrows / connectors *wb-A*
2836================================================================================
29373030-Document/page/shape/binding records plus validation let the editor serialize and
3131-reason about drawings safely.
3838+--------------------------------------------------------------------------------
3939+A2. Editing UX
4040+--------------------------------------------------------------------------------
32413333-================================================================================
3434-4. Milestone D: Store + selectors (reactive core) *wb-D*
3535-================================================================================
4242+[ ] Multi-point editing:
4343+ - Alt/Option+click on segment adds a control point
4444+ - Backspace/Delete on selected point removes it
4545+ - Drag point to reshape polyline
4646+[ ] Orthogonal routing UI toggle:
4747+ - per-arrow toggle (routing.kind)
4848+ - UI control to switch between straight and orthogonal
4949+[ ] Label editing UI:
5050+ - double-click arrow to edit label text
5151+ - label drags along the connector (offset along polyline)
36523737-The reactive store, invariants, and selectors supply deterministic state streams
3838-for both renderer and UI subscribers.
5353+--------------------------------------------------------------------------------
5454+A3. Precise anchors + snapping
5555+--------------------------------------------------------------------------------
39564040-================================================================================
4141-5. Milestone E: Canvas renderer (read-only) *wb-E*
4242-================================================================================
5757+[ ] Anchor preview:
5858+ - show snap indicator when binding will occur
5959+--------------------------------------------------------------------------------
6060+A5. Tests
6161+--------------------------------------------------------------------------------
43624444-The renderer now draws the document via Canvas2D with camera transforms,
4545-DPI scaling, text sizing, and selection outlines.
6363+[ ] Polyline edits preserve endpoints and do not corrupt bindings
6464+[ ] Label placement stable under zoom/pan
46654766================================================================================
4848-6. Milestone F: Hit testing (picking) *wb-F*
6767+Milestone M: Markdown Blocks *wb-M*
4968================================================================================
50695151-Geometry helpers compute bounds and intersections so hit testing can always
5252-return the topmost shape under the cursor.
7070+Goal:
7171+Add a "Markdown block" shape with pleasant editing, predictable layout, and
7272+export. Treat it as a doc-first primitive (not a hacky text element).
53735454-================================================================================
5555-7. Milestone G: Input system (pointer + keyboard) *wb-G*
5656-================================================================================
7474+--------------------------------------------------------------------------------
7575+M1. Data model
7676+--------------------------------------------------------------------------------
57775858-Pointer and keyboard adapters now normalize events, map them into actions, and
5959-feed the editor consistently across platforms.
7878+/packages/core/src/model:
7979+[ ] Add ShapeType: 'markdown'
8080+[ ] MarkdownShape props:
8181+ - md: string
8282+ - w: number, h?: number " fixed width, auto height by layout
8383+ - style: { fontFamily, fontSize, color, bg?, border? }
8484+ - mode?: 'view'|'edit' " not persisted; UI-only
60856161-================================================================================
6262-8. Milestone H: Tool state machine (foundation) *wb-H*
6363-================================================================================
8686+(DoD): Markdown blocks save/load; width preserved; content preserved verbatim.
64876565-Tool interfaces and the router manage lifecycle hooks so each tool is an
6666-explicit, testable state machine.
8888+--------------------------------------------------------------------------------
8989+M2. Rendering
9090+--------------------------------------------------------------------------------
67919292+/packages/renderer-canvas2d:
9393+[ ] Render Markdown in canvas using a minimal subset:
9494+ - headings (#, ##)
9595+ - bold/italic/code
9696+ - bullet lists
9797+ - links (render style only; click later)
9898+Strategy:
9999+[ ] Parse md -> tokens -> lines; draw text runs onto canvas
100100+[ ] Measure to compute auto height; cache layout per (md, w, style)
681016969-================================================================================
7070-9. Milestone I: Select/move tool (MVP interaction) *wb-I*
7171-================================================================================
102102+(DoD): Markdown blocks look consistent and don’t reflow unpredictably during
103103+pan/zoom.
721047373-Selection logic handles hit selection, marquee, dragging, deletion, and escape
7474-so shapes can be moved reliably.
105105+--------------------------------------------------------------------------------
106106+M3. Editing UX
107107+--------------------------------------------------------------------------------
751087676-================================================================================
7777-10. Milestone J: Create basic shapes via tools *wb-J*
7878-================================================================================
109109+/apps/web:
110110+[ ] Double-click Markdown block opens an overlay editor (contenteditable)
111111+[ ] Cmd/Ctrl+Enter toggles edit/view
112112+[ ] Tab inserts spaces (not focus change) when editing
791138080-Rect, ellipse, line, arrow, and text tools now create shapes via click-drag
8181-interactions with proper finalize/cancel behavior.
114114+(DoD): Editing feels fast; no accidental tool switching; commit is one history
115115+ step.
821168383-================================================================================
8484-11. Milestone K: Bindings for arrows (v0) *wb-K*
8585-================================================================================
117117+--------------------------------------------------------------------------------
118118+M4. Selection + resize
119119+--------------------------------------------------------------------------------
861208787-Arrow endpoints bind to target shapes and stay attached by recalculating anchors
8888-whenever shapes move.
121121+[ ] Resizing adjusts width; height recomputed from layout
122122+[ ] Hit-testing uses computed bounds
891239090-================================================================================
9191-12. Milestone L: History (undo/redo) *wb-L*
9292-================================================================================
124124+(DoD): Markdown blocks behave like shapes: move/resize/duplicate/undo.
931259494-All document-affecting actions run through undoable commands with history stacks
9595-and keyboard shortcuts.
126126+--------------------------------------------------------------------------------
127127+M5. Export
128128+--------------------------------------------------------------------------------
961299797-================================================================================
9898-13. Milestone M: Persistence (web) via Dexie + History integration *wb-M*
9999-================================================================================
130130+[ ] SVG export:
131131+ - v0: export as <foreignObject> OR render as text lines
132132+[ ] PNG export: already covered by canvas export path
100133101101-Document changes now persist to IndexedDB via Dexie with migrations, repo API,
102102-and history-driven syncing.
134134+(DoD): Export doesn’t lose the Markdown block content.
103135104104-================================================================================
105105-14. Milestone N: Status Bar (Editor HUD) *wb-N*
106106-================================================================================
136136+--------------------------------------------------------------------------------
137137+M6. Tests
138138+--------------------------------------------------------------------------------
107139108108-The HUD is now powered end-to-end via a `StatusBarVM` + cursor store, a web
109109-persistence/snap manager, and `StatusBar.svelte` with snap/grid toggles backed
110110-by unit/integration tests for selectors, cursor throttling, persistence
111111-transitions, and Canvas wiring.
140140+[ ] Layout cache keying (same md/w/style => stable height)
141141+[ ] Resize changes width and increases/decreases computed height appropriately
142142+[ ] Undo/redo persists through refresh (ties into M persistence)
112143113113-Note: Zoom controls were moved to Toolbar in Milestone O for better UX.
144144+(DoD): Markdown blocks are robust and predictable.
114145115146================================================================================
116116-15. Milestone O: Export (PNG/SVG) *wb-O*
147147+Milestone L: Layers *wb-L*
117148================================================================================
118149119119-PNG/SVG export flows now deliver one-click viewport or selection exports from
120120-the Toolbar across web and desktop builds.
150150+Goal:
151151+Add real layers: reorder, hide/show, lock, and per-layer opacity. This is now a
152152+baseline expectation even for "simple" editors.
121153122122-================================================================================
123123-16. Milestone P: Desktop packaging (Tauri) *wb-P*
124124-================================================================================
154154+--------------------------------------------------------------------------------
155155+L1. Data model (doc)
156156+--------------------------------------------------------------------------------
125157126126-The Tauri build now ships the static SvelteKit bundle with native file dialogs
127127-for open/save/new/rename/delete workflows so the desktop app works end-to-end
128128-offline.
158158+/packages/core/src/model:
159159+[ ] Add LayerRecord:
160160+ - id, boardId/pageId
161161+ - name
162162+ - order: number (or layerIds array on page)
163163+ - visible: boolean
164164+ - locked: boolean
165165+ - opacity: number (0..1)
129166130130-================================================================================
131131-17. Milestone Q: Performance + big docs (pragmatic) *wb-Q*
132132-================================================================================
167167+[ ] Attach shapes to layers:
168168+ - ShapeRecord.layerId: string
169169+ - Default layer created on new board/page
133170134134-Goal: the editor stays responsive with many shapes.
171171+(DoD): Old docs migrate to "single default layer" automatically
172172+(Dexie migration).
173173+174174+--------------------------------------------------------------------------------
175175+L2. Rendering order + behavior
176176+--------------------------------------------------------------------------------
177177+178178+/packages/renderer-canvas2d:
179179+[ ] Render layers in order:
180180+ - skip invisible
181181+ - apply opacity per layer (ctx.globalAlpha)
182182+[ ] Selection rendering respects visibility:
183183+ - do not show selection UI for hidden shapes
135184136136-[ ] Add spatial index (v0: simple grid buckets):
137137- - rebuild index on doc changes
138138- - query nearby shapes for hit testing
139139-[ ] Add view culling:
140140- - compute viewport bounds in world space
141141- - render only shapes whose bounds intersect viewport
142142-[ ] Reduce redraw frequency:
143143- - rAF only while dirty
144144- - optionally batch multiple store updates into one redraw
145145-[ ] Add microbench harness:
146146- - generate 10k shapes doc
147147- - measure hit test and render time
185185+(DoD): Hiding a layer truly removes it from view and interaction.
148186149149-(DoD):
150150-- 10k simple shapes pans/zooms smoothly on a typical machine.
187187+--------------------------------------------------------------------------------
188188+L3. Interaction rules
189189+--------------------------------------------------------------------------------
151190152152-================================================================================
153153-18. Milestone R: File Browser (web: Dexie inspector, desktop: FS) *wb-R*
154154-================================================================================
191191+[ ] Locked layer:
192192+ - shapes cannot be selected or edited
193193+ - marquee ignores locked shapes
194194+[ ] Active layer:
195195+ - new shapes are created into the active layer
196196+[ ] Reorder layers:
197197+ - drag to reorder, updates draw order
155198156156-The shared file browser now offers Dexie-backed search + inspector tooling on
157157-web and full workspace navigation on desktop, all driven by the view model
158158-contracts.
199199+(DoD): Lock/hide behave exactly as users expect.
159200160201--------------------------------------------------------------------------------
161161-R4. Parity behaviors
202202+L4. UI panel
162203--------------------------------------------------------------------------------
163204164164-[x] Same shortcuts:
165165- - Ctrl/Cmd+O opens file browser
166166- - Ctrl/Cmd+N creates board
167167-[x] Consistent metadata display:
168168- - name + updatedAt in both modes
205205+/apps/web:
206206+[ ] Layers panel:
207207+ - list layers with eye + lock toggles
208208+ - rename layer
209209+ - new/delete layer
210210+ - drag reorder
211211+ - set active layer
212212+ - opacity slider per layer (optional v0, recommended v1)
213213+214214+(DoD): Layers are discoverable and usable without shortcuts.
215215+216216+--------------------------------------------------------------------------------
217217+L5. Persistence + migrations
218218+--------------------------------------------------------------------------------
169219170170-(DoD):
171171-- Web and desktop feel like the same app, with storage differences made explicit
220220+[ ] Dexie migration:
221221+ - add layers table and layerId field on shapes (if normalized)
222222+ - backfill existing shapes -> default layer
223223+ - ensure boards/pages have at least 1 layer
224224+225225+(DoD): Existing boards load unchanged but now sit on a default layer.
226226+227227+--------------------------------------------------------------------------------
228228+L6. Tests
229229+--------------------------------------------------------------------------------
172230173173-================================================================================
174174-19. Milestone S: Quality polish. *wb-S*
175175-================================================================================
231231+[ ] Hidden layer shapes not hit-testable
232232+[ ] Locked layer shapes not editable
233233+[ ] New shape inherits active layer
234234+[ ] Migration backfills correctly
176235177177-Comprehensive UX polish adds BEM CSS, space-drag panning, richer keyboard
178178-affordances, improved accessibility and styling, refined snapping, and handles.
236236+(DoD): No regressions in selection/marquee/editing across layers.
179237180238================================================================================
181181-20. Milestone T: Sketching / Pen Tool (perfect-freehand) *wb-T*
239239+Milestone S: Stencils (built-in) *wb-S*
182240================================================================================
183241184184-Perfect-freehand pen strokes now behave like first-class shapes with frame
185185-coalesced drafting, geometry/rendering integration, and brush controls.
242242+Goal:
243243+Ship a curated set of built-in stencils (flowchart + UI + dev diagrams) with a
244244+pleasant insertion workflow. No sharing/community libraries yet—just "your own".
245245+246246+--------------------------------------------------------------------------------
247247+S1. Stencil definition format (core)
248248+--------------------------------------------------------------------------------
249249+250250+/packages/core/src/stencils:
251251+[ ] Define Stencil:
252252+ - id, name, category, tags[]
253253+ - preview: { kind: 'svg'|'canvas', data }
254254+ - spawn: function (atPoint, scale) -> ShapeRecords[] (group)
255255+ (A stencil can insert 1 shape or a grouped set.)
256256+257257+[ ] Create initial categories (v0):
258258+ - Flowchart: process, decision, terminator, data, document
259259+ - Diagrams: server, db, queue, user, browser, mobile
260260+ - UI: button, input, card, modal
261261+262262+(DoD): Stencils load as data and can spawn shapes deterministically.
263263+264264+--------------------------------------------------------------------------------
265265+S2. Insert UX
266266+--------------------------------------------------------------------------------
267267+268268+/apps/web:
269269+[ ] Stencils drawer/palette:
270270+ - search (name + tags)
271271+ - category filter
272272+ - click inserts at viewport center OR
273273+ drag ghost preview onto canvas and drop
274274+275275+[ ] Placement rules:
276276+ - insert into active layer (if layers exist)
277277+ - snap to grid if enabled
278278+279279+(DoD): Inserting stencils is faster than drawing shapes manually.
280280+281281+--------------------------------------------------------------------------------
282282+S3. Grouping behavior
283283+--------------------------------------------------------------------------------
284284+285285+[ ] When a stencil spawns multiple shapes:
286286+ - create a GroupRecord OR a "groupId" on shapes (your existing grouping
287287+ model)
288288+ - allow move as one unit
289289+ - ungroup command
290290+291291+(DoD): Multi-shape stencils behave like a single object until ungrouped.
292292+293293+--------------------------------------------------------------------------------
294294+S4. Preview rendering
295295+--------------------------------------------------------------------------------
296296+297297+[ ] Render stencil previews in the panel:
298298+ - v0: small SVG thumbnails (best) OR draw to offscreen canvas
299299+300300+(DoD): Users can recognize stencils instantly.
301301+302302+--------------------------------------------------------------------------------
303303+S5. Persistence + versioning
304304+--------------------------------------------------------------------------------
305305+306306+[ ] Stencils are "code assets":
307307+ - version them with the app
308308+ - inserted shapes are normal shapes (no dependency on stencil after
309309+ insertion)
310310+311311+(DoD): Old docs do not break if you change stencil definitions later.
312312+313313+--------------------------------------------------------------------------------
314314+S6. Tests
315315+--------------------------------------------------------------------------------
316316+317317+[ ] spawn() returns valid records with unique ids and correct initial positions
318318+[ ] group insert produces expected selection and undo/redo works
319319+[ ] search indexing returns correct stencils for tag queries
320320+321321+(DoD): Stencils are reliable and don’t corrupt docs.
186322187323================================================================================
188324Parking Lot *wb-pl*
···191327- [ ] Opacity for shapes
192328 - expose fill/stroke opacity controls so translucent layering is possible
193329 without exporting.
194194-- [ ] Snapping/binding for arrows
195195- - extend the binding system to keep arrow endpoints magnetized to shapes
196196- even when snapping/grid options are enabled.
197197-198198-================================================================================
199199-References (URLs) *wb-refs*
200200-================================================================================
201201-202202-tldraw conceptual references (inspiration only):
203203-- https://tldraw.dev/docs/shapes
204204-- https://tldraw.dev/docs/editor
205205-- https://tldraw.dev/reference/editor/Editor
206206-207207-SvelteKit + Tauri packaging:
208208-- https://v2.tauri.app/start/frontend/sveltekit/
209209-- https://svelte.dev/docs/kit/adapter-static
210210-- https://tauri.app/v1/guides/getting-started/setup/sveltekit/
211211-212212-Canvas/infinite-canvas performance ideas:
213213-- https://antv.vision/infinite-canvas-tutorial/guide/lesson-008
214214-- https://harrisonmilbradt.com/blog/canvas-panning-and-zooming
215215-216216-Perfect Freehand
217217-- https://github.com/steveruizok/perfect-freehand