Skip to content

Bootstrap CodePress Live Dev Server recipe + dev Dockerfile - #38

Open
codepress-dev[bot] wants to merge 1 commit into
masterfrom
codepress/dev@codepress.dev/bootstrap-live-dev-server-artifacts-f7760c91
Open

Bootstrap CodePress Live Dev Server recipe + dev Dockerfile#38
codepress-dev[bot] wants to merge 1 commit into
masterfrom
codepress/dev@codepress.dev/bootstrap-live-dev-server-artifacts-f7760c91

Conversation

@codepress-dev

@codepress-dev codepress-dev Bot commented Jul 25, 2026

Copy link
Copy Markdown

Summary

This sets up the Live Dev Server for this repo, so a CodePress preview can boot the React app on its own instead of guessing how to run it. Two small files are added under .codepress/dev-server/ — a recipe describing the one runnable frontend (web/), and a dev-mode Dockerfile that runs it with hot reload. Nothing in the app itself changes; these are additive config files only.

Two things this deliberately did NOT do, both to avoid guessing. First, no staging backend URL was recorded: the repo declares one nowhere (no .env.staging, .env.example, deploy workflow, or proxy config), and recording a wrong or production URL would point live previews at the wrong data. Second, no CORS change was made to the Django backend in server/ — it is same-origin by construction (Django's catch-all URL renders the copied React build, and no CORS package or cross-origin caller exists), so previews have no cross-origin API call to unblock. If this app later grows a browser API call from web/ to a separately-hosted Django, that is when preview CORS becomes relevant — and it would need a staging settings path to scope it to, which this repo does not have yet (see Open items).

Technical details

Discovery. One runnable frontend: web/ — create-react-app (react-scripts 1.0.10, webpack 2.6.1, webpack-dev-server 2.5.0 per web/yarn.lock), yarn classic (# yarn lockfile v1), start script, no --port override → CRA default 3000. samples/auth-web/ is not a frontend (no package.json, no framework marker, and its imports — ../../redux/auth, ../header/Header, ../../../config/settings, plus react-spinkit/query-string/secure-random — resolve to nothing in this repo), so it is excluded. web/public/index.html is the CRA template (%PUBLIC_URL%), not a servable static site.

recipe.json. schema_version: 1, one frontends[] entry: working_dir: "web", framework: "cra", package_manager: "yarn", install_command: "yarn install --frozen-lockfile", dependency_manifests: ["web/yarn.lock"] (the per-app lockfile — this is not a workspace, there is no root manifest), dev_port: 3000, system_packages: ["procps"], size: "medium". No prebuild_command: the only extra lifecycle script is postbuild, which copies a production build into server/static/build/ and has no place in a dev-server run. staging_backend_url is omitted entirely rather than written empty.

Dockerfile.web. Thin, toolchain-only: no COPY, no baked node_modules (the runtime hydrates deps onto the bind-mounted checkout at /app), no CodePress binary. Three decisions worth a look:

  • node:18-bookworm, not the current LTS. This is a 2017 toolchain and the repo pins no Node version. Node 18 is the oldest bookworm-based official image, so it is the closest available match. Node 20/22 were considered and rejected as more removal surface for no benefit. The OpenSSL-3 md4 hash failure that breaks CRA on modern Node does not apply here — that is a webpack 4 default, and this app is on webpack 2, which hashes with md5. I also checked the other classic age-related breakers: graceful-fs resolves to 4.1.11 (not the 3.x that throws primordials is not defined), there is no node-sass, and the only native dep, fsevents@1.1.2, is darwin-only and optional so yarn skips it on linux. The full -bookworm variant (never -slim) is used because the runtime dependency install needs the node-gyp toolchain.
  • HMR is origin-based here. react-dev-utils@^3 builds its SockJS URL from window.location, so the HMR socket already rides the preview origin behind the proxy — no client-port flag exists in this version. The four CODEPRESS_* env vars are still declared for the uniform runtime contract, and WDS_SOCKET_PORT is mapped from CODEPRESS_HMR_CLIENT_PORT in the CMD so the wiring is already correct if react-scripts is ever upgraded to a version that honors it (it is inert today).
  • DANGEROUSLY_DISABLE_HOST_CHECK=true. webpack-dev-server 2.5.0 has the DNS-rebinding host check, which would otherwise reject the preview proxy's Host header. This is the CRA counterpart to the server.allowedHosts setting Vite repos get, and it lives only in this dev image — it takes no part in react-scripts build.

Bind is CODEPRESS_BIND_HOST (default 0.0.0.0) rather than the ambient HOSTNAME; ENV PATH prepends /app/web/node_modules/.bin and /app/node_modules/.bin as a backstop, and the CMD still routes through yarn rather than invoking react-scripts bare. Corepack pre-activates yarn@1.22.22 at build time so a cold start never downloads a package manager.

Validation. Static contract checks only, all passing: recipe parses at schema_version 1 with every required field, dockerfile_path exists, the image is dev-mode/thin/0.0.0.0-bound with the four env vars and no localhost literal, install_command is plain argv and not npm ci, and dependency_manifests resolves on disk. The dev_command string was executed through sh -c with the env prefix swapped to env to prove the quoting applies HOST/WDS_SOCKET_PORT/BROWSER/DANGEROUSLY_DISABLE_HOST_CHECK correctly. Docker is not available in this session, so the image was not built and the dev server was not booted — that is the main thing to verify below.

Changes

  • Add .codepress/dev-server/recipe.json — schema_version 1 with one frontend entry for web/ (cra, yarn, port 3000)
  • Add .codepress/dev-server/Dockerfile.web — thin dev-mode image on node:18-bookworm, binds 0.0.0.0, HMR wired to the CODEPRESS_* env vars
  • Omit staging_backend_url — no staging backend is declared anywhere in the repo
  • No backend CORS change — server/ is same-origin (catch-all renders the copied React build; no CORS package, no cross-origin caller)

Test plan

  • Build the dev image from the repo root: docker build -f .codepress/dev-server/Dockerfile.web -t drl-web-dev . — verify it completes (this is the step that was not runnable in the bootstrap session).
  • Run it against the checkout and confirm the dev server binds all interfaces, not localhost: docker run --rm -p 3000:3000 -v "$PWD":/app drl-web-dev sh -c 'yarn install --frozen-lockfile && HOST=0.0.0.0 WDS_SOCKET_PORT=443 BROWSER=none DANGEROUSLY_DISABLE_HOST_CHECK=true yarn start' — expect Compiled successfully and a listener on 0.0.0.0:3000.
  • Load http://localhost:3000 and confirm the React welcome page renders.
  • Confirm hot reload: with the container running, edit the heading text in web/src/containers/home/Home.js and verify the browser updates without a manual refresh.
  • Start a CodePress preview for this branch and confirm it serves the app at the preview URL and that the HMR websocket connects (browser devtools → Network → WS, look for the /sockjs-node connection succeeding rather than erroring).
  • Confirm nothing about the existing production path changed: cd web && yarn build still succeeds and postbuild copies into server/static/build/.

Open items

  • The image was not built or booted — Docker is not available in the bootstrap session, so verification was static (contract + shell-syntax checks) only. The Node-18 choice for this 2017 toolchain is reasoned, not empirically proven; the first two test-plan steps are what confirm it. If the runtime install or dev server does fail on Node 18, the knob is the FROM line in .codepress/dev-server/Dockerfile.web.
  • No staging environment exists in this repo (single server/server/settings.py with DEBUG = True hardcoded, no settings package, no .env.staging, no deploy workflow). That is why no staging backend URL was recorded and why preview CORS would be report-only even if it were needed: there is no staging-only config path to scope such a change to, and it must never be added to production config.
  • server/server/settings.py carries a hardcoded SECRET_KEY and DEBUG = True with ALLOWED_HOSTS = []. Untouched by this PR and out of its scope, but worth flagging if this repo is ever deployed beyond local use.
  • The frontend pins react-scripts 1.0.10 (2017). This PR deliberately accommodates it rather than upgrading it, but the age is the main risk to preview reliability — a CRA upgrade (or a migration to Vite) would let the dev image use a current Node LTS and drop the host-check escape hatch.

Authors

Generated with CodePress · View the chat session

Author the committed Live Dev Server artifacts so previews boot from
repo-owned files instead of a runtime heuristic.

Discovery found one runnable frontend (web/, create-react-app on
react-scripts 1.0.10 + yarn classic) and one backend (server/, Django
1.11) that is same-origin by construction: the catch-all URL renders the
copied React build and there is no CORS surface or cross-origin caller,
so no preview-CORS edit applies.

- .codepress/dev-server/recipe.json: schema_version 1 with the web
  frontend entry (working_dir, dev_command, cra/yarn, dev_port 3000,
  install + dependency_manifests, procps).
- .codepress/dev-server/Dockerfile.web: thin dev-mode image on the full
  node:18-bookworm base, binds via CODEPRESS_BIND_HOST, wires HMR to the
  CODEPRESS_HMR_* env vars, bakes no deps or source.

No staging_backend_url: the repo declares no staging backend anywhere,
so nothing was persisted rather than guessing.

Co-authored-by: dev@codepress.dev <dev@codepress.dev>
@codepress-dev codepress-dev Bot added the cp:in-progress CodePress: still being worked on label Jul 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cp:in-progress CodePress: still being worked on

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants