Skip to content

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

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

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

Conversation

@codepress-dev

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

Copy link
Copy Markdown

Summary

This sets up your repo so CodePress live previews can boot the React app in web/ reliably. Previously the preview had to guess how to run your frontend; now the repo itself declares it, so a preview starts the same way every time.

Along the way I actually booted the app to check the setup works, and found a real blocker worth knowing about: the frontend is pinned to a 2017-era Create React App toolchain that will not start on any modern Node version. It runs fine on Node 18 and crashes immediately on Node 20 and newer. The preview image is pinned to Node 18 accordingly, with the reason documented inline so nobody bumps it by accident and gets a confusing failure.

Nothing about how your app is built or served changes — these are two new files under .codepress/, and no application or Django code was touched.

Technical details

Adds .codepress/dev-server/recipe.json (schema_version 1) with a single frontend entry, plus .codepress/dev-server/Dockerfile.web.

Recipe entrylabel: web, working_dir: web, framework: cra, package_manager: yarn (v1 web/yarn.lock, no packageManager field), install_command: yarn install --frozen-lockfile (verified against the lockfile unchanged), dependency_manifests: ["web/yarn.lock"] (per-app lockfile — there is no workspace root), dev_port: 3000, system_packages: ["procps"], size: medium. prebuild_command is empty: the postbuild script (cp -r build/ ../server/static/build/) is production-build wiring, not a dev prerequisite.

Node 18 pin is load-bearing, not a default. react-scripts@1.0.10webpack-dev-server@2.5.0sockjswebsocket-driver@0.6.5, which calls process.binding('http_parser'). That internal binding was removed after Node 18, so on Node 20+ react-scripts start exits code 1 with Error: No such module: http_parser. Verified by installing deps and booting the dev server: on Node 18.20.5 webpack compiles and both / and /static/js/bundle.js return 200 (1.9 MB bundle with the HMR runtime present); on Node 25 it dies instantly. I also checked whether NODE_OPTIONS=--openssl-legacy-provider was needed and confirmed it is not — webpack 2.6.1 defaults output.hashFunction to md5, not the md4 that breaks webpack 4/5 under OpenSSL 3 (byte-identical bundles with and without the flag), so it was deliberately left out rather than added as a cargo-cult fix.

HMR. No config shim was needed. react-dev-utils/webpackHotDevClient in this version derives its SockJS URL from window.location, so the HMR socket rides the preview origin the same way Next.js does. The CODEPRESS_HMR_* vars are still declared for the uniform runtime contract, and the CMD maps CODEPRESS_HMR_CLIENT_PORTWDS_SOCKET_PORT so the wiring is already correct if react-scripts is ever upgraded (that var is inert in 1.x).

Bind + host check. The CMD sets HOST from CODEPRESS_BIND_HOST (the dedicated bind contract) rather than ambient HOSTNAME; react-scripts 1.x reads HOST/PORT from env directly. BROWSER=none stops it launching a browser in the container. DANGEROUSLY_DISABLE_HOST_CHECK=true is the CRA analogue of Vite's server.allowedHosts — CRA 1.0.10 computes disableHostCheck: !proxy || DANGEROUSLY_DISABLE_HOST_CHECK === 'true', so the check is already off while no proxy field exists in web/package.json; setting it explicitly keeps previews working if one is added later.

The image is thin per contract: no COPY of source or manifests, no baked node_modules, no install layer, no CodePress binary. Dependencies arrive at runtime on the bind-mounted checkout.

Staging backend URL: omitted. There is no .env.staging, .env.example, vercel.json, next/vite config, .github/workflows, or .codepress/verify-staging recipe in the repo — zero candidates, so staging_backend_url was left out rather than guessing. The frontend also reads no REACT_APP_* API base var, so no dev-server env prefill was applicable.

Preview CORS: no change needed (not a skipped safety case). Django is present in server/, but it has no CORS surface at all — django-cors-headers is absent from both Pipfile and INSTALLED_APPS/MIDDLEWARE, and the only mentions of CORS in the tree are prose in the stock CRA web/README.md. The architecture is same-origin: yarn build + postbuild copies the bundle into server/static/build/, TEMPLATES['DIRS'] points there, and the urls.py catch-all renders index.html through server.views.index. The React app in web/src makes no API calls at all (no fetch/axios, no absolute API base URL, no proxy field), so there is no cross-origin caller to allow. Separately, even if a CORS surface existed, this repo has no staging config path to scope an allowance to — a single server/server/settings.py, no settings package, no .env.staging, no deploy config — which is a report case rather than an auto-edit.

