# Development guide > Set up the Firewatch toolchain and run the product, tests, and API generation locally. This is the machine-readable version of this Firewatch documentation page. ## Toolchain Install the following tools on the development host: - .NET 10 SDK; - Node.js 24 or another version satisfying the root `engines` field, with the npm version recorded by `packageManager`; - Docker Engine with the Compose v2 plugin; - Git; and - optionally `psql` for database inspection. ## Initial setup From the repository root, run the reproducible setup command: ```bash dotnet tool restore && dotnet restore Firewatch.sln && npm ci ``` Re-run the setup command whenever the lock files, tool manifest, or project graph changes. ## Run the complete stack ```bash docker compose up --build ``` Open . The API is also published at . Compose waits for PostgreSQL readiness, starts the API and its local migration step, waits for API readiness, then starts the independent worker and web processes. The base stack bootstraps the first self-hosted administrator without an email round trip and leaves email delivery disabled. To test verification and SMTP delivery with Mailpit at , start the explicit development override: ```bash docker compose -f docker-compose.yml -f docker-compose.mailpit.yml up --build ``` Useful commands: ```bash docker compose ps docker compose logs --follow api worker docker compose down ``` `docker compose down` preserves the PostgreSQL named volume. Use `docker compose down --volumes` only when you intentionally want to erase local Firewatch data. ## Run processes directly Keep infrastructure in Docker: ```bash docker compose -f docker-compose.yml -f docker-compose.mailpit.yml up -d postgres mailpit ``` In one terminal, configure a host-reachable database and run the API: ```bash export ConnectionStrings__Firewatch='Host=localhost;Port=5432;Database=firewatch;Username=firewatch;Password=change-me-for-non-local-use' export Database__MigrateOnStartup=true export Auth__PublicBaseUrl=http://localhost:5173 export Email__Enabled=true export Email__Smtp__Host=localhost export Email__Smtp__Port=1025 export Email__Smtp__Security=None dotnet run --project src/Firewatch.Api ``` In a second terminal, export the same connection string, select the local queue provider, then run: ```bash export ConnectionStrings__Firewatch='Host=localhost;Port=5432;Database=firewatch;Username=firewatch;Password=change-me-for-non-local-use' export Queueing__Provider=Postgres dotnet run --project src/Firewatch.Worker ``` In a third terminal, start Vite: ```bash npm run dev ``` Open for the direct Vite workflow. Vite is the only direct development server. The React application still uses the HTTP API through its same-origin development proxy; it never imports backend implementation code. `VITE_DEV_API_PROXY_TARGET` changes the proxy target from its `http://localhost:8080` default while preserving same-origin browser calls. Set `VITE_API_BASE_URL` only when intentionally bypassing that proxy for a different public API origin. ## Exercise the smoke flow With the API and worker running: ```bash curl --include \ --request POST \ --header 'Content-Type: application/json' \ --data '{"name":"documentation-smoke-test"}' \ http://localhost:8080/api/v1/system/test-jobs ``` The response is `202 Accepted` and includes an identifier and status URL. Replace `` below with the returned identifier: ```bash curl http://localhost:8080/api/v1/system/test-jobs/ docker compose logs worker ``` The status eventually becomes `Completed`, and the worker log includes the stable message identifier. Retrying delivery does not create a second completion. ## Tests and quality checks Run backend checks: ```bash dotnet format Firewatch.sln --verify-no-changes --no-restore dotnet build Firewatch.sln --configuration Release dotnet test Firewatch.sln --configuration Release --no-build ``` Integration tests use Testcontainers with real PostgreSQL behavior. Docker must be running; SQLite is intentionally not used as a substitute. Run frontend checks: ```bash npm run frontend:check ``` Or run the constituent commands: ```bash npm run lint npm run format:check npm run typecheck npm test npm run build npm run api:check ``` ## OpenAPI and TypeScript client generation The committed `openapi/firewatch.v1.json` document is the language-neutral API contract. After changing API routes or contracts, first regenerate the document from the ASP.NET Core project using the repository's deterministic OpenAPI generation command, then generate the TypeScript types: ```bash dotnet build src/Firewatch.Api/Firewatch.Api.csproj --configuration Release npm run api:generate npm run api:check ``` `openapi-typescript` is used because it is maintained, produces small static types without a proprietary runtime, and composes with the maintained `openapi-fetch` client. Generated files under `packages/api-client/src/generated` must not be manually edited. The handwritten package wrapper is the stable import surface consumed by `apps/web`. `npm run api:check` regenerates to a temporary file and compares bytes, so CI fails when the checked-in client does not match the checked-in OpenAPI document. Both files must be committed with an API change. A future iOS repository can feed the same OpenAPI file to Apple's Swift OpenAPI Generator (with versions pinned by that repository). No iOS application or Swift-specific API is created here. ## EF Core migrations Restore the pinned local `dotnet-ef` tool before migration work: The design-time fallback matches the unchanged `.env.example` database. Export `ConnectionStrings__Firewatch` first when using different credentials or a different database. ```bash dotnet tool restore ``` Create a migration after changing the EF model: ```bash dotnet ef migrations add \ --project src/Firewatch.Infrastructure \ --startup-project src/Firewatch.Api \ --output-dir Persistence/Migrations ``` Apply it to the configured database: ```bash dotnet ef database update \ --project src/Firewatch.Infrastructure \ --startup-project src/Firewatch.Api ``` Verify that the model and migration snapshot agree, as backend CI does: ```bash dotnet ef migrations has-pending-model-changes \ --project src/Firewatch.Infrastructure \ --startup-project src/Firewatch.Api ``` Containerized deployments should use the API image's one-off migration mode: ```bash docker compose run --rm api --migrate ``` Do not enable automatic startup migrations for a multi-replica deployment. Use forward-compatible expand/contract changes and run each migration once before replacing application replicas. ## Common problems - **Readiness returns 503:** inspect `docker compose logs postgres api` and verify `ConnectionStrings__Firewatch` and the PostgreSQL health check. - **Integration tests cannot start:** verify `docker info` works from the same terminal and that the Docker daemon is running. - **The web page loads but API calls fail:** for Vite, check its `/api` proxy or an explicitly set `VITE_API_BASE_URL`; for the web container, check `FIREWATCH_API_UPSTREAM` and API readiness. - **Registration says email setup is required:** the API is configured to require verification. Start the Mailpit override or configure `Email__Enabled`, the SMTP settings, and `Auth__PublicBaseUrl`. - **Generated client check fails:** regenerate with `npm run api:generate`, review the API diff, and commit the generated file together with the schema change.