Skip to content

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

Open
codepress-dev[bot] wants to merge 1 commit into
masterfrom
codepress/dev@codepress.dev/you-are-bootstrapping-the-live-dev-bed74342
Open

Bootstrap CodePress Live Dev Server recipe + dev Dockerfile#55
codepress-dev[bot] wants to merge 1 commit into
masterfrom
codepress/dev@codepress.dev/you-are-bootstrapping-the-live-dev-bed74342

Conversation

@codepress-dev

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

Copy link
Copy Markdown
Contributor

Summary

This sets up live previews for this repo. Until now, CodePress had to guess how to start your frontend; this PR adds two small config files that tell it exactly how, so a preview of the React app in web/ boots reliably and updates as you edit.

The only runnable frontend here is the create-react-app in web/. It's a 2017-era toolchain (react-scripts 1.0.10 on webpack 2), which is exactly the kind of setup a generic heuristic gets wrong — so rather than guessing, I actually installed and ran it to confirm the image will work: it boots, serves the app under a preview address, and its hot-reload connection comes up.

Nothing about how your app runs changes. These files are only read by CodePress previews; your existing yarn start and production build are untouched.

One thing I deliberately did not do: I left your Django backend alone. Previews sometimes need a CORS tweak so the previewed frontend can call the API, but that doesn't apply here — web/ makes no API calls, and in production Django serves the React build itself, so it's same-origin. There's also no staging environment to scope such a change to. Details in the open items below.

Technical details

Adds .codepress/dev-server/recipe.json (the contract the Live Dev Server reads) and .codepress/dev-server/Dockerfile.web (a thin, dev-mode, toolchain-only image). No application code is touched.

Discovery. One runnable frontend: web/framework: cra, package_manager: yarn (yarn lockfile v1, no packageManager field), dev_port: 3000, dependency_manifests: ["web/yarn.lock"], install_command: yarn install --frozen-lockfile, size: small. No prebuild step (postbuild is a production-only hook that copies the build into server/static/build/, so it stays out of dev_command). samples/auth-web/ is loose reference snippets — no package.json/index.html, not imported by web/src — so it is not a frontend.

Why node:18-bookworm. This was the main judgement call. -bookworm tags start at Node 18, which is also the closest available match to a react-scripts 1.0.10 / webpack 2.6.1 dependency tree. Rather than assume it works, I ran it: installed web/'s deps under Node 18.20.8 (OpenSSL 3.0.16 — identical to the image) with yarn install --frozen-lockfile, started the dev server, and verified HTTP 200 on /, HTTP 200 on a non-loopback interface (proving the 0.0.0.0 bind), and /sockjs-node/info returning {"websocket":true}.

Three findings from that testing changed the output, and are each worth a look:

  • No NODE_OPTIONS=--openssl-legacy-provider. The reflex for webpack-on-OpenSSL-3 is the legacy-provider flag, but that's a webpack 4+ problem (md4). webpack 2.6.1 hashes with md5, which OpenSSL 3 still provides. I confirmed the dev server compiles cleanly without the flag, so it isn't set — one less bit of unexplained config.
  • Corepack is deliberately not enabled, contrary to the usual template. The repo declares no packageManager, so corepack enable would replace the yarn 1.22 already baked into the node image with a shim that resolves a yarn release over the network on first run — a cold-start failure mode for no benefit.
  • No HMR client-port wiring. react-dev-utils 3.0.2's webpackHotDevClient builds its SockJS URL from window.location (verified in the package source), so it follows the preview origin to wss/443 on its own. WDS_SOCKET_PORT is still mapped from CODEPRESS_HMR_CLIENT_PORT in the CMD; it is inert on this pinned version and only takes effect if react-scripts is upgraded to >= 3.4. The Dockerfile comment says so explicitly so it doesn't read as working config.

DANGEROUSLY_DISABLE_HOST_CHECK=true is set defensively: webpack-dev-server 2.5.0 does have checkHost, and react-scripts only auto-disables it while no proxy key exists in web/package.json. That's true today (hence the verified 200 under a preview Host header), but adding a proxy later would otherwise silently break previews with "Invalid Host header".

The image satisfies the thin-image contract: full -bookworm base (not -slim, so runtime node-gyp installs have a toolchain), no baked node_modules, no source COPY, procps installed, WORKDIR /app/app/web, and bind/HMR driven entirely by CODEPRESS_BIND_HOST/PORT/CODEPRESS_HMR_* with no localhost literals.

staging_backend_url is omitted — no .env*, no CI workflows, no vercel.json, no verify-staging recipe, so there was no candidate. Per the never-persist-a-guess rule the key is absent rather than empty, and no Live Dev Server env var was prefilled (web/ reads no API-base env var).

