Conversation
There was a problem hiding this comment.
Pull request overview
This PR enforces a canonical public origin/base-path contract for Docker production builds to prevent localhost:3000 from being embedded into server-generated absolute URLs (fixing #42). It introduces build- and start-time validation for NEXT_PUBLIC_APP_URL/NEXT_PUBLIC_BASE_PATH, adds targeted contract tests, and includes a Docker image smoke test that verifies multiple “public origin” surfaces.
Changes:
- Add
validate:public-buildvalidation (script + tests) and run it beforenext buildand before Dockernext start. - Update Dockerfile to require/propagate
NEXT_PUBLIC_APP_URL+NEXT_PUBLIC_BASE_PATHas build args and validate them in builder/runner stages. - Add a production-image smoke test that builds/runs a container and asserts canonical-origin output across key endpoints; update docs and runtime env examples accordingly.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/lib/base-path.test.ts | Adds coverage for localhost fallback behavior in development when NEXT_PUBLIC_APP_URL is unset. |
| scripts/validate-public-build-config.mjs | Implements validation rules for canonical origin/base-path build configuration. |
| scripts/validate-public-build-config.d.mts | Provides TypeScript type declarations for the public build config validator. |
| scripts/public-build-config.test.mts | Adds unit tests covering validator acceptance/rejection cases. |
| Dockerfile | Removes localhost defaults and enforces validated build args before build and before start in the runner image. |
| package.json | Adds validate:public-build, start:docker, and test:production-origin scripts. |
| scripts/runner-image-contract.test.mts | Adds contract assertions for Dockerfile/script wiring and ensures dockerignore excludes local scratch/worktree dirs. |
| scripts/public-origin-image-smoke.mjs | Adds an end-to-end Docker build/run smoke test for canonical-origin output across multiple endpoints. |
| README.md | Documents the Docker build-time origin/base-path contract and how to build images for subpath or subdomain deployments. |
| DEPLOYMENT.md | Clarifies build-time-only nature of the public origin/base-path and removes runtime env guidance for those variables. |
| deploy/app-session.env.runtime.example | Removes public origin/base-path from runtime env template and documents rebuild requirement. |
| .dockerignore | Excludes .scratch and .worktrees from Docker build context. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 32a0566448
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
32a0566 to
8bbf3aa
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8bbf3aa9c8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 02706d613c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 12 changed files in this pull request and generated no new comments.
Suppressed comments (1)
scripts/validate-public-build-config.mjs:11
NEXT_PUBLIC_BASE_PATHvalues made only of slashes (for example//) normalize to"/"here, so the validator accepts them when the URL pathname is/. The application normalizer instead treats that result as an empty base path (src/lib/base-path.ts:7-8), whilenext.config.tswould pass/as Next'sbasePath. Normalize the computed root path to""here as well so validation and the build use a consistent contract.
return `/${trimmed.replace(/^\/+|\/+$/g, "")}`;
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ef29477624
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3810049a57
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 227defc9ea
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c87cf3cee4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const hostname = normalizeHostname(appUrl.hostname); | ||
| if (!hostname) { | ||
| throw invalidConfig("NEXT_PUBLIC_APP_URL must contain a nonempty hostname."); |
There was a problem hiding this comment.
Reject invalid DNS host labels
When NEXT_PUBLIC_APP_URL uses a syntactically invalid public hostname such as https://-example.com, https://example-.com, or https://a..b, the WHATWG URL parser accepts it and this check passes because the normalized hostname is merely nonempty. The Docker build then succeeds and bakes an unusable canonical origin into metadata and discovery responses; validate domain labels for empty components and invalid leading/trailing hyphens after normalization.
Useful? React with 👍 / 👎.
Docker builds could embed
http://localhost:3000in public Markdown, discovery endpoints and HTML metadata even when the container had the correct runtime URL.Require and validate
NEXT_PUBLIC_APP_URLand its matchingNEXT_PUBLIC_BASE_PATHbefore the image build. Propagate both values into the runner and reject invalid or different runtime configuration beforenext start. Local development keeps its localhost fallback.Includes URL/base-path regression tests, a production-image smoke test and deployment documentation. The HTML smoke checks the actual canonical, OpenGraph and pet
CreativeWork.urlvalues, including negative fixtures with a correct URL elsewhere in the HTML or another JSON-LD object.The smoke rejects
localhost:3000and the temporary container origin in every checked body and Link header, requires the expected origin/base path in each body, validates Link targets, and compares the three named HTML metadata URLs. It does not exhaustively validate every application-owned URL field inside every document.The configuration scope is image consistency and the explicitly documented address checks. DNS resolution and network reachability are deployment checks; a complete special-use IP classification policy is outside this PR.
Fixes #42
Verification
npm test -- --maxWorkers=1: 1171 passed, 1 skipped.npm run lint,npx tsc --noEmit --incremental falseandgit diff --checkpassed.npm run test:production-origin: all nine canonical-origin surfaces passed, including pet JSON-LD; a valid but different runtime origin was rejected before Next.js started. The unique container and image were independently verified removed.Current
main(2b036e1) is integrated. No dependency or lockfile changes relative tomain; the HTML checker uses the existingjsdomdependency.