Single-binary build: embed web dist, SPA fallback, Makefile #3

Closed
opened 2026-07-18 18:15:07 +00:00 by steve · 0 comments
Owner

Part of epic #20 · Design: DESIGN.md

Context

Pansy ships as one static binary: the Vite production build is embedded into the Go binary with embed.FS and served with an SPA fallback. This issue wires that up plus the Makefile that makes dev and release builds one command each.

Scope

  • internal/webdist/dist.go: //go:embed all:dist exposing the built frontend. Commit a minimal placeholder dist/index.html so go build works before/without a web build (the Makefile overwrites it).
  • internal/api/spa.go: serve embedded static files; any non-/api path with no matching file falls back to index.html (client-side routing deep links must work). Correct content types; sensible cache headers (hashed assets long-lived, index.html no-cache).
  • Makefile:
    • make webcd web && npm ci && npm run build, then sync web/distinternal/webdist/dist.
    • make buildmake web + CGO_ENABLED=0 go build -o pansy ./cmd/pansy.
    • make dev — run the Go API server and vite dev together (or document running them in two terminals).
    • make testgo test ./... and cd web && npx vitest run (if tests exist yet).
  • README: quickstart section — build, run, env vars table.

Out of scope

  • Dockerfile / release automation (later if wanted).
  • Any application features.

Key files & patterns

  • Embed + build flow summary: DESIGN.md § Backend layout.

Dependencies

Blocked by #1 (Go server) and #2 (web app).

Acceptance criteria

  • make build produces a single binary with no cgo (file pansy / build with CGO_ENABLED=0).
  • Running the binary and opening http://localhost:8080/gardens directly (deep link) loads the React shell via the SPA fallback; /api/v1/healthz still returns JSON.
  • make dev gives a working iteration loop with the Vite proxy.
Part of epic #20 · Design: [DESIGN.md](https://gitea.stevedudenhoeffer.com/steve/pansy/src/branch/main/DESIGN.md) ## Context Pansy ships as one static binary: the Vite production build is embedded into the Go binary with `embed.FS` and served with an SPA fallback. This issue wires that up plus the Makefile that makes dev and release builds one command each. ## Scope - [ ] `internal/webdist/dist.go`: `//go:embed all:dist` exposing the built frontend. Commit a minimal placeholder `dist/index.html` so `go build` works before/without a web build (the Makefile overwrites it). - [ ] `internal/api/spa.go`: serve embedded static files; any non-`/api` path with no matching file falls back to `index.html` (client-side routing deep links must work). Correct content types; sensible cache headers (hashed assets long-lived, `index.html` no-cache). - [ ] `Makefile`: - `make web` — `cd web && npm ci && npm run build`, then sync `web/dist` → `internal/webdist/dist`. - `make build` — `make web` + `CGO_ENABLED=0 go build -o pansy ./cmd/pansy`. - `make dev` — run the Go API server and `vite dev` together (or document running them in two terminals). - `make test` — `go test ./...` and `cd web && npx vitest run` (if tests exist yet). - [ ] README: quickstart section — build, run, env vars table. ## Out of scope - Dockerfile / release automation (later if wanted). - Any application features. ## Key files & patterns - Embed + build flow summary: `DESIGN.md` § Backend layout. ## Dependencies Blocked by #1 (Go server) and #2 (web app). ## Acceptance criteria - `make build` produces a single binary with no cgo (`file pansy` / build with `CGO_ENABLED=0`). - Running the binary and opening `http://localhost:8080/gardens` directly (deep link) loads the React shell via the SPA fallback; `/api/v1/healthz` still returns JSON. - `make dev` gives a working iteration loop with the Vite proxy.
steve added the infra label 2026-07-18 18:15:07 +00:00
steve closed this issue 2026-07-18 19:25:30 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: steve/pansy#3