PROJECT_ROOT/
├── api/ # Laravel app
├── frontend/ # React app
├── docker/
│ ├── api/
│ │ ├── Dockerfile # Dev: php-fpm only, volume-mounted code
│ │ ├── Dockerfile.prod # Prod: multi-stage → php-fpm + nginx via supervisord
│ │ ├── nginx.conf # Nginx config (prod API container)
│ │ └── supervisord.conf # Supervisord config (prod API container)
│ ├── frontend/
│ │ ├── Dockerfile # Dev: Vite dev server with HMR
│ │ ├── Dockerfile.prod # Prod: multi-stage → nginx serving built dist
│ │ └── nginx.conf # Nginx config (prod frontend container)
│ └── nginx/
│ └── api.conf # Nginx sidecar config for dev (proxies → api:9000)
├── specs/ # Feature specs — written before implementation
├── rules/ # Coding conventions Claude must follow
├── docker-compose.yml # Dev (4 services: api, api-server, frontend, db)
├── docker-compose.prod.yml # Prod (3 services: api, frontend, db)
├── Makefile
├── .env.example
└── .gitignore
- Dev API: php-fpm container + nginx sidecar sharing a volume mount → live code edits work instantly, no rebuild needed
- Prod API: single container with supervisord running both php-fpm and nginx (code baked in)
- Frontend dev: Vite dev server with
--host 0.0.0.0for HMR through Docker - Frontend prod: multi-stage build, nginx serving static
dist/ - MySQL: named volume
db-datasurvivesmake down
- Laravel: latest stable at the time you run
make init(composer create-project laravel/laravel) — not pinned - React: latest stable Vite + React TS template at the time you run
make init— not pinned - PHP: 8.3 (pinned in Dockerfile)
- Node: 20 LTS (pinned in Dockerfile)
- MySQL: 8.0 (pinned in docker-compose)
To pin Laravel to a specific version: edit the init-api target in Makefile and append the version, e.g. laravel/laravel:^11.0.
From It Ain't Broke — Matt Pocock:
- grill-me — interviews you with 40–100 questions before writing any code to build a shared mental model
- ubiquitous-language — extracts and maintains a domain glossary (
CONTEXT.md) from the conversation - improve-codebase-architecture — finds "deepening opportunities" (shallow modules to refactor into deep ones)
- zoom-out — forces a system-wide perspective check before touching cross-cutting concerns
cp .env.example .env # configure ports / DB creds
make init # scaffold Laravel + Vite (runs once)
make build # build images (first time or after Dockerfile changes)
make up # start containers (daily dev use — no rebuild)
make key # generate Laravel app key
make migrate-up # run all pending migrations
make migrate-down # rollback last migration
make deploy # git pull → prod build → restart