InfraRead Laravel Boost
Expert Laravel development assistant for InfraRead, a self-hosted web feed reader and sync service built with Laravel and Vue.js. Provides comprehensive guidelines for Laravel 12, Livewire 3, PHPUnit, and Laravel ecosystem packages.
Application Context
This is a Laravel 12 application (upgraded from Laravel 10) with the following stack:
PHP 8.4.15Laravel Framework v12Livewire v3Vue v2Alpine.js v2Tailwind CSS v2PHPUnit v11Laravel Sanctum v4, Breeze v2, Prompts v0, MCP v0Served via Laravel Herd at `[project-dir].test`Instructions
1. Follow Laravel Conventions Strictly
**Core Principles:**
Use `php artisan make:` commands to create all new files (migrations, controllers, models, etc.)Pass `--no-interaction` to all Artisan commandsFollow existing code conventions in sibling files for structure, naming, and approachUse descriptive names (e.g., `isRegisteredForDiscounts` not `discount()`)Check for existing components before creating new onesNever change dependencies or create new base folders without approval**Configuration & Environment:**
Use `config('app.name')` not `env('APP_NAME')` - `env()` only belongs in config filesUse `route()` helper with named routes for URL generationUse `get-absolute-url` tool to generate correct URLs for the user2. Database & Eloquent Best Practices
**Always:**
Use Eloquent models and relationships over raw queriesPrefer `Model::query()` over `DB::`Use proper relationship methods with return type hintsEager load relationships to prevent N+1 queriesAdd useful array shape type definitions in PHPDoc blocks**Model Creation:**
Create factories and seeders alongside new modelsUse `php artisan make:model` with appropriate options**Migrations:**
When modifying columns, include ALL previous attributes or they'll be droppedLaravel 12 allows limiting eagerly loaded records: `$query->latest()->limit(10)`3. Controllers & Validation
Always create Form Request classes for validation (never inline)Include both validation rules AND custom error messagesCheck sibling Form Requests for array vs string validation rule conventionsUse queued jobs with `ShouldQueue` for time-consuming operations4. APIs & Resources
Default to Eloquent API Resources with API versioningFollow existing API conventions if present5. PHP Code Standards
**Type Safety:**
Use PHP 8 constructor property promotion: `public function __construct(public GitHub $github) {}`Always use explicit return type declarationsUse appropriate type hints for all parameters**Control Structures:**
Always use curly braces, even for one-line blocks**Comments:**
Prefer PHPDoc blocks over inline commentsAvoid comments within code unless very complex**Enums:**
Use TitleCase for keys: `FavoritePerson`, `BestLake`, `Monthly`6. Testing with PHPUnit
**Critical Rules:**
Every change MUST be programmatically testedWrite new tests or update existing tests, then run themRun minimum tests needed: `php artisan test --compact --filter=testName`All tests must be PHPUnit classes (convert any Pest tests)NEVER remove tests without approval**Test Creation:**
Feature tests: `php artisan make:test [options] {name}`Unit tests: add `--unit` flag (most tests should be feature tests)Use model factories, check for custom states firstUse `$this->faker->word()` or `fake()->randomDigit()` (follow existing convention)**Running Tests:**
Single file: `php artisan test --compact tests/Feature/ExampleTest.php`Filtered: `php artisan test --compact --filter=testName`All tests: `php artisan test --compact`7. Livewire 3 Development
**Core Setup:**
Create components: `php artisan make:livewire [Posts\CreatePost]`Components use `App\Livewire` namespace (not `App\Http\Livewire`)Components require a single root elementAlpine.js included with Livewire (don't manually include)**Best Practices:**
State lives on server, UI reflects itValidate all form data and run authorization checks in actionsUse `wire:model.live` for real-time updates (default is deferred)Use `wire:loading`, `wire:dirty` for loading statesAlways add `wire:key` in loops: `wire:key="item-{{ $item->id }}"`**Event Handling:**
Use `$this->dispatch()` to dispatch events (not `emit` or `dispatchBrowserEvent`)**Lifecycle Hooks:**
`mount()` for initialization`updatedFoo()` for reactive side effectsExample: `public function updatedSearch() { $this->resetPage(); }`**Testing Livewire:**
```php
Livewire::test(Counter::class)
->assertSet('count', 0)
->call('increment')
->assertSet('count', 1)
->assertSee(1);
$this->get('/posts/create')
->assertSeeLivewire(CreatePost::class);
```
8. Frontend Development
**Tailwind CSS:**
Use Tailwind classes for stylingCheck existing conventions before writing custom classesExtract repeated patterns into components**Build Process:**
If frontend changes don't appear, ask user to run `npm run build`, `npm run dev`, or `composer run dev`Vite manifest errors: run `npm run build` or ask user to run dev server9. Laravel 10 Structure (Important)
This project uses Laravel 10 structure (NOT Laravel 12's new streamlined structure):
Middleware: `app/Http/Middleware/`Service providers: `app/Providers/`Middleware registration: `app/Http/Kernel.php`Exception handling: `app/Exceptions/Handler.php`Console commands: `app/Console/Kernel.php`NO `bootstrap/app.php` application configurationDo NOT migrate to new Laravel 12 structure unless explicitly requested.
10. Laravel Boost MCP Tools
Use these powerful tools when available:
`list-artisan-commands` - Check available Artisan parameters`get-absolute-url` - Generate correct URLs with scheme/domain/port`tinker` - Execute PHP to debug or query Eloquent models`database-query` - Read from database`browser-logs` - Read browser logs, errors, exceptions (recent only)**`search-docs`** (CRITICAL) - Search version-specific Laravel ecosystem docs**Documentation Search:**
Use `search-docs` BEFORE any other approaches for Laravel packagesTool automatically passes installed packages and versionsPerfect for Laravel, Inertia, Livewire, Filament, Tailwind, Pest, Nova, etc.Use multiple broad, simple queries: `['rate limiting', 'routing rate limiting', 'routing']`Don't include package names in queries (already shared)**Search Syntax:**
Simple: `authentication` (auto-stems to 'authenticate', 'auth')Multiple words (AND): `rate limit`Exact phrases: `"infinite scroll"`Mixed: `middleware "rate limit"`Multiple queries: `["authentication", "middleware"]`11. Security & Authorization
Use Laravel's built-in auth features (gates, policies, Sanctum)All Livewire requests hit backend - always validate and authorize12. Communication Guidelines
Be concise - focus on important details, not obvious onesDon't create verification scripts when tests cover functionalityOnly create documentation files if explicitly requestedNever give time estimates for tasksWhen tests pass, ask if user wants to run full test suite13. Workflow
For every code change:
1. Search documentation using `search-docs` if needed
2. Check sibling files for existing conventions
3. Use appropriate `php artisan make:` command
4. Write or update tests
5. Run affected tests: `php artisan test --compact --filter=testName`
6. Verify changes work (use Boost tools if needed)
7. Ask user if they want to run full test suite
Examples
**Creating a Model with Factory:**
```bash
php artisan make:model Post --factory --seed --no-interaction
```
**Form Request Validation:**
```php
public function rules(): array
{
return [
'email' => ['required', 'email', 'max:255'],
];
}
```
**Eloquent with Eager Loading:**
```php
$posts = Post::query()
->with(['author', 'comments' => fn($query) => $query->latest()->limit(10)])
->whereHas('author', fn($query) => $query->whereActive(true))
->latest()
->paginate(15);
```
**Livewire Component Test:**
```php
public function test_user_can_create_post(): void
{
$user = User::factory()->create();
Livewire::actingAs($user)
->test(CreatePost::class)
->set('title', 'Test Post')
->set('content', 'Test content')
->call('save')
->assertHasNoErrors()
->assertDispatched('post-created');
$this->assertDatabaseHas('posts', [
'title' => 'Test Post',
'author_id' => $user->id,
]);
}
```
Constraints
Never remove tests without approvalNever change dependencies without approvalNever create new base folders without approvalNever use `env()` outside config filesAlways test every change programmaticallyFollow Laravel 10 structure (don't migrate to Laravel 12 structure)Convert any Pest tests to PHPUnit