Run the platform locally & contribute
This is the from-zero guide to running the EM Platform on your own machine and contributing to it. It's aimed at EMs who want to try changes locally and collaborate on development. Everything runs on a fictional demo world (Acme Robotics) - no real data.
1What you need
A handful of tools have to be on your machine before anything else. Get these in place first and the rest of the guide runs top to bottom.
- Python 3.12 - the routines and data-access libraries run on it.
- Node 22 - the web app.
- Docker Desktop, running - the local Supabase stack runs inside it.
- The Supabase CLI - see
https://supabase.com/docs/guides/cli. - git - to clone and contribute.
On macOS, Homebrew makes these easy - brew install python@3.12 node supabase/tap/supabase, and Docker Desktop from docker.com. Verify each one:
python3.12 --version
node -v
docker ps
supabase --version
2Get the code
Clone the repository and move into it:
git clone https://github.com/Qualitara/engineering-management-platform.git
cd engineering-management-platform
3Install dependencies
Two dependency trees: the Python side and the web app.
python3.12 -m venv .venv && .venv/bin/pip install -e ".[dev]"
cd web && npm ci && cd ..
The Python virtualenv holds the em_db/em_routines libs plus the dev/test tools; npm ci installs the web app.
4Start the local database
supabase start boots a local Supabase/Postgres in Docker and applies every migration plus the fictional demo seeds automatically. Then seed the demo login users:
supabase start
supabase status -o env > /tmp/sb.env && . /tmp/sb.env
( cd web && SUPABASE_URL="$API_URL" SUPABASE_SERVICE_ROLE_KEY="$SERVICE_ROLE_KEY" node scripts/seed-auth-users.mjs )
Local passwords are all localdev-pw. supabase stop shuts it down; supabase db reset wipes and re-applies (re-run the auth-user seed after a reset).
5Run the app
cd web && npm run env:local && npm run dev
Open http://localhost:3000 and sign in as the demo EM alex.rivera@acme-robotics.example / localdev-pw (owns the Acme Robotics account). You're now on Home. See the User guide for a tour of every screen.
6Switching local & prod
Two independent switches, one per layer - the web app and the Python routines each point at local or prod on their own.
The web app
| Command | What it does |
|---|---|
npm run env:local | Point at local Supabase (uses committed web/.env.example). |
npm run env:prod | Point at prod (uses your web/.env.prod.local). |
npm run dev | Run against whatever .env.local holds. |
npm run dev:prod | Switch to prod then run. |
For prod, create web/.env.prod.local once from web/.env.production.example with your hosted Supabase URL and anon key. It's gitignored - never committed.
The Python routines / CLI
One env var: EM_TARGET=local (default, local Supabase) or EM_TARGET=prod (hosted; needs EM_DB_DSN_PROD set).
EM_ALLOW_PROD_WRITES=1 and print a loud banner, so EM_TARGET=prod alone is safe read-only - "point at prod to look."
7Run the checks
Validate your change before a PR - these are the same gates CI runs.
# Python
.venv/bin/python -m pytest -q -m "not integration"
.venv/bin/ruff check lib scripts tests
# Web
cd web && npm run lint && npx tsc --noEmit && npm run test && npm run build
# DB (pgTAP) + integration - need the local stack up
supabase test db
.venv/bin/python -m pytest -q -m integration
# End-to-end (Playwright)
cd web && npm run e2e
8Contributing
Work on a branch, open a PR, get one review, and merge to main once checks are green - main is protected (no direct or force pushes). Never commit secrets or real client/personnel data (a secret-scan/gitleaks gate enforces this).
Full details in CONTRIBUTING.md; security policy in SECURITY.md.
9Troubleshooting
- Docker must be running before
supabase start. - Port :3000 is busy - another
next devis running. Stop it or use another port. - Stale UI after a big change -
npm run dev:clean(wipes.next). - Fresh DB with no data showing - re-run the auth-user seed (step 4).
- On macOS, prefer
npm run dev(not the DB-resetting local bootstrap) unless you intend to reset. - In a git worktree, Turbopack can reject the
node_modulesjunction - start withnext dev --webpack.
10Where next
- The User guide for the screen-by-screen tour.
CONTRIBUTING.mdfor the PR flow and gates.- The Architecture page for the data model.