output:
Chunk ID: 6f980f
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 962
Output:
---
name: tailwindcss-development
description: "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."
license: MIT
metadata:
  author: laravel
---

# Tailwind CSS Development

## Documentation

Use `search-docs` for detailed Tailwind CSS v4 patterns and documentation.

## Basic Usage

- Use Tailwind CSS classes to style HTML. Check and follow existing Tailwind conventions in the project before introducing new patterns.
- Offer to extract repeated patterns into components that match the project's conventions (e.g., Blade, JSX, Vue).
- Consider class placement, order, priority, and defaults. Remove redundant classes, add classes to parent or child elements carefully to reduce repetition, and group elements logically.

## Tailwind CSS v4 Specifics

- Always use Tailwind CSS v4 and avoid deprecated utilities.
- `corePlugins` is not supported in Tailwind v4.

### CSS-First Configuration

In Tailwind v4, configuration is CSS-first using the `@theme` directive — no separate `tailwind.config.js` file is needed:

<!-- CSS-First Config -->
```css
@theme {
  --color-brand: oklch(0.72 0.11 178);
}
```

### Import Syntax

In Tailwind v4, import Tailwind with a regular CSS `@import` statement instead of the `@tailwind` directives used in v3:

<!-- v4 Import Syntax -->
```diff
- @tailwind base;
- @tailwind components;
- @tailwind utilities;
+ @import "tailwindcss";
```

### Replaced Utilities

Tailwind v4 removed deprecated utilities. Use the replacements shown below. 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 |

## Spacing

Use `gap` utilities instead of margins for spacing between siblings:

<!-- Gap Utilities -->
```html
<div class="flex gap-8">
    <div>Item 1</div>
    <div>Item 2</div>
</div>
```

## Dark Mode

If existing pages and components support dark mode, new pages and components must support it the same way, typically using the `dark:` variant:

<!-- Dark Mode -->
```html
<div class="bg-white dark:bg-gray-900 text-gray-900 dark:text-white">
    Content adapts to color scheme
</div>
```

## Common Patterns

### Flexbox Layout

<!-- Flexbox Layout -->
```html
<div class="flex items-center justify-between gap-4">
    <div>Left content</div>
    <div>Right content</div>
</div>
```

### Grid Layout

<!-- Grid Layout -->
```html
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
    <div>Card 1</div>
    <div>Card 2</div>
    <div>Card 3</div>
</div>
```

## Common Pitfalls

- Using deprecated v3 utilities (bg-opacity-*, flex-shrink-*, etc.)
- Using `@tailwind` directives instead of `@import "tailwindcss"`
- Trying to use `tailwind.config.js` instead of CSS `@theme` directive
- Using margins for spacing between siblings instead of gap utilities
- Forgetting to add dark mode variants when the project uses dark mode


server: laravel-boost

tool: application-info

type: text

database_engine: sqlite

roster_name: FORTIFY

package_name: laravel/fortify

roster_name: LARAVEL

package_name: laravel/framework

roster_name: PROMPTS

package_name: laravel/prompts

package_name: livewire/flux

roster_name: LIVEWIRE

package_name: livewire/livewire

roster_name: BOOST

package_name: laravel/boost

roster_name: MCP

package_name: laravel/mcp

roster_name: PAIL

package_name: laravel/pail

roster_name: PINT

package_name: laravel/pint

roster_name: SAIL

package_name: laravel/sail

roster_name: PEST

package_name: pestphp/pest

roster_name: PHPUNIT

package_name: phpunit/phpunit

roster_name: TAILWINDCSS

package_name: tailwindcss


packages: livewire/livewire livewire/flux laravel/framework pestphp/pest

queries: full page component route livewire form validation pagination

queries: flux form input select textarea button badge modal

queries: livewire testing component form actions pagination

queries: blade route model binding slug scoped route


tool: search-docs

text:
# Search Results

## Redirecting Redirecting to full-page components
Redirecting | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/redirecting

## Redirecting to full-page components

Because Livewire uses Laravel's built-in redirection feature, you can use all of the redirection methods available to you in a typical Laravel application.

For example, if you are using a Livewire component as a full-page component for a route like so:

```php
Route::livewire('/posts', 'pages::show-posts');
```

You can redirect to it simply by using the route path:

```php
public function save()
{
    // ...

    $this->redirect('/posts');
}
```

---

## Routing Route Model Binding Implicit Binding Custom Keys and Scoping
Routing | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/routing.md

#### Custom Keys and Scoping

When implicitly binding multiple Eloquent models in a single route definition, you may wish to scope the second Eloquent model such that it must be a child of the previous Eloquent model. For example, consider this route definition that retrieves a blog post by slug for a specific user:

```php
use App\Models\Post;
use App\Models\User;

Route::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
    return $post;
});
```

When using a custom keyed implicit binding as a nested route parameter, Laravel will automatically scope the query to retrieve the nested model by its parent using conventions to guess the relationship name on the parent. In this case, it will be assumed that the `User` model has a relationship named `posts` (the plural form of the route parameter name) which can be used to retrieve the `Post` model.

If you wish, you may instruct Laravel to scope "child" bindings even when a custom key is not provided. To do so, you may invoke the `scopeBindings` method when defining your route:

```php
use App\Models\Post;
use App\Models\User;

Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
    return $post;
})->scopeBindings();
```

Or, you may instruct an entire group of route definitions to use scoped bindings:

```php
Route::scopeBindings()->group(function () {
    Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
        return $post;
    });
});
```

Similarly, you may explicitly instruct Laravel to not scope bindings by invoking the `withoutScopedBindings` method:

```php
Route::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
    return $post;
})->withoutScopedBindings();
```

---

## Components Input > With buttons
Components Input | livewire/flux@2.x | Source: https://fluxui.dev/components/input#livewire/flux

With buttons

Attach buttons to the beginning or end of an input element.

<flux:input.group>    <flux:input placeholder="Post title" />    <flux:button icon="plus">New post</flux:button></flux:input.group><flux:input.group>    <flux:select class="max-w-fit">        <flux:select.option selected>USD</flux:select.option>            </flux:select>    <flux:input placeholder="$99.99" /></flux:input.group>

---

## Http Tests Validation Assertions assertInvalid
Http Tests | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/http-tests.md

#### assertInvalid

Assert that the response has validation errors for the given keys. This method may be used for asserting against responses where the validation errors are returned as a JSON structure or where the validation errors have been flashed to the session:

```php
$response->assertInvalid(['name', 'email']);
```

You may also assert that a given key has a particular validation error message. When doing so, you may provide the entire message or only a small portion of the message:

```php
$response->assertInvalid([
    'name' => 'The name field is required.',
    'email' => 'valid email address',
]);
```

---

## Lazy Full-page lazy loading
Lazy | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/lazy

## Full-page lazy loading

You can lazy load or defer full-page Livewire components using route methods.

### Lazy loading full pages

Use `->lazy()` to load the component when it enters the viewport:

```php
Route::livewire('/dashboard', 'pages::dashboard')->lazy();
```

### Deferring full pages

Use `->defer()` to load the component immediately after the page loads:

```php
Route::livewire('/dashboard', 'pages::dashboard')->defer();
```

### Disabling lazy/defer loading

If a component is lazy or deferred by default (via the `#[Lazy]` or `#[Defer]` attribute), you can opt-out using `enabled: false`:

```php
Route::livewire('/dashboard', 'pages::dashboard')->lazy(enabled: false);
Route::livewire('/dashboard', 'pages::dashboard')->defer(enabled: false);
```

---

## Routing Route Model Binding
Routing | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/routing.md

## Route Model Binding

When injecting a model ID to a route or controller action, you will often query the database to retrieve the model that corresponds to that ID. Laravel route model binding provides a convenient way to automatically inject the model instances directly into your routes. For example, instead of injecting a user's ID, you can inject the entire `User` model instance that matches the given ID.

---

## Components Field > With badge
Components Field | livewire/flux@2.x | Source: https://fluxui.dev/components/field#livewire/flux

With badge

Badges allow you to enhance a field with additional information such as being "required" or "optional" when it might not be expected.

<flux:field>    <flux:label badge="Required">Email</flux:label>    <flux:input type="email" required />    <flux:error name="email" /></flux:field><flux:field>    <flux:label badge="Optional">Phone number</flux:label>    <flux:input type="phone" placeholder="(555) 555-5555" mask="(999) 999-9999"  />    <flux:error name="phone" /></flux:field>

---

## Routing Route Model Binding Implicit Binding Customizing the Key
Routing | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/routing.md

#### Customizing the Key

Sometimes you may wish to resolve Eloquent models using a column other than `id`. To do so, you may specify the column in the route parameter definition:

```php
use App\Models\Post;

Route::get('/posts/{post:slug}', function (Post $post) {
    return $post;
});
```

If you would like model binding to always use a database column other than `id` when retrieving a given model class, you may override the `getRouteKeyName` method on the Eloquent model:

```php
/**
 * Get the route key for the model.
 */
public function getRouteKeyName(): string
{
    return 'slug';
}
```

---

## Components Input > Icon buttons
Components Input | livewire/flux@2.x | Source: https://fluxui.dev/components/input#livewire/flux

Icon buttons

Append a button to the inside of an input to provide associated functionality.

<flux:input placeholder="Search orders">    <x-slot name="iconTrailing">        <flux:button size="sm" variant="subtle" icon="x-mark" class="-mr-1" />    </x-slot></flux:input><flux:input type="password" value="password">    <x-slot name="iconTrailing">        <flux:button size="sm" variant="subtle" icon="eye" class="-mr-1" />    </x-slot></flux:input>

---

## Testing See also
Testing | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/testing

## See also

- **[Actions](/docs/4.x/actions)** — Test component actions and interactions
- **[Forms](/docs/4.x/forms)** — Test form submissions and validation
- **[Events](/docs/4.x/events)** — Test event dispatching and listening
- **[Components](/docs/4.x/components)** — Create testable component structure

---

## Test Impact Analysis
Test Impact Analysis | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/test-impact-analysis.md

---
title: Test Impact Analysis (TIA)
description: Test Impact Analysis is a great way to drastically reduce the time it takes to run your test suite by re-running only the tests affected by your latest changes.
---

# Test Impact Analysis (TIA)

Test Impact Analysis is a great way to drastically reduce the time it takes to run your test suite by re-running only the tests affected by your latest changes. The first time you run with `--tia`, Pest records a graph of which tests depend on which files. Every run after that, Pest looks at what you changed, runs only the tests that touched those files, and replays cached results for everything else.

A typical Laravel suite that takes 15 seconds replays in under a second. Edits to a single Blade template re-run a handful of feature tests. Comment-only edits, formatter passes, and README touches re-run nothing at all.

To get started, just add the `--tia` flag to any Pest invocation:

```bash
./vendor/bin/pest --parallel --tia
```

The first run is the **baseline** — Pest enables a coverage driver (PCOV or Xdebug) and records the dependency graph as your tests execute. Expect a small overhead on this run only.

Every subsequent run is a **replay**. Pest compares your working tree against the baseline and re-runs only the tests affected by your changes:

```
Tests:    774 passed (2658 assertions, 7 affected, 767 replayed)
Duration: 0.74s
```

`affected` is the set of tests Pest actually executed. `replayed` is the set whose results were served from cache.

## How Pest Decides What To Run

For each file you've changed, Pest looks for tests that depend on it:

- **PHP source files** — your `app/` classes, controllers, models, helpers — are tracked through the coverage driver. A change to `app/Models/User.php` re-runs only the tests that touched `User`.
- **Migrations** are intersected with the tables each test queried during the baseline. A column rename in `create_users_table.php` re-runs only the tests that queried the `users` table.
- **Inertia pages** under `resources/js/Pages` re-run only the tests that server-side-rendered them.
- **Shared JS components** under `resources/js/Components`, `Layouts`, and friends re-run only the tests whose pages import them — Pest walks Vite's module graph to figure this out.
- **Blade templates** re-run only the tests that rendered them, including renders triggered by browser tests.
- **Anything else** — config files, route files, `.env`, files outside the recorded graph — falls through to a broader pattern. Editing `config/app.php` re-runs every test, because Pest can't statically prove which tests depend on it.

## Cosmetic Edits Don't Run Anything

Pest normalises file content before comparing, so cosmetic changes don't trigger any tests. PHP files have whitespace, line comments, and docblocks stripped before hashing. Blade strips `{{-- … --}}` comments. JS, TS, Vue, and Svelte files have line and block comments removed too.

The result: a comment-only edit, a Prettier reformat, a Pint pass, or a README tweak produces an identical hash, and the file never enters the changed set. Zero tests run.

## Modes

Pest supports a few flags alongside `--tia`:

| Flag | Behaviour |
|---|---|
| `--tia` | Replay if a baseline graph exists, otherwise record. |
| `--tia --fresh` | Discard any existing graph and re-record from scratch. Use this after large refactors or when the graph feels stale. |
| `--tia --refetch` | Force a CI baseline fetch even within the 24-hour cooldown after a previous failed fetch.

## Sharing The Baseline From CI

Recording the baseline locally takes minutes on large suites. Instead, you can have CI record it once per merge to `main`, and every developer downloads the result.

When Pest detects no local graph (or the local graph is out of date), it uses GitHub's CLI to download the latest successful run of a `tia-baseline.yml` workflow's `pest-tia-baseline` artifact. Pest validates the fetched graph against your project state — if it matches, it's adopted. Otherwise it's discarded and a local rebuild proceeds.

Here's a starter workflow you can drop into `.github/workflows/tia-baseline.yml`:

```yaml
name: TIA Baseline
on:
  push: { branches: [main] }
  schedule: [{ cron: '0 3 * * *' }]
  workflow_dispatch:
jobs:
  baseline:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }
      - uses: shivammathur/setup-php@v2
        with: { php-version: '8.5', coverage: xdebug }
      - run: composer install --no-interaction --prefer-dist
      - run: ./vendor/bin/pest --parallel --tia --coverage
      - name: Stage baseline for upload
        shell: bash
        run: |
          mkdir -p .pest-tia-baseline
          cp -R "$HOME/.pest/tia"/*/. .pest-tia-baseline/
      - uses: actions/upload-artifact@v4
        with:
          name: pest-tia-baseline
          path: .pest-tia-baseline/
          retention-days: 30
```

After CI runs, every developer who runs `pest --tia` for the first time on the repo will download this baseline and start replaying immediately, paying no record cost.

## Storage

Pest stores its state at `~/.pest/tia/<project-key>/`, where the project key is derived from your normalised git remote URL — so `git@github.com:foo/bar.git` and `https://github.com/foo/bar` produce the same key. A non-git project falls back to a hash of the project's absolute path.

Sharing state per remote URL means multiple worktrees of the same repository share one cache, while unrelated projects on the same machine stay isolated.

## Custom Watch Patterns

If your project has a directory layout that doesn't match the framework defaults, you can register custom watch patterns in `tests/Pest.php`:

```php
pest()->tia()->watch([
    'config/billing/**/*.php' => ['tests/Feature/Billing'],

    //
]);
```

Each glob maps to a list of test directories; whenever a matching file changes, every test under those directories is invalidated. Use this when you have specific test directories that genuinely depend on a file Pest can't see otherwise.

---

Now that you've learned how to use Test Impact Analysis to speed up your test suite, let's discuss how to integrate Pest with your continuous integration workflow: [Continuous Integration](/docs/continuous-integration)

---

## Attribute Title Only for full-page components
Attribute Title | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/attribute-title

## Only for full-page components

> [!info] Full-page components only
> The `#[Title]` attribute only works for full-page components accessed via routes. Regular components rendered within other views don't use titles—they inherit the parent page's title.

---

## Components Badge > With close button
Components Badge | livewire/flux@2.x | Source: https://fluxui.dev/components/badge#livewire/flux

With close button

Make a badge removable by appending a close button.

<flux:badge>    Admin <flux:badge.close /></flux:badge>

---

## Components Modal > Modal
Components Modal | livewire/flux@2.x | Source: https://fluxui.dev/components/modal#livewire/flux

    Modal

Display content in a layer above the main page. Ideal for confirmations, alerts, and forms.

<flux:modal.trigger name="edit-profile">    <flux:button>Edit profile</flux:button></flux:modal.trigger><flux:modal name="edit-profile" class="md:w-96">

            <flux:heading size="lg">Update profile</flux:heading>            <flux:text class="mt-2">Make changes to your personal details.</flux:text>
        <flux:input label="Name" placeholder="Your name" />        <flux:input label="Date of birth" type="date" />
            <flux:spacer />            <flux:button type="submit" variant="primary">Save changes</flux:button>

</flux:modal>

---

## Filtering Tests `only()`
Filtering Tests | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/filtering-tests.md

### `only()`

During development, you may want to focus on running specific tests while excluding all others. Pest provides two ways to do this: running only tests in a specific file, or running only a specific test within a file.

#### Running Only Tests in a File

When working on a specific feature, you can mark all tests in a file to run exclusively by calling the `pest()->only()` function at the top of your test file:

```php
<?php

pest()->only();

test('first test', function () {
    // This will run
});

test('second test', function () {
    // This will also run
});
```

All tests in files with `pest()->only()` will run, while tests in other files will be skipped.

#### Running a Single Test

To run only a specific test within a file, chain the `->only()` method to the test:

```php
test('sum', function () {
  $result = sum(1, 2);

  expect($result)->toBe(3);
})->only();

test('another test', function () {
  // This will be skipped
});
```

---

As your codebase grows, manually running your tests with filtering can become tedious. That's where skipping tests comes in. Skipping tests is a useful feature that allows developers to exclude specific tests from the test suite temporarily without deleting them entirely: [Skipping Tests →](/docs/skipping-tests)

---

## Components Button > Full width
Components Button | livewire/flux@2.x | Source: https://fluxui.dev/components/button#livewire/flux

Full width

A button that spans the full width of the container.

<flux:button variant="primary" class="w-full">Send invite</flux:button>

---

## Routing Route Model Binding Explicit Binding
Routing | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/routing.md

### Explicit Binding

You are not required to use Laravel's implicit, convention based model resolution in order to use model binding. You can also explicitly define how route parameters correspond to models. To register an explicit binding, use the router's `model` method to specify the class for a given parameter. You should define your explicit model bindings at the beginning of the `boot` method of your `AppServiceProvider` class:

```php
use App\Models\User;
use Illuminate\Support\Facades\Route;

/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    Route::model('user', User::class);
}
```

Next, define a route that contains a `{user}` parameter:

```php
use App\Models\User;

Route::get('/users/{user}', function (User $user) {
    // ...
});
```

Since we have bound all `{user}` parameters to the `App\Models\User` model, an instance of that class will be injected into the route. So, for example, a request to `users/1` will inject the `User` instance from the database which has an ID of `1`.

If a matching model instance is not found in the database, a 404 HTTP response will be automatically generated.

---

## Routing Route Model Binding Implicit Binding Customizing Missing Model Behavior
Routing | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/routing.md

#### Customizing Missing Model Behavior

Typically, a 404 HTTP response will be generated if an implicitly bound model is not found. However, you may customize this behavior by calling the `missing` method when defining your route. The `missing` method accepts a closure that will be invoked if an implicitly bound model cannot be found:

```php
use App\Http\Controllers\LocationsController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redirect;

Route::get('/locations/{location:slug}', [LocationsController::class, 'show'])
    ->name('locations.view')
    ->missing(function (Request $request) {
        return Redirect::route('locations.index');
    });
```

---

## Search Full-Text Search Running Full-Text Queries
Search | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/search.md

### Running Full-Text Queries

Once the index is in place, use the `whereFullText` query builder method to search against it. Laravel will generate the appropriate SQL for your database driver — for example, `MATCH(...) AGAINST(...)` on MariaDB and MySQL, and `to_tsvector(...) @@ plainto_tsquery(...)` on PostgreSQL:

```php
$articles = Article::whereFullText('body', 'web developer')->get();
```

