FullBagERP
School management software for private schools, colleges and school groups: admissions, attendance, academics, exams, fees, transport, staff, library and a parent app, in one system.
Full stack developer, on the team from the beginning
- Role
- Full stack developer, one of the first developers on the team
- Timeline
- March 2026 – September 2026
- Platform
- Web app for school staff, parent app, Android phones for teachers' daily tasks
- Status
- In use at schools in Nepal
- Stack
- Next.js, Node.js, Express, Prisma, PostgreSQL, Redis, BullMQ, AWS S3, Docker, GitHub Actions
The problem
A school in Nepal has to run admissions, attendance, academics, exams, fees, timetables, transport, staff and a library, and parents expect to hear quickly about an absence or a fee that is due.
FullBagERP puts all of that in one system. Each school's data is kept separate, dates follow Bikram Sambat and the Nepali fiscal year, and the interface works in Nepali or English. A school group can run several campuses under one account.
What it does
Dashboards
A view for each role. Leadership sees attendance, fee collection and the exceptions that need a decision; teachers and office staff see their own work.
Admissions
Online enquiry and admission forms, an admission workflow, student profiles, bulk import of existing students, and printed ID and admit cards.
Attendance
Homeroom or period-wise attendance on a phone or by QR scan, with present, absent, late and leave. Parents of absent students get an SMS and an app alert.
Academics
Curriculum setup and tracking for each programme, unit planning, tasks and assessments, and a task board for planning teams.
Exams and results
Custom grading systems, report card templates, OCR-assisted marking of scanned objective answer sheets, and results published to the parent app.
Fees and billing
Class-wise fee structures, discounts, scholarships, fines, receipts, due reminders, a live collection dashboard, and online payments matched to the student.
Academic calendar
Term dates, holidays, exams, briefings and assignments, with Bikram Sambat dates first and AD beneath.
Timetable
Class timetables with clash and substitution detection.
Transport
Vehicles, stops, routes, a transport timetable, student assignments, attendance on the vehicle, a live map of every vehicle, and transport fees on the student bill.
Staff and payroll
Teacher and employee records, logins issued from the people screens, and payroll.
Library
Catalogue with barcodes, loans and automatic late fines.
Messaging and parent app
Bulk SMS and email with templates. Parents see attendance, homework, results and dues, and can message the class teacher.
Reports
Attendance, roster, staff, transport and finance reports, exported to PDF or Excel.
Security
Each school's data in its own database, role-based access for every screen and API route, and daily backups.



School, staff and student names are removed from these screenshots.
How it works
Each school gets its own subdomain. The Next.js app reads the school from the subdomain and sends it with every request as an x-tenant-id header.
The Express API looks the school up in a central database and connects to that school's own PostgreSQL database. Every school has a separate physical database.
Slow work runs outside the request. SMS, email and provisioning jobs go onto BullMQ queues in Redis, with a dead-letter queue for jobs that keep failing. Uploaded files go to S3.
GitHub Actions builds Docker images for the API and the web app, pushes them to GitHub's container registry, and deploys them to the server with Docker Compose.
Hard problems and decisions
One database per school
- Problem
- In a shared database every query needs a school filter, and one forgotten filter shows one school's students to another.
- What I chose
- Each school has its own PostgreSQL database, found through a central registry. The student, teacher and academics models were moved over and their schoolId columns removed.
- Why
- A query can't reach another school's data, because it runs on a connection to one school's database.
Parents only see their own child's bus
- Problem
- The parents' live map must not become a way to look up any bus, or any child, in the school.
- What I chose
- The server builds the list from the parent's own profile: their children, then the buses those children are assigned to. The app never sends student IDs.
- Why
- If the client can't name a student, it can't ask for someone else's.
Permissions checked on the server
- Problem
- Teachers, accountants, office staff and leadership need different parts of the system, and hiding a button in the UI doesn't stop a direct API call.
- What I chose
- Role-based permissions are enforced on the API routes, seeded per role, and the dashboards follow the same roles.
- Why
- The API refuses what the role doesn't allow, whatever the UI shows.