Deployable on serverless hosts (Vercel): WebSocket is now optional
Fixed
Signed-out app no longer hangs / spams the console on Vercel (lib/sync.ts,
lib/spaces.ts). The signed-out path depended on the custom WebSocket server
(server.js), which can't run on a serverless host — so deploys to Vercel saw
endless WebSocket connection to 'wss://…/_ws' failed retries and were stuck on
the "Connecting…" screen (the space list lived only in server memory).
Changed
WebSocket sync is opt-in via NEXT_PUBLIC_SYNC_WS_URL. The client resolves a
target URL: the env var if set, else same-origin /_ws in dev (where pnpm dev
runs server.js), else null. When null, no socket is opened at all — no
retries, no console noise.
Signed-out space list now persists to localStorage (loadSpaces/saveSpaces/
defaultSpace in lib/spaces.ts), matching how cards already persist via
lib/canvas-store. useSync seeds from this cache on mount and flips ready
immediately, so the app renders without waiting on (or requiring) a socket.
Deployment matrix. On Vercel: signed-out → local-only (localStorage),
signed-in → Supabase Realtime (unchanged). To keep signed-out cross-device sync +
presence in production, self-host server.js and set NEXT_PUBLIC_SYNC_WS_URL
(documented in .env.example).