ArchitectureServices & repos

Services & Repos

One-line: six repositories make the product — one API, two web apps, one mobile app, infra, and a marketing site.

Repositories

RepoLocal pathStackPurpose
nexchool/serverserver/Python, Flask, SQLAlchemy 2, Flask-Migrate, CeleryThe API and all business logic
nexchool/school-admin-paneladmin-web/Next.js 16, Tailwind 4, React Hook Form, Zod v4, TanStack Query v5School admin dashboard (tenant-scoped)
nexchool/super-admin-panelpanel/Next.js, same FE stackOperator control plane (/api/platform/*)
nexchool/clientclient/Expo ~54, React Native, TypeScriptMobile app (teachers, students, admins)
nexchool/nexchool-infraschool-erp-infra/Docker Compose, Nginx, GitHub ActionsDeploy, TLS, CI/CD
nexchool/landing-pagelanding-page/Next.jsMarketing site, Vercel-hosted

Backend module anatomy

Each domain lives in server/modules/<name>/ and follows the same shape:

server/modules/students/
  __init__.py        # blueprint registration
  routes.py          # HTTP controllers (thin) → call services
  services.py        # business logic (the real work)
  models.py          # SQLAlchemy models (tenant-scoped via TenantBaseModel)
  schemas.py         # request/response validation (marshmallow/pydantic-style)

Controllers stay thin; the service layer holds logic and is the only layer that touches the database. This keeps business rules testable and out of both the HTTP layer and the DB.

The full module list (37 backend modules) folds into the product domains documented under Product: students, teachers, classes, attendance, fees/finance, timetable/schedule, transport, hostel, notifications/announcements/devices/mailer, academics (academics, academic_programmes, grades, mediums, religions, subjects, subject_contexts, holidays, school_units, school_setup), plus platform, rbac, users, auth, audit, dashboard, search, subscription, sub_admins, student_leaves.

Core infrastructure (server/core/)

ConcernWhere
Tenant resolutioncore/tenant.py
DB base + tenant scopingcore/database.py (TenantBaseModel, loader criteria)
Plan feature gatingcore/plan_features.py
Redis cache layercore/cache.py
RBAC seedserver/scripts/seed_rbac.py

Frontend service layer

Each client centralises HTTP in one place and unwraps the { success, data } envelope:

  • admin-web/src/services/api.ts
  • panel/src/services/… (equivalent)
  • client/common/services/api.ts

Data fetching in the web apps uses TanStack Query, and every tenant-scoped query key ends with tenantId so two tenants never share a cache entry (see Multi-tenancy).

Async work

Celery workers (Redis broker) handle background jobs — bulk imports, notification dispatch/fan-out, scheduled sweeps (e.g. stale-draft cleanup). Anything slow or fan-out-shaped runs off the request thread.