Skip to content

M10: durable Yjs autosave persistence + re-grounded roadmap#16

Merged
pedrobritx merged 1 commit into
mainfrom
claude/notuux-roadmap-design-OWDwj
Jun 1, 2026
Merged

M10: durable Yjs autosave persistence + re-grounded roadmap#16
pedrobritx merged 1 commit into
mainfrom
claude/notuux-roadmap-design-OWDwj

Conversation

@pedrobritx
Copy link
Copy Markdown
Owner

Why

A strategy doc recommended a 7-stage enhancement plan, but it assumed the repo sat at M4. The repo is actually at M9perfect-freehand, Yjs + a custom Supabase-broadcast provider, y-indexeddb, PDF/image import, audio + YouTube/gdrive embeds, named snapshots, and selection/transform are all already shipped. This PR re-grounds the plan around the genuine gaps and ships the highest-priority fix.

The critical gap (lead milestone, M10)

Board state previously lived only in (a) each client's IndexedDB and (b) the ephemeral Supabase Realtime broadcast. shapeStore.initBoard loaded IndexedDB then attached the broadcast provider — it never loaded a server-side snapshot, and lastSaved was a purely local debounced timestamp. Consequence: a fresh client with no IndexedDB, or a late-joiner arriving after all peers had left, got an empty board.

The snapshots table already supports this: a single self-compacting autosave row per board (unique partial index + RLS insert/update on public boards). So — diverging from the original document_updates append-log + compaction-Edge-Function proposal — no migration and no Edge Function are needed. The fix is purely client wiring.

What changed

  • packages/sync/src/autosave.ts (new): loadAutosave (fetch the autosave row and Y.applyUpdate merge — deliberately not the destructive restoreSnapshot used for named-snapshot time travel) and startAutosave (debounced ~2s / max-wait ~10s writer that update-or-inserts the row, with a best-effort pagehide/visibilitychange flush). Also home for the shared bytea hex helpers.
  • packages/canvas/src/store/shapeStore.ts (initBoard): after IndexedDB hydrate + realtime attach, loadAutosave then startAutosave — only when a Supabase client is configured. Local-only mode is unchanged. Stops the previous board's loop on switch.
  • apps/web/src/features/board/snapshotsApi.ts: reuses the hex helpers from @notux/sync (drops the duplicate copies).
  • docs/ROADMAP.md (new): the re-grounded M10–M16 milestones + a Living Cosmos design re-skin track.

Verification

  • pnpm typecheck ✅ and pnpm build ✅ across all packages.
  • Round-trip check: encode → bytea hex → Y.applyUpdate merge reproduces pages/shapes/pageList and is idempotent on re-merge (the late-joiner case).
  • End-to-end (needs VITE_SUPABASE_URL + VITE_SUPABASE_ANON_KEY): draw on a board, wait ~2s for the autosave row to populate, open the same board URL in a fresh incognito window (no IndexedDB) → strokes load; close all tabs and reopen → board persists.

Roadmap (subsequent milestones)

M11 native ink feel · M12 scale (rbush culling + Konva perf flags) · M13 editing polish · M14 URL bookmarks (unfurl Edge Function) · M15 embeds registry · M16 PWA + Capacitor packaging · Living Cosmos re-skin. See docs/ROADMAP.md.

https://claude.ai/code/session_01QFK6Z1fYzo7XSogUETXnwe


Generated by Claude Code

Boards previously lived only in each client's IndexedDB and the ephemeral
Realtime broadcast, so a fresh client or a late-joiner arriving after every
peer had left loaded an empty board. The snapshots table already supports a
single self-compacting `autosave` row per board (unique partial index + RLS
insert/update on public boards), so this wires the missing client loop with
no migration and no compaction function:

- packages/sync/src/autosave.ts: loadAutosave (Y.applyUpdate merge — not the
  destructive restoreSnapshot) and startAutosave (debounced writer with a
  pagehide/visibilitychange flush, update-or-insert), plus shared bytea hex
  helpers.
- shapeStore.initBoard: load then start autosave after IndexedDB + realtime
  attach, only when a Supabase client is configured (local-only unchanged).
- snapshotsApi: reuse the hex helpers from @notux/sync (drop the duplicates).

Adds docs/ROADMAP.md with the re-grounded M10–M16 + Living Cosmos design track.

Verified: pnpm typecheck + pnpm build pass; encode -> hex bytea -> applyUpdate
round-trip reproduces pages/shapes/pageList and is idempotent on re-merge.

https://claude.ai/code/session_01QFK6Z1fYzo7XSogUETXnwe
@pedrobritx pedrobritx marked this pull request as ready for review June 1, 2026 06:16
@pedrobritx pedrobritx merged commit 5ab4d43 into main Jun 1, 2026
4 checks passed
@pedrobritx pedrobritx deleted the claude/notuux-roadmap-design-OWDwj branch June 1, 2026 06:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants