Multi-tenant school ERP. Built with Laravel and React.
School management as a platform. A console onboards and bills schools. Each school gets a full ERP. Demo tenants: “Generic Public School” and “Another Generic School”.
Live demo (opens in a new tab) Pick a demo login on the sign-in page (password: password). Platform console: erp-demo.chetan.cloud, admin@example.com. Resets nightly.
- Stack
- Laravel 13, React 19, Vite, Multi-tenant
- Results
- 540 tests passing. Two demo tenants running side by side on one platform. Overdue fee tracking. The office sees who owes what without a spreadsheet.
Problem
Schools need one place for the daily work: who is enrolled, who teaches what and when, who was present, who owes fees. Each school’s data stays separate from every other school’s.
The platform onboards and bills a school with nobody touching a database by hand.
Built
- API: Laravel 13, one database per tenant.
- Frontend: React 19 + Vite.
- Platform console: onboarding, billing, invoices.
- Per school: students, staff, classes and sections, timetable, attendance, fees with overdue tracking, helpdesk.
Decisions
- A database per tenant
- Isolation is structural, not a where-clause someone has to remember. Backups, restores and exports work per school.
- API plus a separate frontend
- People use the ERP all day, unlike the CMS. A standalone React frontend over a clean API leaves room for a mobile app.
- Onboarding as code
- Creating a school provisions its database, runs migrations and seeds defaults in one step from the console. No manual setup.
Next time
Settle how a request finds its tenant (subdomain, header or path) on day one. Write it down before building screens on it.
Build offline-first attendance early. Classrooms do not always have good connectivity.