When using MariaDB and MySQL, results are automatically ordered by relevance score. On PostgreSQL, `whereFullText` filters matching records but does not order them by relevance — if you need automatic relevance ordering on PostgreSQL, consider using [Scout's database engine](#database-engine), which handles this for you.

If you created a composite full-text index across multiple columns, you may search against all of them by passing the same array of columns to `whereFullText`:

```php
$articles = Article::whereFullText(
    ['title', 'body'], 'web developer'
)->get();
```

The `orWhereFullText` method may be used to add a full-text search clause as an "or" condition. For complete details, consult the [query builder documentation](/docs/{{version}}/queries#full-text-where-clauses).

---

## Arch Testing Modifiers `abstracts()`
Arch Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/arch-testing.md

### `abstracts()`

The `abstracts()` modifier allows you to restrict the expectation to only abstract classes.

```php
arch('app')
    ->expect('App')
    ->abstracts()
    ->toImplement(JsonSerializable::class);
```
---

In this section, you have learned how to perform architectural testing, ensuring that your application or library's architecture meets a specified set of architectural requirements. Next, have you ever wondered how to test the performance of your code? Let's explore [Stress Testing](/docs/stress-testing).

---

## Testing Calling actions
Testing | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/testing

## Calling actions

Use the `call()` method to trigger component actions in your tests:

```php
use App\Models\Post;

it('can create a post', function () {
    expect(Post::count())->toBe(0);

    Livewire::test('post.create')
        ->set('title', 'My new post')
        ->set('content', 'Post content here')
        ->call('save');

    expect(Post::count())->toBe(1);
});
```

> [!tip] Pest expectations
> The examples above use Pest's `expect()` syntax for assertions. For a complete list of available expectations, see the [Pest expectations documentation](https://pestphp.com/docs/expectations).

You can pass parameters to actions:

```php
Livewire::test('post.show')
    ->call('deletePost', $postId);
```

### Testing validation

Assert that validation errors have been thrown using `assertHasErrors()`:

```php
it('title field is required', function () {
    Livewire::test('post.create')
        ->set('title', '')
        ->call('save')
        ->assertHasErrors('title');
});
```

Test specific validation rules:

```php
it('title must be at least 3 characters', function () {
    Livewire::test('post.create')
        ->set('title', 'ab')
        ->call('save')
        ->assertHasErrors(['title' => ['min:3']]);
});
```

### Testing authorization

Ensure authorization checks work correctly using `assertUnauthorized()` and `assertForbidden()`:

```php
use App\Models\User;
use App\Models\Post;

it('cannot update another users post', function () {
    $user = User::factory()->create();
    $stranger = User::factory()->create();
    $post = Post::factory()->for($stranger)->create();

    Livewire::actingAs($user)
        ->test('post.edit', ['post' => $post])
        ->set('title', 'Hacked!')
        ->call('save')
        ->assertForbidden();
});
```

### Testing redirects

Assert that an action performed a redirect:

```php
it('redirects to posts index after creating', function () {
    Livewire::test('post.create')
        ->set('title', 'New post')
        ->set('content', 'Content here')
        ->call('save')
        ->assertRedirect('/posts');
});
```

You can also assert redirects to named routes or page components:

```php
->assertRedirect(route('posts.index'));
->assertRedirectToRoute('posts.index');
```

### Testing events

Assert that events were dispatched from your component:

```php
it('dispatches event when post is created', function () {
    Livewire::test('post.create')
        ->set('title', 'New post')
        ->call('save')
        ->assertDispatched('post-created');
});
```

Test event communication between components:

```php
it('updates post count when event is dispatched', function () {
    $badge = Livewire::test('post-count-badge')
        ->assertSee('0');

    Livewire::test('post.create')
        ->set('title', 'New post')
        ->call('save')
        ->assertDispatched('post-created');

    $badge->dispatch('post-created')
        ->assertSee('1');
});
```

Assert events were dispatched with specific parameters:

```php
it('dispatches notification when deleting post', function () {
    Livewire::test('post.show')
        ->call('delete', postId: 3)
        ->assertDispatched('notify', message: 'Post deleted');
});
```

For complex assertions, use a closure:

```php
it('dispatches event with correct data', function () {
    Livewire::test('post.show')
        ->call('delete', postId: 3)
        ->assertDispatched('notify', function ($event, $params) {
            return ($params['message'] ?? '') === 'Post deleted';
        });
});
```

### Testing JS evaluation

Assert that a component evaluated JavaScript via `$this->js()`:

```php
it('shows an alert after saving', function () {
    Livewire::test('post.create')
        ->set('title', 'New post')
        ->call('save')
        ->assertJs("alert('Post saved!')");
});
```

You can also assert that no JS was evaluated:

```php
->assertNoJs();
```

---

## Browser Testing submit
Browser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md

### submit

The `submit` method submits the first form found on the page:

```php
$page->submit();
```

---

## Search Full-Text Search Adding Full-Text Indexes
Search | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/search.md

### Adding Full-Text Indexes

To use full-text search, first add a full-text index to the columns you want to search. You may add the index to a single column, or pass an array of columns to create a composite index that searches across multiple fields at once:

```php
Schema::create('articles', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->text('body');
    $table->timestamps();

    $table->fullText(['title', 'body']);
});
```

On PostgreSQL, you may specify a language configuration for the index, which controls how words are stemmed:

```php
$table->fullText('body')->language('english');
```

For more information on creating indexes, consult the [migration documentation](/docs/{{version}}/migrations#available-index-types).

---

## Installation Next Steps Laravel the Full Stack Framework
Installation | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/installation.md

### Laravel the Full Stack Framework

Laravel may serve as a full stack framework. By "full stack" framework we mean that you are going to use Laravel to route requests to your application and render your frontend via [Blade templates](/docs/{{version}}/blade) or a single-page application hybrid technology like [Inertia](https://inertiajs.com). This is the most common way to use the Laravel framework, and, in our opinion, the most productive way to use Laravel.

If this is how you plan to use Laravel, you may want to check out our documentation on [frontend development](/docs/{{version}}/frontend), [routing](/docs/{{version}}/routing), [views](/docs/{{version}}/views), or the [Eloquent ORM](/docs/{{version}}/eloquent). In addition, you might be interested in learning about community packages like [Livewire](https://livewire.laravel.com) and [Inertia](https://inertiajs.com). These packages allow you to use Laravel as a full-stack framework while enjoying many of the UI benefits provided by single-page JavaScript applications.

If you are using Laravel as a full stack framework, we also strongly encourage you to learn how to compile your application's CSS and JavaScript using [Vite](/docs/{{version}}/vite).

> [!NOTE]
> If you want to get a head start building your application, check out one of our official [application starter kits](/docs/{{version}}/starter-kits).

---

## Validation Testing validation
Validation | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/validation

## Testing validation

Livewire provides useful testing utilities for validation scenarios, such as the `assertHasErrors()` method.

Below is a basic test case that ensures validation errors are thrown if no input is set for the `title` property:

```php
<?php

namespace Tests\Feature\Livewire;

use App\Livewire\CreatePost;
use Livewire\Livewire;
use Tests\TestCase;

class CreatePostTest extends TestCase
{
    public function test_cant_create_post_without_title()
    {
        Livewire::test(CreatePost::class)
            ->set('content', 'Sample content...')
            ->call('save')
            ->assertHasErrors('title');
    }
}
```

In addition to testing the presence of errors, `assertHasErrors` allows you to also narrow down the assertion to specific rules by passing the rules to assert against as the second argument to the method:

```php
public function test_cant_create_post_with_title_shorter_than_3_characters()
{
    Livewire::test(CreatePost::class)
        ->set('title', 'Sa')
        ->set('content', 'Sample content...')
        ->call('save')
        ->assertHasErrors(['title' => ['min:3']]);
}
```

You can also assert the presence of validation errors for multiple properties at the same time:

```php
public function test_cant_create_post_without_title_and_content()
{
    Livewire::test(CreatePost::class)
        ->call('save')
        ->assertHasErrors(['title', 'content']);
}
```

For more information on other testing utilities provided by Livewire, check out the [testing documentation](/docs/4.x/testing).

_[Truncated]_


output:
Wall time: 4.0499 seconds
Output:
[{"type":"text","text":"# Search Results\n\n## Redirecting Redirecting to full-page components\nRedirecting | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/redirecting\n\n## Redirecting to full-page components\n\nBecause Livewire uses Laravel's built-in redirection feature, you can use all of the redirection methods available to you in a typical Laravel application.\n\nFor example, if you are using a Livewire component as a full-page component for a route like so:\n\n```php\nRoute::livewire('/posts', 'pages::show-posts');\n```\n\nYou can redirect to it simply by using the route path:\n\n```php\npublic function save()\n{\n    // ...\n\n    $this->redirect('/posts');\n}\n```\n\n---\n\n## Routing Route Model Binding Implicit Binding Custom Keys and Scoping\nRouting | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/routing.md\n\n\n#### Custom Keys and Scoping\n\nWhen implicitly binding multiple Eloquent models in a single route definition, you may wish to scope the second Eloquent model such that it must be a child of the previous Eloquent model. For example, consider this route definition that retrieves a blog post by slug for a specific user:\n\n```php\nuse App\\Models\\Post;\nuse App\\Models\\User;\n\nRoute::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) {\n    return $post;\n});\n```\n\nWhen using a custom keyed implicit binding as a nested route parameter, Laravel will automatically scope the query to retrieve the nested model by its parent using conventions to guess the relationship name on the parent. In this case, it will be assumed that the `User` model has a relationship named `posts` (the plural form of the route parameter name) which can be used to retrieve the `Post` model.\n\nIf you wish, you may instruct Laravel to scope \"child\" bindings even when a custom key is not provided. To do so, you may invoke the `scopeBindings` method when defining your route:\n\n```php\nuse App\\Models\\Post;\nuse App\\Models\\User;\n\nRoute::get('/users/{user}/posts/{post}', function (User $user, Post $post) {\n    return $post;\n})->scopeBindings();\n```\n\nOr, you may instruct an entire group of route definitions to use scoped bindings:\n\n```php\nRoute::scopeBindings()->group(function () {\n    Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {\n        return $post;\n    });\n});\n```\n\nSimilarly, you may explicitly instruct Laravel to not scope bindings by invoking the `withoutScopedBindings` method:\n\n```php\nRoute::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) {\n    return $post;\n})->withoutScopedBindings();\n```\n\n---\n\n## Components Input > With buttons\nComponents Input | livewire/flux@2.x | Source: https://fluxui.dev/components/input#livewire/flux\n\n
With buttons

Attach buttons to the beginning or end of an input element.

<flux:input.group>    <flux:input placeholder=\"Post title\" />    <flux:button icon=\"plus\">New post</flux:button></flux:input.group><flux:input.group>    <flux:select class=\"max-w-fit\">        <flux:select.option selected>USD</flux:select.option>            </flux:select>    <flux:input placeholder=\"$99.99\" /></flux:input.group>

\n\n---\n\n## Http Tests Validation Assertions assertInvalid\nHttp Tests | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/http-tests.md\n\n\n#### assertInvalid\n\nAssert that the response has validation errors for the given keys. This method may be used for asserting against responses where the validation errors are returned as a JSON structure or where the validation errors have been flashed to the session:\n\n```php\n$response->assertInvalid(['name', 'email']);\n```\n\nYou may also assert that a given key has a particular validation error message. When doing so, you may provide the entire message or only a small portion of the message:\n\n```php\n$response->assertInvalid([\n    'name' => 'The name field is required.',\n    'email' => 'valid email address',\n]);\n```\n\n---\n\n## Lazy Full-page lazy loading\nLazy | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/lazy\n\n## Full-page lazy loading\n\nYou can lazy load or defer full-page Livewire components using route methods.\n\n### Lazy loading full pages\n\nUse `->lazy()` to load the component when it enters the viewport:\n\n```php\nRoute::livewire('/dashboard', 'pages::dashboard')->lazy();\n```\n\n### Deferring full pages\n\nUse `->defer()` to load the component immediately after the page loads:\n\n```php\nRoute::livewire('/dashboard', 'pages::dashboard')->defer();\n```\n\n### Disabling lazy/defer loading\n\nIf a component is lazy or deferred by default (via the `#[Lazy]` or `#[Defer]` attribute), you can opt-out using `enabled: false`:\n\n```php\nRoute::livewire('/dashboard', 'pages::dashboard')->lazy(enabled: false);\nRoute::livewire('/dashboard', 'pages::dashboard')->defer(enabled: false);\n```\n\n---\n\n## Routing Route Model Binding\nRouting | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/routing.md\n\n\n## Route Model Binding\n\nWhen injecting a model ID to a route or controller action, you will often query the database to retrieve the model that corresponds to that ID. Laravel route model binding provides a convenient way to automatically inject the model instances directly into your routes. For example, instead of injecting a user's ID, you can inject the entire `User` model instance that matches the given ID.\n\n---\n\n## Components Field > With badge\nComponents Field | livewire/flux@2.x | Source: https://fluxui.dev/components/field#livewire/flux\n\n
With badge

Badges allow you to enhance a field with additional information such as being \"required\" or \"optional\" when it might not be expected.

<flux:field>    <flux:label badge=\"Required\">Email</flux:label>    <flux:input type=\"email\" required />    <flux:error name=\"email\" /></flux:field><flux:field>    <flux:label badge=\"Optional\">Phone number</flux:label>    <flux:input type=\"phone\" placeholder=\"(555) 555-5555\" mask=\"(999) 999-9999\"  />    <flux:error name=\"phone\" /></flux:field>

\n\n---\n\n## Routing Route Model Binding Implicit Binding Customizing the Key\nRouting | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/routing.md\n\n\n#### Customizing the Key\n\nSometimes you may wish to resolve Eloquent models using a column other than `id`. To do so, you may specify the column in the route parameter definition:\n\n```php\nuse App\\Models\\Post;\n\nRoute::get('/posts/{post:slug}', function (Post $post) {\n    return $post;\n});\n```\n\nIf you would like model binding to always use a database column other than `id` when retrieving a given model class, you may override the `getRouteKeyName` method on the Eloquent model:\n\n```php\n/**\n * Get the route key for the model.\n */\npublic function getRouteKeyName(): string\n{\n    return 'slug';\n}\n```\n\n---\n\n## Components Input > Icon buttons\nComponents Input | livewire/flux@2.x | Source: https://fluxui.dev/components/input#livewire/flux\n\n
Icon buttons

Append a button to the inside of an input to provide associated functionality.

<flux:input placeholder=\"Search orders\">    <x-slot name=\"iconTrailing\">        <flux:button size=\"sm\" variant=\"subtle\" icon=\"x-mark\" class=\"-mr-1\" />    </x-slot></flux:input><flux:input type=\"password\" value=\"password\">    <x-slot name=\"iconTrailing\">        <flux:button size=\"sm\" variant=\"subtle\" icon=\"eye\" class=\"-mr-1\" />    </x-slot></flux:input>

\n\n---\n\n## Testing See also\nTesting | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/testing\n\n## See also\n\n- **[Actions](/docs/4.x/actions)** — Test component actions and interactions\n- **[Forms](/docs/4.x/forms)** — Test form submissions and validation\n- **[Events](/docs/4.x/events)** — Test event dispatching and listening\n- **[Components](/docs/4.x/components)** — Create testable component structure\n\n---\n\n## Test Impact Analysis\nTest Impact Analysis | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/test-impact-analysis.md\n\n---\ntitle: Test Impact Analysis (TIA)\ndescription: Test Impact Analysis is a great way to drastically reduce the time it takes to run your test suite by re-running only the tests affected by your latest changes.\n---\n\n# Test Impact Analysis (TIA)\n\nTest Impact Analysis is a great way to drastically reduce the time it takes to run your test suite by re-running only the tests affected by your latest changes. The first time you run with `--tia`, Pest records a graph of which tests depend on which files. Every run after that, Pest looks at what you changed, runs only the tests that touched those files, and replays cached results for everything else.\n\nA typical Laravel suite that takes 15 seconds replays in under a second. Edits to a single Blade template re-run a handful of feature tests. Comment-only edits, formatter passes, and README touches re-run nothing at all.\n\nTo get started, just add the `--tia` flag to any Pest invocation:\n\n```bash\n./vendor/bin/pest --parallel --tia\n```\n\nThe first run is the **baseline** — Pest enables a coverage driver (PCOV or Xdebug) and records the dependency graph as your tests execute. Expect a small overhead on this run only.\n\nEvery subsequent run is a **replay**. Pest compares your working tree against the baseline and re-runs only the tests affected by your changes:\n\n```\nTests:    774 passed (2658 assertions, 7 affected, 767 replayed)\nDuration: 0.74s\n```\n\n`affected` is the set of tests Pest actually executed. `replayed` is the set whose results were served from cache.\n\n## How Pest Decides What To Run\n\nFor each file you've changed, Pest looks for tests that depend on it:\n\n- **PHP source files** — your `app/` classes, controllers, models, helpers — are tracked through the coverage driver. A change to `app/Models/User.php` re-runs only the tests that touched `User`.\n- **Migrations** are intersected with the tables each test queried during the baseline. A column rename in `create_users_table.php` re-runs only the tests that queried the `users` table.\n- **Inertia pages** under `resources/js/Pages` re-run only the tests that server-side-rendered them.\n- **Shared JS components** under `resources/js/Components`, `Layouts`, and friends re-run only the tests whose pages import them — Pest walks Vite's module graph to figure this out.\n- **Blade templates** re-run only the tests that rendered them, including renders triggered by browser tests.\n- **Anything else** — config files, route files, `.env`, files outside the recorded graph — falls through to a broader pattern. Editing `config/app.php` re-runs every test, because Pest can't statically prove which tests depend on it.\n\n## Cosmetic Edits Don't Run Anything\n\nPest normalises file content before comparing, so cosmetic changes don't trigger any tests. PHP files have whitespace, line comments, and docblocks stripped before hashing. Blade strips `{{-- … --}}` comments. JS, TS, Vue, and Svelte files have line and block comments removed too.\n\nThe result: a comment-only edit, a Prettier reformat, a Pint pass, or a README tweak produces an identical hash, and the file never enters the changed set. Zero tests run.\n\n## Modes\n\nPest supports a few flags alongside `--tia`:\n\n| Flag | Behaviour |\n|---|---|\n| `--tia` | Replay if a baseline graph exists, otherwise record. |\n| `--tia --fresh` | Discard any existing graph and re-record from scratch. Use this after large refactors or when the graph feels stale. |\n| `--tia --refetch` | Force a CI baseline fetch even within the 24-hour cooldown after a previous failed fetch.\n\n## Sharing The Baseline From CI\n\nRecording the baseline locally takes minutes on large suites. Instead, you can have CI record it once per merge to `main`, and every developer downloads the result.\n\nWhen Pest detects no local graph (or the local graph is out of date), it uses GitHub's CLI to download the latest successful run of a `tia-baseline.yml` workflow's `pest-tia-baseline` artifact. Pest validates the fetched graph against your project state — if it matches, it's adopted. Otherwise it's discarded and a local rebuild proceeds.\n\nHere's a starter workflow you can drop into `.github/workflows/tia-baseline.yml`:\n\n```yaml\nname: TIA Baseline\non:\n  push: { branches: [main] }\n  schedule: [{ cron: '0 3 * * *' }]\n  workflow_dispatch:\njobs:\n  baseline:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with: { fetch-depth: 0 }\n      - uses: shivammathur/setup-php@v2\n        with: { php-version: '8.5', coverage: xdebug }\n      - run: composer install --no-interaction --prefer-dist\n      - run: ./vendor/bin/pest --parallel --tia --coverage\n      - name: Stage baseline for upload\n        shell: bash\n        run: |\n          mkdir -p .pest-tia-baseline\n          cp -R \"$HOME/.pest/tia\"/*/. .pest-tia-baseline/\n      - uses: actions/upload-artifact@v4\n        with:\n          name: pest-tia-baseline\n          path: .pest-tia-baseline/\n          retention-days: 30\n```\n\nAfter CI runs, every developer who runs `pest --tia` for the first time on the repo will download this baseline and start replaying immediately, paying no record cost.\n\n## Storage\n\nPest stores its state at `~/.pest/tia/<project-key>/`, where the project key is derived from your normalised git remote URL — so `git@github.com:foo/bar.git` and `https://github.com/foo/bar` produce the same key. A non-git project falls back to a hash of the project's absolute path.\n\nSharing state per remote URL means multiple worktrees of the same repository share one cache, while unrelated projects on the same machine stay isolated.\n\n## Custom Watch Patterns\n\nIf your project has a directory layout that doesn't match the framework defaults, you can register custom watch patterns in `tests/Pest.php`:\n\n```php\npest()->tia()->watch([\n    'config/billing/**/*.php' => ['tests/Feature/Billing'],\n\n    //\n]);\n```\n\nEach glob maps to a list of test directories; whenever a matching file changes, every test under those directories is invalidated. Use this when you have specific test directories that genuinely depend on a file Pest can't see otherwise.\n\n---\n\nNow that you've learned how to use Test Impact Analysis to speed up your test suite, let's discuss how to integrate Pest with your continuous integration workflow: [Continuous Integration](/docs/continuous-integration)\n\n\n---\n\n## Attribute Title Only for full-page components\nAttribute Title | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/attribute-title\n\n## Only for full-page components\n\n> [!info] Full-page components only\n> The `#[Title]` attribute only works for full-page components accessed via routes. Regular components rendered within other views don't use titles—they inherit the parent page's title.\n\n---\n\n## Components Badge > With close button\nComponents Badge | livewire/flux@2.x | Source: https://fluxui.dev/components/badge#livewire/flux\n\n
With close button

Make a badge removable by appending a close button.

<flux:badge>    Admin <flux:badge.close /></flux:badge>

\n\n---\n\n## Components Modal > Modal\nComponents Modal | livewire/flux@2.x | Source: https://fluxui.dev/components/modal#livewire/flux\n\n

\n    Modal\n

Display content in a layer above the main page. Ideal for confirmations, alerts, and forms.

<flux:modal.trigger name=\"edit-profile\">    <flux:button>Edit profile</flux:button></flux:modal.trigger><flux:modal name=\"edit-profile\" class=\"md:w-96\">

            <flux:heading size=\"lg\">Update profile</flux:heading>            <flux:text class=\"mt-2\">Make changes to your personal details.</flux:text>
        <flux:input label=\"Name\" placeholder=\"Your name\" />        <flux:input label=\"Date of birth\" type=\"date\" />
            <flux:spacer />            <flux:button type=\"submit\" variant=\"primary\">Save changes</flux:button>

</flux:modal>

\n\n---\n\n## Filtering Tests `only()`\nFiltering Tests | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/filtering-tests.md\n\n\n### `only()`\n\nDuring development, you may want to focus on running specific tests while excluding all others. Pest provides two ways to do this: running only tests in a specific file, or running only a specific test within a file.\n\n#### Running Only Tests in a File\n\nWhen working on a specific feature, you can mark all tests in a file to run exclusively by calling the `pest()->only()` function at the top of your test file:\n\n```php\n<?php\n\npest()->only();\n\ntest('first test', function () {\n    // This will run\n});\n\ntest('second test', function () {\n    // This will also run\n});\n```\n\nAll tests in files with `pest()->only()` will run, while tests in other files will be skipped.\n\n#### Running a Single Test\n\nTo run only a specific test within a file, chain the `->only()` method to the test:\n\n```php\ntest('sum', function () {\n  $result = sum(1, 2);\n\n  expect($result)->toBe(3);\n})->only();\n\ntest('another test', function () {\n  // This will be skipped\n});\n```\n\n---\n\nAs your codebase grows, manually running your tests with filtering can become tedious. That's where skipping tests comes in. Skipping tests is a useful feature that allows developers to exclude specific tests from the test suite temporarily without deleting them entirely: [Skipping Tests →](/docs/skipping-tests)\n\n---\n\n## Components Button > Full width\nComponents Button | livewire/flux@2.x | Source: https://fluxui.dev/components/button#livewire/flux\n\n
Full width

A button that spans the full width of the container.

<flux:button variant=\"primary\" class=\"w-full\">Send invite</flux:button>

\n\n---\n\n## Routing Route Model Binding Explicit Binding\nRouting | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/routing.md\n\n\n### Explicit Binding\n\nYou are not required to use Laravel's implicit, convention based model resolution in order to use model binding. You can also explicitly define how route parameters correspond to models. To register an explicit binding, use the router's `model` method to specify the class for a given parameter. You should define your explicit model bindings at the beginning of the `boot` method of your `AppServiceProvider` class:\n\n```php\nuse App\\Models\\User;\nuse Illuminate\\Support\\Facades\\Route;\n\n/**\n * Bootstrap any application services.\n */\npublic function boot(): void\n{\n    Route::model('user', User::class);\n}\n```\n\nNext, define a route that contains a `{user}` parameter:\n\n```php\nuse App\\Models\\User;\n\nRoute::get('/users/{user}', function (User $user) {\n    // ...\n});\n```\n\nSince we have bound all `{user}` parameters to the `App\\Models\\User` model, an instance of that class will be injected into the route. So, for example, a request to `users/1` will inject the `User` instance from the database which has an ID of `1`.\n\nIf a matching model instance is not found in the database, a 404 HTTP response will be automatically generated.\n\n---\n\n## Routing Route Model Binding Implicit Binding Customizing Missing Model Behavior\nRouting | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/routing.md\n\n\n#### Customizing Missing Model Behavior\n\nTypically, a 404 HTTP response will be generated if an implicitly bound model is not found. However, you may customize this behavior by calling the `missing` method when defining your route. The `missing` method accepts a closure that will be invoked if an implicitly bound model cannot be found:\n\n```php\nuse App\\Http\\Controllers\\LocationsController;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Facades\\Redirect;\n\nRoute::get('/locations/{location:slug}', [LocationsController::class, 'show'])\n    ->name('locations.view')\n    ->missing(function (Request $request) {\n        return Redirect::route('locations.index');\n    });\n```\n\n---\n\n## Search Full-Text Search Running Full-Text Queries\nSearch | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/search.md\n\n\n### Running Full-Text Queries\n\nOnce the index is in place, use the `whereFullText` query builder method to search against it. Laravel will generate the appropriate SQL for your database driver — for example, `MATCH(...) AGAINST(...)` on MariaDB and MySQL, and `to_tsvector(...) @@ plainto_tsquery(...)` on PostgreSQL:\n\n```php\n$articles = Article::whereFullText('body', 'web developer')->get();\n```\n\nWhen using MariaDB and MySQL, results are automatically ordered by relevance score. On PostgreSQL, `whereFullText` filters matching records but does not order them by relevance — if you need automatic relevance ordering on PostgreSQL, consider using [Scout's database engine](#database-engine), which handles this for you.\n\nIf you created a composite full-text index across multiple columns, you may search against all of them by passing the same array of columns to `whereFullText`:\n\n```php\n$articles = Article::whereFullText(\n    ['title', 'body'], 'web developer'\n)->get();\n```\n\nThe `orWhereFullText` method may be used to add a full-text search clause as an \"or\" condition. For complete details, consult the [query builder documentation](/docs/{{version}}/queries#full-text-where-clauses).\n\n---\n\n## Arch Testing Modifiers `abstracts()`\nArch Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/arch-testing.md\n\n\n### `abstracts()`\n\nThe `abstracts()` modifier allows you to restrict the expectation to only abstract classes.\n\n```php\narch('app')\n    ->expect('App')\n    ->abstracts()\n    ->toImplement(JsonSerializable::class);\n```\n---\n\nIn this section, you have learned how to perform architectural testing, ensuring that your application or library's architecture meets a specified set of architectural requirements. Next, have you ever wondered how to test the performance of your code? Let's explore [Stress Testing](/docs/stress-testing).\n\n---\n\n## Testing Calling actions\nTesting | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/testing\n\n## Calling actions\n\nUse the `call()` method to trigger component actions in your tests:\n\n```php\nuse App\\Models\\Post;\n\nit('can create a post', function () {\n    expect(Post::count())->toBe(0);\n\n    Livewire::test('post.create')\n        ->set('title', 'My new post')\n        ->set('content', 'Post content here')\n        ->call('save');\n\n    expect(Post::count())->toBe(1);\n});\n```\n\n> [!tip] Pest expectations\n> The examples above use Pest's `expect()` syntax for assertions. For a complete list of available expectations, see the [Pest expectations documentation](https://pestphp.com/docs/expectations).\n\nYou can pass parameters to actions:\n\n```php\nLivewire::test('post.show')\n    ->call('deletePost', $postId);\n```\n\n### Testing validation\n\nAssert that validation errors have been thrown using `assertHasErrors()`:\n\n```php\nit('title field is required', function () {\n    Livewire::test('post.create')\n        ->set('title', '')\n        ->call('save')\n        ->assertHasErrors('title');\n});\n```\n\nTest specific validation rules:\n\n```php\nit('title must be at least 3 characters', function () {\n    Livewire::test('post.create')\n        ->set('title', 'ab')\n        ->call('save')\n        ->assertHasErrors(['title' => ['min:3']]);\n});\n```\n\n### Testing authorization\n\nEnsure authorization checks work correctly using `assertUnauthorized()` and `assertForbidden()`:\n\n```php\nuse App\\Models\\User;\nuse App\\Models\\Post;\n\nit('cannot update another users post', function () {\n    $user = User::factory()->create();\n    $stranger = User::factory()->create();\n    $post = Post::factory()->for($stranger)->create();\n\n    Livewire::actingAs($user)\n        ->test('post.edit', ['post' => $post])\n        ->set('title', 'Hacked!')\n        ->call('save')\n        ->assertForbidden();\n});\n```\n\n### Testing redirects\n\nAssert that an action performed a redirect:\n\n```php\nit('redirects to posts index after creating', function () {\n    Livewire::test('post.create')\n        ->set('title', 'New post')\n        ->set('content', 'Content here')\n        ->call('save')\n        ->assertRedirect('/posts');\n});\n```\n\nYou can also assert redirects to named routes or page components:\n\n```php\n->assertRedirect(route('posts.index'));\n->assertRedirectToRoute('posts.index');\n```\n\n### Testing events\n\nAssert that events were dispatched from your component:\n\n```php\nit('dispatches event when post is created', function () {\n    Livewire::test('post.create')\n        ->set('title', 'New post')\n        ->call('save')\n        ->assertDispatched('post-created');\n});\n```\n\nTest event communication between components:\n\n```php\nit('updates post count when event is dispatched', function () {\n    $badge = Livewire::test('post-count-badge')\n        ->assertSee('0');\n\n    Livewire::test('post.create')\n        ->set('title', 'New post')\n        ->call('save')\n        ->assertDispatched('post-created');\n\n    $badge->dispatch('post-created')\n        ->assertSee('1');\n});\n```\n\nAssert events were dispatched with specific parameters:\n\n```php\nit('dispatches notification when deleting post', function () {\n    Livewire::test('post.show')\n        ->call('delete', postId: 3)\n        ->assertDispatched('notify', message: 'Post deleted');\n});\n```\n\nFor complex assertions, use a closure:\n\n```php\nit('dispatches event with correct data', function () {\n    Livewire::test('post.show')\n        ->call('delete', postId: 3)\n        ->assertDispatched('notify', function ($event, $params) {\n            return ($params['message'] ?? '') === 'Post deleted';\n        });\n});\n```\n\n### Testing JS evaluation\n\nAssert that a component evaluated JavaScript via `$this->js()`:\n\n```php\nit('shows an alert after saving', function () {\n    Livewire::test('post.create')\n        ->set('title', 'New post')\n        ->call('save')\n        ->assertJs(\"alert('Post saved!')\");\n});\n```\n\nYou can also assert that no JS was evaluated:\n\n```php\n->assertNoJs();\n```\n\n---\n\n## Browser Testing submit\nBrowser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md\n\n\n### submit\n\nThe `submit` method submits the first form found on the page:\n\n```php\n$page->submit();\n```\n\n---\n\n## Search Full-Text Search Adding Full-Text Indexes\nSearch | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/search.md\n\n\n### Adding Full-Text Indexes\n\nTo use full-text search, first add a full-text index to the columns you want to search. You may add the index to a single column, or pass an array of columns to create a composite index that searches across multiple fields at once:\n\n```php\nSchema::create('articles', function (Blueprint $table) {\n    $table->id();\n    $table->string('title');\n    $table->text('body');\n    $table->timestamps();\n\n    $table->fullText(['title', 'body']);\n});\n```\n\nOn PostgreSQL, you may specify a language configuration for the index, which controls how words are stemmed:\n\n```php\n$table->fullText('body')->language('english');\n```\n\nFor more information on creating indexes, consult the [migration documentation](/docs/{{version}}/migrations#available-index-types).\n\n---\n\n## Installation Next Steps Laravel the Full Stack Framework\nInstallation | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/installation.md\n\n\n### Laravel the Full Stack Framework\n\nLaravel may serve as a full stack framework. By \"full stack\" framework we mean that you are going to use Laravel to route requests to your application and render your frontend via [Blade templates](/docs/{{version}}/blade) or a single-page application hybrid technology like [Inertia](https://inertiajs.com). This is the most common way to use the Laravel framework, and, in our opinion, the most productive way to use Laravel.\n\nIf this is how you plan to use Laravel, you may want to check out our documentation on [frontend development](/docs/{{version}}/frontend), [routing](/docs/{{version}}/routing), [views](/docs/{{version}}/views), or the [Eloquent ORM](/docs/{{version}}/eloquent). In addition, you might be interested in learning about community packages like [Livewire](https://livewire.laravel.com) and [Inertia](https://inertiajs.com). These packages allow you to use Laravel as a full-stack framework while enjoying many of the UI benefits provided by single-page JavaScript applications.\n\nIf you are using Laravel as a full stack framework, we also strongly encourage you to learn how to compile your application's CSS and JavaScript using [Vite](/docs/{{version}}/vite).\n\n> [!NOTE]\n> If you want to get a head start building your application, check out one of our official [application starter kits](/docs/{{version}}/starter-kits).\n\n---\n\n## Validation Testing validation\nValidation | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/validation\n\n## Testing validation\n\nLivewire provides useful testing utilities for validation scenarios, such as the `assertHasErrors()` method.\n\nBelow is a basic test case that ensures validation errors are thrown if no input is set for the `title` property:\n\n```php\n<?php\n\nnamespace Tests\\Feature\\Livewire;\n\nuse App\\Livewire\\CreatePost;\nuse Livewire\\Livewire;\nuse Tests\\TestCase;\n\nclass CreatePostTest extends TestCase\n{\n    public function test_cant_create_post_without_title()\n    {\n        Livewire::test(CreatePost::class)\n            ->set('content', 'Sample content...')\n            ->call('save')\n            ->assertHasErrors('title');\n    }\n}\n```\n\nIn addition to testing the presence of errors, `assertHasErrors` allows you to also narrow down the assertion to specific rules by passing the rules to assert against as the second argument to the method:\n\n```php\npublic function test_cant_create_post_with_title_shorter_than_3_characters()\n{\n    Livewire::test(CreatePost::class)\n        ->set('title', 'Sa')\n        ->set('content', 'Sample content...')\n        ->call('save')\n        ->assertHasErrors(['title' => ['min:3']]);\n}\n```\n\nYou can also assert the presence of validation errors for multiple properties at the same time:\n\n```php\npublic function test_cant_create_post_without_title_and_content()\n{\n    Livewire::test(CreatePost::class)\n        ->call('save')\n        ->assertHasErrors(['title', 'content']);\n}\n```\n\nFor more information on other testing utilities provided by Livewire, check out the [testing documentation](/docs/4.x/testing).\n\n_[Truncated]_"}]


cmd: find app/Livewire -maxdepth 3 -type f | sort


cmd: find resources/views -maxdepth 4 -type f | sort


command: find app/Livewire -maxdepth 3 -type f | sort

cmd: find app/Livewire -maxdepth 3 -type f

path: Livewire

status: completed


command: find resources/views -maxdepth 4 -type f | sort

path: views


output:
Chunk ID: 7f7ea6
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 75
Output:
app/Livewire/Actions/Logout.php
app/Livewire/Admin/Auth/Login.php
app/Livewire/Settings/Appearance.php
app/Livewire/Settings/DeleteUserForm.php
app/Livewire/Settings/Password.php
app/Livewire/Settings/Profile.php
app/Livewire/Settings/TwoFactor.php
app/Livewire/Settings/TwoFactor/RecoveryCodes.php


output:
Chunk ID: 3b272d
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 491
Output:
resources/views/components/action-message.blade.php
resources/views/components/app-logo-icon.blade.php
resources/views/components/app-logo.blade.php
resources/views/components/auth-header.blade.php
resources/views/components/auth-session-status.blade.php
resources/views/components/desktop-user-menu.blade.php
resources/views/components/placeholder-pattern.blade.php
resources/views/components/settings/layout.blade.php
resources/views/dashboard.blade.php
resources/views/flux/icon/book-open-text.blade.php
resources/views/flux/icon/chevrons-up-down.blade.php
resources/views/flux/icon/folder-git-2.blade.php
resources/views/flux/icon/layout-grid.blade.php
resources/views/flux/navlist/group.blade.php
resources/views/layouts/app.blade.php
resources/views/layouts/app/header.blade.php
resources/views/layouts/app/sidebar.blade.php
resources/views/layouts/auth.blade.php
resources/views/layouts/auth/card.blade.php
resources/views/layouts/auth/simple.blade.php
resources/views/layouts/auth/split.blade.php
resources/views/livewire/admin/auth/login.blade.php
resources/views/livewire/auth/confirm-password.blade.php
resources/views/livewire/auth/forgot-password.blade.php
resources/views/livewire/auth/login.blade.php
resources/views/livewire/auth/register.blade.php
resources/views/livewire/auth/reset-password.blade.php
resources/views/livewire/auth/two-factor-challenge.blade.php
resources/views/livewire/auth/verify-email.blade.php
resources/views/livewire/settings/appearance.blade.php
resources/views/livewire/settings/delete-user-form.blade.php
resources/views/livewire/settings/password.blade.php
resources/views/livewire/settings/profile.blade.php
resources/views/livewire/settings/two-factor.blade.php
resources/views/livewire/settings/two-factor/recovery-codes.blade.php
resources/views/partials/head.blade.php
resources/views/partials/settings-heading.blade.php
resources/views/storefront/account/dashboard.blade.php
resources/views/welcome.blade.php


command:
/bin/zsh
-lc
sed -n '1,240p' routes/web.php

web.php

type: read

cmd: sed -n '1,240p' routes/web.php

aggregated_output:
<?php

use App\Livewire\Admin\Auth\Login as AdminLogin;
use App\Livewire\Storefront\Account\Auth\Login as CustomerLogin;
use App\Livewire\Storefront\Account\Auth\Register as CustomerRegister;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;

Route::middleware(['storefront'])->group(function (): void {
    Route::get('/', function () {
        return view('welcome');
    })->name('home');
});

Route::livewire('admin/login', AdminLogin::class)
    ->middleware('guest')
    ->name('admin.login');

Route::post('admin/logout', function () {
    Auth::guard('web')->logout();

    request()->session()->invalidate();
    request()->session()->regenerateToken();

    return redirect()->route('admin.login');
})->middleware('auth')->name('admin.logout');

Route::view('admin', 'dashboard')
    ->middleware(['auth', 'verified', 'admin'])
    ->name('admin.dashboard');

Route::middleware(['storefront'])->group(function (): void {
    Route::livewire('account/login', CustomerLogin::class)
        ->middleware('guest:customer')
        ->name('account.login');

    Route::livewire('account/register', CustomerRegister::class)
        ->middleware('guest:customer')
        ->name('account.register');

    Route::view('account', 'storefront.account.dashboard')
        ->middleware('auth:customer')
        ->name('account.dashboard');
});

Route::redirect('dashboard', 'admin')
    ->middleware(['auth', 'verified'])
    ->name('dashboard');

require __DIR__.'/settings.php';


command:
/bin/zsh
-lc
sed -n '1,260p' config/livewire.php

livewire.php

cmd: sed -n '1,260p' config/livewire.php

aggregated_output: sed: config/livewire.php: No such file or directory

status: failed


output:
Chunk ID: a7c51a
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 376
Output:
<?php

use App\Livewire\Admin\Auth\Login as AdminLogin;
use App\Livewire\Storefront\Account\Auth\Login as CustomerLogin;
use App\Livewire\Storefront\Account\Auth\Register as CustomerRegister;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;

Route::middleware(['storefront'])->group(function (): void {
    Route::get('/', function () {
        return view('welcome');
    })->name('home');
});

Route::livewire('admin/login', AdminLogin::class)
    ->middleware('guest')
    ->name('admin.login');

Route::post('admin/logout', function () {
    Auth::guard('web')->logout();

    request()->session()->invalidate();
    request()->session()->regenerateToken();

    return redirect()->route('admin.login');
})->middleware('auth')->name('admin.logout');

Route::view('admin', 'dashboard')
    ->middleware(['auth', 'verified', 'admin'])
    ->name('admin.dashboard');

Route::middleware(['storefront'])->group(function (): void {
    Route::livewire('account/login', CustomerLogin::class)
        ->middleware('guest:customer')
        ->name('account.login');

    Route::livewire('account/register', CustomerRegister::class)
        ->middleware('guest:customer')
        ->name('account.register');

    Route::view('account', 'storefront.account.dashboard')
        ->middleware('auth:customer')
        ->name('account.dashboard');
});

Route::redirect('dashboard', 'admin')
    ->middleware(['auth', 'verified'])
    ->name('dashboard');

require __DIR__.'/settings.php';


output:
Chunk ID: aa7de1
Wall time: 0.0000 seconds
Process exited with code 1
Original token count: 13
Output:
sed: config/livewire.php: No such file or directory


cmd: find resources/views/livewire -type f | sort


cmd: sed -n '1,260p' resources/views/layouts/app.blade.php


cmd: sed -n '1,260p' resources/views/layouts/app/sidebar.blade.php


command:
/bin/zsh
-lc
find app/Livewire -type f | sort

cmd: find app/Livewire -type f


output:
Chunk ID: 16b131
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 99
Output:
app/Livewire/Actions/Logout.php
app/Livewire/Admin/Auth/Login.php
app/Livewire/Settings/Appearance.php
app/Livewire/Settings/DeleteUserForm.php
app/Livewire/Settings/Password.php
app/Livewire/Settings/Profile.php
app/Livewire/Settings/TwoFactor.php
app/Livewire/Settings/TwoFactor/RecoveryCodes.php
app/Livewire/Storefront/Account/Auth/Login.php
app/Livewire/Storefront/Account/Auth/Register.php


command: find resources/views/livewire -type f | sort

cmd: find resources/views/livewire -type f

path: livewire


output:
Chunk ID: 80c8e5
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 227
Output:
resources/views/livewire/admin/auth/login.blade.php
resources/views/livewire/auth/confirm-password.blade.php
resources/views/livewire/auth/forgot-password.blade.php
resources/views/livewire/auth/login.blade.php
resources/views/livewire/auth/register.blade.php
resources/views/livewire/auth/reset-password.blade.php
resources/views/livewire/auth/two-factor-challenge.blade.php
resources/views/livewire/auth/verify-email.blade.php
resources/views/livewire/settings/appearance.blade.php
resources/views/livewire/settings/delete-user-form.blade.php
resources/views/livewire/settings/password.blade.php
resources/views/livewire/settings/profile.blade.php
resources/views/livewire/settings/two-factor.blade.php
resources/views/livewire/settings/two-factor/recovery-codes.blade.php
resources/views/livewire/storefront/account/auth/login.blade.php
resources/views/livewire/storefront/account/auth/register.blade.php


command: sed -n '1,260p' resources/views/layouts/app/sidebar.blade.php

aggregated_output:
<!DOCTYPE html>
getLocale()) }}" class="dark">

        @include('partials.head')

        <flux:sidebar sticky collapsible="mobile" class="border-e border-zinc-200 bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900">
            <flux:sidebar.header>
                <x-app-logo :sidebar="true" href="{{ route('dashboard') }}" wire:navigate />
                <flux:sidebar.collapse class="lg:hidden" />
            </flux:sidebar.header>

            <flux:sidebar.nav>
                <flux:sidebar.group :heading="__('Platform')" class="grid">
                    <flux:sidebar.item icon="home" :href="route('dashboard')" :current="request()->routeIs('dashboard')" wire:navigate>
                        {{ __('Dashboard') }}
                    </flux:sidebar.item>
                </flux:sidebar.group>
            </flux:sidebar.nav>

            <flux:spacer />

            <flux:sidebar.nav>
                <flux:sidebar.item icon="folder-git-2" href="https://github.com/laravel/livewire-starter-kit" target="_blank">
                    {{ __('Repository') }}
                </flux:sidebar.item>

                <flux:sidebar.item icon="book-open-text" href="https://laravel.com/docs/starter-kits#livewire" target="_blank">
                    {{ __('Documentation') }}
                </flux:sidebar.item>
            </flux:sidebar.nav>

            <x-desktop-user-menu class="hidden lg:block" :name="auth()->user()->name" />
        </flux:sidebar>

        <flux:header class="lg:hidden">
            <flux:sidebar.toggle class="lg:hidden" icon="bars-2" inset="left" />

            <flux:spacer />

            <flux:dropdown position="top" align="end">
                <flux:profile
                    :initials="auth()->user()->initials()"
                    icon-trailing="chevron-down"
                />

                <flux:menu>
                    <flux:menu.radio.group>

                                <flux:avatar
                                    :name="auth()->user()->name"
                                    :initials="auth()->user()->initials()"
                                />

                                    <flux:heading class="truncate">{{ auth()->user()->name }}</flux:heading>
                                    <flux:text class="truncate">{{ auth()->user()->email }}</flux:text>

                    </flux:menu.radio.group>

                    <flux:menu.separator />

                    <flux:menu.radio.group>
                        <flux:menu.item :href="route('profile.edit')" icon="cog" wire:navigate>
                            {{ __('Settings') }}
                        </flux:menu.item>
                    </flux:menu.radio.group>

                    <flux:menu.separator />

                    <form method="POST" action="{{ route('logout') }}" class="w-full">
                        @csrf
                        <flux:menu.item
                            as="button"
                            type="submit"
                            icon="arrow-right-start-on-rectangle"
                            class="w-full cursor-pointer"
                            data-test="logout-button"
                        >
                            {{ __('Log Out') }}
                        </flux:menu.item>
                    </form>
                </flux:menu>
            </flux:dropdown>
        </flux:header>

        {{ $slot }}

        @fluxScripts


command: sed -n '1,260p' resources/views/layouts/app.blade.php

aggregated_output:
<x-layouts::app.sidebar :title="$title ?? null">
    <flux:main>
        {{ $slot }}
    </flux:main>
</x-layouts::app.sidebar>


output:
Chunk ID: 5bb70d
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 32
Output:
<x-layouts::app.sidebar :title="$title ?? null">
    <flux:main>
        {{ $slot }}
    </flux:main>
</x-layouts::app.sidebar>


output:
Chunk ID: 7e3279
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 992
Output:
<!DOCTYPE html>
getLocale()) }}" class="dark">

        @include('partials.head')

        <flux:sidebar sticky collapsible="mobile" class="border-e border-zinc-200 bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900">
            <flux:sidebar.header>
                <x-app-logo :sidebar="true" href="{{ route('dashboard') }}" wire:navigate />
                <flux:sidebar.collapse class="lg:hidden" />
            </flux:sidebar.header>

            <flux:sidebar.nav>
                <flux:sidebar.group :heading="__('Platform')" class="grid">
                    <flux:sidebar.item icon="home" :href="route('dashboard')" :current="request()->routeIs('dashboard')" wire:navigate>
                        {{ __('Dashboard') }}
                    </flux:sidebar.item>
                </flux:sidebar.group>
            </flux:sidebar.nav>

            <flux:spacer />

            <flux:sidebar.nav>
                <flux:sidebar.item icon="folder-git-2" href="https://github.com/laravel/livewire-starter-kit" target="_blank">
                    {{ __('Repository') }}
                </flux:sidebar.item>

                <flux:sidebar.item icon="book-open-text" href="https://laravel.com/docs/starter-kits#livewire" target="_blank">
                    {{ __('Documentation') }}
                </flux:sidebar.item>
            </flux:sidebar.nav>

            <x-desktop-user-menu class="hidden lg:block" :name="auth()->user()->name" />
        </flux:sidebar>

        <flux:header class="lg:hidden">
            <flux:sidebar.toggle class="lg:hidden" icon="bars-2" inset="left" />

            <flux:spacer />

            <flux:dropdown position="top" align="end">
                <flux:profile
                    :initials="auth()->user()->initials()"
                    icon-trailing="chevron-down"
                />

                <flux:menu>
                    <flux:menu.radio.group>

                                <flux:avatar
                                    :name="auth()->user()->name"
                                    :initials="auth()->user()->initials()"
                                />

                                    <flux:heading class="truncate">{{ auth()->user()->name }}</flux:heading>
                                    <flux:text class="truncate">{{ auth()->user()->email }}</flux:text>

                    </flux:menu.radio.group>

                    <flux:menu.separator />

                    <flux:menu.radio.group>
                        <flux:menu.item :href="route('profile.edit')" icon="cog" wire:navigate>
                            {{ __('Settings') }}
                        </flux:menu.item>
                    </flux:menu.radio.group>

                    <flux:menu.separator />

                    <form method="POST" action="{{ route('logout') }}" class="w-full">
                        @csrf
                        <flux:menu.item
                            as="button"
                            type="submit"
                            icon="arrow-right-start-on-rectangle"
                            class="w-full cursor-pointer"
                            data-test="logout-button"
                        >
                            {{ __('Log Out') }}
                        </flux:menu.item>
                    </form>
                </flux:menu>
            </flux:dropdown>
        </flux:header>

        {{ $slot }}

        @fluxScripts


cmd: sed -n '1,260p' app/Livewire/Storefront/Account/Auth/Login.php


cmd: sed -n '1,260p' resources/views/livewire/storefront/account/auth/login.blade.php


cmd: sed -n '1,220p' app/Livewire/Admin/Auth/Login.php


cmd: sed -n '1,240p' resources/views/dashboard.blade.php


command: sed -n '1,260p' app/Livewire/Storefront/Account/Auth/Login.php

aggregated_output:
<?php

namespace App\Livewire\Storefront\Account\Auth;

use App\Models\Store;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Validation\ValidationException;
use Livewire\Component;

class Login extends Component
{
    public int $storeId;

    public string $email = '';

    public string $password = '';

    public bool $remember = false;

    public function mount(): void
    {
        $store = app('current_store');

        abort_unless($store instanceof Store, 404);

        $this->storeId = $store->getKey();
    }

    public function login(): void
    {
        $this->validate([
            'email' => ['required', 'email'],
            'password' => ['required', 'string'],
            'remember' => ['boolean'],
        ]);

        $key = 'customer-login:'.request()->ip();

        if (RateLimiter::tooManyAttempts($key, 5)) {
            throw ValidationException::withMessages([
                'email' => __('Too many attempts. Try again in :seconds seconds.', [
                    'seconds' => RateLimiter::availableIn($key),
                ]),
            ]);
        }

        app()->instance('current_store', Store::query()->findOrFail($this->storeId));

        if (! Auth::guard('customer')->attempt([
            'email' => $this->email,
            'password' => $this->password,
        ], $this->remember)) {
            RateLimiter::hit($key, 60);

            throw ValidationException::withMessages([
                'email' => __('Invalid credentials'),
            ]);
        }

        RateLimiter::clear($key);

        if (request()->hasSession()) {
            request()->session()->regenerate();
        }

        $this->redirectRoute('account.dashboard', navigate: true);
    }

    public function render(): mixed
    {
        return view('livewire.storefront.account.auth.login')
            ->layout('layouts.auth');
    }
}


output:
Chunk ID: 30e81c
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 481
Output:
<?php

namespace App\Livewire\Storefront\Account\Auth;

use App\Models\Store;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Validation\ValidationException;
use Livewire\Component;

class Login extends Component
{
    public int $storeId;

    public string $email = '';

    public string $password = '';

    public bool $remember = false;

    public function mount(): void
    {
        $store = app('current_store');

        abort_unless($store instanceof Store, 404);

        $this->storeId = $store->getKey();
    }

    public function login(): void
    {
        $this->validate([
            'email' => ['required', 'email'],
            'password' => ['required', 'string'],
            'remember' => ['boolean'],
        ]);

        $key = 'customer-login:'.request()->ip();

        if (RateLimiter::tooManyAttempts($key, 5)) {
            throw ValidationException::withMessages([
                'email' => __('Too many attempts. Try again in :seconds seconds.', [
                    'seconds' => RateLimiter::availableIn($key),
                ]),
            ]);
        }

        app()->instance('current_store', Store::query()->findOrFail($this->storeId));

        if (! Auth::guard('customer')->attempt([
            'email' => $this->email,
            'password' => $this->password,
        ], $this->remember)) {
            RateLimiter::hit($key, 60);

            throw ValidationException::withMessages([
                'email' => __('Invalid credentials'),
            ]);
        }

        RateLimiter::clear($key);

        if (request()->hasSession()) {
            request()->session()->regenerate();
        }

        $this->redirectRoute('account.dashboard', navigate: true);
    }

    public function render(): mixed
    {
        return view('livewire.storefront.account.auth.login')
            ->layout('layouts.auth');
    }
}


command: sed -n '1,220p' app/Livewire/Admin/Auth/Login.php

aggregated_output:
<?php

namespace App\Livewire\Admin\Auth;

use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Validation\ValidationException;
use Livewire\Component;

class Login extends Component
{
    public string $email = '';

    public string $password = '';

    public bool $remember = false;

    public function login(): void
    {
        $this->validate([
            'email' => ['required', 'email'],
            'password' => ['required', 'string'],
            'remember' => ['boolean'],
        ]);

        $key = 'admin-login:'.request()->ip();

        if (RateLimiter::tooManyAttempts($key, 5)) {
            throw ValidationException::withMessages([
                'email' => __('Too many attempts. Try again in :seconds seconds.', [
                    'seconds' => RateLimiter::availableIn($key),
                ]),
            ]);
        }

        if (! Auth::guard('web')->attempt([
            'email' => $this->email,
            'password' => $this->password,
            'status' => 'active',
        ], $this->remember)) {
            RateLimiter::hit($key, 60);

            throw ValidationException::withMessages([
                'email' => __('Invalid credentials'),
            ]);
        }

        RateLimiter::clear($key);

        if (request()->hasSession()) {
            request()->session()->regenerate();
        }

        Auth::user()?->forceFill(['last_login_at' => now()])->save();

        $this->redirectRoute('admin.dashboard', navigate: true);
    }

    public function render(): mixed
    {
        return view('livewire.admin.auth.login')
            ->layout('layouts.auth');
    }
}


command: sed -n '1,260p' resources/views/livewire/storefront/account/auth/login.blade.php

aggregated_output:
    <x-auth-header :title="__('Log in')" :description="__('Access your orders and saved addresses')" />

    <form wire:submit="login" class="flex flex-col gap-6">
        <flux:input
            wire:model="email"
            :label="__('Email address')"
            type="email"
            required
            autofocus
            autocomplete="email"
            placeholder="customer@acme.test"
        />

        <flux:input
            wire:model="password"
            :label="__('Password')"
            type="password"
            required
            autocomplete="current-password"
            :placeholder="__('Password')"
            viewable
        />

        <flux:checkbox wire:model="remember" :label="__('Remember me')" />

        <flux:button variant="primary" type="submit" class="w-full" data-test="customer-login-button">
            {{ __('Log in') }}
        </flux:button>
    </form>

        {{ __('New customer?') }}
        <flux:link :href="route('account.register')" wire:navigate>{{ __('Create an account') }}</flux:link>


command: sed -n '1,240p' resources/views/dashboard.blade.php

aggregated_output:
<x-layouts::app :title="__('Dashboard')">

                <x-placeholder-pattern class="absolute inset-0 size-full stroke-gray-900/20 dark:stroke-neutral-100/20" />

                <x-placeholder-pattern class="absolute inset-0 size-full stroke-gray-900/20 dark:stroke-neutral-100/20" />

                <x-placeholder-pattern class="absolute inset-0 size-full stroke-gray-900/20 dark:stroke-neutral-100/20" />

            <x-placeholder-pattern class="absolute inset-0 size-full stroke-gray-900/20 dark:stroke-neutral-100/20" />

</x-layouts::app>


output:
Chunk ID: 1cdfe3
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 300
Output:

    <x-auth-header :title="__('Log in')" :description="__('Access your orders and saved addresses')" />

    <form wire:submit="login" class="flex flex-col gap-6">
        <flux:input
            wire:model="email"
            :label="__('Email address')"
            type="email"
            required
            autofocus
            autocomplete="email"
            placeholder="customer@acme.test"
        />

        <flux:input
            wire:model="password"
            :label="__('Password')"
            type="password"
            required
            autocomplete="current-password"
            :placeholder="__('Password')"
            viewable
        />

        <flux:checkbox wire:model="remember" :label="__('Remember me')" />

        <flux:button variant="primary" type="submit" class="w-full" data-test="customer-login-button">
            {{ __('Log in') }}
        </flux:button>
    </form>

        {{ __('New customer?') }}
        <flux:link :href="route('account.register')" wire:navigate>{{ __('Create an account') }}</flux:link>


output:
Chunk ID: 66923a
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 419
Output:
<?php

namespace App\Livewire\Admin\Auth;

use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Validation\ValidationException;
use Livewire\Component;

class Login extends Component
{
    public string $email = '';

    public string $password = '';

    public bool $remember = false;

    public function login(): void
    {
        $this->validate([
            'email' => ['required', 'email'],
            'password' => ['required', 'string'],
            'remember' => ['boolean'],
        ]);

        $key = 'admin-login:'.request()->ip();

        if (RateLimiter::tooManyAttempts($key, 5)) {
            throw ValidationException::withMessages([
                'email' => __('Too many attempts. Try again in :seconds seconds.', [
                    'seconds' => RateLimiter::availableIn($key),
                ]),
            ]);
        }

        if (! Auth::guard('web')->attempt([
            'email' => $this->email,
            'password' => $this->password,
            'status' => 'active',
        ], $this->remember)) {
            RateLimiter::hit($key, 60);

            throw ValidationException::withMessages([
                'email' => __('Invalid credentials'),
            ]);
        }

        RateLimiter::clear($key);

        if (request()->hasSession()) {
            request()->session()->regenerate();
        }

        Auth::user()?->forceFill(['last_login_at' => now()])->save();

        $this->redirectRoute('admin.dashboard', navigate: true);
    }

    public function render(): mixed
    {
        return view('livewire.admin.auth.login')
            ->layout('layouts.auth');
    }
}


output:
Chunk ID: 8f31f8
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 319
Output:
<x-layouts::app :title="__('Dashboard')">

                <x-placeholder-pattern class="absolute inset-0 size-full stroke-gray-900/20 dark:stroke-neutral-100/20" />

                <x-placeholder-pattern class="absolute inset-0 size-full stroke-gray-900/20 dark:stroke-neutral-100/20" />

                <x-placeholder-pattern class="absolute inset-0 size-full stroke-gray-900/20 dark:stroke-neutral-100/20" />

            <x-placeholder-pattern class="absolute inset-0 size-full stroke-gray-900/20 dark:stroke-neutral-100/20" />

</x-layouts::app>


cmd: find app/Http/Middleware app/Providers app/Policies app/Models -maxdepth 3 -type f | sort


cmd: sed -n '1,260p' app/Http/Middleware/ResolveStore.php


cmd: sed -n '1,260p' app/Http/Middleware/CheckStoreRole.php


command: sed -n '1,260p' app/Http/Middleware/CheckStoreRole.php

aggregated_output:
<?php

namespace App\Http\Middleware;

use App\Enums\StoreUserRole;
use App\Models\Store;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class CheckStoreRole
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next, string ...$roles): Response
    {
        $store = app()->bound('current_store') ? app('current_store') : null;
        $user = $request->user();

        abort_unless($store instanceof Store && $user, 403);

        $role = $user->roleForStore($store);

        if ($roles === []) {
            abort_unless($role !== null, 403);

            return $next($request);
        }

        $allowedRoles = array_filter(array_map(
            fn (string $role): ?StoreUserRole => StoreUserRole::tryFrom($role),
            $roles,
        ));

        abort_unless($role !== null && in_array($role, $allowedRoles, true), 403);

        return $next($request);
    }
}


