Comprehensive Laravel development guidelines for GitHub Copilot, covering Laravel 12, Livewire 3, Tailwind v4, Pint, and Laravel Boost MCP tools
Comprehensive Laravel development guidelines for GitHub Copilot, optimized for Laravel 12, Livewire 3, Tailwind CSS v4, and Laravel Boost MCP server integration.
Laravel Boost provides powerful tools designed specifically for this application. Always leverage them:
Before making any code changes, use `search-docs` with these guidelines:
1. **Always search first** - This tool returns version-specific docs for the user's exact package versions
2. **Multiple broad queries** - Example: `['rate limiting', 'routing rate limiting', 'routing']`
3. **Filter by package** - Pass array of packages if you know which docs you need
4. **Supports Laravel ecosystem** - Laravel, Inertia, Livewire, Filament, Tailwind, Pest, Nova, Nightwatch, etc.
**Search Syntax:**
Use `php artisan make:` commands for all new files:
```php
// ✅ Prefer Eloquent relationships with type hints
public function posts(): HasMany
{
return $this->hasMany(Post::class);
}
// ✅ Use Model::query() over DB::
$posts = Post::query()->where('active', true)->get();
// ✅ Prevent N+1 with eager loading
$users = User::with(['posts', 'comments'])->get();
// ⚠️ Only use query builder for complex operations
DB::table('users')->whereRaw('LOWER(email) = ?', [$email])->get();
```
When creating models, also generate:
```php
// ✅ Use Eloquent API Resources
class PostResource extends JsonResource
{
public function toArray($request): array
{
return [
'id' => $this->id,
'title' => $this->title,
'author' => new UserResource($this->whenLoaded('author')),
];
}
}
// ✅ API versioning unless existing convention differs
Route::prefix('v1')->group(function () {
Route::apiResource('posts', PostController::class);
});
```
```php
// ✅ Always create Form Request classes
php artisan make:request StorePostRequest
// Include both rules and messages
public function rules(): array
{
return [
'title' => ['required', 'string', 'max:255'],
'content' => ['required', 'string'],
];
}
public function messages(): array
{
return [
'title.required' => 'Please provide a post title.',
];
}
```
Check sibling Form Requests for array vs. string rule conventions.
```php
// ✅ Use ShouldQueue for time-consuming operations
class ProcessPodcast implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
}
```
```php
// ✅ Use config() everywhere except config files
$appName = config('app.name');
// ❌ Never use env() outside config files
$appName = env('APP_NAME'); // WRONG
```
```php
// ✅ Prefer named routes
<a href="{{ route('posts.show', $post) }}">View Post</a>
// Use get-absolute-url tool when sharing URLs with users
```
```php
// ✅ Use factories with states
$user = User::factory()->verified()->create();
// ✅ Use $this->faker or fake() (check existing convention)
$email = $this->faker->safeEmail();
$name = fake()->name();
// Create tests with artisan
php artisan make:test PostTest // Feature test
php artisan make:test PostTest --unit // Unit test
```
**Vite Error Fix:** Run `npm run build` or ask user to run `npm run dev` or `composer run dev`.
Always use `search-docs` tool for Laravel 12 examples.
This project upgraded from Laravel 10 **without migrating** to the new streamlined structure. This is recommended by Laravel. Follow existing structure:
```php
// ⚠️ When modifying columns, include ALL previous attributes
Schema::table('users', function (Blueprint $table) {
$table->string('email', 255)->nullable()->change(); // Must include ALL attributes
});
// ✅ Laravel 11+ native eager loading limits
$users = User::with(['posts' => fn($query) => $query->latest()->limit(10)])->get();
```
```php
// ✅ Prefer casts() method (check existing conventions)
protected function casts(): array
{
return [
'email_verified_at' => 'datetime',
'is_admin' => 'boolean',
];
}
```
Verify application conventions before assuming these are implemented:
```blade
{{-- ✅ Single root element required --}}
<div>
{{-- ✅ Loading states --}}
<button wire:click="save" wire:loading.attr="disabled">
<span wire:loading.remove>Save</span>
<span wire:loading>Saving...</span>
</button>
{{-- ✅ Wire keys in loops --}}
@foreach ($items as $item)
<div wire:key="item-{{ $item->id }}">
{{ $item->name }}
</div>
@endforeach
</div>
```
```php
// ✅ Lifecycle hooks for initialization and reactive side effects
public function mount(User $user)
{
$this->user = $user;
}
public function updatedSearch()
{
$this->resetPage();
}
```
Use `search-docs` for examples: `wire:show`, `wire:transition`, `wire:cloak`, `wire:offline`, `wire:target`
```js
document.addEventListener('livewire:init', function () {
Livewire.hook('request', ({ fail }) => {
if (fail && fail.status === 419) {
alert('Your session expired');
}
});
Livewire.hook('message.failed', (message, component) => {
console.error(message);
});
});
```
```php
Livewire::test(Counter::class)
->assertSet('count', 0)
->call('increment')
->assertSet('count', 1)
->assertSee(1)
->assertStatus(200);
// Test component exists on page
$this->get('/posts/create')
->assertSeeLivewire(CreatePost::class);
```
```css
/* ✅ Tailwind v4 */
@import "tailwindcss";
/* ❌ Don't use v3 directives */
@tailwind base;
@tailwind components;
@tailwind utilities;
```
```html
<!-- ✅ Use gap utilities -->
<div class="flex gap-8">
<div>Superior</div>
<div>Michigan</div>
<div>Erie</div>
</div>
<!-- ❌ Don't use margins for item spacing -->
```
If existing components support dark mode, new components must also use `dark:` variants consistently.
Do not use deprecated utilities. Opacity values remain numeric.
| Deprecated | Replacement |
|------------|-------------|
| `bg-opacity-*` | `bg-black/*` |
| `text-opacity-*` | `text-black/*` |
| `border-opacity-*` | `border-black/*` |
| `divide-opacity-*` | `divide-black/*` |
| `ring-opacity-*` | `ring-black/*` |
| `placeholder-opacity-*` | `placeholder-black/*` |
| `flex-shrink-*` | `shrink-*` |
| `flex-grow-*` | `grow-*` |
| `overflow-ellipsis` | `text-ellipsis` |
| `decoration-slice` | `box-decoration-slice` |
| `decoration-clone` | `box-decoration-clone` |
**Note:** `corePlugins` is not supported in Tailwind v4.
**CRITICAL:** Run `vendor/bin/pint --dirty` before finalizing any changes.
```bash
vendor/bin/pint --dirty
vendor/bin/pint --test # WRONG
```
**Every change must be programmatically tested.**
1. Write a new test or update an existing test
2. Run the minimum tests needed: `php artisan test --filter=PostTest`
3. Ensure all affected tests pass
```bash
php artisan test tests/Feature/PostTest.php
php artisan test --filter=can_create_post
```
1. **Search documentation first** - Use `search-docs` with multiple broad queries
2. **Use Boost tools** - Leverage `list-artisan-commands`, `tinker`, `database-query`, etc.
3. **Create files with Artisan** - Always use `php artisan make:` commands
4. **Follow Laravel conventions** - Check existing code patterns before writing new code
5. **Write or update tests** - Every change needs test coverage
6. **Format code** - Run `vendor/bin/pint --dirty` before committing
7. **Verify URLs** - Use `get-absolute-url` when sharing URLs with users
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/laravel-boost-github-copilot-instructions/raw