# Garage dashboard (garage-erp) — Coolify deploy

Domain: **tenant.reparee.com**
Build: Docker (multi-stage), Next.js standalone output
Port: **3000** inside container; Coolify maps to 80/443 + TLS

---

## 1. New Application in Coolify

1. **+ New Resource → Application → Public Repository** (or GitHub App).
2. Repo: this monorepo. Branch: `main` (or whatever).
3. **Build Pack: Dockerfile**.
4. **Base Directory**: `garage-erp` (where the Dockerfile lives — relative to repo root).
   - If `garage-erp` IS the repo root, leave blank.
5. **Dockerfile Location**: `Dockerfile` (default).
6. **Port**: `3000`.

## 2. Environment variables

Coolify → Application → **Environment Variables**. Add:

| Key | Value |
|---|---|
| `NEXT_PUBLIC_API_URL` | `https://api.reparee.com` |
| `NEXT_PUBLIC_SAAS_URL` | `https://reparee.com` |
| `NEXT_PUBLIC_GARAGE_HOST_PATTERN` | `*.reparee.com` |
| `NODE_ENV` | `production` |
| `HOSTNAME` | `0.0.0.0` |
| `PORT` | `3000` |
| `NEXT_TELEMETRY_DISABLED` | `1` |

> `NEXT_PUBLIC_*` values are **baked into the JS bundle at build time**. Changing them requires a redeploy, not just a restart.

## 3. Domain + TLS

Coolify → Application → **Domains** → add `https://tenant.reparee.com`. Coolify auto-provisions Let's Encrypt cert. DNS A record must already point to the Coolify server's public IP.

## 4. Healthcheck

Coolify → Application → **Healthcheck**:

- **Path**: `/api/proxy/health` — set this once the backend is reachable; otherwise `/` works for the first deploy.
- **Port**: `3000`
- **Interval**: 30s
- **Timeout**: 10s

## 5. Build options

- **Build pack**: Dockerfile
- **Custom build command**: leave blank (Dockerfile handles it)
- **Build args**: none required; all envs are runtime

## 6. Deploy

Click **Deploy**. Watch build logs:

- Stage 1 (`deps`): `pnpm install --frozen-lockfile` — ~2-4 min.
- Stage 3 (`builder`): `pnpm --filter @garage/dashboard build` — ~3-6 min. Watch for Next.js trace warnings; they are non-fatal.
- Stage 4 (`runner`): copies standalone output; tiny.

First build is slow. Subsequent builds reuse Docker layer cache.

## 7. Smoke test

```bash
curl -I https://tenant.reparee.com
# → 200 OK + Set-Cookie not yet set (no session)

# Activation: full flow goes SaaS → /activate/handoff/{token}?ws=&api=
# Cookies expected after redirect: auth_token, auth_user, workspace_uuid, api_base_url
```

## 8. CORS / cookies sanity

The dashboard only sets cookies on its own origin (`tenant.reparee.com`). The Next.js server proxy at `/api/proxy/*` strips upstream `Set-Cookie` headers — Laravel cookies never reach the browser. Workspace context is read from cookies on every server-side proxy call.

Verify in browser DevTools after handoff:

- 4 cookies on `tenant.reparee.com`, all HttpOnly + SameSite=Strict + Secure.
- Network tab: all `XHR/fetch` go to `tenant.reparee.com/api/proxy/...`. **Zero direct calls** to `api.reparee.com` from the browser.

## 9. Logs

Coolify → Application → **Logs** tab streams container stdout/stderr. Next.js logs requests as `GET / 200 in 45ms` etc.

## 10. Rollback

Coolify → **Deployments** tab → pick a previous successful deployment → **Redeploy**.

## 11. Notes on monorepo

- The Dockerfile builds **only** the `@garage/dashboard` app. `@garage/api` is built as part of dashboard's `prebuild` hook (it generates OpenAPI types from `postman/collection.json`).
- If you split apps later (e.g. a separate admin app), copy the Dockerfile and change the `--filter @garage/dashboard` line.
- `output: 'standalone'` in `apps/dashboard/next.config.mjs` is required for the runner stage to work. Do not remove.

## 12. Cypress / e2e

Out of scope for the runtime container. If you want CI e2e runs:

- Use Coolify's **GitHub Actions integration** to run `pnpm test:e2e` in CI before the deploy webhook fires.
- Update `apps/dashboard/cypress.config.ts` to read `baseUrl` from env (currently hard-coded to `https://newgarage.yslootahtech.com`).
