Repository navigation
docs: run the production frontend with bun scripts/serve.ts - #272
Conversation
With Bun 1.4.2's default system shell, `bun run start` and `bun start` deliver one terminal Ctrl+C to the server twice (the terminal signals the foreground group and `bun run` forwards it as npm does), so adapter-bun treats it as a second signal and exits 1 at once without the SHUTDOWN_TIMEOUT drain. A group SIGTERM is doubled the same way. `NODE_ENV=production bun scripts/serve.ts`, run from frontend/, receives each signal once. Point README.md, frontend/README.md, CLAUDE.md, frontend/CLAUDE.md and .env.example at the direct command, say why, and name the working directory. The `start` package script is unchanged. Signed-off-by: edbfi <326875205+edbfi@users.noreply.github.com>
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
Reviewed the full docs-only diff (5 files) against main, and checked the documented command against frontend/package.json and the remaining references in the repo.
README.mdandfrontend/README.md— the production start command is nowNODE_ENV=production bun scripts/serve.tsfromfrontend/, with a short explanation of whybun run startandbun startare avoided.CLAUDE.mdandfrontend/CLAUDE.md— the production notes name the direct command, its working directory and the double-signal reason..env.example— theORIGINcomment names the direct command instead ofbun run start.
The new command matches the start script in frontend/package.json exactly. No stale bun run start recommendations remain; the two leftover mentions in frontend/scripts/serve.ts and serve.test.ts are accurate code comments about the double hangup.
ℹ️ Nitpicks
- The command string now lives in
package.jsonand in five doc locations. If thestartscript changes (for example a new flag), the docs will drift silently. Not worth fixing here.
claude-sonnet-5-5 | 𝕏
|
Re the nitpick in this review (the command string now lives in |
…273) The SIGHUP comment in frontend/scripts/serve.ts explains the double hangup under `bun run start`. Keep that and add that the production command, `NODE_ENV=production bun scripts/serve.ts` from frontend/, gets it once, as CLAUDE.md says since #272. Comment only. Signed-off-by: edbfi <326875205+edbfi@users.noreply.github.com>

Summary
The README files, both
CLAUDE.mdfiles and.env.exampletell people to start the production frontend withbun run start. With Bun 1.4.2's default system shell,bun run startandbun startdeliver one terminal Ctrl+C to the server twice: the terminal signals the foreground process group, andbun runalso forwards the signal to its child, as npm does. adapter-bun 1.0.0 treats the second delivery as a second signal (if (shutting_down) return process.exit(1);), and the front's own handler does the same before the adapter has loaded, so a single Ctrl+C exits 1 at once with noSHUTDOWN_TIMEOUTdrain. A groupSIGTERMis doubled the same way.NODE_ENV=production bun scripts/serve.ts, run fromfrontend/(what thestartscript runs), receives each signal once.This PR changes the documented production command to
NODE_ENV=production bun scripts/serve.ts, says why, and names the working directory. It is docs only: thestartpackage script, the code, the Docker image and CI are unchanged. Same defect and fix shape as edbfi/poyo-studio#90.Changes
README.md, "Development and production frontend": the block now says it runs infrontend/and starts withNODE_ENV=production bun scripts/serve.ts, followed by one line saying it is what thestartscript runs and whybun run startandbun startare not used. "WithORIGINset,startfronts the SvelteKit server" now namesscripts/serve.ts. The note that the container runs the same entry point stays true (the s6runfile in zondarr-docker execsbun ./scripts/serve.ts).frontend/README.md: the "Start the built server" row isNODE_ENV=production bun scripts/serve.ts(fromfrontend/, since the--cwdprefix in the table's intro applies only tobun runscripts), with one paragraph below the table on why.CLAUDE.md: the production note names the direct command, its directory, and why notbun run start.frontend/CLAUDE.md: the production note names the direct command and why (one Ctrl+C or groupSIGTERMarrives twice underbun run start; the second exits 1 without the drain)..env.example: theORIGINcomment names the frontend server by its direct command instead ofbun run start.No existing doc in this repository said "a second Ctrl+C /
SIGTERMstops at once" or described repeatedSIGHUPs, so there was no such wording to re-check. The code comment infrontend/scripts/serve.tsabout the hangup arriving twice underbun run startis accurate and left alone (docs-only PR).Rationale
Changing how
bun runlaunches the script (a bunfig[run] shell = "bun"or--shell=bun) was considered and not chosen: under the Bun shell,SIGTERM/SIGHUPsent to the launcher PID kill the launcher and orphan the server (oven-sh/bun#41802, still open). The system-shell double forwarding is intentional npm parity in Bun (oven-sh/bun#36711). Running the front directly avoids both.Validation
Signal run on this repository's built frontend, Bun 1.4.2 on macOS, 2026-10-07,
origin/main8a51968:bun run build, thenbuild/,package.jsonandscripts/serve.tscopied into a fresh temp directory (withnode_moduleslinked) and started through each launcher in its own process group on a free loopback port, withSHUTDOWN_TIMEOUT=3andINTERNAL_API_URLpointing at a stand-in backend that accepts requests and never answers. One group signal was then sent, as a terminal does.SIGINT(Ctrl+C)SIGTERMbun run startORIGINset (front), idleNODE_ENV=production bun scripts/serve.tsORIGINset (front), idlebun run startORIGINset, one/apirequest openNODE_ENV=production bun scripts/serve.tsORIGINset, one/apirequest openSHUTDOWN_TIMEOUTdeadline); the request got a 503 at the deadlinebun run startORIGINunset (adapter only), idleNODE_ENV=production bun scripts/serve.tsORIGINunset (adapter only), idleUnder
bun run startthe adapter printed "Waiting for 1 requests to finish before shutting down... Press Ctrl+C again to force shutdown." and exited 1 in the same instant: the forwarded copy of the one Ctrl+C was taken as that second press. Under the direct command it waited out the drain and exited 0.Local gates on head
83f5dc0(the repository's only workflow is Pullfrog):prek run --from-ref origin/main --to-ref HEAD: every applicable hook passed (whitespace, end of file, line endings, merge conflicts, case conflicts, large files, private keys, branch guard, gitleaks); Biome, Ruff and the JSON/TOML/YAML checks were skipped because no matching file changed.prek run --hook-stage commit-msg: Conventional Commit passed.bun run check:biome(biome ci .., fromfrontend/): passed, 267 files, no errors; its 17 warnings and 3 infos are in source files this PR does not touch.TypeScript Check(bun run --cwd frontend check) andFrontend Tests(bun run --cwd frontend test) passed.git diff origin/main --stat:.env.example,CLAUDE.md,README.md,frontend/CLAUDE.md,frontend/README.mdonly.