Skip to content

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

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

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

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 that opening a live preview boots the React app from files committed here rather than from a guess made at runtime. Two files are added under .codepress/dev-server/: a recipe that records how the frontend runs (where it lives, how to install it, the command that starts it, and the port it listens on), and a matching dev-mode Docker image definition for it. Nothing about how the app builds or runs for you locally changes — these files are only read by the preview system.

Discovery found one runnable frontend (web/, a Create React App project) and one backend (server/, Django). The Django API was inspected for preview CORS setup and intentionally left untouched: it has no cross-origin API surface (it serves the built React app itself, same-origin, and has no CORS allowlist or django-cors-headers dependency), and the repo has a single settings module with no separate staging environment to scope such a change to. No staging backend URL exists anywhere in the repo, so none was recorded — a guessed or production URL would point previews at the wrong API. The frontend has no social sign-in, so no auth work was needed either.

Because this frontend is a 2017-era toolchain (react-scripts 1.0.10 / webpack 2 / React 15), the setup was validated by actually installing and booting it rather than assumed — see the test plan.

Technical details

.codepress/dev-server/recipe.jsonschema_version: 1 with a single frontends[] 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"] (the per-app lockfile, not a root one — there is no workspace here), system_packages: ["procps"], size: medium. prebuild_command is empty: the postbuild script (cp -r build/ ../server/static/build/) is production-only and never runs in dev. staging_backend_url is omitted — there is no .env*, vercel.json, CI workflow, or .codepress/verify-staging/recipe.json to detect one from, so nothing was persisted and the Live Dev Server env prefill was skipped.

dev_command is sh -c 'HOST="${CODEPRESS_BIND_HOST:-0.0.0.0}" WDS_SOCKET_PORT="${CODEPRESS_HMR_CLIENT_PORT:-443}" BROWSER=none yarn start'. react-scripts reads HOST/PORT from env (confirmed against the 1.0.10 source), so CRA's HOST is mapped from the CodePress bind var rather than hardcoded.

.codepress/dev-server/Dockerfile.web — thin, toolchain-only image on public.ecr.aws/docker/library/node:22-bookworm (full base, not -slim): no COPY, no baked node_modules, no install layer; deps arrive at runtime on the bind-mounted checkout. WORKDIR /app/app/web, procps via apt, the four bind/HMR env vars declared with defaults, and node_modules/.bin prepended to PATH as a backstop.

Three decisions worth a close look:

  1. Node 22, and no corepack. The repo pins no Node version, so this uses the current LTS — verified to work, not assumed (webpack 2 defaults to an md5 hash function, so it sidesteps the OpenSSL 3 md4 breakage that kills webpack 4 on modern Node; only deprecation warnings appear). Corepack is deliberately not enabled: node:22-bookworm already ships yarn 1.22.22 (verified in the official image Dockerfile), which is exactly what this v1 yarn.lock needs, and corepack enable would replace that working binary with a shim that resolves a version at first use — a possible network fetch during a cold start. A RUN yarn --version assertion fails the build loudly if a future base image ever drops the bundled yarn. Node 18 was also verified to work, if the base ever needs to move back.

  2. DANGEROUSLY_DISABLE_HOST_CHECK=true in the dev image. react-scripts 1.x only skips webpack-dev-server's DNS-rebinding host check when no proxy is set in package.json — which is the case today, so previews work either way. Setting it explicitly keeps the preview's *.preview.codepress.dev Host header accepted if a proxy key is ever added. This is the same role Vite's server.allowedHosts plays, and it applies only to this dev-preview image, never to a production build.

  3. HMR needs no config shim. react-scripts 1.0.10's hot client builds its SockJS URL from window.location (verified in react-dev-utils@4.2.1/webpackHotDevClient.js), so the websocket rides the preview origin over wss automatically, like Next.js. WDS_SOCKET_PORT is carried for the uniform runtime contract but is inert on this CRA version — worth knowing so nobody later "fixes" HMR by editing config that isn't read.