No backend CORS edit. Django is in server/, but the gate fails on two independent counts: it has no cross-origin surface (no django-cors-headers anywhere, and web/src issues zero API calls — redux/example.js is a boilerplate reducer, not an auth flow), and there is no staging-only config path to scope an allowance to (a single server/server/settings.py, no settings package, no env gating). Adding CORS would have meant introducing a dependency and inventing a staging environment, which is well outside an append-only allowance — so this is correctly report-only.

No social-auth work. No runnable frontend has social or enterprise sign-in (web/ has a single / route and no sign-in UI), so the preview social-auth audit was not applicable.

Changes

  • Add .codepress/dev-server/recipe.json — schema_version 1, one frontend entry for web/ (cra, yarn, port 3000)
  • Add .codepress/dev-server/Dockerfile.web — thin dev-mode image on node:18-bookworm with env-driven bind and HMR
  • Pin node:18-bookworm and omit the OpenSSL legacy-provider flag, both verified by running the dev server
  • Skip corepack in favour of the image's preinstalled yarn 1, since the repo declares no packageManager
  • Set DANGEROUSLY_DISABLE_HOST_CHECK so previews keep working if a proxy key is ever added to web/package.json

Test plan

  • Build the image from the repo root: docker build -f .codepress/dev-server/Dockerfile.web -t ddi-web . — it should succeed and bake no node_modules.
  • Install deps the way the runtime does: from web/, run yarn install --frozen-lockfile on Node 18. It should complete without node-gyp errors (fsevents is darwin-only and is skipped on linux).
  • Run the container with the checkout mounted at /app and confirm the dev server starts: docker run --rm -p 3000:3000 -v "$PWD":/app ddi-web. Expect create-react-app's "Compiled successfully!".
  • Confirm it binds all interfaces, not loopback: curl -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3000/ returns 200.
  • Confirm the preview Host header is accepted (the "Invalid Host header" regression): curl -o /dev/null -w '%{http_code}\n' -H 'Host: 0123456789abcdef0123456789abcdef-de116f94b7ab06ad.preview.codepress.dev' http://127.0.0.1:3000/ returns 200.
  • Confirm the hot-reload endpoint is live: curl http://127.0.0.1:3000/sockjs-node/info returns JSON containing "websocket":true.
  • Open a CodePress preview, edit web/src/containers/home/Home.js, and verify the browser hot-reloads without a manual refresh.
  • Confirm nothing else changed: git diff --stat origin/master...HEAD should list only the two files under .codepress/dev-server/.

Open items

  • Backend CORS was intentionally not changed. The Django API in server/ is same-origin (web/ makes no API calls, and its production build is served by Django's catch-all index view), and the repo has no staging-only config path to scope an allowance to. If you later add cross-origin API calls from the previewed frontend, preview requests will need an anchored allowance for ^https://[0-9a-f]{32}-de116f94b7ab06ad.preview.codepress.dev$ added to a staging-only Django settings path (via django-cors-headers' CORS_ALLOWED_ORIGIN_REGEXES) — never to base or production config. Any such change only affects the live API after staging is deployed with it.
  • No staging backend URL was detected, so staging_backend_url is omitted from the recipe and no backend URL was prefilled into the Live Dev Server env settings. Previews still run; the UI just won't pre-fill a backend.
  • The dev image was validated by running this app's dev server on a matching Node 18.20 / OpenSSL 3 toolchain, but the Docker image itself was not built (no Docker daemon in the bootstrap environment). The build step in the test plan is the one unexercised path.
  • react-scripts 1.0.10 is pinned exactly and is ~8 years old. The recipe is built around that pin (Node 18 base, no corepack, window.location-based HMR). If you upgrade react-scripts, re-run /codepress-bootstrap-dev-server so the base image and HMR wiring are re-derived — the generated files carry managed-file headers and are safe to regenerate.

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.

Discovered one runnable frontend: the create-react-app app in web/
(react-scripts 1.0.10 / webpack 2.6.1, yarn classic lockfile).

Dockerfile.web pins node:18-bookworm -- the oldest Debian-bookworm Node
image and the closest match to this 2017-era toolchain. Verified on Node
18.20 / OpenSSL 3 that the app installs with `yarn install
--frozen-lockfile`, boots, binds 0.0.0.0, serves HTTP 200 under a
preview Host header, and exposes a live /sockjs-node HMR endpoint.

Notes on deliberate choices:
- No --openssl-legacy-provider: webpack 2 hashes with md5, not md4, so
  OpenSSL 3 does not break it (confirmed by running the dev server).
- Corepack is not enabled: the repo declares no `packageManager`, so a
  corepack shim would try to fetch yarn from the network on cold start.
- No HMR client-port wiring needed: react-dev-utils 3.0.2 builds its
  SockJS URL from window.location, so it follows the preview origin.

No backend CORS change: the Django API in server/ is same-origin only
(web/ makes no API calls and its build is served by Django), and the
repo has no staging config path to scope an allowance to.

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