Skip to content

Local development setup

This is the canonical onboarding guide for a clean checkout of the Sport Analytics Tool.

Component getting-started audit

Each independently developed or operated part of the monorepo has a repository entry point:

Component / location Getting-started README Responsibility
Repository root README.md Overall project setup, architecture boundaries and links to specialist guides.
apps/frontend/ apps/frontend/README.md React/Vite application setup, environment, run, test and build guidance.
apps/backend/ apps/backend/README.md Express API setup, environment, database access, run, test and build guidance.
database/ database/README.md PostgreSQL migrations, development connection, seeding and database testing.
packages/contracts/ packages/contracts/README.md Shared Zod/TypeScript contract build, test and usage boundaries.
docs/ docs/README.md MkDocs prerequisites, local serve/build and deployment guidance.
tests/ tests/README.md Unit, API, database, E2E, accessibility, performance and coverage entry points.
infra/ infra/README.md Infrastructure/deployment boundaries and Azure-specific guidance.
scripts/ scripts/README.md Developer-facing repository scripts, prerequisites and safe usage.
evidence/ evidence/README.md Evidence artefact purpose, locations and integrity rules.

Each listed README is the component's getting-started entry point. Separate GETTING_STARTED.md files are intentionally not created because they would duplicate the same setup instructions.

1. Required software

Tool Project requirement Why it is needed
Git Git 2.x Clone, branch, commit and Pull Request workflow.
Node.js 20.19+ (20.x) or 22.12+ Backend runtime and all JavaScript/TypeScript tooling. Vite 7 sets this floor; Azure and hosted CI use Node.js 22 LTS.
npm 10 or later Workspace installation and repository scripts.
Python 3.10 or later MkDocs documentation and the Cricsheet downloader.
Docker Docker Desktop or compatible Docker runtime with Compose Optional explicit PostgreSQL integration-test workflow.

Optional:

  • the Supabase CLI/local Supabase stack, only if the team deliberately chooses to use it;
  • an editor/IDE of your choice. The repository does not require VS Code, Qoder or any other editor.

Docker is not required to run the application, npm run test, or npm run check. It is required only for the explicit npm run test:database:local alternative.

Record the exact versions used during onboarding:

git --version
node --version
npm --version
python --version

On Windows, py --version may be used if python is not on PATH.

Windows PowerShell: Commands in this guide use portable npm/npx syntax. If PowerShell attempts to run npm.ps1 or npx.ps1 and blocks it, use npm.cmd or npx.cmd instead. For this repository's Docker database verification, use npm.cmd run test:database:local.

2. Clean clone and reproducible install

Clone the repository and install exactly the dependency graph recorded in package-lock.json.

git clone https://sdp.ms.wits.ac.za/git-push-pray/Sport-Analytics-Tool.git
cd Sport-Analytics-Tool
npm ci

When verifying an unmerged Pull Request from a clean clone, fetch the remote and switch to the branch named by that Pull Request before following the rest of this guide:

git fetch origin
git switch <pull-request-branch>

Use npm ci rather than npm install for clean-clone verification. npm ci fails if the lock file and package manifests do not agree, which is useful evidence that the repository can be installed reproducibly.

3. Create local environment files

Real .env files are ignored and must never be committed.

Windows PowerShell

Copy-Item apps/backend/.env.example apps/backend/.env
Copy-Item apps/frontend/.env.example apps/frontend/.env

macOS / Linux / Git Bash

cp apps/backend/.env.example apps/backend/.env
cp apps/frontend/.env.example apps/frontend/.env

Populate the required values using the shared development configuration. See Environment Variables for the authoritative variable list.

4. Backend database connection

The application database is hosted on PostgreSQL through Supabase. Use the session pooler on port 5432. ADR-003 records why the direct connection and transaction-mode pooler were rejected for this project.

A typical development value has the form:

DATABASE_URL=postgresql://postgres.<project-ref>:<password>@<pooler-host>:5432/postgres

Use the current connection string supplied through the team's secret-sharing process rather than copying a host from an old document. Percent-encode reserved URL characters in the password.

TLS certificate verification uses the committed authority certificate:

apps/backend/certs/supabase-ca.crt

Do not disable certificate verification to bypass a connection error.

Verify the configured database connection:

npm run db:check --workspace=@sport-analytics/backend

A successful run reports the database name and server version and confirms prepared-statement support.

5. Supabase Auth configuration

The frontend needs:

