Skip to content

fix: let self-hosted web builds bake their own public URL - #2267

Open
fancyHeat wants to merge 1 commit into
CapSoftware:mainfrom
fancyHeat:fix/web-url-build-arg
Open

fix: let self-hosted web builds bake their own public URL#2267
fancyHeat wants to merge 1 commit into
CapSoftware:mainfrom
fancyHeat:fix/web-url-build-arg

Conversation

@fancyHeat

@fancyHeat fancyHeat commented Sep 10, 2026

Copy link
Copy Markdown

Problem

apps/web/Dockerfile hardcodes:

ENV NEXT_PUBLIC_WEB_URL=http://localhost:3000

Next inlines process.env.NEXT_PUBLIC_* into the client bundle at build time, so this value reaches the browser regardless of what WEB_URL / CAP_URL says at runtime. packages/env/build.ts resolves NEXT_PUBLIC_WEB_URL as process.env.WEB_URL ?? process.env.NEXT_PUBLIC_WEB_URL, which fixes the server side, but inside a client chunk process.env.WEB_URL is undefined and the fallback is whatever the Dockerfile baked. Anything client-side that reads buildEnv.NEXT_PUBLIC_WEB_URL (for example components/LinkifiedText.tsx, and the origin list seeded in utils/cors.ts) therefore sees http://localhost:3000 on a self-hosted build.

A self-hoster cannot fix this with .env alone: dotenv does not override a variable already present in the environment, and the Dockerfile's ENV puts it there before next build runs.

Fix

Back the ENV with an ARG carrying the same default:

ARG NEXT_PUBLIC_WEB_URL=http://localhost:3000
ENV NEXT_PUBLIC_WEB_URL=$NEXT_PUBLIC_WEB_URL

Passing nothing is a no-op, so the published ghcr.io/capsoftware/cap-web image is unchanged. Anyone building the image themselves can pass --build-arg NEXT_PUBLIC_WEB_URL=https://cap.example.com and get the right origin in the browser bundle.

Also adds a short note to the self-hosting docs explaining the runtime vs build-time split, since CAP_URL looks like it should be enough and is not.

Validation

  • docker build --check -f apps/web/Dockerfile . reports only the pre-existing JSONArgsRecommended warning on the CMD line.
  • We run this exact change in production on a self-hosted instance; a CI smoke test there greps the built client bundle for the passed origin and confirms it is present in place of localhost:3000.

RetriggerConfidence Score: 5/5

The PR appears safe to merge and preserves existing image behavior when no build argument is supplied.

Summary

  • Adds a NEXT_PUBLIC_WEB_URL Docker build argument and exposes it during the Next.js build.
  • Documents the distinction between the server's runtime URL and the browser bundle's build-time URL.
  • Provides a self-hosted Docker build example using the new argument.

Reviews (1) · Last reviewed commit: "fix: let self-hosted web builds bake the..."

The web Dockerfile hardcodes NEXT_PUBLIC_WEB_URL=http://localhost:3000. Next
inlines NEXT_PUBLIC_* into the client bundle, so that value reaches the
browser no matter what WEB_URL or CAP_URL says at runtime: share links,
embeds, oEmbed and the CORS allowlist all use localhost on a self-hosted
build. Back the ENV with an ARG of the same default so a build can pass
--build-arg NEXT_PUBLIC_WEB_URL=... without changing the published image.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant