Local development & testing
Tooling
- Runtime and package manager: Bun. Install with
bun install, run withbun run dev. - Language: TypeScript, checked with
bun run typecheck(tsc --noEmit). - Tests: Vitest.
- Backend services use Express 5 and mongoose; the frontend uses Next.js and React.
Configuration comes from environment files that are never committed. Each repo lists the keys it needs (names only) in an example file. Ask a maintainer for development values; never paste real values into code, tests, tickets or chat.
Two kinds of tests
| Kind | File name | Run with | Needs |
|---|---|---|---|
| Unit | *.test.ts | bun run test | nothing: fast, no database |
| Integration | *.int.test.ts | bun run test:int | an in-memory MongoDB started per test file |
bun run testexcludes integration files, so it stays fast and runs everywhere.- Integration tests start their own in-memory database (the first run may download it). Never point a test at a shared or real database.
- Pure logic (readiness, provenance, recommendation rules, validators) gets unit tests. Anything that reads or writes the database gets integration tests.
- Filter a run by path, for example
bun run test:int modules/strategy.
Code rules
- Files stay at or under 500 lines. Split by responsibility when a file grows.
- Object-oriented, one singleton per concern. A module exports one instance of a class, for example
export const readiness = new Readiness();. Keep pure classes (no I/O, no clock) separate from the ones that touch the database or network, so they are easy to test. - Separation of concerns per module:
routers(paths and guards),controllers(request in, response out),services(logic),models(schemas),jobs(scheduled work),types,data(versioned catalogues). - Routers declare permissions next to each path; controllers never check permissions themselves.
- Errors answer
{ reason }with a stable machine-readable reason; user-facing text lives in the frontend message catalogues (English and Arabic). - Content shown to clients (criteria, guides, glossary) is data in
modules/catalogue/data, with English and Arabic side by side.
Frontend
- Pages live under
app/, feature code underfeatures/(for examplefeatures/Launch,features/Strategy). - UI text comes from
i18n/messages/en.jsonandar.json. Add every new key to both. - Pages are guarded by the same permission the backend route needs.