Fix cross-OS installs (pin deps, drop lockfiles) and boot playground out of the box#3
Merged
Merged
Conversation
Workshop installs were breaking on macOS/Linux. The committed package-lock.json was generated on Windows and pinned only win32-x64 native binaries (@rollup/rollup, @esbuild, @tailwindcss/oxide, lightningcss, @unrs/resolver), so other platforms hit npm's optional-deps bug (npm/cli#4828): "Cannot find module @rollup/rollup-darwin-arm64". - Pin every dependency to an exact version across the root, all 20 exercise apps, and epicshop (per-workspace resolution, so divergent versions like exercises' @types/node@20 / zod@4 are preserved). - Gitignore + untrack package-lock.json so each machine resolves its own OS-native binaries on a fresh install. Exact pins keep top-level versions deterministic without a committed lockfile. Verified: clean-room root install (no ERESOLVE), standalone install of every exercise, and a from-scratch --strict-peer-deps resolve all pass.
Fresh playgrounds had no .env, so DATABASE_URL was unset and the app crashed on boot (db.server.ts calls prisma.$connect() at import). And from the first exercise's solution onward, the OpenRouter adapter is constructed at module scope, which throws when OPENROUTER_API_KEY is empty -> every page 500s, not just chat. - post-set-playground.js now creates the playground .env from the exercise's .env.example when none exists (after the stash/restore, so a student's edited key is never clobbered). - .env.example ships DATABASE_URL plus a non-empty placeholder OPENROUTER_API_KEY, so openRouterText() constructs and every exercise boots. Chat returns 401 until the student pastes a real key. Verified: all 20 exercise dev servers serve the homepage (HTTP 200) from .env alone, with no key set beyond the placeholder.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Students kept hitting OS-specific setup failures. Two root causes:
package-lock.jsonwas generated on Windows and only pinnedwin32-x64native binaries (@rollup/rollup,@esbuild,@tailwindcss/oxide,lightningcss,@unrs/resolver). macOS/Linux students hit npm's optional-deps bug (npm/cli#4828) →Cannot find module @rollup/rollup-darwin-arm64. (There's no rolldown in this repo — the native-binary chain is rollup/esbuild/oxide/lightningcss/unrs.).env, soDATABASE_URLwas unset anddb.server.tscrashed atprisma.$connect(). And from exercise 1's solution onward the OpenRouter adapter is constructed at module scope, which throws on an emptyOPENROUTER_API_KEY→ every page 500s (not just chat).What changed
Deps / installs
epicshop. Per-workspace resolution, so divergent versions are preserved (exercises keep@types/node@20.19.41/zod@4.4.3; root keeps@types/node@24.12.4).package-lock.json. Each machine now resolves its own OS-native binaries on a fresh install; exact pins keep top-level versions deterministic without a committed lockfile.Boot out of the box
epicshop/post-set-playground.jsseeds the playground.envfrom the exercise's.env.examplewhen none exists — placed after the existing stash/restore so a student's edited key is never clobbered..env.examplenow shipDATABASE_URL+ a non-empty placeholderOPENROUTER_API_KEY. App boots on every exercise; chat returns 401 until the student pastes a real key. No app/teaching code touched.Verification
npm install: exit 0, noERESOLVE.--strict-peer-depsresolve passes → peers are genuinely compatible, not just force-installed (legacy-peer-deps=truekept as a safety net)..envalone.Tradeoff
Direct deps are frozen; transitive patches still float on fresh installs (e.g.
rollup 4.60 → 4.62). If byte-for-byte reproducibility is ever needed, the alternative is committing an all-platform lockfile viaoptionalDependencies(~100 entries, higher maintenance) — deliberately not taken here.