Skip to content

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

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

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

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 django-react-intro, so opening a live preview of the React app boots from configuration committed here in the repo rather than a best-guess made at runtime. The React app in web/ is now a first-class previewable frontend: the preview knows to run it with yarn on port 3000 with hot reloading on, and the image it runs in is pinned to a Node version that this 2017-era Create React App toolchain actually works on. Two things were deliberately left alone. There is no staging backend URL anywhere in this repo, so none was recorded — guessing one would risk pointing live previews at the wrong API. And the Django app in server/ serves the React bundle from its own domain and has no cross-origin API surface, so it needed no CORS changes for previews. Nothing about how the app builds, runs, or deploys today changes; these are new files only.

Technical details

Adds .codepress/dev-server/recipe.json (schema_version 1) and .codepress/dev-server/Dockerfile.web. Both are new files; no existing file is touched.

Discovery. One runnable frontend: web/ — Create React App (react-scripts 1.0.10), yarn classic (web/yarn.lock is lockfile v1), start script, default port 3000. One backend: server/ — Django 1.11. samples/auth-web/ is inert reference code (no manifest, unresolvable imports, unreachable from web/src), so it is not a frontend. web/public/index.html is a CRA template with %PUBLIC_URL% placeholders — build input, not a static site — so it is correctly not classified framework: "static".

Recipe. working_dir: "web", framework: "cra", package_manager: "yarn", install_command: "yarn install --frozen-lockfile", dependency_manifests: ["web/yarn.lock"], dev_port: 3000, system_packages: ["procps"], size: "small". prebuild_command is empty: the only build-ish script is postbuild, which copies a production build into server/static/build/ — that is deploy packaging, not a dev prebuild, so it is intentionally excluded.

Node 18, not current LTS. This is the main judgement call. web/yarn.lock pins webpack@2.6.1 / webpack-dev-server@2.5.0 / react-dev-utils@^3.0.2. That pipeline hashes with md4, which OpenSSL 3 removed, so it needs NODE_OPTIONS=--openssl-legacy-provider — a flag that exists on Node 17+ but has been dropped in newer majors. Node 18 is the newest base that both offers that escape hatch and has a -bookworm variant (verified present on the public.ecr.aws/docker/library/node mirror). I grepped the lockfile for the usual old-toolchain landmines rather than assuming: graceful-fs resolves to ^4 (so no natives/process.binding breakage), there is no node-sass, and the sole native dep fsevents@1.1.2 is optional and darwin-only, so it is skipped on linux and compiles nothing — hence procps alone in system_packages.

Bind and HMR. react-scripts start reads HOST/PORT from env, so the CMD derives HOST from CODEPRESS_BIND_HOST and maps WDS_SOCKET_PORT from CODEPRESS_HMR_CLIENT_PORT. Worth knowing: WDS_SOCKET_PORT is a CRA 3.4+ feature and is inert on 1.0.10 — it is set for contract uniformity and forward-compatibility. HMR still works because react-dev-utils@3's client opens its sockjs connection against the page's own origin (like Next.js), so it rides the preview proxy as long as websocket upgrades to /sockjs-node are forwarded. DANGEROUSLY_DISABLE_HOST_CHECK=true is the load-bearing one: without it webpack-dev-server 2.5 can reject the preview hostname with "Invalid Host header" and the preview never renders. It is the CRA analogue of Vite's allowedHosts. BROWSER=none stops react-scripts trying to launch a browser in the container.

No staging URL. I swept every tracked file for http(s) URLs. Every hit is CRA README documentation or a localhost example; there is no .env*, vercel.json, CI workflow, or .codepress/verify-staging/recipe.json. Per the never-persist-a-guess rule, staging_backend_url is omitted rather than written as empty. The env-var prefill was also skipped — the frontend reads no API base env var at all (its only process.env reads are NODE_ENV and PUBLIC_URL).

No preview-CORS edit. The gate requires a backend that serves cross-origin browser clients. server/ has no CORS surface (no django-cors-headers in Pipfile, INSTALLED_APPS, MIDDLEWARE, or any CORS_* setting) and no cross-origin caller: web/ issues zero API calls, and server/urls.py ends in a catch-all index view rendering the React index.html from server/static/build, i.e. same-origin by design. Independently, the repo has only a single settings.py with no staging module or .env.staging, so there is no staging-only config path to scope an allowance to — that alone would make this report-only rather than an auto-edit.

