Skip to content

Development setup

Terminal window
cp .env.example .env # then set SECRET_KEY and DATA_ENCRYPTION_KEY
docker compose up --build

The frontend is on http://localhost:5173, the API on http://localhost:8000, and PostgreSQL on port 5432. Source is mounted, so changes reload. The backend migrates the database when it starts.

To generate the encryption key:

Terminal window
openssl rand -base64 32 | tr '+/' '-_'

This creates a demo organization, with an exercise ready to conduct:

Terminal window
docker compose exec backend python -m scripts.seed_demo

--reset rebuilds it, --codes prints the current two-factor codes, and --extras adds polls, rooms and an instance administrator.

You need Python 3.12, Node.js 22 and PostgreSQL 16.

Terminal window
cd backend
python3.12 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt -r requirements-dev.txt
alembic upgrade head
uvicorn app.main:app --reload
Terminal window
cd frontend
npm install
npm run dev

These are what CI runs.

backend/
ruff check . && ruff format --check .
alembic upgrade head && alembic check
pytest
# frontend/
npm run lint && npm run format:check && npm run build && npm test
# docs/site/
npm run build

Run one test at a time against that database: concurrent runs deadlock.

Browser tests run on their own stack:

Terminal window
cd frontend
npm run e2e
npm run e2e:down

After changing a model, generate a migration. CI fails if a model changed without one.

Terminal window
docker compose exec backend alembic revision --autogenerate -m "message"

A changed route needs the API description regenerated, or CI fails:

Terminal window
docker compose exec -T backend python -m scripts.export_openapi > docs/site/schemas/openapi.json

Every operation needs a docstring, which becomes its description in the API reference. A new route must also be classified as PUBLIC or INTERNAL_ONLY in backend/app/api/exposure.py.