VITE_SUPABASE_URL=https://your-project-ref.supabase.co
VITE_SUPABASE_PUBLISHABLE_KEY=your-supabase-publishable-key

The backend needs:

SUPABASE_URL=https://your-project-ref.supabase.co
SUPABASE_PUBLISHABLE_KEY=your-supabase-publishable-key
# Optional locally; required to exercise account deletion.
# SUPABASE_SECRET_KEY=your-server-only-supabase-secret-key

The URL and publishable key are public project values. The optional secret key is backend-only and must remain in the ignored environment file or deployment secret store. Never commit database passwords, OAuth client secrets, user access tokens, Supabase secret keys or legacy service_role keys.

Google OAuth is configured in the Google and Supabase dashboards. Its client secret remains outside the repository.

6. Build shared contracts

The frontend and backend both import @sport-analytics/contracts.

The complete root check builds contracts before repository-wide type-checking, but when running an isolated workspace check on a fresh installation it is safe to build contracts first:

npm run build --workspace=@sport-analytics/contracts

7. Run the applications

Start the backend in one terminal:

npm run dev:backend

Start the frontend in a second terminal:

npm run dev:frontend

The root dispatcher also supports npm run dev backend and npm run dev frontend. Arguments after -- are forwarded to the selected application, such as npm run dev frontend -- --host 0.0.0.0.

Default local endpoints:

  • frontend: http://localhost:5173
  • backend health: http://localhost:3000/api/v1/health
  • current user profile: http://localhost:3000/api/v1/auth/me

A basic local smoke test is successful when the frontend loads and the backend health endpoint responds without a server error.

8. Repository checks

The normal pre-Pull-Request gate is:

npm run check

It currently runs, in order:

  1. required-file structure check;
  2. Prettier formatting check;
  3. ESLint;
  4. shared-contract build;
  5. TypeScript type-checking;
  6. unit/frontend/API/contract/deployment-helper tests;
  7. OpenAPI linting; and
  8. production builds for contracts, backend and frontend.

Useful individual commands:

npm run structure:check
npm run format:check
npm run lint
npm run typecheck
npm run test
npm run test:backend
npm run openapi:lint
npm run build

npm run test:backend runs all backend unit, API, and PostgreSQL integration tests with the default disposable database runtime. Use npm run test:backend:local to run the same complete backend workflow with Docker. The normal npm run test and npm run check commands remain database-independent.

The extended CI/testing suite also includes Playwright browser/accessibility tests and coverage generation. See Testing.

9. Local PostgreSQL integration tests

Database integration tests exercise the application against a real PostgreSQL database. The default npm run test:database command provisions a disposable PostgreSQL 16 cluster without Docker. The steps below describe the optional Docker Compose workflow, which is useful for parity with CI.

From the repository root, run the default workflow with:

npm run test:database

The runner chooses an available loopback port, applies migrations and deterministic seed data, runs the database suite, and removes its temporary cluster after the tests finish.

Optional Docker workflow

Start Docker Desktop before using npm run test:database:local.

On Windows:

  1. Open Docker Desktop from the Start menu.
  2. Wait until Docker Desktop reports that the Docker engine is running.
  3. Open PowerShell in the repository and verify:
docker --version
docker compose version
docker info

On macOS, start Docker Desktop from Applications and wait for the engine to become available before running the same verification commands.

A different Docker-compatible runtime may be used if it provides the docker compose command used by the repository.

Run the database integration suite

From the repository root:

npm run test:database:local

The command automatically:

  1. starts the repository-managed PostgreSQL 16 test container;
  2. waits until PostgreSQL is healthy;
  3. supplies NODE_ENV=test;
  4. supplies the local DATABASE_URL_TEST;
  5. resets the test schema;
  6. applies all migrations;
  7. loads the deterministic test seed; and
  8. runs the complete PostgreSQL integration suite.

No manual NODE_ENV change, .env.test file, hosted test database, Supabase test project or shared database password is required for this normal workflow.

The local test database is:

postgresql://test_user:test_password@127.0.0.1:55432/sport_analytics_test

These are repository-defined test-only local credentials, not application secrets. Port 55432 is intentionally different from PostgreSQL's common 5432 port to reduce conflicts with an existing local installation.

Development database versus test database

DATABASE_URL is the normal application development database connection. In the team's current configuration it points to the Supabase-hosted PostgreSQL development database.

DATABASE_URL_TEST is used only by PostgreSQL integration tests and destructive test-database commands.

The disposable Docker workflow supplies DATABASE_URL_TEST itself. It does not replace, reset or modify DATABASE_URL.

