Skip to content

Getting Started

This chapter is for developers joining the SIS backend. Start with REFERENCE.md to locate the domain you are changing and read the repository's agent instructions before asking an agent to edit it.

1. Stack and entry points

The backend is a NestJS 11 application using TypeScript, Prisma 7 with the PostgreSQL driver adapter, and PostgreSQL. Node.js 24 is required by package.json engines.node, which CI and Railway also use to choose the Node version; use the lockfile for exact dependency versions. TypeScript targets ES2023 with NodeNext module resolution. Jest and Supertest cover unit and HTTP behavior.

Path Purpose
src/main.ts HTTP bootstrap, validation, CORS, API documentation, startup invariants
src/app.module.ts Module composition, global guards and tenant transaction interceptor
src/common/ Shared contracts, CRUD base service, errors and temporal primitives
src/prisma/ Runtime and administrative clients, RLS coverage and tenant helpers
src/auth/, src/permissions/ Authentication, session context and authorization
src/<domain>/ Controllers, services, query functions, DTOs and unit specs
prisma/schema.prisma, prisma/migrations/ Database model and ordered SQL migrations
src/generated/prisma/ Generated client; never edit by hand
test/ E2E configuration, database provisioning, fixtures and HTTP specs
backoffice/ Embedded internal React application
solver/ Python timetable generation service

The complete domain map belongs in REFERENCE.md, rather than a second module inventory here.

2. Local setup

Install Node.js and Docker, then install the locked dependencies. These commands are instructions for a developer; agents run setup, migrations and verification only when authorized under the repository workflow.

npm ci
cp .env.template .env

Edit .env before starting the application:

  • Keep DATABASE_URL as the owner connection for migrations and tooling. Set APP_DATABASE_URL to the restricted app_user connection used by the application.
  • Use NODE_ENV=local and a local JWT secret. Set MAIL_TRANSPORT=log to avoid requiring real Resend credentials; the template contains provider placeholders.
  • Configure the S3_* values for your local bucket. S3_ENDPOINT must reach the MinIO API port published by Docker, and the bucket must exist or local auto-creation must be enabled. Check the container listener and host mapping together when diagnosing connectivity.
  • Keep PUSH_TRANSPORT=log unless deliberately configuring Firebase delivery.

Read migration safety before running migration commands. For a local development database:

npm run db:setup
npx prisma generate
npx prisma db seed
npm run start:dev

db:setup starts Docker Compose, runs prisma migrate dev, and provisions the application database role. Prisma client generation is a separate step. Seed behavior depends on the environment; see seeding.

Docker Compose defines PostgreSQL and MinIO. NestJS runs on the host, with port 8080 as its default. The API prefix is /api/v1. Health routes are /api/v1/health/live and /api/v1/health/ready. In local mode, Swagger is at /docs and Scalar at /reference.

3. Request lifecycle

An authenticated domain request passes through authentication and permission guards, then the tenant transaction interceptor. DTO validation and the controller/service execute inside that request boundary; query helpers use the tenant-scoped Prisma connection. Response filtering strips fields the session cannot read. External side effects registered for post-commit run only after the transaction succeeds.

Read multitenancy, permissions, and CRUD patterns when changing those boundaries. Public, administrative and background flows have explicit transaction rules of their own.

4. Commands

package.json is the command authority.

Command Effect
npm run start:dev NestJS with hot reload
npm run build Install/build the backoffice, generate Prisma client, compile NestJS
npm run lint ESLint with automatic fixes
npm run format Format TypeScript under src/ and test/
npm test Unit specs
npm run test:e2e E2E runner with its database provisioning lifecycle
npm run test:e2e:scale Dedicated scale runner
npm run test:cov Unit coverage
npx prisma generate Regenerate the Prisma client
npx prisma migrate dev Create/apply local development migrations
npx prisma db seed Run the environment-aware seed
npm run db:provision-app-role Provision the restricted runtime database role
npm run docker:up / docker:down Start/stop Compose services
npm run docker:reset Destroy Compose volumes, restart, provision the role, migrate, provision again and seed

docker:reset destroys local database and storage volumes. It is not an ordinary startup command and does not need a second migrate dev appended to it.

5. Prisma and the first change

prisma.config.ts supplies the CLI datasource URL and seed command. Application services inject PrismaService; they do not instantiate PrismaClient. Import generated model types with import type, keep domain queries in their owning query files, and parameterize raw SQL with Prisma's tagged templates.

Choose an existing implementation from REFERENCE.md, read its chapter, and follow the workflow recipes. Keep tenant, academic-year, record-access and field-access rules intact. Update the handbook only when implemented behavior or a durable development rule changes; progress and release notes do not belong in numbered chapters.