Social auth: not applicable. The runnable frontend has no social or enterprise sign-in, and Django installs allauth.account but not allauth.socialaccount (no providers configured). samples/auth-web/components/GithubButton.js does contain a GitHub OAuth authorize link, but samples/ has no package.json, is not a runnable frontend, and nothing in web/src imports it — it is reference material, so no auth wiring was attempted.

Changes

  • Added .codepress/dev-server/recipe.json — schema_version 1, one cra frontend entry for web/ (yarn, port 3000, fingerprinted on web/yarn.lock).
  • Added .codepress/dev-server/Dockerfile.web — thin dev-mode image on public.ecr.aws/docker/library/node:18-bookworm, installs procps, enables Corepack, wires bind/HMR from env, CMD runs yarn start.
  • Pinned the base image to Node 18 with an inline comment explaining the http_parser binding removal, so a future bump is a deliberate choice paired with a react-scripts upgrade.
  • Omitted staging_backend_url — no staging candidates exist anywhere in the repo, and a guess would be worse than nothing.
  • Made no backend, CORS, or auth changes — none were warranted; the reasoning is recorded in the technical details.

Test plan

  • The dev-server path was already verified end-to-end by booting the app on Node 18.20.5: yarn install --frozen-lockfile succeeded, webpack reported Compiled successfully!, / returned 200, and /static/js/bundle.js returned a 1.9 MB bundle containing the HMR runtime. The steps below reproduce that and confirm the image itself.
  • Build the dev image from the repo root (the build context is the root; the Dockerfile is passed with -f): docker build -f .codepress/dev-server/Dockerfile.web -t drx-web-dev .
  • Install deps on the checkout the way the runtime does, then run the container against it: cd web && yarn install --frozen-lockfile && cd .. then docker run --rm -p 3000:3000 -v "$PWD":/app drx-web-dev
  • Expect Compiled successfully! in the logs, then confirm it really compiled rather than just opening a socket: curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3000/200, and curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3000/static/js/bundle.js200.
  • Confirm hot reload: edit the "Welcome to React" text in web/src/containers/home/Home.js and watch the browser update without a manual refresh.
  • Optional — see the Node ceiling for yourself: change the FROM line to node:20-bookworm and rebuild. The container should exit immediately with Error: No such module: http_parser. Revert afterwards.
  • Sanity-check the contract: python3 -c "import json;print(json.load(open('.codepress/dev-server/recipe.json'))['frontends'][0])" should show working_dir: web, dev_port: 3000, and a dockerfile_path that exists on disk.

Open items

  • The Node 18 pin is a ceiling, not a preference. react-scripts@1.0.10, react@15.6, and webpack@2.6.1 are from 2017 and cannot run on a supported Node release, so this preview image is pinned to a runtime that is itself past end-of-life. Modernizing react-scripts (or migrating to Vite) is the real fix and would let the base image track a current LTS — well outside the scope of this bootstrap.
  • No staging environment exists to detect. If you add one later (a .env.staging, a deploy workflow, or a /verify-staging recipe), re-running the bootstrap will pick up staging_backend_url and prefill the preview's API base URL.
  • If you later make the React app call Django cross-origin (an absolute API base URL instead of the current same-origin build), the preview will need a CORS allowance on Django for *.preview.codepress.dev. That cannot be added safely today: the project has no CORS surface and no staging-only settings path to scope it to, so it would land in shared/production config. Introducing a staging settings module (or .env.staging) first, then re-running the bootstrap, is the clean route.
  • samples/auth-web/components/GithubButton.js contains a GitHub OAuth snippet that is not part of any runnable frontend. Flagged only so its presence is not mistaken for configured social sign-in — no action was taken on it.

Authors

Generated with CodePress · View the chat session

Co-authored-by: dev@codepress.dev dev@codepress.dev

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

- .codepress/dev-server/recipe.json — one frontend entry for the CRA app in
  web/ (yarn, dev port 3000, `yarn install --frozen-lockfile`, fingerprinted on
  web/yarn.lock).
- .codepress/dev-server/Dockerfile.web — thin, dev-mode image. Binds via
  CODEPRESS_BIND_HOST, installs procps, enables Corepack, and bakes no
  node_modules or source.

Pins node:18-bookworm deliberately. react-scripts 1.0.10 pulls
webpack-dev-server 2.5.0 -> sockjs -> websocket-driver@0.6.5, which calls
process.binding('http_parser') — an internal binding removed after Node 18, so
`react-scripts start` exits immediately on Node 20+. Verified by booting the app:
Node 18.20.5 compiles and serves it, Node 25 fails.

No staging backend URL was detected, so the recipe omits staging_backend_url
rather than storing a guess. No preview CORS change was needed: Django serves the
React build same-origin and the repo has no CORS surface.

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 26, 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