command:
/bin/zsh
-lc
sed -n '1,260p' bootstrap/app.php

app.php

cmd: sed -n '1,260p' bootstrap/app.php

aggregated_output:
<?php

use App\Http\Middleware\CheckStoreRole;
use App\Http\Middleware\ResolveStore;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware): void {
        $middleware->alias([
            'role.check' => CheckStoreRole::class,
            'store.resolve' => ResolveStore::class,
        ]);

        $middleware->appendToGroup('storefront', [
            ResolveStore::class,
        ]);

        $middleware->appendToGroup('admin', [
            ResolveStore::class,
            CheckStoreRole::class,
        ]);
    })
    ->withExceptions(function (Exceptions $exceptions): void {
        //
    })->create();


command: sed -n '1,260p' app/Http/Middleware/ResolveStore.php

aggregated_output:
<?php

namespace App\Http\Middleware;

use App\Enums\StoreStatus;
use App\Models\Store;
use App\Models\StoreDomain;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Symfony\Component\HttpFoundation\Response;

class ResolveStore
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        $store = $request->is('admin*')
            ? $this->resolveAdminStore($request)
            : $this->resolveStorefrontStore($request);

        abort_unless($store, 404);

        app()->instance('current_store', $store);

        if (! $request->is('admin*') && $store->status === StoreStatus::Suspended) {
            abort(503);
        }

        if ($request->is('admin*') && $store->status === StoreStatus::Suspended && ! $request->isMethodSafe()) {
            abort(403);
        }

        return $next($request);
    }

    private function resolveStorefrontStore(Request $request): ?Store
    {
        $hostname = $request->getHost();
        $cacheKey = "store_domain:{$hostname}";

        $storeId = Cache::remember($cacheKey, now()->addMinutes(5), function () use ($hostname): ?int {
            return StoreDomain::query()
                ->where('hostname', $hostname)
                ->value('store_id');
        });

        return $storeId ? Store::query()->find($storeId) : null;
    }

    private function resolveAdminStore(Request $request): ?Store
    {
        $user = $request->user();

        if (! $user) {
            return null;
        }

        $storeId = $request->session()->get('current_store_id');

        if (! $storeId) {
            $storeId = $user->stores()->oldest('stores.id')->value('stores.id');

            if ($storeId) {
                $request->session()->put('current_store_id', $storeId);
            }
        }

        if (! $storeId || ! $user->stores()->whereKey($storeId)->exists()) {
            return null;
        }

        return Store::query()->find($storeId);
    }
}


command: find app/Http/Middleware app/Providers app/Policies app/Models -maxdepth 3 -type f | sort

path: Middleware

aggregated_output:
app/Http/Middleware/CheckStoreRole.php
app/Http/Middleware/ResolveStore.php
app/Models/Collection.php
app/Models/Concerns/BelongsToStore.php
app/Models/Customer.php
app/Models/InventoryItem.php
app/Models/Organization.php
app/Models/Product.php
app/Models/ProductMedia.php
app/Models/ProductOption.php
app/Models/ProductOptionValue.php
app/Models/ProductVariant.php
app/Models/Scopes/StoreScope.php
app/Models/Store.php
app/Models/StoreDomain.php
app/Models/StoreSettings.php
app/Models/StoreUser.php
app/Models/User.php
app/Policies/CollectionPolicy.php
app/Policies/CustomerPolicy.php
app/Policies/DiscountPolicy.php
app/Policies/FulfillmentPolicy.php
app/Policies/OrderPolicy.php
app/Policies/PagePolicy.php
app/Policies/ProductPolicy.php
app/Policies/RefundPolicy.php
app/Policies/StorePolicy.php
app/Policies/ThemePolicy.php
app/Providers/AppServiceProvider.php
app/Providers/FortifyServiceProvider.php