# CFL — InMotion VPS checklist (Lavish)

Replace `USER`, `YOUR-DOMAIN`, and the three secrets. Do not run `next build` or `npm run dev`.

## 0. Once on the box

- [ ] SSH in
- [ ] Unzip the zip into `/home/USER/cfl`
- [ ] `cd /home/USER/cfl`

## 1. Node 22

```bash
curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
source ~/.bashrc
nvm install 22 && nvm use 22
node -v    # must print v22.x
```

## 2. Install + env

```bash
npm ci
cp deploy/inmotion.env.sample .env
nano .env
```

Fill:

| Key | Value |
|---|---|
| `BETTER_AUTH_URL` | `https://YOUR-DOMAIN` (no trailing slash) |
| `BETTER_AUTH_SECRET` | `node -e "console.log(require('crypto').randomBytes(48).toString('hex'))"` |
| `DATABASE_URL` | Neon connection string (`sslmode=require`) |
| `VITE_AUTH_ENABLED` | `true` |

## 3. Build + start

```bash
npm run build:vps
npm run db:migrate
npm i -g pm2
CFL_ROOT=/home/USER/cfl pm2 start deploy/ecosystem.config.cjs
pm2 save && pm2 startup    # run the sudo command it prints
```

## 4. nginx + TLS

- [ ] Copy `deploy/inmotion.nginx.conf` → site config
- [ ] Change `forge.example.com` → `YOUR-DOMAIN`
- [ ] Issue cert (AutoSSL or certbot)
- [ ] `nginx -t && systemctl reload nginx`

## 5. Prove it

```bash
curl -sS http://127.0.0.1:3000/api/health
# {"ok":true,"service":"capital-forge-league",...}

curl -sS -o /dev/null -w "%{http_code}\n" http://127.0.0.1:3000/
# 200

VERIFY_URL=https://YOUR-DOMAIN npm run verify:deploy
```

Browser: homepage loads, stadium tunnels match the sport, `/api/health` is JSON.

## If RAM < 2 GB

Build on a laptop (`npm ci && npm run build:vps`), copy `.output` up, skip step 3 build on the VPS, still run PM2 + nginx.

## Red flags

- `next build` — wrong stack
- `npm run dev` as production — no
- `VITE_AUTH_ENABLED=false` with a `DATABASE_URL` — auth fails closed
- 502 on the domain but `/api/health` on `:3000` works — nginx/port, not the app
