PHP 8.5 / Symfony 8 / FrankenPHP boilerplate. Vertical Slices + CQRS over Symfony Messenger. PostgreSQL 16, Redis 7. Designed to be readable by both humans and AI agents.
For architecture rules and code-level guidance, see AGENTS.md โ it is the single source of truth, โค 2 000 tokens, equally usable by developers and AI tools.
| Layer | Choice | Why |
|---|---|---|
| Application server | FrankenPHP 1.x (Caddy + worker mode) | one binary, HTTP/3, kernel kept hot |
| Framework | Symfony 8.0 | mature, attribute-based wiring |
| Bus | Symfony Messenger (CQRS) | sync commands/queries, async events |
| Database | PostgreSQL 16 | Doctrine ORM 3 |
| Cache / Queue | Redis 7 | Predis + Messenger transport |
| Frontend (default) | AssetMapper + Twig | no Webpack/Vite needed for HTML-first |
| Code style | Laravel Pint (PSR-12) | one-flag autofix |
| Static analysis | PHPStan level 9 | enforced in CI |
| Tests | PHPUnit 11 + Zenstruck (Foundry, Browser, Messenger-Test) + DAMA | pyramid 60/30/10 |
git clone https://github.com/k2gl/pragmatic-franken.git
cd pragmatic-franken
make install # env, containers, deps, migrations
make smoke # bin/console list && /healthzThe app comes up at https://pragmatic-franken.localhost:${HTTPS_PORT:-4750}. Caddy resolves *.localhost automatically โ no /etc/hosts edits.
| Command | Effect |
|---|---|
make up / make down |
start / stop containers |
make shell (alias make e) |
shell inside the app container |
make test |
PHPUnit, fail-fast |
make check |
Pint + PHPStan (pre-commit gate) |
make ci |
lint-check + analyze + test (CI parity) |
make smoke |
end-to-end smoke check |
make slice module=Foo feature=Bar |
scaffold a vertical slice |
make adr title="My Decision" |
scaffold a new ADR |
make docs-check |
lint ADR front-matter & AGENTS.md budget |
src/ # application code
Kernel.php # App\Kernel (Symfony MicroKernel)
Health/Features/Healthz/ # reference slice (JSON, /healthz)
Home/Features/Index/ # reference slice (Twig + AssetMapper, /)
config/ bin/ public/ assets/
docs/ # ADRs and guides (Tier 2)
adr/ # 10 ADRs with YAML front-matter
guides/{development,testing,worker-mode}.md
dev/ # codegen helpers (create-slice, new-adr, check-docs)
ops/ # deployment scripts
tests/ # mirrors src/ โ tests/{Module}/Features/{Feature}/
docker/ # Dockerfile, Caddyfile, php.ini
AGENTS.md # Tier-1 agent context, โค 2 000 tokens
AGENTS.local.md.example # per-developer overrides template (gitignored target)
The two example slices (Health/Healthz, Home/Index) are reference implementations โ Healthz is normative for ADR-0005 health checks; Home/Index is non-normative (drop it for API-only or SPA projects).
All decisions live in docs/adr/. Each ADR carries YAML front-matter (status, date, audience, summary) so agents can skim without loading the full body.
| ADR | Topic | Status |
|---|---|---|
| 0001 | Vertical Slices | Accepted |
| 0002 | Messenger Transport | Accepted |
| 0003 | Pragmatic Symfony | Superseded |
| 0004 | FrankenPHP Runtime | Accepted |
| 0005 | Health Checks | Accepted |
| 0006 | Memory Management | Accepted |
| 0007 | AssetMapper | Accepted |
| 0008 | Testing Strategy | Accepted |
| 0009 | Shared Architecture | Accepted |
| 0010 | Documentation & AI Layout | Accepted |
docs/guides/development.mdโ daily commands, slice scaffolding detailsdocs/guides/testing.mdโ concrete PHPUnit + Foundry + Messenger-Test patternsdocs/guides/worker-mode.mdโ debugging FrankenPHP worker behaviordocs/MERCURE.mdโ real-time updatesdocs/PERFORMANCE.mdโ benchmark methodologydocs/ROADMAP.mdโ quarterly plan
The repository ships with a single AGENTS.md at the root, intended to be read by every AI tool by convention. There are no .cursorrules, .windsurfrules, .cursor/rules/* or per-tool prompt files โ see ADR-0010 for the rationale.
For per-developer overrides (tone, language, IDE quirks), copy AGENTS.local.md.example to AGENTS.local.md (gitignored).
See .github/CONTRIBUTING.md. Conventional Commits required for the message header. CI gates: Pint, PHPStan level 9, PHPUnit. make ci mirrors the pipeline locally.
MIT.