Bicitra EMS
Product Architect / Lead Engineer
A multi-tenant Education Management System for schools, madrasas, and colleges: one shared platform serving any number of independently isolated institutions, built to run on nothing more than a phone — QR-code student IDs, camera-based scanning, and a bilingual (Bangla/English) interface instead of dedicated hardware.
Problem
Schools in Bangladesh run on paper registers — admission, attendance, fees, stock, visitors, meeting minutes — that are disconnected from parents and expensive to digitize one institution at a time. Bicitra EMS is built as a single multi-tenant platform instead: any school signs up, self-serves onboarding, and runs on shared infrastructure with its data fully isolated from every other school, so the cost of serving the next institution is close to zero. The non-negotiable constraint: it has to work on a single Android phone per role — teacher, gateman, bus driver — with no dedicated scanner hardware, QR codes plus a phone camera standing in for all identity verification.
Approach
A monorepo with three apps sharing one domain model: a NestJS/TypeScript API on Prisma and PostgreSQL, a Next.js web dashboard for institution and platform admins, and a Flutter app covering four personas (parent, teacher, gateman, driver). Multi-tenancy is enforced structurally rather than by convention: every tenant table carries a schoolId, and isolation is applied by a Prisma Client Extension in apps/api/src/prisma/ so a query can't accidentally skip the scope — a caller doesn't get the chance to forget a WHERE clause. A separate platform-admin console handles cross-tenant billing, plan enforcement, and analytics, reusing the same tenant-scoped services as the school-facing app rather than duplicating query logic. Built in phases — admission and QR identity first, then fee collection and academic records, then transport tracking and the parent portal, then bilingual UI and analytics — with push-to-pay, SMS delivery, and native push notifications deliberately built to a swap-later boundary: the production shape is in place, waiting on real payment-gateway and SMS-vendor credentials rather than on more engineering.
A hard problem I solved
I put 338 automated checks behind the product — 225 API tests against a real Postgres, 66 Playwright browser tests against a real build, 47 Flutter tests — specifically because tenant isolation and money arithmetic are exactly the two things a mock can't tell you anything about. Writing them wasn't a formality: they found six real defects in code that had already been called done, the worst of which was a critical cross-tenant data leak. The isolation extension correctly scopes every row it writes, but a nested Prisma include on a relation is evaluated as part of its parent query and never gets routed back through that extension — so a fee invoice, an attendance record, or a salary row referencing another school's student id would read that school's guardian details and QR gate-scan credential straight back out to the wrong tenant. It was reachable through seven different endpoints. Rather than patch each one, I fixed it structurally: every inbound tenant-scoped foreign key is now declared in one central registry and validated at write time inside the same extension that already owns tenant scoping — so a new endpoint gets the protection automatically instead of depending on whoever writes it remembering to add it. The same test pass also caught a double-payment race condition (two simultaneous 'Pay now' taps on a flaky connection could both record a payment) and a gate console accidentally handing staff password hashes to the lowest-privilege role in the building.
Status
Currently building toward launch — roughly three weeks of solo full-stack engineering across the API, web, and mobile apps, with a collaborator (Hossain al Ashrafi) contributing the registers and government-compliance requirements. Core registers, QR identity, class and gate attendance, fee invoicing, academic records, live bus-position tracking, and a full bilingual Bangla/English interface are built and covered by the test suite above. Real mobile-banking (bKash/Nagad/Rocket) integration, SMS delivery, and device push notifications are the remaining pieces — blocked on vendor credentials, not on unbuilt architecture.
Technology
- NestJS
- TypeScript
- Prisma
- PostgreSQL
- Next.js
- Flutter
- Redis
- Docker
Currently launching — product link coming soon.