---
description: Laravel 13 conventions
globs: ["app/**/*.php","routes/**/*.php","database/**/*.php","resources/views/**/*.blade.php"]
alwaysApply: false
---

# Laravel 13

- Generate with Artisan (`php artisan make:model Order -mfsc --policy`, `make:request`, `make:job`) so files land in the right place.
- Controllers stay thin: validate with Form Requests (`authorize()` + `rules()`), authorize with policies (`Gate::authorize('update', $order)` or the `can` middleware), then call an action/service class in `app/Actions` or `app/Services`.
- Responses for APIs via API Resources (`OrderResource`), never raw models.
- Eloquent: define `$fillable` (or guarded) explicitly, casts via the `casts()` method, relationships with return types. Turn on `Model::preventLazyLoading(! app()->isProduction())` and eager load with `with()`.
- Migrations for every schema change; never edit a migration that has run in production.
- Slow work (mail, webhooks, exports) in queued jobs implementing `ShouldQueue`, dispatched `afterCommit()`.
- Config values through `config()`; `env()` only inside `config/*.php`.
- Use typed properties, return types, enums, and readonly classes; strict types where the project uses them.
- Blade escapes by default (`{{ }}`); use `{!! !!}` only for trusted HTML.

## Done when
`./vendor/bin/pint --test`, `./vendor/bin/phpstan analyse` (Larastan, if present), and `php artisan test` (Pest/PHPUnit) pass.
