Database & Supabase
This guide documents how we use Supabase Postgres for Frapp: schema, migrations, and conventions.
1. Supabase as the database layer
Frapp uses Supabase Cloud for staging/production and Supabase CLI + Docker for local development.
- Postgres is the single source of truth.
- Supabase provides Auth, Storage, and Realtime on top of Postgres.
- The schema lives in
supabase/migrations/and is applied vianpx supabase db resetlocally.
2. Schema location
- All migrations:
supabase/migrations/*.sql - Seed data:
supabase/seed.sql - Supabase config:
supabase/config.toml
To reset your local database:
npx supabase db reset
This drops and recreates the database, applies all migrations, and reruns seed.sql.
3. Conventions
- Primary keys:
uuidgenerated viagen_random_uuid() - Timestamps:
created_at TIMESTAMPTZ DEFAULT now() - Tenant scoping: nearly every table includes
chapter_id - Row-Level Security (RLS): policies scope by
chapter_idand authenticated user
Examples:
- Core tables:
users,chapters,members,roles,invites - Backwork:
backwork_departments,backwork_professors,backwork_resources - Points/Events:
point_transactions,events,event_attendance - Chat:
chat_channel_categories,chat_channels,chat_messages,message_reactions - Others:
study_sessions,service_entries,tasks,chapter_documents,semester_archives
Info
The canonical description of the data model is in
spec/architecture.md Section 5. Always update the spec before
changing the schema.
4. Adding a new table
- Create a new migration:
npx supabase migration new add_polls
- Edit the generated SQL file in
supabase/migrations/:
create table if not exists public.polls (
id uuid primary key default gen_random_uuid(),
chapter_id uuid not null references public.chapters(id),
channel_id uuid not null references public.chat_channels(id),
question text not null,
created_by uuid not null references public.users(id),
created_at timestamptz not null default now()
);
- Apply the migration locally:
npx supabase db reset
- Update:
spec/architecture.md(data model)- Domain entity & repository interfaces in the API
- Any relevant behavior in
spec/behavior.md
5. RLS and security
We rely on Supabase RLS for defense in depth:
- Policies restrict access by
chapter_idand membership. - The API still enforces its own RBAC permissions (roles + permissions catalog).
When adding tables:
- Add appropriate RLS policies in the migration.
- Ensure every query from the API filters on
chapter_idand respects RLS expectations.
Warning
Never disable RLS in production. Local testing may temporarily relax policies, but staging and prod must always run with RLS enabled.
6. Table inventory (high level)
See spec/architecture.md §5 for a full table-by-table reference. At a high level:
- Core: users, chapters, members, roles, invites
- Engagement: events, event_attendance, point_transactions, study_sessions, service_entries, tasks
- Content: backwork_departments, backwork_professors, backwork_resources, chapter_documents
- Communication: chat_channel_categories, chat_channels, chat_messages, message_reactions
- Meta: semester_archives, financial_invoices, financial_transactions, notifications, notification_preferences