Cards/spaces persistence migrated to Supabase (signed-in)
Added
lib/use-workspace.ts — unified data layer. Signed-out keeps localStorage
WebSocket; signed-in makes Supabase authoritative, with localStorage as a
per-space cache the page seeds before the canvas mounts (so Canvas.tsx is
untouched). Owns the auth switch, cloud space list, card seed/push, default
board creation, and import detection.
lib/supabase/cards.ts — loadCloudCards and saveCloudCards
(debounced upsert + delete-reconcile against a per-space id snapshot).
One-time import — on first sign-in with local boards, a modal offers to
import them into the account (spaces + cards remapped to fresh UUIDs).
Changed
app/page.tsx now uses useWorkspace; cloud spaces gate the canvas behind a
per-space "seeding" state; onSync pushes to Supabase (cloud) or WS (local).
IDs are now crypto.randomUUID() (canvas-store.uid, TopBar space id) so
rows are valid in the uuidid columns.
Bumped @supabase/supabase-js → 2.108.1 and @supabase/ssr → 0.12.0.
Notes
Persistence-first: cloud edits are durable + cross-device on reopen, but not
yet live across sessions (Supabase Realtime is the next step). WebSocket is
retained for presence.
Image cards still embed their resized data URL in the cards.data jsonb;
moving them to the Storage bucket is a follow-up.
Requires being signed in (magic link) for the cloud path; signed-out behaviour
is unchanged.