Docs / deployment/chimti-web-cutover.md

Chimti Web Cutover — old two apps → merged chimti-web

Date prepared: 2026-08-01 (Phase 5).

Target: Coolify on the Otlu server. Domains stay the same — this is a

drop-in replacement, users notice only the new UI.

| Surface | Domain | Source after cutover |

|---|---|---|

| API | chimti-api.otlu.io | chimti-api (unchanged repo, + billing routes) |

| User app | chimti-user-app.otlu.io | **chimti-web-app**, build arg `VITE_APP_VARIANT=user` |

| Admin app | chimti-admin-app.otlu.io | **chimti-web-app**, build arg `VITE_APP_VARIANT=admin` |

The old `chimti-user-app/.github/workflows/deploy-vps.yml` (PM2 `chimti`, port

4000, in-repo `backend/`) is from the pre-split era and is dead — do not use it.

Order of operations

0. Push the repos (local machine)


# 1) chimti-api — billing endpoints (invoices/plans/subscriptions)

cd /Volumes/JS-Sethi/Code/Chimti/chimti-api

git add src/routes/billing.js src/app.js

git commit -m "feat(api): read-only billing endpoints (invoices, plans, subscriptions)"

git push



# 2) chimti-web-app — phases 0–5 (theme, shell, registers, bespoke pages, comms/AI, deploy files)

cd /Volumes/JS-Sethi/Code/Chimti/chimti-web-app

git add -A

git commit -m "feat(web): merged user+admin app on OTLU theme — phases 0–5"

git push



# 3) chimti-docs — decision record, runbook, app README

cd /Volumes/JS-Sethi/Code/Chimti/chimti-docs

git add -A

git commit -m "docs: chimti-web merge decision record + cutover runbook"

git push

1. Deploy the API first

Coolify → chimti-api app → Redeploy (it now has `/v1/invoices`, `/v1/plans`,

`/v1/subscriptions`). Then verify:


curl -s https://chimti-api.otlu.io/v1/health

# expect: {"service":"chimti-api", ...}



# with a real token (login first):

TOKEN=$(curl -s -X POST https://chimti-api.otlu.io/v1/auth/login \

  -H 'Content-Type: application/json' \

  -d '{"email":"<admin-email>","password":"REDACTED_MIGRATION_PASSWORD"}' | python3 -c 'import sys,json;print(json.load(sys.stdin)["accessToken"])')

curl -s https://chimti-api.otlu.io/v1/invoices -H "Authorization: Bearer $TOKEN" | head -c 300

curl -s https://chimti-api.otlu.io/v1/plans -H "Authorization: Bearer $TOKEN" | head -c 300

2. Verify CORS on the server

The API's production env (`CORS_ORIGIN`) must include BOTH:

`https://chimti-user-app.otlu.io,https://chimti-admin-app.otlu.io`

(the old apps ran on these domains, so they are almost certainly present —

confirm in the Coolify env editor before cutover; `.env.example` in the repo

does not list them and is not the source of truth).

3. Stand up the two new Coolify apps (blue-green, safest)

Create two NEW Coolify apps pointing at the `chimti-web-app` Git repo

(branch: whichever you push production code to — `main`/`production`):

`VITE_APP_VARIANT=user` (defaults already correct; API base defaults to

https://chimti-api.otlu.io). Temporary domain, e.g. chimti-web-user.otlu.io.

chimti-web-admin.otlu.io.

Deploy both, smoke-test on the temp domains (checklist below), THEN move the

real domains: old user app → remove domain chimti-user-app.otlu.io, add it to

chimti-web-user; same for admin. Old apps stay deployed (domain-less) as

instant rollback.

*(Faster alternative: change the Git source of the two existing Coolify apps

to chimti-web-app + set the build args. One less smoke step, but rollback

means a redeploy instead of a domain flip.)*

4. Smoke checklist (after domain move)

User app — https://chimti-user-app.otlu.io:

Admin app — https://chimti-admin-app.otlu.io:

5. Rollback

Blue-green path: move the domains back to the old Coolify apps (they are

still deployed). Nothing else to undo — API changes are additive.

6. After cutover

chimti-web-app), keep them readable for reference.

secure context even from HTTPS pages, same as the old app.