No backend CORS change. Documented rather than silently skipped: server/server/settings.py has no corsheaders app, no middleware, and no CORS_* settings, and no frontend code performs any fetch/XHR (web/src/redux/example.js is a local-only redux stub). Adding a CORS surface would mean introducing a new Python dependency and inventing a cross-origin contract this app doesn't have — and there is no staging-only config path to scope it to, since settings.py is the single settings module. If a preview later needs the frontend to call this Django API cross-origin, that is an explicit follow-up: add django-cors-headers, split out a staging settings module, and allow only the anchored preview-origin pattern there.

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:22-bookworm that binds 0.0.0.0, installs procps, and runs yarn start with HMR wired to the runtime env vars
  • Omit staging_backend_url — no staging URL exists anywhere in the repo, so none was guessed
  • Leave the Django backend untouched — no cross-origin CORS surface and no staging-only config path to scope a preview allowance to

Test plan

  • Confirm the recipe is well-formed: python3 -c "import json;print(json.load(open('.codepress/dev-server/recipe.json'))['frontends'][0])" — one entry, working_dir: web, dev_port: 3000.
  • Reproduce the install on the base image's toolchain: cd web && yarn install --frozen-lockfile under Node 22 with yarn 1.22.x. It completed in ~10-27s here with no native build failures (the only native package, fsevents, is darwin-only and is skipped on linux).
  • Run the recipe's dev_command verbatim: cd web && env PORT=3200 CODEPRESS_BIND_HOST=0.0.0.0 CODEPRESS_HMR_CLIENT_PORT=443 DANGEROUSLY_DISABLE_HOST_CHECK=true sh -c 'HOST="$CODEPRESS_BIND_HOST" WDS_SOCKET_PORT="$CODEPRESS_HMR_CLIENT_PORT" BROWSER=none yarn start' → expect "Compiled successfully!" and a bind on all interfaces (it prints an "On Your Network" URL, not just localhost).
  • Verify what a preview needs: curl -o /dev/null -w '%{http_code}' http://127.0.0.1:3200/ → 200; /static/js/bundle.js → 200; /sockjs-node/info → 200; and with -H 'Host: <32-hex>-f99e6fb9528a8773.preview.codepress.dev' → 200 (the preview Host header is accepted).
  • Verify the HMR websocket accepts an upgrade: curl -i --max-time 5 -H 'Connection: Upgrade' -H 'Upgrade: websocket' -H 'Sec-WebSocket-Version: 13' -H 'Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==' 'http://127.0.0.1:3200/sockjs-node/1/abc/websocket'HTTP/1.1 101 (the client-side URL is derived from window.location, so it targets the preview origin over wss).
  • Verify live reload: append a comment to web/src/index.js while the server runs → the log shows "Compiling..." then "Compiled successfully!".
  • After merge, open a Live Dev Server preview for this repo and confirm the React welcome page renders and an edit to web/src/containers/home/Home.js appears without a manual restart.

Open items

  • The Docker image itself was not built here — no Docker daemon was available in this session. Everything the image does was validated directly on the same Node 22 / yarn 1.22.22 toolchain the base image ships, but the first real image build happens on the next preview claim.
  • Preview CORS was intentionally not configured. The Django API has no cross-origin surface today (it serves the React build same-origin) and the repo has no staging environment to scope an allowance to. If the frontend later calls this API cross-origin from a preview, that needs an explicit follow-up: add django-cors-headers, introduce a staging settings module, and allow only the anchored preview-origin pattern there — never in the shared/production settings.
  • react-scripts 1.0.10 (2017) is what this app pins, so the dev image is validated against that, not upgraded. Node 22 runs it with only deprecation warnings; Node 18 was also verified as a fallback if a future toolchain change breaks it.
  • samples/auth-web/ contains a GitHub OAuth button sample, but it is not part of the runnable frontend (no package.json, not imported by web/src), so no preview social-auth work applied.

Authors

Generated with CodePress · View the chat session

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

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

Discovery found one runnable frontend, `web/` (Create React App via
react-scripts 1.0.10, yarn 1 classic lockfile, dev port 3000), and one backend,
`server/` (Django 1.11). The Django app has no CORS surface and no cross-origin
caller — it serves the React production build itself — so no preview-CORS edit
was made. No staging backend URL was detected anywhere in the repo, so
`staging_backend_url` is deliberately omitted rather than guessed.

Verified on the same Node/yarn versions the base image ships (node 22.x with the
bundled yarn 1.22.22): `yarn install --frozen-lockfile` resolves the 2017
lockfile cleanly, the recipe's `dev_command` compiles and serves HTTP 200 on
`$PORT`, binds all interfaces, answers a `*.preview.codepress.dev` Host header,
serves `/sockjs-node` with a 101 websocket upgrade, and recompiles on file edits.

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