The database safety guard requires NODE_ENV=test, requires the target database name to identify it as a test database, and rejects a test connection that resolves to the same PostgreSQL host, port and database as the configured development connection.

Statement execution bound

DATABASE_STATEMENT_TIMEOUT_MS bounds how long one PostgreSQL statement may run before the server cancels it. It is optional: the backend defaults to 15000 milliseconds and the asynchronous worker declares the same variable in its own configuration with a default of 60000. Both accept 1000 to 120000 milliseconds, and a value outside that range fails startup with the other environment validation. It is a bound rather than a credential, so it belongs in .env and in deployment configuration as a plain value.

The bound applies only to the application pools. Committed migrations, the operator scripts under apps/backend/scripts/, and the PostgreSQL integration tests each open their own connections and remain unbounded, because a corpus import or an index build legitimately runs far longer than any application statement.

A cancelled statement returns 503 with the error code DATABASE_STATEMENT_TIMEOUT. The condition is temporary and the request may be retried. The full contract is recorded in database access.

Stop or remove the local test database

The container may remain running between test runs. Each local database-test run resets the schema, so tests do not depend on data left by the previous run.

Stop the container while keeping its disposable volume:

docker compose -f compose.test.yml down

Stop it and remove all local test-database data:

docker compose -f compose.test.yml down --volumes

The next npm run test:database:local command recreates the environment automatically.

Using a different test database

A manually managed database is another alternative to the default embedded and explicit Docker workflows.

A developer who already has a dedicated PostgreSQL test database may supply a safe DATABASE_URL_TEST and run:

npm run db:test:reset --workspace=@sport-analytics/backend
npm run db:test:migrate --workspace=@sport-analytics/backend
npm run db:test:seed --workspace=@sport-analytics/backend
npm run test:database

The supported npm commands set NODE_ENV=test automatically.

See apps/backend/.env.test.example for the expected test configuration shape. Never use the application development or production database for this workflow.

10. Documentation site

Create a Python virtual environment and install the documentation requirements.

Windows PowerShell

python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -r requirements-docs.txt
python -m mkdocs serve

macOS / Linux / Git Bash

python -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements-docs.txt
python -m mkdocs serve

Preview URL:

http://127.0.0.1:8000

Before a documentation Pull Request, also run:

python -m mkdocs build --strict

The generated site/ directory is build output and must not be committed as part of normal documentation changes.

11. Optional Cricsheet data download

Historical T20/IT20 source data is acquired with the committed Python script:

python scripts/download_cricsheet_t20.py

On Windows, py scripts/download_cricsheet_t20.py is also valid.

The downloader uses the Python standard library and requires internet access. Downloaded archives, extracted match data and generated manifests are ignored by Git. See Cricsheet T20 data.

12. Importing the dataset

Once the source data has been downloaded, it is imported with:

npm run db:import --workspace=@sport-analytics/backend -- ../../data/cricsheet/matches

The path is relative to apps/backend, because npm runs a workspace script from that directory.

Options

Flag Effect
--dry-run Reports how many match files would be imported and writes nothing. Reads every file, so it takes about a minute over the full corpus.
--limit N Imports at most N matches, in the same stable order. Useful for a first run against a new database.

What the importer does

Each match is ingested in its own transaction. A file that cannot be ingested rolls back on its own and the run continues; its reason is printed as it happens and summarised at the end, so a rejected file is never silently discarded.

Ingestion is idempotent. A match already present is recognised and skipped, so an interrupted run is resumed by issuing the same command again. Re-scanning matches already imported is fast.

A live progress line reports the count, the rate and an estimate of the time remaining. On completion the importer prints the number of files considered, imported, already present and rejected, and the resulting database totals.

Expected duration

The full corpus of 13,953 matches takes approximately twelve hours at roughly 0.3 matches per second. Most of that is round-trip latency to the hosted database rather than work; see issue #105.

A machine running the import must be prevented from sleeping, or the run stops silently while the clock continues. On Windows:

powercfg /change standby-timeout-ac 0
powercfg /change hibernate-timeout-ac 0

Restore these afterwards.

Before importing to a shared database

The importer writes to whatever DATABASE_URL points at. Before a full import against the shared development database, confirm with the team that the storage and the scope are agreed: the corpus is approximately 3.2 million deliveries.

For local development the smaller deterministic seed is usually what you want instead:

npm run db:seed --workspace=@sport-analytics/backend

