Skip to main content

Dedicated Deployment

A dedicated deployment is a single-school instance of GradeBook hosted on its own infrastructure. The school gets their own Supabase instance (self-hosted or Supabase-managed) and their own backend/frontend deployment.

This is distinct from the default multi-tenant setup where multiple schools share one platform.


How It Works

When DEDICATED_DEPLOYMENT=true is set on the backend:

  • School creation is limited to one. The first school can be created during onboarding. Any subsequent attempt to create a school returns 403 Forbidden.
  • Onboarding skips school selection. New users are automatically assigned to the single existing school - no dropdown, no school picker.
  • School switching is hidden in the frontend sidebar.

The schema, RLS policies, and all API behaviour remain identical to the multi-tenant setup. The only difference is the enforcement of the one-school limit and the simplified onboarding flow.


Setup

1. Provision a Supabase Instance

Use either:

2. Run Migrations

Pull the schema from the reference project or apply your migration file:

supabase link --project-ref <your-project-ref>
supabase db push

3. Configure Backend

backend/.env

SUPABASE_URL=https://your-instance.supabase.co
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
SUPABASE_PUSHABLE_KEY=your-anon-key
FRONTEND_URL=https://your-frontend-domain.com
DEDICATED_DEPLOYMENT=true

4. Configure Frontend

frontend/.env.local

NEXT_PUBLIC_API_URL=https://your-backend-domain.com
NEXT_PUBLIC_DEDICATED_DEPLOYMENT=true

5. First Login - Create the School

On the very first login, the onboarding form will include a Create school option (since no school exists yet). Create the school during this step - this is the only time school creation is permitted.

All subsequent users who log in will be automatically assigned to this school, with no school selection shown.


Behavioural Differences vs Multi-Tenant

FeatureMulti-TenantDedicated
School creationUnlimitedOne-time only (first onboard)
Onboarding school selectorShownHidden
School switcher in sidebarShownHidden
RLS policiesSameSame
API endpointsSameSame
Supabase instanceSharedDedicated

Security Notes

  • DEDICATED_DEPLOYMENT=true is enforced server-side - even if a client sends a request to POST /schools, it will be rejected once a school exists.
  • All existing RLS policies apply as normal. Since the entire database belongs to one school, get_user_school_id() will always resolve to the same school for every user.
  • NEXT_PUBLIC_DEDICATED_DEPLOYMENT only controls UI visibility. The backend enforcement does not depend on this frontend variable.