k2gl/pragmatic-franken
Composer 安装命令:
composer create-project k2gl/pragmatic-franken
包简介
Pragmatic FrankenPHP — PHP 8.5 / Symfony 8 starter: Vertical Slices + CQRS over Messenger, FrankenPHP worker mode, real prod image, agent-ready docs
关键字:
README 文档
README
Pragmatic FrankenPHP is a PHP 8.5 / Symfony 8 / FrankenPHP starter that real production projects actually grew out of — and the lessons were ported back. Vertical Slices + CQRS over Messenger, PostgreSQL 17, worker mode, real prod image, supply-chain attestations. The goal: fork it and ship a real product on day one, operated by humans and AI agents alike.
The promises are CI-proven, not vibes:
- the production image boots on every PR (
prod-imagejob: build → run →/ready); - scaffolded code passes PHPStan 10 + tests untouched (
agent-smokejob); - release images carry SLSA build provenance, and the deploy gate verifies it (ADR-0014);
- docs are linted against reality (
make docs-check: routes, Makefile targets, ADR sync).
For architecture rules and code-level guidance, see AGENTS.md — the single source of truth, ≤ 2 000 tokens, equally usable by developers and AI tools.
Stack
| 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 17 | Doctrine ORM 3 |
| Queue | Messenger on Doctrine transport | no extra extension, inspectable, production-proven |
| Cache | Redis 7 (Predis) | ready for caching and custom needs |
| Frontend (default) | AssetMapper + Twig | no Webpack/Vite needed for HTML-first |
| Code style | Laravel Pint (PSR-12) | one-flag autofix |
| Static analysis | PHPStan level 10 | enforced in CI |
| Tests | PHPUnit 12 + Zenstruck (Foundry, Browser, Messenger-Test) + DAMA + Faker + Fluent Assertions | pyramid 60/30/10 |
Quickstart
Path 1 — template + Docker (nothing but Docker needed):
gh repo create my-app --template k2gl/pragmatic-franken --clone && cd my-app # or: git clone https://github.com/k2gl/pragmatic-franken.git my-app make install # env, containers, deps, migrations make init name=my-app # rename + real secrets (optionally: prune=1 reset-git=1) make smoke # bin/console + /ready
Path 2 — composer create-project (needs PHP ≥ 8.5 on the host):
composer create-project k2gl/pragmatic-franken my-app cd my-app && make install && make init name=my-app
The app comes up at https://my-app.localhost:${HTTPS_PORT:-4750} (browsers
resolve *.localhost automatically — no /etc/hosts edits). Try the example
API: POST /tasks, GET /tasks, POST /tasks/{id}/complete — completion
pushes a Mercure live update on /tasks.
Why not just symfony/skeleton?
| pragmatic-franken | symfony/skeleton | dunglas/symfony-docker | API Platform | |
|---|---|---|---|---|
| Architecture opinion | Vertical Slices + CQRS, 17 ADRs | none | none | API-first framework |
| Prod image | built, booted & scanned per PR | — | built | built |
| Real example vertical | entity→migration→factory→tests | — | — | generated CRUD |
| Deploy story | blue-green to a VDS + backups + DR drill | — | — | k8s helm |
| Supply chain | attestations + offline verifier + gate | — | — | — |
| Agent affordances | AGENTS.md (≤2k tokens) + CI-proven scaffolding | — | — | — |
| Best when | product API/app on one VDS, agents in the loop | you want vanilla | you want plain Docker | your product is the API |
Honest non-goals: no auth in core (recipe instead), no bundled SPA, no Kubernetes, no multi-DB.
Daily commands
| 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 context=Foo feature=Bar |
scaffold a vertical slice |
make adr title="My Decision" |
scaffold a new ADR |
make docs-check |
lint docs against reality (routes, targets, budgets) |
make agent-smoke |
prove scaffolded code passes all gates untouched |
make db-seed |
demo data (app:seed) |
Project layout
src/ # application code
Kernel.php # App\Kernel (Symfony MicroKernel)
SharedKernel/ # cross-context infra (repository base, problem+json listeners)
Context/{Name}/ # bounded contexts: Entity/, Repository/, Features/{Feature}/
Health/Features/Healthz/ # reference slice (JSON, /healthz + /ready)
Home/Features/Index/ # reference slice (Twig + AssetMapper, /)
config/ bin/ public/ assets/ # standard Symfony layout
migrations/ # Doctrine migrations
docs/ # ADRs and guides (Tier 2)
adr/ # ADRs with YAML front-matter
guides/ # development, testing, worker-mode, …
dev/ # codegen helpers (create-slice, new-adr, check-docs)
ops/ # deployment scripts
tests/ # mirrors src/ — tests/Context/{Name}/Features/{Feature}/
docker/ # Dockerfile, Caddyfile, php.ini
AGENTS.md # Tier-1 agent context, ≤ 2 000 tokens
The example slices (Health/Healthz, Home/Index, Task) are reference implementations — Healthz is normative for ADR-0005 health checks, Task for the full entity → migration → factory → tests vertical; Home/Index is non-normative (drop it for API-only or SPA projects).
Architecture decisions
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 | Pragmatism Charter | Accepted |
| 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 |
| 0011 | Event Sourcing Lite | Accepted |
| 0012 | Ubiquitous Language & Entity Placement | Accepted |
| 0013 | Doctrine Repository Pattern | Accepted |
| 0014 | Supply-Chain Security | Accepted |
| 0015 | Scheduler & Periodic Tasks | Accepted |
| 0016 | HTTP Response Contract | Accepted |
| 0017 | Parallel Agent Sessions | Accepted |
Guides
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/guides/mercure-integration.md— real-time SSE via FrankenPHP's built-in Mercure hubdocs/guides/sdk-generation.md— auto-generate TypeScript types from PHP Result DTOsdocs/guides/deployment.md— single-VDS topology, zero-downtime rolloutdocs/guides/disaster-recovery.md— backups and the restore drilldocs/guides/parallel-sessions.md— isolated worktree stacks for parallel agentsdocs/guides/supply-chain.md— sign releases, verify before deploying
Recipes (opt-in capabilities)
Proven in real production projects grown from this skeleton, documented instead of bundled: JWT auth · feature flags · SPA frontend · preview environments.
Staying close to the template
Forks don't merge templates — they apply changes. Each release ships an
UPGRADE.md entry with the few changes worth porting; see
docs/guides/fork-maintenance.md.
AI agents
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.
Machine-local Claude Code settings live in .claude/settings.local.json (gitignored); parallel agent sessions get isolated stacks via dev/worktree.sh (ADR-0017).
Contributing
See .github/CONTRIBUTING.md. Conventional Commits required for the message header. CI gates: Pint, PHPStan level 10, PHPUnit. make ci mirrors the pipeline locally.
License
MIT.
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 2
- 点击次数: 1
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-06-12