# Remove In-Repo Nginx Implementation Plan > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. **Goal:** Remove repository-managed Nginx and replace it with a standalone frontend image plus backend image that are intended to sit behind an external reverse proxy. **Architecture:** The compose stack runs `db`, `backend`, and `frontend`. The frontend image builds the Vite SPA and serves it directly from its own container, while the backend continues serving the API on port `8000`. External infrastructure performs the only reverse proxy routing. **Tech Stack:** Docker Compose, FastAPI, Vue/Vite, Node.js, PostgreSQL, GitHub Actions --- ### Task 1: Define the frontend runtime image **Files:** - Modify: `frontend/Dockerfile` **Step 1: Keep the multi-stage frontend build** Retain the existing build stage so `npm ci` and `npm run build` still produce `dist`. **Step 2: Turn the final image into a runnable frontend container** Use a lightweight runtime image that copies `dist`, exposes a stable frontend port, and starts a static file server suitable for SPA delivery. **Step 3: Verify Dockerfile shape** Run: `sed -n '1,200p' frontend/Dockerfile` Expected: final stage exposes a frontend port and contains a runnable `CMD`. ### Task 2: Replace nginx topology with frontend topology **Files:** - Modify: `docker-compose.yaml` **Step 1: Remove the `nginx` service** Delete the Nginx image, build, ports, and volume mounts. **Step 2: Add a `frontend` service** Build from `frontend/Dockerfile`, define a private-registry-backed `FRONTEND_IMAGE` default, and expose the frontend runtime port. **Step 3: Verify rendered compose** Run: `docker compose config` Expected: only `db`, `backend`, `backend-init`, and `frontend` render. ### Task 3: Update image publishing **Files:** - Modify: `scripts/build-and-push-registry.sh` - Modify: `.github/workflows/publish-images.yml` **Step 1: Publish `frontend` instead of `nginx`** Build and push `${REGISTRY_HOST}/ctms/ctms-frontend` alongside `${REGISTRY_HOST}/ctms/ctms-backend`. **Step 2: Keep branch-based tag logic unchanged** Preserve the existing `dev`, `release`, `release/*`, and `main` tag conventions. **Step 3: Verify script syntax** Run: `bash -n scripts/build-and-push-registry.sh` Expected: PASS ### Task 4: Rewrite docs to match the new topology **Files:** - Modify: `README.md` - Modify: `docs/guides/release-checklist.md` - Modify: `docs/plans/2026-03-27-production-compose-design.md` - Modify: `docs/plans/2026-03-27-production-compose-implementation.md` - Modify: `docs/plans/2026-03-27-production-init-design.md` - Modify: `docs/plans/2026-03-27-production-init-implementation.md` - Modify: `docs/plans/2026-03-30-tcloud-private-registry-design.md` - Modify: `docs/plans/2026-03-30-tcloud-private-registry.md` **Step 1: Remove repository-managed Nginx language** Replace every statement that says Nginx is the public entrypoint, serves the SPA, or is a published runtime image. **Step 2: Document the external reverse proxy expectation** Describe the runtime as frontend and backend containers behind an external proxy. **Step 3: Verify search results** Run: `rg -n --hidden -g '!/.git' -S "nginx|ctms-nginx|NGINX_IMAGE|Nginx" README.md docker-compose.yaml .github scripts docs` Expected: no active repository-managed Nginx references remain. ### Task 5: Remove obsolete nginx files and verify end-to-end cleanup **Files:** - Delete: `nginx/Dockerfile` - Delete: `nginx/nginx.conf` **Step 1: Delete the obsolete files** Remove the Nginx directory because nothing in the repository should depend on it anymore. **Step 2: Validate compose and script syntax** Run: `docker compose config` Expected: PASS Run: `bash -n scripts/build-and-push-registry.sh` Expected: PASS **Step 3: Validate frontend and backend image references** Run: `sed -n '1,160p' README.md` Expected: deployment instructions mention `frontend` and `backend`, not `nginx`.