Skip to content

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

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

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

Conversation

@codepress-dev

@codepress-dev codepress-dev Bot commented Jul 25, 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 a preview would have had to guess how to start the app; from here on it boots from a recipe that lives in the repo, so previews are predictable and you can change how they start by editing these two files. Nothing about how the app runs today changes — the added files are only read by CodePress previews. Two things were deliberately left alone: no staging backend URL is recorded (the repo has no environment or deploy config to read one from, and guessing one would be worse than leaving it blank), and the Django API in server/ was not modified, because it serves the built React app on the same origin and has no cross-origin API surface that would need a preview allowance.

Technical details

Adds .codepress/dev-server/recipe.json (schema_version 1) with a single frontend entry for web/, plus the matching dev-mode Dockerfile.web. No existing file is touched.

Frontend discovery. web/ is the only runnable frontend: CRA via react-scripts@1.0.10, yarn.lock v1 → package_manager: yarn, install_command: yarn install --frozen-lockfile, dependency_manifests: ["web/yarn.lock"] (per-app lockfile, not a root one), dev_port: 3000. samples/auth-web/ is dead reference code — it imports paths that do not exist in this repo (../../redux/auth, ../../../config/settings) and is not reachable from web/src, so it is not a frontend and its GitHub button does not make this a social-auth repo. web/public/index.html is a CRA template with %PUBLIC_URL% placeholders, i.e. build input, not a static site. prebuild_command is empty: the postbuild script that copies build/ into Django's static dir is production-only, not a dev prerequisite.

Node 18, on purpose. The repo pins no version (engines/.nvmrc absent) and this is a 2017-era toolchain (webpack 2.6.1, webpack-dev-server 2.5.0, React 15) that does not run on current Node majors, so the base is the oldest Debian-bookworm Node image rather than current LTS. It is the full image, not the trimmed variant, since dependencies install at runtime and need the node-gyp toolchain.

Corepack is deliberately NOT enabled. The repo declares no packageManager field, and node:18-bookworm already bundles Yarn 1.22. Enabling corepack would replace that binary with a shim that downloads Yarn from the public registry on first use, adding a network dependency to every cold start. A pinned npm i -g yarn@1.22.22 fallback runs only if the base image ever stops shipping Yarn.

CRA specifics were verified against the pinned source (react-scripts@1.0.10, react-dev-utils@3.0.2) rather than assumed:

  • scripts/start.js reads HOST and PORT for bind, so the CMD maps HOST from CODEPRESS_BIND_HOST — bind is 0.0.0.0, never loopback-only.
  • config/webpackDevServer.config.js sets disableHostCheck: !proxy || DANGEROUSLY_DISABLE_HOST_CHECK === 'true'. This package.json has no proxy field, so webpack-dev-server's DNS-rebinding host check is already off and the preview hostname is accepted; the env var is set explicitly anyway so a later proxy addition doesn't silently break previews.
  • react-dev-utils/webpackHotDevClient.js builds its SockJS URL from window.location (protocol/hostname/port) at /sockjs-node, so HMR rides the public preview origin automatically. This version has no WDS_SOCKET_PORT support — it is passed for the uniform runtime contract and for a future react-scripts upgrade, and is inert today.
  • BROWSER=none stops openBrowser from trying to launch a browser inside the container; NODE_OPTIONS=--openssl-legacy-provider is appended (preserving any existing value) as insurance for this vintage webpack's hashing under OpenSSL 3.

Image shape. Thin per contract: no COPY of source or manifests, no baked node_modules, no install layer, no CodePress binary. WORKDIR /app then /app/web, with /app/web/node_modules/.bin:/app/node_modules/.bin prepended to PATH as a backstop. The recipe's dev_command is byte-identical to the Dockerfile CMD body, so the container path and the direct MicroVM path behave the same — that equality is machine-checked.

Why server/ was not edited. Preview CORS requires a backend that serves cross-origin browser clients. web/src makes zero API calls (no fetch, no axios, no absolute base URL, no process.env API var), and server/server/settings.py has no CORS middleware and no django-cors-headers dependency — no allowlist to append to. The architecture is same-origin by design: postbuild copies the CRA build into server/static/build/ and Django's catch-all URL renders index.html. There is also no staging environment (single settings.py, DEBUG=True, no .env*, no vercel.json, no CI workflows), and the staging-scoping rule forbids adding a preview allowance to shared/production config. Adding django-cors-headers plus middleware would be an unrequested architectural change to production-shared settings, so this is a report, not an edit.

