# Godsfavour Okpara — Portfolio CMS (Laravel 13 + Filament 5)

Governing docs (read before changing code): `docs/implementation/MASTER-PROMPT.md` (instructions and phases),
`docs/prd/portfolio-prd.md` (functional source of truth), `docs/implementation/PROGRESS.md` (current phase),
`docs/architecture/ARCHITECTURE.md`, `docs/architecture/DECISIONS.md` (ADRs), `docs/implementation/TRACEABILITY.md`.

## Environment
- PHP **8.4** is required, but the machine's default `php` is 8.1. Prefix commands with
  `PATH=/opt/homebrew/opt/php@8.4/bin:$PATH` (composer, artisan, pest, pint, phpstan).
- MySQL: `gf_portfolio` (dev) and `gf_portfolio_testing` (tests). `TestCase` refuses any non-`_testing` DB.
- Redis cache via predis. The cache only unserializes allowlisted classes (config/cache.php, ADR-033).

## Commands
- Tests: `./vendor/bin/pest` (Unit, Feature, Arch suites; MySQL; lazy loading throws)
- Style: `./vendor/bin/pint`, then `./vendor/bin/pint --test`
- Static analysis: `./vendor/bin/phpstan analyse --memory-limit=1G` (level 7, no baseline)
- Browser/a11y suite: `npm run test:browser` (Playwright + axe; disposable `gf_portfolio_e2e` DB via `.env.e2e`, rebuilt each run)
- Assets: `npm run build` / `npm run dev`
- Seed essentials: `php artisan db:seed` (idempotent). First admin: `php artisan portfolio:create-admin`

## Rules that are easy to break
- No professional copy in Blade/PHP/JS/CSS. It belongs in the CMS or settings. `lang/` holds only brand-neutral microcopy.
- `{!! !!}` is allowed only in `components/rich-text.blade.php` and `components/seo/head.blade.php` (arch test).
- Public queries use the `live()` scope (`HasPublishing`). Never hand-roll status checks.
- Project organisation names are read for public output only through the anonymisation presenter (PRD §31).
- Filament 5 APIs: check `vendor/filament/*` rather than recalling v3 syntax.
- Never run destructive DB commands (`migrate:fresh`, `db:wipe`) against `gf_portfolio` without approval.
