TutorLoom
The learning platform for companies, colleges and training institutes. Free and open source, with an Enterprise edition.
School Management System
Translation pending
EducationGitHub @ZChigzOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Repository information has not been collected yet.
No updates detected yet. GitHub releases will appear here.
School management system with dual-currency payments, student portal, academic results, assets, and library
Taken from the repository README
Loading the full README.
Read the full README ↗A full-stack multi-tenant school management platform covering fee accounting, academic results, library management, and asset tracking.
| Layer | Technology |
|---|---|
| Framework | Next.js 14 (App Router) |
| Language | TypeScript 5 |
| Database | PostgreSQL 15 via Prisma 5 |
| Auth | NextAuth v5 (JWT, credentials) |
| Styling | Tailwind CSS |
| Forms | React Hook Form + Zod |
| Charts | Recharts |
| File uploads | UploadThing |
| PDF generation | @react-pdf/renderer |
| Unit/component tests | Vitest + Testing Library |
| E2E tests | Playwright |
| Containerisation | Docker (standalone build) |
npm 10+# 1. Install dependencies
npm install
# 2. Copy and fill environment variables
cp .env.example .env
# Edit .env — set DATABASE_URL, NEXTAUTH_SECRET, NEXTAUTH_URL
# 3. Run database migrations
npm run db:migrate
# 4. Seed with demo data
npm run db:seed
# 5. Start dev server
npm run dev
Open http://localhost:3000.
All seed users share the password School@2026.
| Role | |
|---|---|
| Director | [email protected] |
| Head Teacher | [email protected] |
| Bursar | [email protected] |
| Teacher | [email protected] |
| Librarian | [email protected] |
app/
(auth)/ # Login page (no sidebar layout)
(dashboard)/ # Authenticated app shell with sidebar
accounting/ # Fee management, expenses, dashboard
results/ # Marks entry, report cards
library/ # Books, borrowing, members
assets/ # Asset register, maintenance, disposal
api/ # Route handlers (all wrapped with withApi)
portal/[token]/ # Public student fee portal (no auth)
error.tsx # Root error boundary
not-found.tsx # 404 page
components/
ui/ # Button, Badge, Modal, etc.
accounting/ # PaymentModal, StudentTable, etc.
results/ # ReportCardDocument, MarksTable
library/ # BookCard, BorrowingTable
assets/ # AssetCard, MaintenanceForm
lib/
auth.ts # NextAuth config
prisma.ts # Prisma client singleton
permissions.ts # RBAC guard functions
utils.ts # formatUSD, formatZiG, getDaysOverdue, etc.
logger.ts # Structured JSON logger
api.ts # apiSuccess/apiError helpers + withApi HOF
audit.ts # logAudit() for transaction audit trail
validations/ # Zod schemas per domain
prisma/
schema.prisma # Database schema
migrations/ # Migration history
seed.ts # Demo data seed
tests/
unit/ # Pure function tests (Vitest)
components/ # RTL component tests (Vitest + jsdom)
e2e/ # Browser tests (Playwright)
/portal/[token] — shows a student's fee balance. No login required. Tokens regenerated on demand by staff.| Variable | Required | Description |
|---|---|---|
DATABASE_URL | Yes | PostgreSQL connection string |
NEXTAUTH_SECRET | Yes | JWT signing secret (openssl rand -base64 32) |
NEXTAUTH_URL | Yes | Base URL of the app (e.g. http://localhost:3000) |
UPLOADTHING_SECRET | Yes | UploadThing API secret |
UPLOADTHING_APP_ID | Yes | UploadThing app ID |
DAILY_FINE_RATE | No | Library overdue fine per day in USD (default 0) |
LOAN_PERIOD_DAYS | No | Default loan period in days (default 14) |
| Script | Description |
|---|---|
npm run dev | Start Next.js dev server |
npm run build | Production build |
npm run start | Start production server |
npm run lint | ESLint |
npm run db:migrate | Run Prisma migrations (dev) |
npm run db:seed | Seed demo data |
npm run db:studio | Open Prisma Studio |
npm run db:reset | Reset DB and re-seed |
npm run test | Vitest (watch mode) |
npm run test -- --run | Vitest (single run) |
npm run test:e2e | Playwright E2E tests |
schoolId: user.schoolId. Never trust a schoolId from the request body.balance = Σ charges − Σ VERIFIED payments. PENDING and VOIDED payments do not reduce balance.logAudit() inside the same Prisma transaction.can*() function from lib/permissions.ts before mutating data. guard() throws a Response(403) which route handlers must catch and return.withApi(label, handler). Unhandled errors are logged with logger.error and return { success: false, message: 'Internal server error' } with status 500.Decimal and serialised to number (.toNumber()) before being sent in API responses.NEXT_PUBLIC_.# Run all Vitest tests
npm run test -- --run
# Watch mode during development
npm run test
Playwright tests require a running app and a seeded database.
# 1. Seed the database
npm run db:seed
# 2. In one terminal, start the app
npm run dev
# 3. In another terminal, run Playwright
npm run test:e2e
To view the HTML report after a run:
npx playwright show-report
docker build -f Dockerfile.prod -t school-ms .
docker run -p 3000:3000 \
-e DATABASE_URL="..." \
-e NEXTAUTH_SECRET="..." \
-e NEXTAUTH_URL="http://localhost:3000" \
school-ms