DoodleDesk is a collaborative visual workspace built with React + Vite and backed by Supabase. It lets users create desks, place notes/checklists/decorations on a freeform canvas, collaborate with friends, and keep lightweight activity history.
This README is intended for two audiences:
- New users and contributors who need to run and modify the app.
- Engineers reviewing the codebase who need a quick architecture and data-flow map.
Core capabilities:
- Email/password auth with session recovery flow.
- Multi-desk workspace with shelf organization.
- Freeform desk canvas with sticky notes, checklists, and decorative items.
- Drag/resize/rotate interactions with optional snap-to-grid.
- Undo/redo and autosave/history synchronization behavior.
- Desk collaboration (membership roles and requests).
- Friend requests and social profile surfaces.
- Activity feed and profile stats.
- Desk import/export and background customization.
Frontend:
- React 19
- Vite 7
- ESLint 9
Backend/services:
- Supabase Auth
- Supabase Postgres + RLS
- Supabase Realtime
- Supabase Edge Functions (TypeScript)
Project style:
- Feature-first organization under
src/features. - Public feature APIs via
src/features/*/index.jsbarrel files. - App-level orchestration in
src/App.jsx.
High-level runtime flow:
src/main.jsxmounts the app and applies iframe/top-window safety behavior.src/App.jsxreads auth session state and gates UI via auth boundary.- The
Deskflow composes desk orchestration hooks (state, lifecycle, actions, UI derivations). - Data persistence and realtime synchronization are handled through the shared Supabase client in
src/supabase.js.
Primary feature boundaries:
src/features/auth- Login/reset/recovery screens and session hooks.
src/features/desk- Canvas UI components, desk actions, data queries, realtime wiring, history, import/export, shelf hierarchy, membership, and social interactions.
Backend boundary:
supabase/functions/delete-account: authenticated account-deletion workflow.supabase/functions/friend-request-email: friend request email/webhook processing.
flowchart TD
U[User Browser] --> M[src/main.jsx]
M --> A[src/App.jsx]
A --> AB[src/features/auth]
A --> DB[src/features/desk]
AB --> SA[(Supabase Auth)]
DB --> SC[src/supabase.js]
SC --> SP[(Supabase Postgres + RLS)]
SC --> SR[(Supabase Realtime)]
DB --> EF[supabase/functions]
EF --> SP
Read this as:
- The browser boots through
src/main.jsxintosrc/App.jsx. - App orchestration branches into auth and desk feature boundaries.
- Both feature flows rely on Supabase services through the shared client and edge-function workflows.
src/App.jsx: top-level app and desk orchestration composition.src/main.jsx: React root entrypoint.src/supabase.js: shared Supabase client and required frontend env validation.src/features/auth: auth hooks and auth screens/components.src/features/desk: desk domain implementation (components, hooks, constants, utils, data).supabase/functions: edge functions used by production workflows.BACKEND_SQL_README.md: canonical SQL migration and security hardening source.docs/PROJECT_ORGANIZATION.md: maintainability conventions and decomposition guidance.new changes.md: running changelog.
- Node.js 20+ recommended.
- npm 10+ recommended.
- A Supabase project with Auth/Postgres enabled.
npm installCreate a .env file in the project root with:
VITE_SUPABASE_URL=your_supabase_project_url
VITE_SUPABASE_ANON_KEY=your_supabase_anon_key
VITE_ENABLE_FINAL_PROJECT=falseThe app will throw a startup error if either value is missing (enforced in src/supabase.js).
Set VITE_ENABLE_FINAL_PROJECT=true to show the DoodleDesk Analytics submission shell instead of the desk app.
npm run devOpen the local URL printed by Vite (commonly http://localhost:5173).
npm run lint
npm run buildnpm run dev: start Vite dev server.npm run build: create production build.npm run preview: preview production build locally.npm run lint: run ESLint across the project.
Run SQL migrations from:
BACKEND_SQL_README.md(source of truth; run sections in order)
Important backend entities managed there:
- Core tables for profiles, desks, notes, checklists, checklist items, decorations, memberships, friend requests, and shelf organization.
- Index creation.
- Realtime publication membership.
- RLS enablement and policy guidance.
- Security hardening steps (including forced RLS and defensive constraints).
Recommended workflow:
- Apply migration sections in order from
BACKEND_SQL_README.md. - Confirm tables/policies/publication state in Supabase SQL editor.
- Test end-to-end app flows locally.
- Run all SQL sections from
BACKEND_SQL_README.mdSection 12 - Enable "Havebeenpwned" password checks in Supabase Auth settings
- Verify all RLS policies are in place with
select tablename from pg_tables where schemaname='public' - Check that realtime publication is configured for all required tables
- Test that viewers cannot edit desks or items
- Test that users cannot access other users' private desks
- Rotate any shared secrets (webhook credentials, etc.) used in production
- Review
SECURITY.mdfor vulnerability reporting process
Set these Supabase Edge Function environment variables:
ALLOWED_ORIGINS: comma-separated allowed browser origins.APP_BASE_URL: canonical app URL for links and origin fallback checks.FRIEND_REQUEST_WEBHOOK_SECRET: shared secret forfriend-request-emailwebhook validation.FRIEND_REQUEST_FROM_EMAIL: sender email identity.RESEND_API_KEY: provider API key for outbound email.
Security reminders:
- Never expose
SUPABASE_SERVICE_ROLE_KEYin frontend code. - Keep only anon credentials in Vite client env variables.
- Enable leaked password protection in Supabase Auth settings.
At a high level:
- Desk owners create and manage desks.
- Members can be granted roles (owner/editor/viewer behavior is enforced by app logic + backend policies).
- Viewers are read-only for desk item modifications.
- Friend requests and desk member requests are modeled separately.
Data safety depends on both layers:
- Frontend gating to keep UX coherent.
- Backend RLS/policies to enforce actual data security.
If you are auditing or extending the codebase, start here:
src/App.jsxto see orchestration boundaries and integration points.src/features/desk/index.jsto understand the desk feature public surface.src/features/auth/index.jsfor auth module boundaries.src/supabase.jsfor client initialization and required env contract.docs/PROJECT_ORGANIZATION.mdfor maintainability conventions and decomposition strategy.BACKEND_SQL_README.mdfor schema, policies, and security migration history.
Cause:
VITE_SUPABASE_URLorVITE_SUPABASE_ANON_KEYis not set.
Fix:
- Add both variables to
.envand restartnpm run dev.
Potential causes:
- Another local Vite process already occupies the expected port.
- Terminal exited before noticing the actual assigned fallback port.
Fix:
- Restart dev server with
npm run dev. - Use the exact URL Vite prints in terminal output.
- Stop stale local Vite/node processes if multiple are running.
Check:
- Supabase URL/key values in
.env. - Required SQL sections applied from
BACKEND_SQL_README.md. - RLS policies and realtime publication were applied successfully.
README.md: onboarding, architecture, and development workflows.BACKEND_SQL_README.md: backend SQL and security migration source.docs/PROJECT_ORGANIZATION.md: maintainability and module-organization practices.new changes.md: chronological project change log.
When shipping changes:
- Keep feature boundaries intact (
authvsdesk). - Prefer hook/component extraction instead of growing
App.jsxinline complexity. - Run
npm run lintandnpm run buildbefore finalizing. - Update docs/changelog files when behavior, architecture, or setup expectations change.