Flagr — Go feature flag service with Vue 3 UI.
Run make help from the repo root for the full catalog. Common targets:
| Command | What it does |
|---|---|
make build |
Go server → ./flagr |
make build-ui |
UI: lint, typecheck, Vite → browser/flagr-ui/dist/ |
make build-docs |
VitePress production build → docs/.vitepress/dist |
make start |
Backend :18000 + UI dev :8080 |
make stop-ui |
Free ports :18000 / :8080 (lsof, not pkill) |
make rebuild-run |
build → stop-ui → start |
make test |
Lint + swagger validate + Go unit tests |
make test-e2e |
build + UI lint/typecheck + Playwright |
make test-integration |
API integration tests (SQLite, local server) |
make test-integration-compose |
Same suite vs Docker Compose (6 DBs) |
make bench-integration |
HTTP eval benchmarks (local) |
make swagger |
Regenerate swagger_gen/ |
Go tests: Prefer t.Parallel() unless the test mutates global state (config.Config, singletons, os.Setenv). See docs/flagr_testing.md for the decision tree.
Run from repo root. Match what .github/workflows/ci.yml enforces so PR checks stay green.
| You changed | Run before commit | Run before push (recommended) |
|---|---|---|
browser/flagr-ui/ only |
make flagr-ui-check |
make test-e2e |
docs/ (VitePress) |
make build-docs |
make build-docs |
pkg/ or Go tests |
make test |
make test (+ make test-integration if handler/API behavior) |
Swagger (swagger/, handlers → OpenAPI) |
make swagger then commit swagger_gen/ + cmd/flagr-server/main.go |
make ci-swagger (regen + git diff --exit-code) |
| UI + Go or unsure | make test and make flagr-ui-check |
make test + make test-e2e |
CI mapping (same commands):
| GitHub Actions job | Makefile |
|---|---|
unit_test |
make ci-swagger then make ci (= make test: golangci-lint + swagger validate + go test ./pkg/...) |
ui_lint |
make build-ui (= flagr-ui-check + Vite production build) |
docs_build |
make build-docs (VitePress; same as Pages deploy) |
e2e_test |
make test-e2e (= make build + flagr-ui-check + Playwright) |
integration_test |
make ci-integration (Docker Compose; usually not every UI PR) |
Fast UI loop: make flagr-ui-check ≈ ESLint + vue-tsc + Vitest (~10s). Do not rely on make run-ui alone — it does not lint.
PR hygiene: Follow PULL_REQUEST_TEMPLATE.md. For UI work, use plan As-built in docs/plans/2026-06-26-001-migrate-flagr-ui-js-to-ts-plan.md.
Backend (pkg/):
handler/eval.go— evaluation engine (POST/GET), batch;handler/eval_get_test.go— GET eval tests;handler/crud.go— CRUD API handlershandler/builtin_context.go— built-in context injection (@ts*,@http_*keys into entityContext)handler/exposure.go— exposure (impression) logging;handler/data_recorder*.go— recorders (Kafka, Kinesis, Pub/Sub, Datar)entity/— domain models (flag, segment, constraint, variant, distribution)config/env.go— all environment variables (single source of truth)
Frontend (browser/flagr-ui/src/):
api/types.ts— DTOs;api/crud.ts(flag CRUD + tags/variants/segments),api/eval.ts(POST /evaluation),http.tspages/flagPage.ts,pages/flagsListPage.ts(incl. list snapshot cache) — orchestration;flagPage.*(page)/flagsListPage.*(page)viacastFlagPage/castFlagsList- Composed REST in
api/crud.ts; UI viahelpers/runApi; eval UI helpers inhelpers/evaluation.ts - Architecture:
docs/plans/2026-06-26-001-migrate-flagr-ui-js-to-ts-plan.md(As-built) - Duplicate flag + transactional snapshots:
docs/plans/2026-06-30-001-duplicate-flag-plan.md(As-built)
The API spec has a two-step generation pipeline:
- Source of truth: edit
swagger/index.yaml(and the split files underswagger/that it references). - Bundle:
make api_docsmergesswagger/index.yamlintodocs/api_docs/bundle.yamlviaswagger-merger. - Generate Go server models:
make swaggerregeneratesswagger_gen/fromdocs/api_docs/bundle.yaml.
Never hand-edit docs/api_docs/bundle.yaml or swagger_gen/ directly. If you change a model used by handlers, commit all three artifacts: swagger/index.yaml, docs/api_docs/bundle.yaml, and swagger_gen/.
Single command: make gen (runs api_docs + swagger).
- Don't edit
swagger_gen/—make swagger - Dev mode uses SQLite, no external deps needed
- Process management uses
lsof -ti:<port>notpkill -f— never touches other projects' processes - See deepwiki.com/openflagr/flagr and
docs/ - File size & layout: Prefer medium-sized files with a clear, logical split — not monoliths, not one-off micro-files for a single helper. Group by responsibility (e.g. handler
error.gofor API/handler errors and DB error classification;validate.gofor request validation;crud*.gofor CRUD surfaces). New code should extend an existing cohesive file when it fits; add a new file only when it names a real subsystem or API slice. - No magic numbers: Prefer named constants over inline literals. In Go, define
constblocks for test values, timing durations, rollout percents, and HTTP status codes (usehttp.StatusOKnot200). In CSS/SCSS, use design tokens (--space-*,--font-size-*,--radius-*) or component-scoped variables (--constraint-logic-col) instead of hardcodedpxvalues. Exceptions:0,1,-1, and values defined in:rootvariable declarations. - Go tests: Prefer
t.Parallel()unless the test mutates global state (config.Config, singletons,os.Setenv). Seedocs/flagr_testing.mdfor the decision tree. - When creating a PR, follow
PULL_REQUEST_TEMPLATE.md - Never push directly to
main— always create a PR