School Management SystemMulti-Tenant Laravel Platform
- Period
- Jun 2026 - Jun 2026
- Project type
- Independent-Led Project
- Role
- Lead Full-Stack Developer (Primary Author)
- Team
- Primary author (40 of 41 commits)
A multi-tenant school-administration platform that lets a platform operator onboard schools and assign admins, while each School Admin manages their own teachers, grades, academic years, and student enrollments under role-based access control.
- Eloquent models
- 11Eloquent models
- Migrations
- 16Migrations
- Form Request validators
- 19Form Request validators
- Across 4 audience-split route files
- 12ControllersAcross 4 audience-split route files
Overview
Small/mid schools juggle student records, teacher rosters, grade structures and yearly enrollments across spreadsheets with no shared platform that enforces school-level isolation when one operator runs multiple schools. This platform provides two administrative tiers (Super Admin for the operator, School Admin per school) so onboarding a new school is a guarded workflow rather than a manual DB edit, and a School Admin can never read or mutate another school's data — enforced at the model layer via Eloquent query scopes.
Role & context
- Role
- Lead Full-Stack Developer
- Team
- Primary author (40 of 41 commits)
- Type
- Independent-Led Project
- Period
- Jun 2026 - Jun 2026
Primary full-stack author of the checked-out Laravel repository: 40 of 41 commits are attributable to my aliases, with one commit by Rainas. The platform uses two admin tiers so an operator can onboard schools while each School Admin manages only their own teachers, grades, academic years, and student enrollments.
Problem
Small-to-mid schools typically juggle student records, teacher rosters, grade structures, and yearly enrollments across spreadsheets and ad-hoc tools, with no shared platform that enforces school-level data isolation when one operator runs multiple schools. The platform adds two administrative tiers so onboarding is a guarded workflow and one school admin cannot touch another school's data.
Approach & architecture
Role middleware gates four audience-split route files; controllers re-derive school_id from the authenticated user and query through forSchool() scopes so cross-tenant access is impossible by construction.
Practices followed
Strict multi-tenant isolation by construction
every tenant-scoped query goes through
scopeForSchool($schoolId), so a forgotten WHERE in a controller can't leak cross-tenant rowsRBAC with defense in depth
RoleMiddleware guards the route, the controller re-derives school_id from the authenticated user (never from request input), and the UI hides per-role actions
Centralized API response shape
one ApiResponse helper (success/error/unauthorized/forbidden/
notFound/validationError) keeps every endpoint consistent in payload and HTTP statusForm Request validation per endpoint
19 dedicated FormRequest classes with
rules()+messages()keep controllers thin and validation declarativeReversible, ordered migrations with proper
down(); soft deletes on Student/Teacher for audit trail; UUIDs auto-set in modelboot()for User and SchoolReproducible local setup
composer setup (install -> env -> key -> migrate -> npm build) and composer dev (server + queue + logs + Vite) so a contributor goes clone-to-running in one command
Challenges & resolutions
Preventing cross-tenant data leaks when one User model serves both Super Admin and School Admin against shared global tables (teachers, students) linked to schools via pivot tables.
FixEnforced isolation at the model layer with Eloquent query scopes (scopeForSchool, scopeActive) and resolved school_id from the authenticated user inside the controller rather than trusting any client-supplied id, so even a tampered form field can't reach another school's rows.
Managing the academic-year lifecycle (pending -> active -> completed) safely so enrollments attach to the correct year and state transitions don't corrupt history.
FixModelled academic years and academic-grade-sections as first-class entities with explicit status, scoping enrollments to the active year per school.
Outcomes
Shipped: Auth + RBAC, Super Admin user management, school onboarding with admin assignment, teacher/student/grade/grade-section management, academic-year lifecycle, and student enrollment with transfer/completed/dropped states
- 11
Eloquent models, 16 migrations, 12 controllers, 19 Form Request validators, 4 audience-split route files, and 15+ reusable Blade UI components
Strict multi-tenant isolation enforced at the model layer (Eloquent scopes), not just the UI
Tech stack
Concepts & skills12
- Multi-tenant SaaS architecture
- Role-Based Access Control (RBAC) with middleware
- Eloquent query scopes for tenant isolation
- Laravel Sanctum (SPA cookie + API token auth)
- Form Request validation
- RESTful API design with consistent response envelopes
- TALL-stack frontend (Tailwind + Alpine + Laravel + Blade components)
- Migrations with reversible down() and soft deletes
- UUID primary identifiers
- Service-layer pattern in Laravel
- Vite + Tailwind 4 build pipeline
- Reproducible dev environment (concurrently)