TEA PlatformTEA Docs
Technical DocumentationContributing

Code style

Follow the repository's TypeScript, data access, logging and test conventions.

Edit on GitHub

Use the repository's checks and existing module patterns when changing code. package.json defines the commands, while biome.json and the Ultracite configuration define formatting and lint rules.

Checks

Run the named scripts before submitting a change:

pnpm lint
pnpm typecheck
pnpm test:unit
pnpm test:integration

pnpm format applies the Ultracite fixes. The integration suite needs its PostgreSQL test database.

Outside CI, pnpm test:e2e runs prisma migrate reset --force and reseeds whatever database DATABASE_URL names. Run it only against a disposable database after checking that URL.

The pull request guide explains the local hooks and CI checks.

TypeScript and imports

Keep types close to the domain code that owns them. Reusable types live in types/, and request validation schemas live in lib/schemas/. Prisma generates its client into src/generated/prisma; import generated types from @/src/generated/prisma where needed. Prefer a precise type or unknown with a guard over an unchecked any.

Use the @/ alias for imports from the repository root. Follow the import order enforced by the formatter rather than arranging groups by hand. React components that use browser state or effects carry the "use client" directive; pages can remain server components when they do not need those browser APIs. In the App Router, dynamic route params may be a promise and are awaited in the current case page.

Data access and expected failures

Keep application Prisma access in services and lib/prisma.ts. Never add direct Prisma access to routes, actions, components or hooks. API handlers and server actions should authenticate callers, validate input and delegate domain operations to lib/services/. Importing Prisma into a new action simply to bypass a service also bypasses the established permission and validation paths. lib/prisma.ts owns the configured client, including element validation on writes.

Services commonly use ServiceResult from types/service.ts for expected success or failure. Follow the result shape of the service you are extending. lib/schemas/ holds the Zod schemas used at boundaries. For an element change, check both the schema and the service rule; the database enum alone does not express every allowed combination.

Names, wording and logging

Most source files use kebab case, exported React components use PascalCase, and functions and values use camelCase. Match the neighbouring code. Use British spelling in product text where external API names do not dictate a spelling. Follow the existing Tailwind CSS v4 conventions for styling.

Use the structured logger in lib/logger.ts for application events and errors. A child logger can bind a component name. Supply useful fields without placing secrets or raw credentials in a log entry. Keep comments for a rule, trade-off or surprising behaviour that the code alone does not explain.

For changes to documented API routes, run pnpm docs:generate and include the updated public/openapi.json; CI checks for drift.

Tests

Tests are not all beside the file they cover. Component and service tests often sit in a nearby __tests__/ directory; broader integration tests are under src/__tests__/integration/, and browser tests are under e2e/. Add a test at the level that exercises the behaviour you changed. The CI workflow runs unit, integration and Playwright suites, and merges the first two suites' coverage for its structural-quality check.

MIT 2026 © Alan Turing InstituteTrustworthy and Ethical Assurance Platform