Extending
This page summarizes where to put new code and which conventions to follow. The repository’s EXTENDING.md has step-by-step instructions and the full convention table.
Convention overview
| Area | Project custom | Check docs |
|---|---|---|
| Models | Core: app/Core/Models/. Domain: app/Domains/<Name>/Models/. No app/Models/. Add to config/ide-helper.php, run ide-helper:models -M. | Laravel Eloquent |
| Policies | Core: app/Core/Policies/. Domain: app/Domains/<Name>/Policies/. Register in AppServiceProvider::registerPolicies(). | Laravel Authorization |
| Jobs | app/Domains/<Name>/Jobs/ or app/Core/Jobs/. No global app/Jobs/. Create folder when adding first job. | Laravel Queues |
| Auth (login, 2FA, profile) | Fortify views render Inertia; routes under locale prefix. Profile in app/Domains/Profile/. | Laravel Fortify |
| Feature flags | Define in app/Core/Features/, register in AppServiceProvider. Toggleable: config/features.php + FeatureFlagSeeder. | Laravel Pennant |
| Search | Add model to config/scout.php meilisearch.index-settings (key = full class name). | Laravel Scout |
| Filament | Resources under app/Filament/Resources/; reference domain/Core models. Add permission in RoleAndPermissionSeeder. | Filament 5 |
| Inertia pages | resources/js/features/<name>/pages/. Backend renders component name (e.g. blog/Index). | Inertia 2 |
| Routes/actions (frontend) | Import from @/routes or @/actions; run build after adding backend routes. | Laravel Wayfinder |
Backend: quick steps
- New domain: Create
app/Domains/<Name>/with Http, Models, etc.; register routes and policy. Add model path toconfig/ide-helper.phpif needed. Or use Scaffolding. - Migrations:
php artisan make:migration; place indatabase/migrations/. - Observers:
app/Core/Observers/orapp/Domains/<Name>/Observers/; register inAppServiceProvider::boot(). Use model cache-key helpers for cache invalidation (e.g.Setting::siteCacheKey(),Page::slugCacheKey($slug)). - Feature flag (toggleable): Feature class in
app/Core/Features/, register withFeature::define(), add toconfig/features.php, run FeatureFlagSeeder, gate withFeature::active().
Frontend: quick steps
- New feature module: Create
resources/js/features/<name>/withpages/,components/, etc. Backend component name (e.g.blog/Index) resolves viapagePath()tofeatures/blog/pages/Index.tsx. - New Inertia page: Add
.tsxunderfeatures/<name>/pages/; backend callsInertia::render('<name>/PageName', ...). Single-segmentwelcome→features/landing/pages/welcome.tsx. - UI: Prefer
components/ui(Shadcn), thencomponents/common, then feature-specific components. - Wayfinder: After adding backend routes, run
npm run build(or dev).
Edge cases
- Use model-based cache keys (e.g.
Setting::siteCacheKey()) so cache survives namespace moves; runphp artisan cache:clearafter deploy if needed. - Feature-flagged routes: controllers
abort(404)when inactive; tests useFeature::activate('key')when testing that route. - Filament resources reference
App\Domains\*orApp\Core\*models; keep business logic in domain Queries/Actions.
For full detail and the complete table, see EXTENDING.md in the repository.