Skip to content

Bundle the frontend into one binary with production CLI startup - #8

Merged
luhe19001 merged 6 commits into
mainfrom
helu/eng-1313-bundle-the-frontend-into-one-binary-with-production-cli
Aug 4, 2026
Merged

Bundle the frontend into one binary with production CLI startup#8
luhe19001 merged 6 commits into
mainfrom
helu/eng-1313-bundle-the-frontend-into-one-binary-with-production-cli

Conversation

@luhe19001

@luhe19001 luhe19001 commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Context

Running the product needed Node, Vite, and a separate API process. This change produces one executable that serves the compiled React app and the Go API from the same loopback origin, so a release build is enough to run the full product locally.

Host/origin hardening, CI for the release path, and published artifacts are intentionally out of scope.

Changes

  • make release builds the frontend, stages it into the Go module for embedding, and writes a single bin/coslash binary; missing index.html fails the build clearly.
  • The binary serves real frontend files (including hashed assets), falls back to index.html for client routes like /coslash, and returns 404 for missing asset paths and unrouted /api/* paths.
  • Startup listens on loopback only, binds before opening the browser, and supports --version, --port, and --no-open, with actionable errors for port conflicts and browser-open failures.
  • Root README is a short quick start for build, run, and local develop.

Test

  • make release — passed
  • go build ./... — passed
  • Manual: release binary on --port 8899 --no-open
    • / and /coslash → 200 HTML
    • hashed /assets/* → 200
    • missing hashed asset → 404
    • /api/sessions → 200 JSON
    • /api/bogus → 404
    • --version, bad --port, and port conflict → actionable errors

luhe19001 and others added 3 commits August 3, 2026 12:55
Serve the compiled frontend and the API from one loopback origin, so
running the product needs neither Node nor a second process.

Go cannot embed ../frontend/dist, so `make release` stages it into
internal/web/dist before compiling; the staged copy stays untracked
behind a committed placeholder that keeps the package building in a
plain checkout. A binary without staged assets says so at / instead
of serving nothing, which keeps `make run` plus `npm run dev` working.

The frontend handler serves real files as themselves, extensionless
paths as index.html so client routes survive a refresh, and anything
else as a 404 — a missing hashed asset is a broken build, not a route.
An unrouted /api path 404s rather than falling through to the SPA.

Add --version (ldflags-injected), --port, and --no-open, and bind the
listener before opening the browser so a port conflict is an error the
user reads rather than a tab pointed at nothing.

Handlers move to api.go unchanged, leaving main.go to startup.
Make build-and-run the path people follow first, with clear paths from
the collector directory and a short develop note.

Co-authored-by: Cursor <cursoragent@cursor.com>
Keep the release path simple while the product shell is still settling.

Co-authored-by: Cursor <cursoragent@cursor.com>
@milanshen

Copy link
Copy Markdown
Contributor

Reduce inline comments, only use inline comments for todos or special cases, not as overall logic or plan

@luhe19001 luhe19001 added the enhancement New feature or request label Aug 4, 2026
Comment thread collector/Makefile
Comment thread README.md
- `build`, `run`, and `clean` now clear internal/web/dist first, so a
  build after `make release` no longer embeds that release's frontend.
- `make run` passes --no-open; the README points dev at Vite on 5173.
- Cut the explanatory inline comments added by this branch.
@luhe19001

luhe19001 commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator Author

Trimmed the comments in main.go, web.go, and browser.go down to the non-obvious bits. The ones in api.go are pre-existing text this PR only moved, so I left them as they were.

Captures the conventions this PR's review surfaced — comment discipline,
build targets that clear the state they consume, and docs that match real
behavior. Discoverable by Codex via .agents/skills, Claude Code via the
.claude/skills link, and Cursor via a .cursor rule.
SKILL.md is all the skill needs; openai.yaml only earns its place when a
skill declares tool dependencies.
@luhe19001
luhe19001 merged commit eb6f3d4 into main Aug 4, 2026
@luhe19001
luhe19001 deleted the helu/eng-1313-bundle-the-frontend-into-one-binary-with-production-cli branch August 4, 2026 03:56
@luhe19001
luhe19001 restored the helu/eng-1313-bundle-the-frontend-into-one-binary-with-production-cli branch August 4, 2026 04:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants