Files
XQKqueue/docs/superpowers/plans/2026-07-14-web-container.md

3.8 KiB

Web Container Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Add a production frontend image so docker build -t xqkqueue-web:<tag> ./web succeeds and React client-side routes work behind Kubernetes Ingress.

Architecture: A Node.js 22 Alpine build stage installs locked pnpm dependencies and creates the Vite dist output. An Nginx Alpine runtime stage serves that output on port 80 and falls back to index.html for client-side routes; Kubernetes Ingress routes /api/* directly to the API Service.

Tech Stack: Node.js 22, pnpm 10.17.0, Vite 7, Nginx 1.28 Alpine, Docker

Global Constraints

  • Keep the Docker build context as ./web.
  • Serve the frontend on container port 80.
  • Do not proxy /api in the web container; Kubernetes Ingress owns API routing.
  • Use pnpm install --frozen-lockfile for reproducible dependency resolution.
  • Do not modify frontend business code or add Kubernetes manifests.

Task 1: Production web image and SPA server

Files:

  • Create: web/Dockerfile
  • Create: web/nginx.conf
  • Create: web/.dockerignore

Interfaces:

  • Consumes: web/package.json, web/pnpm-lock.yaml, the Vite source tree, and a Kubernetes Ingress that sends non-API paths to port 80.

  • Produces: a static Nginx image exposing port 80, with Vite assets in /usr/share/nginx/html and SPA fallback for unknown non-file paths.

  • Step 1: Reproduce the missing build definition

Run from the repository root:

docker build -t xqkqueue-web:verify ./web

Expected before implementation: FAIL with failed to read dockerfile: open Dockerfile: no such file or directory.

  • Step 2: Add the multi-stage Dockerfile

Create web/Dockerfile:

FROM node:22-alpine AS build
WORKDIR /app
RUN corepack enable && corepack prepare pnpm@10.17.0 --activate
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
COPY . .
RUN pnpm build

FROM nginx:1.28-alpine
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
  • Step 3: Add SPA-aware Nginx configuration

Create web/nginx.conf:

server {
    listen 80;
    server_name _;

    root /usr/share/nginx/html;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }
}
  • Step 4: Exclude local and generated files from the build context

Create web/.dockerignore:

node_modules
dist
coverage
playwright-report
test-results
*.log
*.tsbuildinfo
.DS_Store
.idea
.vscode
  • Step 5: Verify the existing production frontend build

Run:

pnpm --dir web build

Expected: TypeScript checks and the Vite production build finish with exit code 0 and write web/dist/index.html.

  • Step 6: Build the container image

Run:

docker build --progress=plain -t xqkqueue-web:verify ./web

Expected: exit code 0, including successful pnpm install --frozen-lockfile, pnpm build, and Nginx runtime stages.

  • Step 7: Verify root and client-side route responses

Run:

docker run --rm -d --name xqkqueue-web-verify -p 18080:80 xqkqueue-web:verify
curl --fail http://127.0.0.1:18080/
curl --fail http://127.0.0.1:18080/admin
docker stop xqkqueue-web-verify

Expected: both requests return the Vite application HTML with HTTP 200, and the verification container stops cleanly.

  • Step 8: Review and commit the implementation

Run:

git diff --check
git status --short
git add web/Dockerfile web/nginx.conf web/.dockerignore
git commit -m "build: add frontend container image"

Expected: only the three intended web container files are committed.