Changes

  • Add .codepress/dev-server/recipe.json — schema_version 1, one web frontend entry (CRA, yarn, port 3000, procps, size medium)
  • Add .codepress/dev-server/Dockerfile.web — thin dev-mode image on node:18-bookworm, binds 0.0.0.0 via CODEPRESS_BIND_HOST, declares the PORT/HMR env contract, CMD runs yarn start
  • Omit staging_backend_url — no environment or deploy config in the repo to detect one from
  • Leave server/ untouched — no CORS surface, same-origin architecture, no staging config path

Test plan

  • Confirm the recipe parses and matches the Dockerfile: python3 -c "import json;r=json.load(open('.codepress/dev-server/recipe.json'));print(r['schema_version'], r['frontends'][0]['label'], r['frontends'][0]['dev_port'])" → prints 1 web 3000.
  • Confirm the Dockerfile CMD body is identical to the recipe's dev_command (so container and MicroVM runs match): compare grep '^CMD' .codepress/dev-server/Dockerfile.web with the dev_command value in recipe.json.
  • Build the dev image from the repo root: docker build -f .codepress/dev-server/Dockerfile.web -t ddi-web-dev . → succeeds, and docker run --rm ddi-web-dev yarn --version prints a 1.22.x version (Yarn Classic, matching web/yarn.lock).
  • Run it against the checkout the way the runtime does: docker run --rm -v "$PWD:/app" -e PORT=3000 -p 3000:3000 --entrypoint yarn ddi-web-dev install --frozen-lockfile, then docker run --rm -v "$PWD:/app" -e PORT=3000 -p 3000:3000 ddi-web-dev. Expect Compiled successfully! and the dev server listening on 0.0.0.0:3000 (not 127.0.0.1).
  • Load http://localhost:3000 → the React welcome page renders. Edit web/src/containers/home/Home.js, save, and confirm the browser updates without a manual reload (the HMR socket connects at /sockjs-node on the page origin).
  • Start a CodePress live preview for this repo and confirm it boots from the recipe (framework cra, port 3000) and that the preview URL renders the app rather than failing a host check.

Open items

  • Not run end-to-end: this bootstrap environment has no Docker, so the image was validated against the contract and against the pinned react-scripts@1.0.10 / react-dev-utils@3.0.2 source, but never actually built or booted. The first preview build is the real test — the most likely snag is the 2017 dependency tree installing under Node 18, which is why Node is held at 18 rather than current LTS.
  • No staging backend URL is recorded, so previews will not pre-fill a backend target. If a staging API exists somewhere outside the repo, add staging_backend_url to the recipe and it will be picked up.
  • Preview CORS was intentionally not configured. The frontend makes no API calls today, so nothing is broken. If you later wire web/ to call the Django API cross-origin from a preview, server/ will need a staging-scoped CORS allowance for the preview origin — that means adding django-cors-headers and, ideally, a staging settings module to scope it to, which this run declined to introduce unprompted.
  • Preview social auth was not applicable: the runnable frontend has no sign-in flow. The GitHub OAuth button under samples/auth-web/ is unreachable reference code, so no auth-relay wiring was added.

Authors

Generated with CodePress · View the chat session

Author 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 web/ (CRA via
  react-scripts@1.0.10, Yarn 1 Classic, port 3000, procps).
- .codepress/dev-server/Dockerfile.web: thin, dev-mode image on
  node:18-bookworm. Binds 0.0.0.0 through CODEPRESS_BIND_HOST, wires the
  HMR/bind env contract, bakes no node_modules and no source.

Node is pinned to 18 because this app's 2017-era toolchain (webpack 2.6.1,
webpack-dev-server 2.5.0, React 15) does not run on current Node majors and
the repo pins no version itself. Corepack is deliberately left off so the
base image's bundled Yarn 1 is used instead of a shim that downloads Yarn on
every cold start.

No staging backend URL was detected (no .env files, deploy config, or CI
workflows), so staging_backend_url is omitted rather than guessed. The Django
API in server/ was left untouched: it has no CORS surface and serves the
built React app same-origin, so no preview-CORS allowance applies.

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