# Development Environment — Agent Setup Instructions
Companion to `SPEC.md` (webmail-client-spec). This file tells the implementing agent exactly how to build and verify the development environment **before writing any application code**. Approach: **conda for the toolchain** (Python 3.11, Node 20), **Docker for stateful services** (PostgreSQL, Redis, Meilisearch, test mail servers) — identical images in dev and CI.
Rules:
- Do not install anything into the host system Python/apt beyond verifying prerequisites. All language tooling lives in the conda env; all services live in containers.
- Do not substitute versions or images. If something is unavailable, stop and record it in `docs/open-questions.md`.
- Every step below has a verification command. A step is not done until its verification passes.
Create `docker/docker-compose.yml`. Host ports are deliberately **non-default** (5433/6380) so they never collide with anything already running on the host — do not change them.
docker compose -f docker/docker-compose.yml up -d postgres redis meilisearch
docker compose -f docker/docker-compose.yml ps # all must be "healthy"
```
Greenmail is started on demand by integration tests and for manual testing (`--profile` it later if noise bothers; keep the definition here).
## 4. Environment file
Create `.env.dev` at repo root (add to `.gitignore`; commit a `.env.example` copy with the same content — these are dev-only credentials, still never reuse them anywhere):
cd frontend && npx tsc --noEmit && npm run lint && npx vitest run
```
Integration smoke (once M0 sync exists): start greenmail, configure account `dev@dev.local` / `devpass` against `127.0.0.1:3143` (plain, dev-only), send a message into Greenmail via SMTP 3025, assert it appears via the API within 10 s.
## 7. Day-to-day commands (put these in a root `Makefile`)
```make
up:## start services
docker compose -f docker/docker-compose.yml up -d postgres redis meilisearch
down:## stop services (data kept)
docker compose -f docker/docker-compose.yml down
reset-db:## DESTRUCTIVE: wipe db + search + blobs, re-migrate
docker compose -f docker/docker-compose.yml down -v
rm -rf var/blobs && mkdir -p var/blobs
docker compose -f docker/docker-compose.yml up -d --wait postgres redis meilisearch
cd backend && pytest -q &&cd ../frontend && npx vitest run
mail-test:## start throwaway IMAP/SMTP server
docker compose -f docker/docker-compose.yml up -d greenmail
```
## 8. CI parity
`docker/docker-compose.ci.yml` extends the same file: adds Dovecot (`dovecot/dovecot:2.3`) for provider-compat tests and runs Playwright against a production build. CI must use the same image tags as this file — when bumping a service version, bump it in exactly one place (this compose file) and update SPEC §3 in the same commit.
## 9. Troubleshooting
- **Port already in use** — something on the host occupies 5433/6380/7700/8000/5173. Do not change this file's ports without recording it in `docs/open-questions.md`; prefer stopping the conflicting service.
- **`alembic upgrade` connection refused** — services not healthy yet; `docker compose ... up -d --wait`.
- **mypy/ruff not found** — you're outside the conda env; `conda activate webmail`.
- **Frontend can't reach WS** — check the Vite proxy `ws: true` and that the session cookie is set (login first).
- **Blob permission errors** — `BLOB_ROOT` must be inside the repo (`./var/blobs`), never a system path.
## 10. Testing
Use: test@imaginary-pixels.com account for testing. Login: test@imaginary-pixels.com, password: webmail!@A