# Deployment

The production artifact is one Express container: it serves both the API and
the built React application. MySQL is the only required service.

## Before first release

1. Copy `.env.example` to `.env` and replace every placeholder secret. Do not
   commit that file or put any secrets in `VITE_*` variables.
2. Build and start the stack:

   ```bash
   docker compose up -d --build
   ```

3. On a new database, create the schema and sample data once:

   ```bash
   docker compose exec app npm run db:install
   ```

   For an existing database, use the additive migration instead:

   ```bash
   docker compose exec app npm run db:migrate
   docker compose exec app npm run db:doctor
   ```

4. Verify the deployed service:

   ```bash
   curl http://localhost:3000/health/live
   curl http://localhost:3000/health/ready
   ```

`/health/live` means the Node process is alive. `/health/ready` also verifies
MySQL connectivity; `/health` remains an alias for compatibility.

## Production operations

Put the app behind a TLS-terminating reverse proxy and route HTTPS traffic to
port 3000. Set the public host's port with `APP_PORT`; never expose MySQL unless
there is a specific operational need. Back up the named `mysql_data` volume (or
use a managed MySQL service and point `DB_HOST` at it) before upgrades.

Run `npm test`, `npm run typecheck`, and `npm run build` in CI before building
the image. Treat `npm run db:migrate` as a release step and take a database
backup beforehand, even though its schema changes are additive.
