Skip to main content

Environment setup

What you need installed, how the local database is expected to be wired, and the setup mistakes that produce confusing failures later.

Prerequisites​

ToolVersion
Python3.14+
Node.jsLTS
PostgreSQL16+ with the pgvector extension

Use the pgvector/pgvector:pg16 image rather than stock postgres:16 — plain PostgreSQL lacks the vector extension, and the failure surfaces late, as a migration or query error rather than a connection error.

A pre-configured Dev Container and GitHub Codespace are available and skip the manual steps below.

Install​

make install

This installs the backend in editable mode with dev extras, installs frontend dependencies, and registers pre-commit hooks.

Use make ci-install when you need reproducibility — it runs npm ci against package-lock.json instead of npm install, so the lockfile is respected rather than updated.

Configuration​

Copy .env.example to .env and fill it in. The database can be configured two ways:

  • DATABASE_URL pointing at PostgreSQL, or
  • POSTGRES_HOST, POSTGRES_PORT, POSTGRES_DB, POSTGRES_USER, and POSTGRES_PASSWORD.

.env is git-ignored. It is not copied into new worktrees automatically — see Worktrees below.

The test database​

Backend tests need a live PostgreSQL instance. The project convention is a dedicated container, deliberately not the Postgres you might already run on port 5432:

SettingValue
Containernd-test-pg (postgres:16)
Host port55432
Databasenews_dashboard_test
Rolenews_dashboard

Check it is running:

podman ps --filter name=nd-test-pg

Both DATABASE_URL and TEST_DATABASE_URL in .env must point at localhost:55432/news_dashboard_test as role news_dashboard.

:::warning Pointing at the wrong instance is the most common setup failure If these point at an unrelated native PostgreSQL on 5432, tests do not fail with a connection error. They connect successfully and then fail with InsufficientPrivilege or ownership errors, because the role does not own the objects. If you are seeing permission errors from a database that is clearly reachable, check the port before anything else. :::

Run backend tests with the environment loaded:

source .env && make test

Running the app​

The README covers the full local run. In short: the backend serves the API, and the frontend dev server proxies to it. make build produces the production frontend bundle that the backend serves in container deployments.

Worktrees​

A fresh git worktree has no .venv, no node_modules, and no .env — .env is ignored, so git does not carry it across. Bootstrap before testing or committing:

scripts/bootstrap-worktree.sh

The script copies .env from the main checkout, creates the virtualenv with uv sync --frozen --all-extras (which leaves uv.lock untouched, unlike make install), runs npm ci, and verifies that DATABASE_URL and TEST_DATABASE_URL are actually set — failing loudly rather than letting you discover it during a test run. It is safe to re-run.

Keep .venv/bin on PATH in the worktree so pre-commit hooks find their tools — several hooks invoke .venv/bin/<tool> directly.

Pre-commit hooks​

make install registers the pre-commit stage. Hooks are scoped by file type, so a docs-only commit does not run mypy or ESLint.

To also gate pushes:

pre-commit install --hook-type pre-push

The pre-push stage re-runs linters and type checkers — so a push is blocked even if individual commits skipped hooks — and adds the test suites, which are too slow for every commit.

Do not use git push --no-verify.

Run everything manually with:

pre-commit run --all-files