EduSpace
Multi-Tenant School Management Platform
EduSpace is a pnpm/Turborepo workspace holding seven independently deployable frontends and nine shared packages. Five are Vite SPAs (admin, student, alumni and admission portals); two are Next.js sites (marketing and Fumadocs documentation). Shared packages carry the HTTP client, payments flow, UI primitives, tenant resolution and admissions checklist logic.
- Lead Frontend Engineer
- Attesta Labs
- 2026
- React 19 / TypeScript / Vite / Next.js / Turborepo + pnpm / TanStack Query / Zustand / Zod / React Hook Form / Tailwind CSS + shadcn/ui / axios / Vitest + MSW / Fumadocs

The problem
Schools need one system for admissions, fee collection, student records and alumni, but each school configures its own programmes, fees and application requirements.
The solution
A monorepo where per-school variation is server-driven: admission forms render from a checklist blueprint, branding resolves per domain, and every app shares one axios factory and one payments package.
In the product



Key features
- Admission adverts with server-defined application checklists, document uploads and fees
- Applicant review, single and bulk admission, application removal and acknowledgement slips
- Fee types with amount tiers, programme/level scopes and assigned-student restriction
- Invoices, transactions, settlements with disbursement, RRR entry and receipt attachments
- Student records, bulk upload, e-clearance, hostel booking and course registration
- Alumni directory, dues, events, giving and matric-number-verified registration
- Public payment verification pages reached by QR code printed on receipts
Architecture & tech decisions
- Nine source-consumed packages exporting raw src/: no build step, no dist/
- createHttpClient factory: one axios instance with per-app options for encryption and auth bypass
- Checklist-driven admissions: advert blueprint × profile × options × client section registry
- Capability-based auth: buildAbility reads scope:read/write; RequireWrite guards routes
- Response validation via parseResponse, with soft() fields and openEnum() for backend enums
- Per-domain tenant resolution through /school/resolve-domain with a known-good fallback
Challenges faced
- Rendering an entire applicant portal from server-defined checklist data, with nothing school-specific hardcoded
- Response parsing that tolerates backend drift after a strict schema failed the fees gate open
- One payments package serving three apps with different endpoints, envelopes and post-settlement behaviour
What I'd improve
- Wire the change-course flow: the UI is built, the initiate/confirm endpoints are not
- Add a CI pipeline; lint, typecheck and tests currently run only via local git hooks
- Remove the deprecated application portal and its stubbed API calls
Impact & results
Lets a school configure its own admission requirements, fee structure and branding from the server without a frontend release, while staff permissions stay scoped per area.
Interested in working together?
Get in touchGorvoo