That loads four fixtures chosen to exercise the awkward cases, and is described in database/seeds/README.md.

13. Optional local Supabase stack

A local Supabase stack is not required for normal onboarding. If the team deliberately chooses to use it, the Supabase CLI requires a Docker-compatible runtime and the work must be coordinated with the database workstream. Do not initialize or reset a shared environment without team agreement.

14. Common setup problems

npm ci fails because Node/npm is too old

Check:

node --version
npm --version

Use Node.js 20.19+ (20.x) or Node.js 22.12+ and npm 10+.

PowerShell blocks virtual-environment activation

You may run MkDocs without activating the environment by calling the environment's Python executable directly, or use a shell configuration permitted by your machine policy. Do not weaken organisation security controls merely to follow this guide.

Cannot find module '@sport-analytics/contracts'

Build the contracts workspace:

npm run build --workspace=@sport-analytics/contracts

The root npm run check already performs this build before type-checking.

Frontend reports missing Supabase variables

Populate VITE_SUPABASE_URL and VITE_SUPABASE_PUBLISHABLE_KEY in apps/frontend/.env.

Backend fails with invalid environment configuration

Populate SUPABASE_URL and SUPABASE_PUBLISHABLE_KEY in apps/backend/.env. The backend validates these at startup.

DATABASE_URL is not configured

Populate the current hosted PostgreSQL session-pooler connection string in apps/backend/.env.

Database hostname/connection fails

Use the current session pooler connection string rather than the direct database host. Do not copy a stale region-specific host from old notes.

self-signed certificate in certificate chain

Confirm that apps/backend/certs/supabase-ca.crt exists and that the documented migration/connection command is being used. Do not disable TLS verification.

Browser requests fail with CORS errors

The backend currently reads CORS_ORIGINS, not CORS_ALLOWED_ORIGINS. For local development, the default is http://localhost:5173.

npm run check reports formatting failures

Run:

npm run format
npm run format:check

Review the resulting diff before committing. Formatting should not be used to hide unrelated changes.

Docker command is not found

If PowerShell reports that docker is not recognised as a command, Docker Desktop is either not installed or is not yet available on PATH.

Install Docker Desktop using the official Docker Desktop installation guide: https://docs.docker.com/desktop/

After installation, open a new terminal and verify:

docker --version
docker compose version

If Docker Desktop is already installed, start it and wait until the Docker engine is running.

Docker is required only for the explicit npm run test:database:local workflow. The default npm run test:database workflow does not require Docker.

Docker cannot connect to the engine

Start Docker Desktop and wait until the Docker engine is running. Then verify:

docker info

Retry npm run test:database:local only after docker info succeeds.

Port 55432 is already in use

The repository deliberately uses port 55432 rather than the usual PostgreSQL port 5432. If another process already uses 55432, stop that process before running the local database workflow. Do not change the test workflow to point at an unknown existing database.

Database test safety check fails

Do not bypass the safety check. Confirm that the command is using a dedicated test database and that DATABASE_URL_TEST does not resolve to the same PostgreSQL database as DATABASE_URL.

For the Docker workflow, do not manually set DATABASE_URL_TEST; run:

npm run test:database:local

Playwright cannot find a browser

Playwright requires its managed Chromium browser for the local end-to-end suite. On a fresh development environment, or after a Playwright upgrade, install it with:

npx playwright install chromium

On Windows PowerShell, use npx.cmd playwright install chromium if script execution blocks npx.

Then rerun:

npm run test:e2e

CI installs Chromium and its Linux dependencies with npx playwright install --with-deps chromium.

MkDocs command is not found

Install documentation requirements inside the active virtual environment:

python -m pip install -r requirements-docs.txt

Then prefer python -m mkdocs ... so the command uses the intended Python environment.

15. Onboarding verification record

Issue #12 requires a second team member to follow this guide from a clean clone. The verifier must record:

  • name;
  • date;
  • operating system;
  • shell/terminal;
  • editor/IDE used, if any;
  • Git, Node.js, npm and Python versions;
  • whether npm ci succeeded;
  • whether environment setup was understandable;
  • whether frontend/backend start commands worked;
  • whether npm run check succeeded;
  • whether the MkDocs strict build succeeded;
  • any unclear step or failure; and
  • the final result after fixes.

The repository evidence template is evidence/validation/issue-12-onboarding-verification.md.

AI Declaration

The preceding document was reviewed, reorganised and expanded with the assistance of ChatGPT-Web[GPT-5.6 Sol].