The HomeTest Service is a service that provides a central hub for ordering home tests for NHS patients.
This repository contains the full stack, including the frontend, backend lambdas, and infrastructure-as-code.
-
Clone the repository
git clone https://github.com/NHSDigital/hometest-service.git cd hometest-service -
Install mise (recommended package manager)
curl https://mise.run | sh echo 'eval "$(mise activate zsh)"' >> ~/.zshrc # or ~/.bashrc for bash source ~/.zshrc
-
Install project dependencies using mise
mise install # Installs Node.js and Terraform versions from .mise.toml -
Install dependencies for the root, lambdas, and tests, start the local development environment
pnpm install pnpm run start
The following software packages, or their equivalents, are expected to be installed and configured:
- Docker
- Node v24 LTS,
- A tool version manager:
- nvm version manager. This repository contains a
.nvmrcfile, to make the runtime version consistent. - mise (reads
.mise.toml)
- nvm version manager. This repository contains a
- Terraform. The version is specified in [.tool-versions].
- Local development uses Terraform to deploy to LocalStack.
Mise can read the .nvmrc file by following the instructions.
Important commands:
pre-commit install # Enables the git hook to run the checks locally on commit
mise run pre-commit # Run the pre-commit task defined in .mise.tomlBefore starting, ensure the following files are present in
local-environment/infra/resources/secrets/.
Warning
These files contain sensitive credentials. They must never be committed to git or shared in plaintext. Obtain them only through a team-approved secure channel.
nhs-login-private-key.pem— NHS Login private keyos-places-creds.json— OS Places API credentials
To spin up the entire local environment (LocalStack, Postgres, and the Next.js Frontend):
pnpm startThis command:
- Starts the Docker containers defined in
local-environment/docker-compose.yml. - Bootstraps LocalStack via Terraform, and deploys the lambdas to it from the
/lambdasdirectory. - Starts the frontend on http://localhost:3000.
To stop the environment:
pnpm run stopAfter running pnpm start, use targeted commands instead of restarting everything:
-
Lambda code changes (build/package/deploy lambdas to LocalStack):
pnpm run local:deploy
-
Database schema or seed changes (rerun DB migration container, including goose migrations):
pnpm run local:service:db:migrate
-
Terraform infrastructure changes (apply infra updates to LocalStack without restarting containers):
pnpm run local:terraform:apply
This expects the backend containers, including LocalStack, to already be running. If they are not, start them first:
pnpm run local:backend:start
To switch local integrations between WireMock and real upstreams, pass Terraform variables when applying - some examples below.
To only use WireMock everywhere (default mode - only needed to switch over):
TF_VAR_local_service_mode=wiremock pnpm run local:terraform:apply # this is the default mode, only needed to switch overTo not use WireMock anywhere (real downstream APIs):
TF_VAR_local_service_mode=real pnpm run local:terraform:apply
To use WireMock except for specific services, pass only the overrides you need:
TF_VAR_local_service_mode=wiremock \ TF_VAR_local_supplier_service_url_override=https://supplier.example.com \ TF_VAR_local_use_ui_auth_url_override=https://auth.sandpit.signin.nhs.uk \ TF_VAR_local_postcode_lookup_base_url_override=https://api.os.uk/search/places/v1 \ pnpm run local:terraform:apply # pnpm run local:frontend:restart - if overriding UI authIf you change UI-facing auth settings, restart the frontend so it picks up the updated
ui/.env.localvalues:pnpm run local:frontend:restart
-
Restart backend containers only (Postgres, LocalStack, WireMock, db-migrate):
pnpm run local:compose -- stop postgres-db localstack wiremock pnpm run local:backend:start
-
Restart frontend only:
pnpm run local:frontend:restart
-
Start/stop backend only:
pnpm run local:backend:start pnpm run local:compose -- stop postgres-db localstack wiremock
-
Start/stop frontend only:
pnpm run local:frontend:start pnpm run local:compose -- stop ui
-
Start/stop specified lambda
LAMBDA={lambda_name} pnpm run local:service:lambda:enable LAMBDA={lambda_name} pnpm run local:service:lambda:disable
The frontend is located in the /ui directory. It is a React Router SPA built with Next.js as
a static-export shell — not a standard Next.js application.
- cd to
/uidirectory. - Run
pnpm install. - Run
pnpm run dev.
- When creating a new page, use the PageLayout component found in
/ui/src/components. - To create a new route, create a directory with the name of your route in
/ui/src/app, and add apage.tsxfile within. - All route/page components live under
ui/src/routes/and are registered inui/src/app.tsx(the React Router config). - Layout components live under
ui/src/layouts/. Use these (e.g.FormPageLayout,JourneyLayout) when building new pages. - Use components from
nhsuk-react-componentsfor standard NHS UI elements; use Tailwind utility classes for custom spacing and layout. - Never use
next/link,next/navigation, or Next.js API routes — all navigation goes through React Router and all backend logic lives in Lambda functions.
Local infrastructure is managed via Terraform in the /local-environment/infra directory.
We use Playwright for end-to-end testing, located in the /tests
directory.
The service follows a serverless-first architecture on AWS:
- Frontend: Next.js (React)
- Backend: AWS Lambda (Node.js/TypeScript)
- Database: PostgreSQL (managed via Docker locally)
- Infrastructure: Terraform
System diagrams and design documents can be found in the /docs and /architecture folders.
View the contributing guidelines.
The LICENCE.md file will need to be updated with the correct year and owner
Unless stated otherwise, the codebase is released under the MIT License. This covers both the codebase and any sample code in the documentation.
Any HTML or Markdown documentation is © Crown Copyright and available under the terms of the Open Government Licence v3.0.