From 12c6b8bcc96dc6fc7bfce5777ff67f43a36c5a9d Mon Sep 17 00:00:00 2001 From: jjbrunton Date: Sun, 30 Aug 2026 16:18:55 +0100 Subject: [PATCH] fix(web): build from monorepo context --- .dockerignore | 6 ++++++ apps/web/Dockerfile | 26 ++++++++++++-------------- apps/web/docker-compose.prod.yml | 6 +++--- docs/index.md | 1 + docs/operations/web-deployments.md | 26 ++++++++++++++++++++++++++ 5 files changed, 48 insertions(+), 17 deletions(-) create mode 100644 docs/operations/web-deployments.md diff --git a/.dockerignore b/.dockerignore index 085f751..f6e50f1 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,5 +1,7 @@ node_modules **/node_modules +.next +**/.next .git .gitignore *.md @@ -23,11 +25,15 @@ apps/mcp apps/mobile apps/supabase apps/web +!apps/web +!apps/web/** e2e evidence etc infra scripts +!scripts +!scripts/fix-hoisting.js terraform .agents .claude diff --git a/apps/web/Dockerfile b/apps/web/Dockerfile index 756af08..9efa8de 100644 --- a/apps/web/Dockerfile +++ b/apps/web/Dockerfile @@ -12,15 +12,12 @@ ENV NEXT_PUBLIC_POSTHOG_KEY=$NEXT_PUBLIC_POSTHOG_KEY ENV NEXT_PUBLIC_POSTHOG_HOST=$NEXT_PUBLIC_POSTHOG_HOST ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL -# Install dependencies -COPY package*.json ./ -RUN npm ci - -# Copy source code -COPY . . - -# Build the application -RUN npm run build +# Install dependencies from the committed monorepo lockfile. +COPY . . +RUN npm ci + +# Build the web workspace from the repository root. +RUN npm run build -w @sauci/web # Production stage FROM node:20-alpine AS runner @@ -37,10 +34,11 @@ RUN apk add --no-cache curl RUN addgroup --system --gid 1001 nodejs RUN adduser --system --uid 1001 nextjs -# Copy built assets from builder -COPY --from=builder /app/public ./public -COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ -COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static +# Next preserves the workspace path in standalone output. Keep that layout so +# the generated server can resolve its .next directory and public assets. +COPY --from=builder --chown=nextjs:nodejs /app/apps/web/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/apps/web/public ./apps/web/public +COPY --from=builder --chown=nextjs:nodejs /app/apps/web/.next/static ./apps/web/.next/static USER nextjs @@ -49,4 +47,4 @@ EXPOSE 3000 ENV PORT=3000 ENV HOSTNAME="0.0.0.0" -CMD ["node", "server.js"] +CMD ["node", "apps/web/server.js"] diff --git a/apps/web/docker-compose.prod.yml b/apps/web/docker-compose.prod.yml index d22d192..16c486c 100644 --- a/apps/web/docker-compose.prod.yml +++ b/apps/web/docker-compose.prod.yml @@ -2,9 +2,9 @@ version: '3.8' services: web: - build: - context: . - dockerfile: Dockerfile + build: + context: ../.. + dockerfile: apps/web/Dockerfile args: - NEXT_PUBLIC_POSTHOG_KEY=${NEXT_PUBLIC_POSTHOG_KEY} - NEXT_PUBLIC_POSTHOG_HOST=${NEXT_PUBLIC_POSTHOG_HOST:-https://eu.i.posthog.com} diff --git a/docs/index.md b/docs/index.md index cc50425..6c5b1eb 100644 --- a/docs/index.md +++ b/docs/index.md @@ -11,6 +11,7 @@ historical notes. Agents should load only the section relevant to their task. - [Testing strategy](testing/strategy.md) - [Database migration safety](operations/database-migrations.md) - [Backend deployment and branching](operations/backend-deployments.md) +- [Website deployment](operations/web-deployments.md) - [Agent routing and effort](agents/routing.md) - [Learning promotion](agents/learnings.md) - [Authentication](authentication.md) diff --git a/docs/operations/web-deployments.md b/docs/operations/web-deployments.md new file mode 100644 index 0000000..4222c2c --- /dev/null +++ b/docs/operations/web-deployments.md @@ -0,0 +1,26 @@ +# Website deployment + +Dokploy deploys the public Sauci website from the `main` branch using +`apps/web/docker-compose.prod.yml`. The Compose file builds from the repository +root so the Docker build can use the committed workspace lockfile. Its Dockerfile +builds `@sauci/web` and runs the Next standalone server from its workspace path. + +## Required configuration + +`NEXT_PUBLIC_API_URL` is required at build time and must be the intended public +standalone API URL. `NEXT_PUBLIC_POSTHOG_KEY` is optional. When it is set, +`NEXT_PUBLIC_POSTHOG_HOST` defaults to `https://eu.i.posthog.com` unless Dokploy +provides a different value. These public values are inlined into the Next build; +do not place server credentials in them. + +## Promotion and acceptance + +Promote the verified website commit to `main` before allowing Dokploy to deploy +it. After the deployment reports success, verify valid TLS and HTTP 200 for: + +- `https://sauci.app/` +- `https://sauci.app/delete-account` + +The second check is required for the Google Play account-deletion resource. A +successful Dokploy deployment alone is not sufficient evidence that either URL +is publicly reachable.