Skip to main content
Blitz
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

The build

Specs: monorepo, release.

Bazel

Everything builds with Bazel 9.2 (bzlmod only), which brings its own Go, Node, pnpm, buf and Hugo:

Ruleset For
rules_go, Gazelle The Go code; dependencies from go.mod; BUILD files written by bazel run //:gazelle
protobuf, rules_buf The protos; buf lint and breaking-change checks
aspect_rules_js, rules_nodejs The desktop page: Node 22, npm packages from its pnpm lockfile, Vite, vitest, tsc
rules_pkg Release archives and the Linux packages
apple_support Xcode toolchains, for the tray’s cgo on macOS
rules_hugo This site

Plain go build doesn’t work: the generated proto package exists only in the build. Editors reach Bazel’s view through GOPACKAGESDRIVER=tools/gopackagesdriver.sh.

Layout

Directory
apps/, pkg/, proto/ The code
build/ How things are built: code generators, nogo and its analyzers, macOS signing, version stamping
tools/ Runnable checks and upkeep: dependency rules, formatting, license headers, third-party notices, specs, tidy
third_party/ Patches to dependencies
release/ The CLI release archives
docs/ This site

Generated code

  • Go protos: one package with the messages and Connect’s handlers, generated by protoc-gen-go and protoc-gen-connect-go.
  • TypeScript: protoc-gen-es writes the desktop page’s client (//apps/desktop/web:api_ts).
  • The page: Vite builds it; the Electron app carries the result, and the tray embeds it with //go:embed.
  • License texts: pkg/legal embeds the repository’s LICENSE, NOTICE and THIRD_PARTY_NOTICES, copied in at build time, so every program can show them.

Nothing generated is committed or written into the source tree.

Static analysis

nogo runs in every compile of the repository’s own Go code: Go vet’s analyzers, staticcheck’s default checks, and doccomment, Blitz’s own analyzer, which requires a doc comment on every package and exported declaration. A finding fails the build. The page has tsc and a doc-comment lint of its own, and buf checks the protos’ comments.

Pure Go where it counts

The CLI and the service build with CGO_ENABLED=0: static binaries with no runtime dependencies, cross-compiled from either macOS or Linux to every platform. Only the tray uses cgo, on macOS (its Dock icon); the desktop app is Electron, from its prebuilt archives (spec_electron_038), with the same pure-Go programs inside.

Reproducible releases

The release archives come out byte for byte the same whether built on macOS or Linux. CI builds them on both and compares the checksums. What makes that work:

  • Output directories are named after the target platform, not the host, since generated files’ paths end up in the binaries.
  • rules_go links with a fixed build ID, and --config=release stamps only the version, from git describe.
  • Archives have fixed owners and modification times.

Tagging v* runs the release workflow: the archives, an SPDX SBOM for each, a checksums.txt signed keylessly with cosign through GitHub’s OIDC, and the desktop packages (a notarized macOS disk image for each Mac, a Windows zip, and the Linux packages), each with its own signature. Getting started shows how to verify them.

Continuous integration

.github/workflows/ci.yml runs on macOS and Linux:

  • Every test, Go with the race detector; the Linux job installs bubblewrap and a pinned gVisor, and fails if the sandbox or gVisor tests skip.
  • Formatting (gofmt, Gazelle’s BUILD files), license headers, the dependency rules, third-party notices, and the specs’ index and paths.
  • govulncheck on the built binaries; buf lint, format and breaking-change checks.
  • The release archives, compared across the two platforms.

.github/workflows/docs.yml builds this site with Bazel and publishes it to GitHub Pages from main.