diff --git a/.junie/skills/livewire-development/SKILL.md b/.junie/skills/livewire-development/SKILL.md
new file mode 100644
index 0000000..70ecd57
--- /dev/null
+++ b/.junie/skills/livewire-development/SKILL.md
@@ -0,0 +1,115 @@
+---
+name: livewire-development
+description: "Use for any task or question involving Livewire. Activate if user mentions Livewire, wire: directives, or Livewire-specific concepts like wire:model, wire:click, invoke this skill. Covers building new components, debugging reactivity issues, real-time form validation, loading states, migrating from Livewire 2 to 3, converting component formats (SFC/MFC/class-based), and performance optimization. Do not use for non-Livewire reactive UI (React, Vue, Alpine-only, Inertia.js) or standard Laravel forms without Livewire."
+license: MIT
+metadata:
+ author: laravel
+---
+
+# Livewire Development
+
+## Documentation
+
+Use `search-docs` for detailed Livewire 3 patterns and documentation.
+
+## Basic Usage
+
+### Creating Components
+
+Use the `php artisan make:livewire [Posts\CreatePost]` Artisan command to create new components.
+
+### Fundamental Concepts
+
+- State should live on the server, with the UI reflecting it.
+- All Livewire requests hit the Laravel backend; they're like regular HTTP requests. Always validate form data and run authorization checks in Livewire actions.
+
+## Livewire 3 Specifics
+
+### Key Changes From Livewire 2
+
+These things changed in Livewire 3, but may not have been updated in this application. Verify this application's setup to ensure you follow existing conventions.
+- Use `wire:model.live` for real-time updates, `wire:model` is now deferred by default.
+- Components now use the `App\Livewire` namespace (not `App\Http\Livewire`).
+- Use `$this->dispatch()` to dispatch events (not `emit` or `dispatchBrowserEvent`).
+- Use the `components.layouts.app` view as the typical layout path (not `layouts.app`).
+
+### New Directives
+
+- `wire:show`, `wire:transition`, `wire:cloak`, `wire:offline`, `wire:target` are available for use.
+
+### Alpine Integration
+
+- Alpine is now included with Livewire; don't manually include Alpine.js.
+- Plugins included with Alpine: persist, intersect, collapse, and focus.
+
+## Best Practices
+
+### Component Structure
+
+- Livewire components require a single root element.
+- Use `wire:loading` and `wire:dirty` for delightful loading states.
+
+### Using Keys in Loops
+
+
+```blade
+@foreach ($items as $item)
+
+ {{ $item->name }}
+
+@endforeach
+```
+
+### Lifecycle Hooks
+
+Prefer lifecycle hooks like `mount()`, `updatedFoo()` for initialization and reactive side effects:
+
+
+```php
+public function mount(User $user) { $this->user = $user; }
+public function updatedSearch() { $this->resetPage(); }
+```
+
+## JavaScript Hooks
+
+You can listen for `livewire:init` to hook into Livewire initialization:
+
+
+```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);
+ });
+});
+```
+
+## Testing
+
+
+```php
+Livewire::test(Counter::class)
+ ->assertSet('count', 0)
+ ->call('increment')
+ ->assertSet('count', 1)
+ ->assertSee(1)
+ ->assertStatus(200);
+```
+
+
+```php
+$this->get('/posts/create')
+ ->assertSeeLivewire(CreatePost::class);
+```
+
+## Common Pitfalls
+
+- Forgetting `wire:key` in loops causes unexpected behavior when items change
+- Using `wire:model` expecting real-time updates (use `wire:model.live` instead in v3)
+- Not validating/authorizing in Livewire actions (treat them like HTTP requests)
+- Including Alpine.js separately when it's already bundled with Livewire 3
\ No newline at end of file
diff --git a/.junie/skills/pest-testing/SKILL.md b/.junie/skills/pest-testing/SKILL.md
new file mode 100644
index 0000000..97a1e5d
--- /dev/null
+++ b/.junie/skills/pest-testing/SKILL.md
@@ -0,0 +1,108 @@
+---
+name: pest-testing
+description: "Use this skill for Pest PHP testing in Laravel projects only. Trigger whenever any test is being written, edited, fixed, or refactored — including fixing tests that broke after a code change, adding assertions, converting PHPUnit to Pest, adding datasets, and TDD workflows. Always activate when the user asks how to write something in Pest, mentions test files or directories (tests/Feature, tests/Unit) or architecture tests. Covers: it()/expect() syntax, datasets, mocking, browser testing, arch(), Livewire component tests, RefreshDatabase, and all Pest 4 features. Do not use for editing factories, seeders, migrations, controllers, models, or non-test PHP code."
+license: MIT
+metadata:
+ author: laravel
+---
+
+# Pest Testing 3
+
+## Documentation
+
+Use `search-docs` for detailed Pest 3 patterns and documentation.
+
+## Basic Usage
+
+### Creating Tests
+
+All tests must be written using Pest. Use `php artisan make:test --pest {name}`.
+
+### Test Organization
+
+- Tests live in the `tests/Feature` and `tests/Unit` directories.
+- Do NOT remove tests without approval - these are core application code.
+- Test happy paths, failure paths, and edge cases.
+
+### Basic Test Structure
+
+
+```php
+it('is true', function () {
+ expect(true)->toBeTrue();
+});
+```
+
+### Running Tests
+
+- Run minimal tests with filter before finalizing: `php artisan test --compact --filter=testName`.
+- Run all tests: `php artisan test --compact`.
+- Run file: `php artisan test --compact tests/Feature/ExampleTest.php`.
+
+## Assertions
+
+Use specific assertions (`assertSuccessful()`, `assertNotFound()`) instead of `assertStatus()`:
+
+
+```php
+it('returns all', function () {
+ $this->postJson('/api/docs', [])->assertSuccessful();
+});
+```
+
+| Use | Instead of |
+|-----|------------|
+| `assertSuccessful()` | `assertStatus(200)` |
+| `assertNotFound()` | `assertStatus(404)` |
+| `assertForbidden()` | `assertStatus(403)` |
+
+## Mocking
+
+Import mock function before use: `use function Pest\Laravel\mock;`
+
+## Datasets
+
+Use datasets for repetitive tests (validation rules, etc.):
+
+
+```php
+it('has emails', function (string $email) {
+ expect($email)->not->toBeEmpty();
+})->with([
+ 'james' => 'james@laravel.com',
+ 'taylor' => 'taylor@laravel.com',
+]);
+```
+
+## Pest 3 Features
+
+### Architecture Testing
+
+Pest 3 includes architecture testing to enforce code conventions:
+
+
+```php
+arch('controllers')
+ ->expect('App\Http\Controllers')
+ ->toExtendNothing()
+ ->toHaveSuffix('Controller');
+
+arch('models')
+ ->expect('App\Models')
+ ->toExtend('Illuminate\Database\Eloquent\Model');
+
+arch('no debugging')
+ ->expect(['dd', 'dump', 'ray'])
+ ->not->toBeUsed();
+```
+
+### Type Coverage
+
+Pest 3 provides improved type coverage analysis. Run with `--type-coverage` flag.
+
+## Common Pitfalls
+
+- Not importing `use function Pest\Laravel\mock;` before using mock
+- Using `assertStatus(200)` instead of `assertSuccessful()`
+- Forgetting datasets for repetitive validation tests
+- Deleting tests without approval
\ No newline at end of file
diff --git a/AGENTS.md b/AGENTS.md
index 3ada7a4..fa46ce9 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -19,6 +19,7 @@ ## Foundational Context
- laravel/mcp (MCP) - v0
- laravel/pail (PAIL) - v1
- laravel/sail (SAIL) - v1
+- pestphp/pest (PEST) - v3
- phpunit/phpunit (PHPUNIT) - v11
- tailwindcss (TAILWINDCSS) - v4
@@ -27,6 +28,8 @@ ## Skills Activation
This project has domain-specific skills available. You MUST activate the relevant skill whenever you work in that domain—don't wait until you're stuck.
- `laravel-best-practices` — Apply this skill whenever writing, reviewing, or refactoring Laravel PHP code. This includes creating or modifying controllers, models, migrations, form requests, policies, jobs, scheduled commands, service classes, and Eloquent queries. Triggers for N+1 and query performance issues, caching strategies, authorization and security patterns, validation, error handling, queue and job configuration, route definitions, and architectural decisions. Also use for Laravel code reviews and refactoring existing Laravel code to follow best practices. Covers any task involving Laravel backend PHP code patterns.
+- `livewire-development` — Use for any task or question involving Livewire. Activate if user mentions Livewire, wire: directives, or Livewire-specific concepts like wire:model, wire:click, invoke this skill. Covers building new components, debugging reactivity issues, real-time form validation, loading states, migrating from Livewire 2 to 3, converting component formats (SFC/MFC/class-based), and performance optimization. Do not use for non-Livewire reactive UI (React, Vue, Alpine-only, Inertia.js) or standard Laravel forms without Livewire.
+- `pest-testing` — Use this skill for Pest PHP testing in Laravel projects only. Trigger whenever any test is being written, edited, fixed, or refactored — including fixing tests that broke after a code change, adding assertions, converting PHPUnit to Pest, adding datasets, and TDD workflows. Always activate when the user asks how to write something in Pest, mentions test files or directories (tests/Feature, tests/Unit) or architecture tests. Covers: it()/expect() syntax, datasets, mocking, browser testing, arch(), Livewire component tests, RefreshDatabase, and all Pest 4 features. Do not use for editing factories, seeders, migrations, controllers, models, or non-test PHP code.
- `tailwindcss-development` — Always invoke when the user's message includes 'tailwind' in any form. Also invoke for: building responsive grid layouts (multi-column card grids, product grids), flex/grid page structures (dashboards with sidebars, fixed topbars, mobile-toggle navs), styling UI components (cards, tables, navbars, pricing sections, forms, inputs, badges), adding dark mode variants, fixing spacing or typography, and Tailwind v3/v4 work. The core use case: writing or fixing Tailwind utility classes in HTML templates (Blade, JSX, Vue). Skip for backend PHP logic, database queries, API routes, JavaScript with no HTML/CSS component, CSS file audits, build tool configuration, and vanilla CSS.
## Conventions
@@ -162,22 +165,20 @@ ### Models
- Casts can and likely should be set in a `casts()` method on a model rather than the `$casts` property. Follow existing conventions from other models.
-=== phpunit/core rules ===
+=== livewire/core rules ===
-# PHPUnit
+# Livewire
-- This application uses PHPUnit for testing. All tests must be written as PHPUnit classes. Use `php artisan make:test --phpunit {name}` to create a new test.
-- If you see a test using "Pest", convert it to PHPUnit.
-- Every time a test has been updated, run that singular test.
-- When the tests relating to your feature are passing, ask the user if they would like to also run the entire test suite to make sure everything is still passing.
-- Tests should cover all happy paths, failure paths, and edge cases.
-- You must not remove any tests or test files from the tests directory without approval. These are not temporary or helper files; these are core to the application.
+- Livewire allow to build dynamic, reactive interfaces in PHP without writing JavaScript.
+- You can use Alpine.js for client-side interactions instead of JavaScript frameworks.
+- Keep state server-side so the UI reflects it. Validate and authorize in actions as you would in HTTP requests.
-## Running Tests
+=== pest/core rules ===
-- Run the minimal number of tests, using an appropriate filter, before finalizing.
-- To run all tests: `php artisan test --compact`.
-- To run all tests in a file: `php artisan test --compact tests/Feature/ExampleTest.php`.
-- To filter on a particular test name: `php artisan test --compact --filter=testName` (recommended after making a change to a related file).
+## Pest
+
+- This project uses Pest for testing. Create tests: `php artisan make:test --pest {name}`.
+- Run tests: `php artisan test --compact` or filter: `php artisan test --compact --filter=testName`.
+- Do NOT delete tests without approval.
diff --git a/boost.json b/boost.json
index d1ba48e..fdc73bb 100644
--- a/boost.json
+++ b/boost.json
@@ -5,6 +5,8 @@
"guidelines": true,
"skills": [
"laravel-best-practices",
+ "livewire-development",
+ "pest-testing",
"tailwindcss-development"
]
}
diff --git a/composer.json b/composer.json
index e702e43..5d5c7e6 100644
--- a/composer.json
+++ b/composer.json
@@ -20,6 +20,7 @@
"laravel/sanctum": "^4.0",
"laravel/tinker": "^2.10.1",
"league/flysystem-aws-s3-v3": "^3.0",
+ "livewire/livewire": "^3.7",
"maatwebsite/excel": "^3.1",
"rap2hpoutre/fast-excel": "^5.6",
"santigarcor/laratrust": "^8.4",
@@ -35,8 +36,8 @@
"laravel/sail": "^1.41",
"mockery/mockery": "^1.6",
"nunomaduro/collision": "^8.6",
- "pestphp/pest": "*",
- "pestphp/pest-plugin-laravel": "*",
+ "pestphp/pest": "^3.8",
+ "pestphp/pest-plugin-laravel": "^3.2",
"phpunit/phpunit": "^11.5.3",
"spatie/laravel-ignition": "^2.9"
},
@@ -101,7 +102,10 @@
"config": {
"optimize-autoloader": true,
"preferred-install": "dist",
- "sort-packages": true
+ "sort-packages": true,
+ "allow-plugins": {
+ "pestphp/pest-plugin": true
+ }
},
"minimum-stability": "stable",
"prefer-stable": true
diff --git a/composer.lock b/composer.lock
index 7a2d06c..b7855ea 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "a697e341b64053fa6d0011f8fec1ee8b",
+ "content-hash": "e0f1d8d7662b5a589c4fb33e4fb321a6",
"packages": [
{
"name": "ahmedhakeem/extra",
@@ -6114,16 +6114,16 @@
},
{
"name": "livewire/livewire",
- "version": "v3.7.11",
+ "version": "v3.7.12",
"source": {
"type": "git",
"url": "https://github.com/livewire/livewire.git",
- "reference": "addd6e8e9234df75f29e6a327ee2a745a7d67bb6"
+ "reference": "7fcb612d1274980d80703efb5658e58d6d37ada9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/livewire/livewire/zipball/addd6e8e9234df75f29e6a327ee2a745a7d67bb6",
- "reference": "addd6e8e9234df75f29e6a327ee2a745a7d67bb6",
+ "url": "https://api.github.com/repos/livewire/livewire/zipball/7fcb612d1274980d80703efb5658e58d6d37ada9",
+ "reference": "7fcb612d1274980d80703efb5658e58d6d37ada9",
"shasum": ""
},
"require": {
@@ -6178,7 +6178,7 @@
"description": "A front-end framework for Laravel.",
"support": {
"issues": "https://github.com/livewire/livewire/issues",
- "source": "https://github.com/livewire/livewire/tree/v3.7.11"
+ "source": "https://github.com/livewire/livewire/tree/v3.7.12"
},
"funding": [
{
@@ -6186,7 +6186,7 @@
"type": "github"
}
],
- "time": "2026-02-26T00:58:19+00:00"
+ "time": "2026-03-25T23:04:42+00:00"
},
{
"name": "maatwebsite/excel",