Personas & Permissions
Five users. One database. Carefully different views. The full permission matrix and how each persona logs in.
The school SaaS has five kinds of users. Each sees a different subset of the same database, decided by their role and (for most) their assigned branch. This page is the definitive permission matrix and how to bring each persona to life.
The Five Personas
| Persona | Who they are | What they care about |
|---|---|---|
| Super Admin | The school's owner/principal across all branches | Everything across all branches: enrolment numbers, revenue, attendance trends. |
| Branch Admin | The principal or office manager of one campus | Their branch's students, teachers, fees, day-to-day operations. |
| Teacher | A teacher assigned to one or more sections | Their assigned sections — attendance, marks, parent contact. |
| Parent | The parent of one or more enrolled children | Their child's attendance, marks, fees, circulars. |
| Student (optional v1.5) | Older students (grade 6+) reading their own data | Their own marks, attendance, schedule. |
Every persona logs in with the same email/password screen. The system reads profiles.role after login and routes accordingly.
The Full Permission Matrix
Footnotes:
- ¹ Limited to their assigned branch only.
- ² Limited to their assigned section(s) only.
- ³ Limited to their own children's data only.
This matrix is what your RLS policies enforce. Never enforce a permission in only the UI — anyone with the API key can bypass UI checks.
How Each Persona Logs In
Each persona uses the same /login page but is routed to a different home after login.
| Persona | Routed to | What they see first |
|---|---|---|
| Super Admin | /admin | Dashboard with all branches, total enrolment, payment summary |
| Branch Admin | /admin | Same UI as super admin, but data filtered to their branch (RLS enforces this) |
| Teacher | /teacher | List of their sections; click to mark attendance / enter marks |
| Parent | /parent | List of their children; click to see attendance / marks / fees |
| Student | /student | Their own dashboard — marks, attendance, schedule |
You don't need to build separate apps. One Next.js app, route guards based on role.
The Role Switch on Login
In Project 2 the contact form didn't need auth. In Project 3 every page does. The auth flow:
- User visits any URL.
- Middleware checks for a Supabase session cookie.
- If no session → redirect to
/login. - After successful login, look up
profiles.role. - Redirect based on role:
super_adminorbranch_admin→/adminteacher→/teacherparent→/parentstudent→/student
Code sketch (in src/middleware.ts):
Then per-route components also check profiles.role server-side and either render or 404. Defense in depth.
Creating Test Users (Seed Script)
Before you start building features, seed a few test users so you can develop against realistic data.
In the Supabase SQL editor (use the service role with caution — only for seeding):
Test passwords for development only: use Aurora-Test-2026 or similar. Never reuse on production. Save to VaultMate under category "Test Account."
Once seeded, you can log in as each persona separately to verify the right page renders and RLS isolates the data correctly.
The "Surprise" Permission Cases
Real schools have edge cases that don't fit a clean matrix. Decide upfront how you'll handle them:
| Edge case | Recommendation |
|---|---|
| Parent has children in 2 different branches | Two parent.children relationships — one row per child. UI shows a branch dropdown if >1 child. |
| Teacher transfers branches mid-year | Change profiles.branch_id. Past attendance records keep their original branch_id — they're already scoped to a section. |
| A child changes from one section to another | Add student_section_history table for the audit trail. The students.section_id is "current section." |
| Two siblings share one parent | One parents row, two students rows both with same parent_id. |
| A super admin temporarily acts on behalf of a branch admin | Don't fake it. Super admins inherently see everything; they don't need to "switch." |
These decisions matter because they shape your foreign keys.
What's Next
Now you have:
- The 12-table schema (from the previous page).
- The full permission matrix.
- Test users seeded.
- Per-persona routing decided.
Time to build the first module. Students is the right first module — every other module references students.