Skip to content

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

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

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

Conversation

@codepress-dev

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

Copy link
Copy Markdown

Summary

This sets up the files CodePress needs to run a live, hot-reloading preview of this project's React frontend. Until now the preview system would have had to guess how to start this app; from here on it reads the instructions committed in this PR, which means previews start the same way every time and can be adjusted by editing these files.

The only thing added is a new .codepress/dev-server/ folder — two config files. No application code, dependencies, or backend settings were touched, so nothing about how the app builds, deploys, or behaves today changes.

Worth knowing: this project is on Create React App 1.0.10, which is about eight years old, so "will it even start on a modern machine?" was the real risk here rather than anything about the config format. Rather than assume, I installed the dependencies and actually booted the dev server to confirm it runs, serves pages under a preview-style web address, and has a working live-reload connection. It does.

Technical details

Adds .codepress/dev-server/recipe.json (schema_version 1) with a single frontend entry for web/, plus the matching thin dev-mode image at .codepress/dev-server/Dockerfile.web. Nothing else in the tree is modified.

Recipe entry: label: web, working_dir: web, framework: cra, package_manager: yarn, dev_port: 3000, install_command: yarn install --frozen-lockfile, dependency_manifests: ["web/yarn.lock"], system_packages: ["procps"], size: medium. No prebuild_command — the postbuild script in web/package.json is a production-build hook (it copies build/ into server/static/build/), not a dev prerequisite.

Node 18 is pinned deliberately. web/ is Create React App 1.0.10 → webpack 2.6.1 / webpack-dev-server 2.5.0. Node 18 is the oldest LTS with a Debian bookworm image, so it is the most conservative base that still satisfies the full--bookworm requirement (the runtime installs deps inside this image and needs the node-gyp toolchain that -slim strips). I checked webpack 2.6.1's WebpackOptionsDefaulter directly: output.hashFunction defaults to md5, not md4, so the usual OpenSSL 3 ERR_OSSL_EVP_UNSUPPORTED breakage does not apply and no --openssl-legacy-provider shim is baked in.

Two CRA-1.x specifics a reviewer may want to scrutinize, both verified against the actual published package source rather than assumed:

  • Host header. react-scripts@1.0.10/config/webpackDevServer.config.js sets disableHostCheck: !proxy || DANGEROUSLY_DISABLE_HOST_CHECK === 'true'. web/package.json declares no proxy field, so host checking is off and the preview hostname is accepted. This is why no DANGEROUSLY_DISABLE_HOST_CHECK env var is needed — if a proxy field is ever added to web/package.json, host checking flips on and this Dockerfile will need that var.
  • HMR socket. react-dev-utils@3.0.2's webpackHotDevClient builds its SockJS URL from window.location (protocol/hostname/port) + /sockjs-node, so the websocket already follows the public preview origin through the proxy. WDS_SOCKET_PORT is still mapped from CODEPRESS_HMR_CLIENT_PORT in the CMD for contract uniformity; react-scripts only reads it from 3.4+, so today it is an intentional no-op that starts working if CRA is upgraded.

The CMD is sh -c 'HOST="$CODEPRESS_BIND_HOST" WDS_SOCKET_PORT="$CODEPRESS_HMR_CLIENT_PORT" exec yarn start' — a wrapper rather than plain ENV so the mappings resolve against runtime-injected values instead of being frozen at build time, and exec so signals reach react-scripts. BROWSER=none is a static ENV. The image bakes yarn 1.22.22 via corepack (repo ships a yarn lockfile v1, no packageManager field) so a cold MicroVM start doesn't fetch it from the registry first.

staging_backend_url is omitted, not empty. Exhaustive scan found no candidate at all: no .env* anywhere, no .github/workflows, no vercel.json, no next.config/vite.config, no .codepress/verify-staging/recipe.json. Per the "never persist a guess" rule the key is left out entirely. The frontend env-var prefill step was skipped as a consequence, and web/src reads no API base URL env var anyway.

No preview-CORS change, deliberately. The Django app in server/ was detected, but it fails the cross-origin gate on both signals: it carries no CORS surface (no django-cors-headers in Pipfile, nothing in INSTALLED_APPS/MIDDLEWARE, no CORS_* settings), and no same-repo frontend calls it cross-origin — web/src contains no fetch/axios/XHR call whatsoever. The architecture is same-origin by design: postbuild copies the CRA build into server/static/build/ and server/server/views.py renders index.html from the catch-all url(r'^', ...) route. Independently, server/ has a single flat settings.py with no staging module and no .env.staging, so even an eligible backend would have been a report-only case for lack of a staging-scoped config path.

No social-auth work. The runnable frontend has no sign-in flow — App.js routes only /Home. The backend exposes rest_auth/allauth endpoints but installs only allauth.account, with no allauth.socialaccount and no provider configured. samples/auth-web/ contains a GitHub OAuth button but is dead sample code: it lives outside web/, is imported by nothing, and references a ../../redux/auth module that does not exist.

