# CLAUDE.md

This is a **Laravel 11 admin dashboard + versioned REST API base project** (Arabic + English),
built to be cloned and adapted to any domain. **Consistency over creativity:** reuse the existing
patterns, services, traits, and response helpers before inventing anything new. Do not introduce
alternative architecture patterns without strong justification.

> **Session start — read `docs/project/CONTEXT.md` FIRST:** the project **map** (where things live) +
> **state** (what's built + decisions) + **patterns to mirror** (exact reference files). Act from it + the
> task's plan/sprint; **don't re-scan the whole repo** — open a source file only when CONTEXT points to it.
> Append to CONTEXT §B at each sprint's DoD.

---

## Rules

The non-negotiable standards for every change in this codebase.

### Stack
- Laravel 11, PHP 8.2+. Admin = Blade + session guard (`auth:admin`). API = versioned (`/api/v1/…`) + Sanctum.
- Key packages: Sanctum (API auth), Astrotomic Translatable (i18n), Spatie Media Library (uploads),
  Maatwebsite Excel + PHPOffice PHPWord (exports). Frontend: Blade + Tailwind v4 via Vite — no Vue/React/Inertia/Livewire.

### Architecture (enforced)
- **Thin controllers** — resolve the Form Request, call a service, return a response. No business rules in controllers beyond orchestration.
- **Services hold business logic** — `app/Services/` and `app/Services/Admin/`. All non-trivial logic lives here.
- **Form Requests for all validation** — `app/Http/Requests/Admin/{Entity}/` and `app/Http/Requests/Api/{Module}/`. Never `$request->validate()` inline.
- **Blade = presentation only** — zero DB queries, zero service calls, zero business rules in templates.
- **Repositories + Contracts** (`app/Repositories/`, `app/Contracts/`) when behavior is shared or swappable.
- Admin controllers extend `AdminBaseController` and follow store/update/destroy/restore. API output uses `JsonResource` under `app/Http/Resources/Api/V1/`.
- **Group an API flow into a subfolder with focused controllers** — a multi-endpoint flow (auth, …) → `Api/V1/<Flow>/` with one controller per action/concern (mirror base's `Api/V1/Auth/`: `LoginCodeController`, `RequestCodeController`, `MeController`, `LogoutController`), each injecting only the service(s) it uses. Never one fat controller with many injected services; single-entity CRUD stays one `Api/V1/<Entity>Controller`.

### Code methodology (think-first, Laravel-first, no drift)
- **Think before coding** — before generating any feature/sprint, produce a short plan: entities & flow touched, the Laravel building blocks used, edge cases, side effects (events fired, jobs queued, notifications sent). Don't jump straight to code.
- **Laravel-first** — prefer framework-native constructs over hand-rolled logic, *inside* the base layering: **Events + Listeners** (side effects/decoupling), **Jobs + Queues** (slow/async: mail/SMS, exports, external calls), **Notifications**, **API Resources** (never manual array shaping), **Policies/Gates** (authorization), **Observers** (model lifecycle), Eloquent scopes/casts/accessors/Enums, container DI. Services still own orchestration; events/jobs are how a service delegates. Use them when they fit — not speculatively.
- **No style drift** — match the base's existing conventions exactly (naming, placement, base classes/traits, response helpers); read a sibling implementation and mirror it. Never introduce an alternative architecture or coding style.
- **Simplicity (least code, senior-level)** — don't re-specify already-defaulted values; put **defaults in the model** (`$attributes` + casts) not the migration; create/update from `$request->validated()` + only computed fields (never hand-list every column); derived values via mutators/casts/accessors/Observers, not ad-hoc helpers; **prefer `match` + early returns over `if`/`if` chains**; PHP 8 idioms (match, enums, promotion, `readonly`); Eloquent idioms (`firstOrCreate`/`updateOrCreate`, scopes). Code must read like a 15-year engineer wrote it. No over-engineering.
- **Design patterns — propose & approve** — if a sprint genuinely benefits from a pattern (Strategy, State, Pipeline, Action, Repository, Factory, Observer…), propose it in that sprint's plan (pattern + why it fits + how it sits in the base layering + trade-off) and **wait for the developer's yes/no at sprint execution time** before implementing. Default to the base's existing patterns; never add a pattern speculatively.

### Database & translations
- Migrations in `database/migrations/{domain}/` subdirectories. **Additive only** — never edit existing migrations; add a new column migration instead.
- Foreign keys + indexes on lookup/filter columns. `nullable()` only when absence is a valid domain state. `SoftDeletes` only when sibling models in the domain use it.
- **Translatable entities = two tables + two models**: main model (`Country`) + `{Model}Translation` (`CountryTranslation`) + `{table}_translations` table (Astrotomic). Both `ar` and `en` translations required.

### Media
- Use Spatie `HasMedia`/`InteractsWithMedia` + the `app/Traits/Upload/` traits. Avoid ad-hoc file-path columns.

### API response format
- **Always** use the shared response traits in `app/Traits/Response/` (`respondWithSuccess()`, `respondWithFail()`, `respondWithPaginated()`). **Never** create custom response shapes.
- Protected endpoints require `auth:sanctum`. Do not bypass `api.lang` or admin auth middleware.
- **API correctness (learned from real projects) — enforced in `docs/build/build-api.md`:** validation excludes client-only rules (`terms=>accepted`); enum fields use `Rule::enum(...)`; `unique`/`exists` on SoftDeletes tables are `->whereNull('deleted_at')`-aware (and such columns are `index()`, not DB-`unique()`); phone = separate `country_code` (`exists:countries,code`) + normalized `phone` (`PhoneNormalizer`); files are normal inputs (model `FILES`/`BaseFilesTrait` uploads them — no manual service handling). **Resource:** single resource → flat `data`; auth token **inside** the Resource (`UserResource`); enums serialize as `{value,label}` (`App\Traits\Enums\GeneralEnumTrait::toValueLabel()`); include computed/derived fields (accessors) the client needs.
- **Build flows whole, from the design:** a multi-step flow gets **one endpoint per step**, never collapsed — e.g. change-phone/email is `verify-current → set-new → verify-new` (the base ships `OtpType::OLD_PHONE_VERIFY`/`NEW_PHONE_VERIFY` + email variants for exactly this); walk the whole Figma flow screen-by-screen. And **success/error messages mirror the design's exact copy** (`lang/{ar,en}/api/*`, ar+en) — not generic. Enforced in `docs/build/build-schema.md` + `build-api.md`.

### Internationalization
- All user-facing strings go in `lang/ar/` and `lang/en/` (`admin/routes`, `admin/inputs`, `admin/main`, `api/messages`). Never hardcode Arabic/English in PHP or Blade. Default language is `ar`.
- **Validation messages live in `lang/{ar,en}/validation.php`** — the standard rule messages + `attributes` (translated field names) + `custom` for field-specific overrides. Do **not** hand-write `messages()`/`attributes()` in Form Requests with ad-hoc `api/*` keys (a Form Request normally needs neither). Anti-pattern: `messages()` returning `'phone.exists' => __('api/auth.exists', [...])` → move it to `validation.php` (`attributes.phone` + the standard `exists` message).

### Code quality
- PSR-12 / Laravel Pint. Constructor DI, typed properties + return types, `readonly` where it fits, `App\Enums` for fixed value sets.
- Small focused methods, descriptive names (no `$data`/`$result`/`$arr`). No `dd()`/`var_dump()` in committed code. Never log secrets or tokens.
- **Non-interactive execution (never hang):** never run interactive `php artisan tinker` (it waits on a REPL and hangs the agent — a real incident left zombie sub-agents stuck ~1h). Use `schema:check` / `migrate:status` / a test / `tinker --execute="…"` for state probes; add `--no-interaction`/`--force` where prompts are possible; no `-i` git commands. Bound any parallel fan-out to small, self-terminating, non-blocking units with timeouts.

### Collaboration & file placement
- Read surrounding code first; match the directory's style. Make the **smallest safe change**; do not refactor/rename unrelated code.
- **Keep the project docs current (same change, not later):** any **structure change** (new/moved/renamed layer or module) or **feature add/remove** → update `docs/project/CONTEXT.md` (§A map · §B state · §C patterns). At each **sprint DoD** also prepend a section to `docs/project/CHANGELOG.md` and refresh the affected parts of the root `README.md`.
- New admin feature → `Admin/` namespace (Controllers/Services/Requests/Views) + update `config/sidebar_routes.php` + lang files.
- New API endpoint → `Api/V1/` (Controllers/Requests/Resources) + `routes/api/v1/`. New enum → `app/Enums/`. New rule → `app/Rules/`.

---

## Project context

A multi-language, production-ready base: admin auth + RBAC, user management, OTP/password API auth,
complaints, geography (country/region/city/district), translatable content, uploads, notifications, settings.
Details live in:
- `.claude/context/project.md` — structure, modules, key paths, packages.
- `.claude/context/domain.md` — entities, relationships, workflows, enums.
- `.claude/context/team.md` — coding style, naming conventions, file placement.

---

## Execution source of truth

Code generation follows the canonical playbooks in `docs/` — never duplicate their procedures, reference them:
- `docs/build/README.md` — index, builder order, and the developer-review gate.
- `docs/build/build-database.md` — migrations + models (+ translation models) + factories + seeders.
- `docs/build/build-dashboard-crud.md` — admin CRUD (controller/service/requests/views/routes/sidebar/translations/statistics).
- `docs/build/build-api.md` — versioned API endpoints (route/controller/service/request/resource + standard response).
- `docs/build/build-postman-collection.md` — Postman collection, built then edited per plan.
- `docs/schema-json-contract.md` — the shared schema JSON contract for `database/schema/<feature>.json`.

---

## Developer-review GATE (hard stop)

After the schema is produced (`database/schema/<feature>.json`, editable on `/schema-designer`)
and **before any code generation**:

> **STOP.** The developer reviews the tables, columns, types, relations, indexes,
> `timestamps`/`soft_deletes`, and translatable fields. Generation proceeds **only** after
> explicit approval. Never infer-and-generate past an unreviewed schema.

See `docs/build/README.md`.

---

## Skills

Task playbooks live in `.claude/skills/` (setup / development / specialized phases) and are invoked
per task. They carry the purpose, trigger, and intake checklist for each task, then reference the
`docs/build/*` playbooks for the actual generation steps.

---

## Workflows

Slash-command workflows in `.claude/commands/`:
- `/setup-workflow` — prepare a new project from the base (initialize → adapt to domain → context → readiness review).
- `/development-workflow` — implement a feature (analyze → map → **Schema Review GATE** → backend → API/UI → test → validate).
- `/hotfix-workflow` — urgent fix (identify → root cause → smallest safe fix → regression check → review).
