Strip Local Development
Strip Local Development
Strip is a Go SSR app: Templ → Tailwind → Go binary. The Templ and Tailwind CLIs are not Go-managed dependencies; install them once before building.
Prerequisites
| Tool | How to install | Notes |
|---|---|---|
| Go | match apps/strip/go.mod toolchain | check go version. |
templ CLI | go install github.com/a-h/templ/cmd/templ@latest | must be on PATH. The Makefile shells out to it. |
| Tailwind CLI | via pnpm/npx tailwindcss (root workspace) | invoked by make build-ui. |
make | system | drives the build. |
| Running sirloin | repo make dev-up-d (or local sirloin) | strip cannot start without STRIP_SIRLOIN_GRPC_HOST reachable. |
First-time bootstrap
cd apps/stripmake deps # go mod download + tidymake build-ui # templ generate -> tailwind -> asset bundlermake build # produces bin/stripThe asset bundler is a tiny Go program at cmd/build-assets/main.go that versions CSS/JS into internal/app/assets/.
Run
The Makefile gives you the minimum env:
make run-dev# equivalent to:# STRIP_STAGE=development \# STRIP_PORT=:8080 \# STRIP_SIRLOIN_GRPC_HOST=localhost:50051 \# go run cmd/app/main.goIn development with no Clerk env, RequireAuth falls back to a fake dev_user and logs SECURITY WARNING: Skipping authentication. This is intentional for local dev. To exercise the real Clerk path locally, also set:
STRIP_CLERK_PUBLISHABLE_KEY=pk_test_...STRIP_CLERK_DOMAIN=clerk.<your-test-domain>STRIP_CLERK_SECRET_KEY=sk_test_...To test as a user without re-auth, set STRIP_AUTH_BYPASS_UUID=<uuid> and request:
curl -H "X-Auth-Bypass: $STRIP_AUTH_BYPASS_UUID" http://localhost:8080/dashboardSee /services/strip-env/ for the full variable list.
Watch mode
make watch-ui # parallel templ generate --watch + tailwindcss --watch# in a second terminalmake run # plain go run, no rebuild triggerThere is no built-in Go file-watcher. Use air, reflex, or your editor’s task runner if you want auto-restart on .go changes — templ and Tailwind are the slow parts and make watch-ui already handles them.
Build flow
flowchart LR A[*.templ files] --> B[templ generate] B --> C[*_templ.go] D[input.css] --> E[tailwindcss -o output.css] C --> F[go build] E --> G[asset bundler] G --> H[versioned assets] F --> I[bin/strip] H --> Imake build enforces this order. Skipping build-ui produces a binary that serves stale CSS or fails to render Templ pages.
Tests, lint, mocks
make run-tests # go test ./... -racemake test-coverage # coverage profilemake lint # golangci-lint v2 (excludes generated *_templ.go)Project-wide line length is 180 and cyclomatic max 20 (see root CLAUDE.md). Tests must pass with -race.
Talking to a local sirloin
Default: STRIP_SIRLOIN_GRPC_HOST=localhost:50051. With the repo-wide Docker stack:
# from repo rootmake dev-up-d# strip will reach sirloin at sirloin:50051 inside the network,# or localhost:50051 from your host if sirloin's port is exposed.If sirloin is unreachable, every protected page returns 500 — Strip has no offline mode.
Gotchas
- Templ files aren’t Go.
*.templmust be regenerated after edits or you’ll see “function not defined” on build.make build-uifixes it; CI runstempl generatetoo. - Tailwind purge. The Tailwind config scans
internal/app/strip/templates/**/*.templ. New page files outside that path won’t pick up classes — add the path to the Tailwind config. - Lint excludes templates.
golangci-lintskipsinternal/app/strip/templates/*(generated). Hand-written code inhandlers/,services/,middleware/is fully linted. - Auth bypass logs are loud. Every dev request without Clerk emits
SECURITY WARNING. That’s expected locally — it must never appear in staging/prod logs. - Cookies require HTTPS in non-dev.
__sessionis set withSecure: truewhenever stage is notdevelopment. If you run staging locally without TLS, login appears to silently fail. - gRPC client is per-process. Editing
STRIP_SIRLOIN_GRPC_HOSTand HUP’ing won’t pick up the change — restart the process. - No DB writes from strip. All persistence flows through sirloin RPCs (
StripServiceinproto/sirloin/v5/strip.proto). If you find yourself wantingdatabase/sqlin a handler, push the change into sirloin instead.
Further reading
/services/strip-api/— full route/RPC surface./services/strip-datatable/,/services/strip-filters/— shared Templ primitives./services/strip-runbook/— operational behaviour.