Repo Layout¶
The workspace root holds four independent git repos and a shared orchestrator script.
<workspace>/
├── ftl-backend/ Go services, migrations, Lua scripts
├── ftl-frontend/ React SPA (Vite, TypeScript)
├── ftl-docs/ Architecture docs, ADRs, living specs, this site
├── ftl-support/ Operator runbooks and lifecycle scripts
└── ftl.sh Local-dev orchestrator
ftl-backend¶
All three Go binaries plus shared internal packages.
ftl-backend/
├── cmd/
│ ├── api-server/ main.go for the HTTP API binary
│ ├── ws-server/ main.go for the WebSocket binary
│ └── flusher/ main.go for the background sync binary
├── deployments/
│ ├── docker/ Dockerfile.api, Dockerfile.ws, Dockerfile.flusher
│ └── docker-compose.yml Local infra (postgres:16-alpine, redis:7-alpine) + all three services
├── internal/ Shared packages (amm, auth, trade, wallet, leaderboard, redis, sportmonks, …)
├── migrations/ Sequential SQL migration files (golang-migrate format, named 000NNN_*.up.sql)
├── scripts/ gen-dev-keys.sh, seed/main.go
├── Makefile build, test, lint, migrate, run-api, run-ws, run-flusher
├── go.mod
└── go.sum
ftl-frontend¶
React SPA served from Azure Static Web Apps in production and Vite dev server locally.
ftl-frontend/
├── src/
│ ├── components/ Shared UI components
│ ├── pages/ Route-level views (instruments, portfolio, leaderboard, admin)
│ ├── hooks/ Custom React hooks
│ ├── stores/ State (likely Zustand or similar)
│ └── lib/ API client, WebSocket client
├── tests/ Playwright E2E specs
├── vite.config.ts
├── tsconfig.json
├── package.json
└── pnpm-lock.yaml
ftl-docs¶
All architecture documents, ADRs, and living specs. This dev-docs site (mkdocs.yml) also lives here.
ftl-docs/
├── architecture/
│ ├── 12-new-stack-architecture.md PRIMARY architecture reference
│ ├── 13-product-requirements.md PRD with engineering targets
│ ├── specs/ Living domain specs (amm-pricing.md, auth-flow.md, …)
│ └── decisions/ ADRs (0001-*.md, 0002-*.md, …)
├── guides/
│ └── PROD-CUTOVER-2026-04.md Production cutover runbook
├── reports/
│ ├── azure-cost-audit-2026-05-02.md Staging revision-mode cost incident
│ └── codexreview-01.md Scalability and correctness audit
├── proposals/
│ └── 10-client-project-proposal.md
├── pr-reports/ Per-commit HTML walkthroughs
├── mkdocs.yml
└── CHANGE-MANAGEMENT.md
ftl-support¶
Runbooks for operators. Not application code.
Branch strategy¶
Each repo uses the same branching model.
| Branch | Purpose |
|---|---|
feat/<slug> |
New feature. Cut from the current integration branch. |
bug/<slug> |
Bug fix. Cut from the current integration branch. |
integration/<theme> |
Accumulates related feat/ and bug/ PRs before staging promotion. Cut from release/staging. |
release/staging |
Pushing here triggers deploy-staging.yml — runs migrations, rolls staging Container Apps, smoke-checks /health. |
release/prod |
Pushing here triggers deploy-prod.yml with a GitHub Environment approval gate before rolling production. |
main |
Not the integration point. Does not trigger deploys. |
The flow is forward-only: feat/ → integration/<theme> → release/staging → release/prod.
Warning
Never branch feature or bug work off main. Always cut from the current integration branch, which is itself cut from release/staging.
Decision: two long-lived release branches instead of trunk-based deploy. Staging acts as a pre-production gate; prod requires an explicit approval click in GitHub Environments. This prevents accidental production deploys during the tournament.