Changes

  • Add .codepress/dev-server/recipe.json — schema_version 1, one frontend entry for web/ (CRA, yarn, dev_port 3000)
  • Add .codepress/dev-server/Dockerfile.web — thin dev-mode image on node:18-bookworm from the public ECR mirror
  • Pin Node 18 and document why (CRA 1.0.10 / webpack 2.6.1; md5 hashing, so no OpenSSL 3 workaround needed)
  • Bake yarn 1.22.22 via corepack to avoid a registry fetch on cold MicroVM start
  • Map CODEPRESS_BIND_HOST → HOST and CODEPRESS_HMR_CLIENT_PORT → WDS_SOCKET_PORT in a sh -c CMD wrapper so both resolve at runtime
  • Omit staging_backend_url — no .env*, CI, or deploy config exists to detect one from

Test plan

  • Build the image from the repo root: docker build -f .codepress/dev-server/Dockerfile.web -t drf-web-dev . — expect a clean build with no node_modules or source baked in.
  • Run it against the checkout and confirm the dev server compiles: docker run --rm -p 3000:3000 -v "$PWD":/app -e PORT=3000 drf-web-dev (run yarn install --frozen-lockfile in web/ first, or let the runtime hydrate deps). Expect Compiled successfully! in the logs.
  • Confirm it binds all interfaces, not loopback: the startup banner should print an On Your Network: address, and curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:3000/ should return 200.
  • Confirm the preview hostname is accepted (the CRA Invalid Host header failure mode): curl -s -H 'Host: 0123456789abcdef0123456789abcdef-a3bdc7594d3a2b9e.preview.codepress.dev' http://127.0.0.1:3000/ | grep -c 'Invalid Host header' should print 0, and the response should be the CRA index HTML with <title>React App</title>.
  • Confirm the HMR endpoint is live: curl -s http://127.0.0.1:3000/sockjs-node/info should return JSON containing "websocket":true.
  • Confirm client-side routing still falls through: curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:3000/some/deep/route should return 200.
  • Sanity-check the recipe parses and points at a real file: python3 -c "import json;r=json.load(open('.codepress/dev-server/recipe.json'));print(r['schema_version'], r['frontends'][0]['dockerfile_path'])".

Open items

  • I could not run a real docker build in this environment (no Docker daemon available), so the Dockerfile itself is validated statically against the contract rather than built. What I did verify for real: on Node 18.20.8 I ran yarn install --frozen-lockfile and then the recipe's literal dev_command with the Dockerfile's exact env defaults — it compiled, honored a non-default PORT, bound all interfaces, returned HTTP 200 for a preview-style Host header, and served a live /sockjs-node endpoint. The first docker build is the remaining unproven step.
  • Hot module replacement was verified only to the extent that the SockJS endpoint is live and reachable under a preview hostname; an actual browser edit-and-see-it-update cycle was not exercised. Note that CRA 1.x only hot-reloads CSS — JS edits trigger a full page refresh. That is upstream CRA behavior, not a limitation of this config.
  • Node 18 is EOL upstream. It is the right conservative choice for react-scripts 1.0.10 today, but if this frontend is ever upgraded past CRA 1.x the base image should be revisited — the pin exists for the old toolchain, not by preference.
  • This project has no staging environment, so if a preview ever needs to reach a real API, both a staging backend URL and (if it becomes cross-origin) a staging-scoped CORS allowance would need to be added. Neither is actionable from the repo as it stands today.

Authors

Generated with CodePress · View the chat session

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

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

- .codepress/dev-server/recipe.json  - one frontend entry for web/ (CRA,
  yarn, port 3000)
- .codepress/dev-server/Dockerfile.web - thin dev-mode image (no baked
  node_modules, no source COPY) that binds 0.0.0.0 and wires HMR to env vars

Node 18 is pinned because this app is Create React App 1.0.10
(webpack 2.6.1 / webpack-dev-server 2.5.0). Verified during bootstrap that
yarn install --frozen-lockfile + react-scripts start compile and serve on
Node 18.20.8, honor PORT, bind all interfaces, answer a preview-style Host
header with HTTP 200, and expose a live /sockjs-node HMR endpoint.

No staging backend URL was detected (repo has no .env*, CI, or deploy
config), so staging_backend_url is intentionally omitted. No preview-CORS
change was needed: the Django app in server/ serves the built React bundle
same-origin and has no CORS surface or cross-origin caller.

Co-authored-by: dev@codepress.dev <dev@codepress.dev>
@codepress-dev codepress-dev Bot added the cp:ready-for-review CodePress: finished and ready for review label Jul 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cp:ready-for-review CodePress: finished and ready for review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants