Skip to content

Supabase Sync

NesiciCoding edited this page May 15, 2026 · 3 revisions

Supabase Sync (optional)

Rubric Maker works entirely offline via localStorage. The Supabase sync layer is an opt-in feature that adds:

  • Cross-device sync — your rubrics, students, and grades are available on every device you sign in to.
  • Colleague sharing — share a rubric or class with another teacher account (read-only or editable).
  • File storage offload — attachments and export templates are stored in Supabase Storage instead of base64 strings in localStorage, removing the 5–10 MB browser storage limit for files.

localStorage remains the synchronous primary store. Supabase syncs in the background and the app loads instantly from localStorage even when offline or disconnected.


Architecture

Browser
  └── AppContext (localStorage — primary, synchronous)
        └── StorageSync singleton (background, async)
              ├── SupabaseAdapter  — Supabase client wrapper
              └── AttachmentSync  — file upload/download via Supabase Storage

The AppContext reducer is unchanged — components never talk to Supabase directly. StorageSync subscribes to state changes, mirrors them to Supabase, and hydrates localStorage from the DB on reconnect.


Option A — Local Supabase (development)

Prerequisites

Steps

# Start a local Supabase stack
supabase start

The CLI prints something like:

API URL:  http://127.0.0.1:54321
anon key: eyJhbGci...
Studio:   http://127.0.0.1:54323

In the app, go to Settings → Database → Connect & Sync and paste the URL and anon key.

Alternatively, add them to .env.local to pre-fill the form automatically:

VITE_SUPABASE_URL=http://127.0.0.1:54321
VITE_SUPABASE_ANON_KEY=eyJhbGci...

.env.local is gitignored. Never commit real credentials to the repository.

Stopping the local stack

supabase stop

Option B — Cloud Supabase (production / shared)

1. Create a Supabase project

Go to supabase.com and create a new project.

Region: Choose eu-central-1 (Frankfurt) for AVG/GDPR compliance when serving EU users.

2. Run the database migrations

The four migration files in supabase/migrations/ set up the full schema. Run them in order using the Supabase dashboard SQL editor, or push them via the CLI:

supabase db push --db-url "postgresql://postgres:<password>@<host>:5432/postgres"
Migration What it does
001_initial_schema.sql Creates all tables (rubrics, students, classes, student_rubrics, attachments, etc.)
002_rls_policies.sql Enables Row Level Security — each user can only read/write their own rows
003_storage_buckets.sql Creates the attachments and templates storage buckets with RLS
004_profile_trigger.sql Auto-creates a profiles row when a new auth user signs up

3. Connect the app

In the app, go to Settings → Database → Connect & Sync and enter your project URL and anon key (found in Project Settings → API in the Supabase dashboard).


Database schema

All tables follow the same pattern: id (text, primary key), owner_id (uuid, FK to profiles), and a data JSONB column holding the full entity. This avoids complex camelCase ↔ snake_case column mapping while keeping RLS policies simple.

Table Description
profiles One row per auth user; auto-created by trigger
rubrics Rubric definitions
classes Class definitions
class_members Many-to-many: classes shared with other teachers (viewer or editor role)
students Student records, linked to a class
student_rubrics Graded rubrics + peer reviews (distinguished by is_peer_review)
attachments Attachment metadata; the file lives in Supabase Storage
comment_bank Reusable feedback snippets
export_templates Word mail-merge template metadata; file in Storage
grade_scales Custom grade scale definitions
comment_snippets Individual comment snippet entries
favorite_standards Saved CSP standard codes

Authentication

Stage Mechanism
First connect Anonymous session — no email required
Upgrade to named account Email magic-link (OTP) sign-in via Settings
Sharing rubrics/classes Both parties must have a named (non-anonymous) account

Anonymous sessions persist across browser restarts via the Supabase auth cookie. Upgrading to a named account merges the anonymous data into the new user's account.


Sharing rubrics and classes

Once signed in with a named account:

  1. Open a rubric or class in the app.
  2. Go to Share and enter a colleague's email address.
  3. Choose Viewer (read-only) or Editor access.
  4. The colleague sees the shared item appear in their list on next sync.

Sharing is managed via the class_members table and RLS policies that grant read access to shared rows.


Migrating existing data to Supabase

If you have existing data in localStorage and want to move it to Supabase:

  1. Connect to Supabase (Settings → Database → Connect & Sync).
  2. Click Push local → database to bulk-upload all localStorage data to Supabase.

Environment variables

Variable Description Required
VITE_SUPABASE_URL Your Supabase project URL (e.g. https://xyz.supabase.co) No — can be entered in UI
VITE_SUPABASE_ANON_KEY Supabase anon (public) key No — can be entered in UI

Copy .env.example to .env.local and fill in the values. .env.local is never committed to version control.


Troubleshooting

"Failed to connect" in Settings

  • Check that the URL starts with https:// (cloud) or http://127.0.0.1:54321 (local).
  • Check that the anon key is the full JWT string.
  • For local: confirm supabase start is running and Docker is up.

Data not appearing after connect

Click Pull Now in Settings → Database. The initial hydration runs automatically on connect, but can be triggered manually.

localStorage and Supabase out of sync

After a long offline period, Supabase may have newer data than localStorage. Use Pull Now to overwrite localStorage with the DB state, or Push local → database to do the reverse.

Clone this wiki locally