No social-auth work. The runnable frontend has no sign-in flow at all (App.js routes / to a Home page). The GitHub OAuth button under samples/auth-web/ is documentation-grade sample code and is not wired into any runnable frontend.

The image is thin per contract: no source COPY, no baked node_modules, no CodePress binary. Yarn 1.22.22 is pre-activated via corepack at build time so a cold start never fetches a package manager.

Changes

  • Add .codepress/dev-server/recipe.json — one frontends[] entry for the web CRA app (yarn, port 3000, web/yarn.lock as the dependency fingerprint)
  • Add .codepress/dev-server/Dockerfile.web — thin dev-mode image on node:18-bookworm, binds 0.0.0.0, wires HMR/bind to the runtime env vars, CMD runs yarn start
  • Pin Node 18 with NODE_OPTIONS=--openssl-legacy-provider so webpack 2.6.1's md4 hashing works under OpenSSL 3
  • Set DANGEROUSLY_DISABLE_HOST_CHECK=true and BROWSER=none so the dev server accepts the preview hostname and does not try to open a browser in the container
  • Omit staging_backend_url — no staging backend is declared anywhere in the repo

Test plan

  • Build the dev image from the repo root: docker build -f .codepress/dev-server/Dockerfile.web -t drx-web-dev . — it should succeed and pull public.ecr.aws/docker/library/node:18-bookworm.
  • Install deps the way the runtime does: from web/, run yarn install --frozen-lockfile and confirm it completes (fsevents should be skipped on linux, not fail the install).
  • Run the container with the checkout bind-mounted at /app and deps present: docker run --rm -p 3000:3000 -v "$PWD":/app drx-web-dev — confirm it logs "Compiled successfully" and "On Your Network" rather than an ERR_OSSL_EVP_UNSUPPORTED / md4 error.
  • Confirm the bind is on all interfaces, not loopback: curl -sS -o /dev/null -w '%{http_code}\n' http://localhost:3000/ returns 200 from the host.
  • Confirm the preview hostname is accepted (the host-check path): curl -sS -o /dev/null -w '%{http_code}\n' -H 'Host: abc123.preview.codepress.dev' http://localhost:3000/ returns 200 and NOT an "Invalid Host header" body.
  • Verify hot reload: with the container running, edit the heading text in web/src/containers/home/Home.js and confirm the browser at localhost:3000 updates without a manual refresh.
  • Validate the contract: python3 -c "import json;r=json.load(open('.codepress/dev-server/recipe.json'));print(r['schema_version'], [f['label'] for f in r['frontends']])" prints 1 ['web'], and confirm staging_backend_url is absent.

Open items

  • The dev image could not be built or run here — this bootstrap environment has no Docker daemon. The Node 18 + --openssl-legacy-provider choice is derived from the pinned versions in web/yarn.lock (webpack 2.6.1) rather than from an observed successful boot, so the first build is the real proof. If yarn install --frozen-lockfile trips over a 2017-era package, that is the thing to look at first.
  • WDS_SOCKET_PORT is set but is a no-op on react-scripts 1.0.10 (it landed in CRA 3.4). HMR relies instead on this CRA version's origin-based sockjs client, which needs websocket upgrades to /sockjs-node forwarded by the preview proxy.
  • No preview-CORS allowance was added, by design (the Django app is same-origin and has no CORS surface). If this repo later grows a cross-origin API for the React app to call, it will also need a staging settings module or .env.staging before a preview-CORS allowance can be scoped safely to non-production.

Authors

Generated with CodePress · View the chat session

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

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 1.0.10 on
yarn classic) and one backend (server/, Django 1.11). The Django app serves
the React bundle same-origin through its catch-all index view and carries no
CORS surface, so no preview-CORS edit applies here. No staging backend URL
exists anywhere in the repo, so staging_backend_url is deliberately omitted
rather than guessed.

The dev image pins Node 18 with --openssl-legacy-provider because webpack
2.6.1 predates OpenSSL 3, and sets DANGEROUSLY_DISABLE_HOST_CHECK so
webpack-dev-server answers requests addressed to the preview hostname.

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