Embed a Svelte frontend in a Go binary¶
This applies to a Go project that embeds a Svelte UI via //go:embed — the
pattern keyrx and haileys-app use. Read
Explanation: the Svelte frontend track
for the full reasoning; this page is the decision + the wiring.
Step 1: decide how the release binary gets the real bundle¶
Do you already have (or can you add) a //go:generate build-web.sh
directive, invoked by goreleaser's before: hooks: - go generate ./...?
- Yes → use that hook. Do not also wire
svelte-build. The hook builds the frontend as part of the ordinary release build — a plaingo build/go installworks standalone for anyone with Node available, and addingsvelte-buildon top would build the bundle twice at tag time for no benefit. - No → use
svelte-build. It builds the bundle as a CI job and hands it togoreleaseras an artifact.
If you're setting this up from scratch and don't have a strong reason
otherwise, the go:generate hook is the better default — it's what the
projects this track was built for actually use, and it doesn't require any
CI-side artifact wiring.
Step 2a: wiring with go:generate (no svelte-build)¶
Nothing extra to add for the build itself — your existing
.goreleaser.yaml's before.hooks already covers it. Just add the
quality/security gates:
include:
- component: gitlab.com/phpboyscout/cicd/[email protected]
inputs:
paths: "pkg/studio/web"
- component: gitlab.com/phpboyscout/cicd/[email protected]
inputs:
paths: "pkg/studio/web"
- component: gitlab.com/phpboyscout/cicd/[email protected]
inputs:
paths: "pkg/studio/web"
Step 2b: wiring with svelte-build¶
include:
- component: gitlab.com/phpboyscout/cicd/[email protected]
inputs:
paths: "pkg/studio/web"
stage: build
- component: gitlab.com/phpboyscout/cicd/[email protected]
inputs:
paths: "pkg/studio/web"
- component: gitlab.com/phpboyscout/cicd/[email protected]
inputs:
paths: "pkg/studio/web"
- component: gitlab.com/phpboyscout/cicd/[email protected]
inputs:
paths: "pkg/studio/web"
- component: gitlab.com/phpboyscout/cicd/[email protected]
goreleaser:
needs:
- job: svelte-build
artifacts: true
The needs: overlay is required — without it, goreleaser runs without
waiting for (or downloading) the built bundle artifact.
Step 3: couple the Go tests to frontend changes (required either way)¶
Your Go embed test(s) — typically an embed_test.go asserting on the
served SPA — depend on what's actually in the embedded bundle directory,
but go-test's default
change-detection filter only watches
Go source and module files. Extend it so a frontend-only change still
runs those tests:
include:
- component: gitlab.com/phpboyscout/cicd/[email protected]
inputs:
changes:
- "**/*.go"
- "**/go.mod"
- "**/go.sum"
- ".golangci.*"
- ".gitlab-ci.yml"
- "pkg/studio/web/**" # your frontend root
This step is easy to skip and the failure mode is silent — a PR that only touches the frontend could merge having never exercised the Go code that serves it. See How-to: add change-detection to a gate for the general mechanics.
Step 4: verify¶
Open an MR that only touches pkg/studio/web/. Confirm: go-test runs
(not skipped); svelte-lint/svelte-test/svelte-security run; if using
svelte-build, its job runs too. Then cut a release tag and confirm the
published binary serves the real UI, not the committed placeholder.
See also¶
- Reference:
svelte-build,svelte-lint,svelte-test,svelte-security,goreleaser,go-test - Explanation: the Svelte frontend track