sed -n '1,220p' /Users/fabianwesner/Herd/shop/.agents/skills/livewire-development/SKILL.md

---
name: livewire-development
description: "Use for any task or question involving Livewire. Activate if user mentions Livewire, wire: directives, or Livewire-specific concepts like wire:model, wire:click, wire:sort, or islands, invoke this skill. Covers building new components, debugging reactivity issues, real-time form validation, drag-and-drop, loading states, migrating from Livewire 3 to 4, converting component formats (SFC/MFC/class-based), and performance optimization. Do not use for non-Livewire reactive UI (React, Vue, Alpine-only, Inertia.js) or standard Laravel forms without Livewire."
license: MIT
metadata:
  author: laravel
---

# Livewire Development

## Documentation

Use `search-docs` for detailed Livewire 4 patterns and documentation.

## Basic Usage

### Creating Components

```bash

# Single-file component (SFC - default in v4)

# Creates: resources/views/components/⚡create-post.blade.php

php artisan make:livewire create-post

# Page component (SFC - Full Page in v4)

# Creates: resources/views/pages/⚡create-post.blade.php

php artisan make:livewire pages::create-post

# Multi-file component (MFC)

# Creates: resources/views/components/⚡create-post/create-post.php

#          resources/views/components/⚡create-post/create-post.blade.php

php artisan make:livewire create-post --mfc

# Class-based component (v3 style)

# Creates: app/Livewire/CreatePost.php AND resources/views/livewire/create-post.blade.php

php artisan make:livewire create-post --class

# With namespace

php artisan make:livewire Posts/CreatePost
```

### Converting Between Formats

Use `php artisan livewire:convert create-post` to convert between single-file, multi-file, and class-based formats.

### Choosing a Component Format

> **Always follow the project's existing conventions first.** Before creating any component, inspect the project's existing Livewire components to determine the established format (SFC, MFC, or class-based) and directory structure. Check `app/Livewire/`, `resources/views/components/`, and `resources/views/livewire/` for existing components. If the project already uses a consistent format, **use that same format** — even if it differs from the Livewire v4 defaults below. Only fall back to the v4 defaults (SFC in `resources/views/components/`) when no existing convention is established.

Also check `config/livewire.php` for `make_command.type`, `make_command.emoji`, `component_locations`, and `component_namespaces` overrides, which change the default format and where files are stored.

### Component Format Reference

| Format | Flag | Class Path | View Path |
|--------|------|------------|-----------|
| Single-file (SFC) | default | — | `resources/views/components/⚡create-post.blade.php` (PHP + Blade in one file) |
| Full Page SFC | `pages::name` | — | `resources/views/pages/⚡create-post.blade.php` |
| Multi-file (MFC) | `--mfc` | `resources/views/components/⚡create-post/create-post.php` | `resources/views/components/⚡create-post/create-post.blade.php` |
| Class-based | `--class` | `app/Livewire/CreatePost.php` | `resources/views/livewire/create-post.blade.php` |
| View-based | default (Blade-only) | — | `resources/views/components/⚡create-post.blade.php` (Blade-only with functional state) |

> **Important:** The ⚡ prefix shown above is the **default** behavior in Livewire v4 — it is **configurable**. Check `config/livewire.php` for the `make_command.emoji` setting. When `true` (default), always include the ⚡ prefix in filenames you create. When `false`, omit the ⚡ prefix from all paths above.

Namespaced components map to subdirectories: `make:livewire Posts/CreatePost` creates `resources/views/components/posts/⚡create-post.blade.php` (single-file by default). Use `make:livewire Posts/CreatePost --mfc` for multi-file output at `resources/views/components/posts/⚡create-post/create-post.php` and `resources/views/components/posts/⚡create-post/create-post.blade.php`.

### Single-File Component Example

<!-- Single-File Component Example -->
```php
<?php
use Livewire\Component;

new class extends Component {
    public int $count = 0;

    public function increment(): void
    {
        $this->count++;
    }
};
?>

<div>
    <button wire:click="increment">Count: @{{ $count }}</button>
</div>
```

## Livewire 4 Specifics

### Key Changes From Livewire 3

These things changed in Livewire 4, but may not have been updated in this application. Verify this application's setup to ensure you follow existing conventions.

- Use `Route::livewire()` for full-page components (e.g., `Route::livewire('/posts/create', CreatePost::class)`); config keys renamed: `layout` → `component_layout`, `lazy_placeholder` → `component_placeholder`.
- `wire:model` now ignores child events by default (use `wire:model.deep` for old behavior); `wire:scroll` renamed to `wire:navigate:scroll`.
- Component tags must be properly closed; `wire:transition` now uses View Transitions API (modifiers removed).
- JavaScript: `$wire.$js('name', fn)` → `$wire.$js.name = fn`; `commit`/`request` hooks → `interceptMessage()`/`interceptRequest()`.

### New Features

- Component formats: single-file (SFC), multi-file (MFC), view-based components.
- Islands (`@island`) for isolated updates; async actions (`wire:click.async`, `#[Async]`) for parallel execution.
- Deferred/bundled loading: `defer`, `lazy.bundle` for optimized component loading.

| Feature | Usage | Purpose |
|---------|-------|---------|
| Islands | `@island(name: 'stats')` | Isolated update regions |
| Async | `wire:click.async` or `#[Async]` | Non-blocking actions |
| Deferred | `defer` attribute | Load after page render |
| Bundled | `lazy.bundle` | Load multiple together |

### New Directives

- `wire:sort`, `wire:intersect`, `wire:ref`, `.renderless`, `.preserve-scroll` are available for use.
- `data-loading` attribute automatically added to elements triggering network requests.

| Directive | Purpose |
|-----------|---------|
| `wire:sort` | Drag-and-drop sorting |
| `wire:intersect` | Viewport intersection detection |
| `wire:ref` | Element references for JS |
| `.renderless` | Component without rendering |
| `.preserve-scroll` | Preserve scroll position |

## Best Practices

- Always use `wire:key` in loops
- Use `wire:loading` for loading states
- Use `wire:model.live` for instant updates (default is debounced)
- Validate and authorize in actions (treat like HTTP requests)

## Configuration

- `smart_wire_keys` defaults to `true`; new configs: `component_locations`, `component_namespaces`, `make_command`, `csp_safe`.

## Alpine & JavaScript

- `wire:transition` uses browser View Transitions API; `$errors` and `$intercept` magic properties available.
- Non-blocking `wire:poll` and parallel `wire:model.live` updates improve performance.

For interceptors and hooks, see [reference/javascript-hooks.md](reference/javascript-hooks.md).

## Testing

<!-- Testing Example -->
```php
Livewire::test(Counter::class)
    ->assertSet('count', 0)
    ->call('increment')
    ->assertSet('count', 1);
```

## Verification

1. Browser console: Check for JS errors
2. Network tab: Verify Livewire requests return 200
3. Ensure `wire:key` on all `@foreach` loops

## Common Pitfalls

- Missing `wire:key` in loops → unexpected re-rendering
- Expecting `wire:model` real-time → use `wire:model.live`
- Unclosed component tags → syntax errors in v4
- Using deprecated config keys or JS hooks
- Including Alpine.js separately (already bundled in Livewire 4)


Output:
Chunk ID: 3fb881
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1888
Output:
---
name: livewire-development
description: "Use for any task or question involving Livewire. Activate if user mentions Livewire, wire: directives, or Livewire-specific concepts like wire:model, wire:click, wire:sort, or islands, invoke this skill. Covers building new components, debugging reactivity issues, real-time form validation, drag-and-drop, loading states, migrating from Livewire 3 to 4, converting component formats (SFC/MFC/class-based), and performance optimization. Do not use for non-Livewire reactive UI (React, Vue, Alpine-only, Inertia.js) or standard Laravel forms without Livewire."
license: MIT
metadata:
  author: laravel
---

# Livewire Development

## Documentation

Use `search-docs` for detailed Livewire 4 patterns and documentation.

## Basic Usage

### Creating Components

```bash

# Single-file component (SFC - default in v4)

# Creates: resources/views/components/⚡create-post.blade.php

php artisan make:livewire create-post

# Page component (SFC - Full Page in v4)

# Creates: resources/views/pages/⚡create-post.blade.php

php artisan make:livewire pages::create-post

# Multi-file component (MFC)

# Creates: resources/views/components/⚡create-post/create-post.php

#          resources/views/components/⚡create-post/create-post.blade.php

php artisan make:livewire create-post --mfc

# Class-based component (v3 style)

# Creates: app/Livewire/CreatePost.php AND resources/views/livewire/create-post.blade.php

php artisan make:livewire create-post --class

# With namespace

php artisan make:livewire Posts/CreatePost
```

### Converting Between Formats

Use `php artisan livewire:convert create-post` to convert between single-file, multi-file, and class-based formats.

### Choosing a Component Format

> **Always follow the project's existing conventions first.** Before creating any component, inspect the project's existing Livewire components to determine the established format (SFC, MFC, or class-based) and directory structure. Check `app/Livewire/`, `resources/views/components/`, and `resources/views/livewire/` for existing components. If the project already uses a consistent format, **use that same format** — even if it differs from the Livewire v4 defaults below. Only fall back to the v4 defaults (SFC in `resources/views/components/`) when no existing convention is established.

Also check `config/livewire.php` for `make_command.type`, `make_command.emoji`, `component_locations`, and `component_namespaces` overrides, which change the default format and where files are stored.

### Component Format Reference

| Format | Flag | Class Path | View Path |
|--------|------|------------|-----------|
| Single-file (SFC) | default | — | `resources/views/components/⚡create-post.blade.php` (PHP + Blade in one file) |
| Full Page SFC | `pages::name` | — | `resources/views/pages/⚡create-post.blade.php` |
| Multi-file (MFC) | `--mfc` | `resources/views/components/⚡create-post/create-post.php` | `resources/views/components/⚡create-post/create-post.blade.php` |
| Class-based | `--class` | `app/Livewire/CreatePost.php` | `resources/views/livewire/create-post.blade.php` |
| View-based | default (Blade-only) | — | `resources/views/components/⚡create-post.blade.php` (Blade-only with functional state) |

> **Important:** The ⚡ prefix shown above is the **default** behavior in Livewire v4 — it is **configurable**. Check `config/livewire.php` for the `make_command.emoji` setting. When `true` (default), always include the ⚡ prefix in filenames you create. When `false`, omit the ⚡ prefix from all paths above.

Namespaced components map to subdirectories: `make:livewire Posts/CreatePost` creates `resources/views/components/posts/⚡create-post.blade.php` (single-file by default). Use `make:livewire Posts/CreatePost --mfc` for multi-file output at `resources/views/components/posts/⚡create-post/create-post.php` and `resources/views/components/posts/⚡create-post/create-post.blade.php`.

### Single-File Component Example

<!-- Single-File Component Example -->
```php
<?php
use Livewire\Component;

new class extends Component {
    public int $count = 0;

    public function increment(): void
    {
        $this->count++;
    }
};
?>

<div>
    <button wire:click="increment">Count: @{{ $count }}</button>
</div>
```

## Livewire 4 Specifics

### Key Changes From Livewire 3

These things changed in Livewire 4, but may not have been updated in this application. Verify this application's setup to ensure you follow existing conventions.

- Use `Route::livewire()` for full-page components (e.g., `Route::livewire('/posts/create', CreatePost::class)`); config keys renamed: `layout` → `component_layout`, `lazy_placeholder` → `component_placeholder`.
- `wire:model` now ignores child events by default (use `wire:model.deep` for old behavior); `wire:scroll` renamed to `wire:navigate:scroll`.
- Component tags must be properly closed; `wire:transition` now uses View Transitions API (modifiers removed).
- JavaScript: `$wire.$js('name', fn)` → `$wire.$js.name = fn`; `commit`/`request` hooks → `interceptMessage()`/`interceptRequest()`.

### New Features

- Component formats: single-file (SFC), multi-file (MFC), view-based components.
- Islands (`@island`) for isolated updates; async actions (`wire:click.async`, `#[Async]`) for parallel execution.
- Deferred/bundled loading: `defer`, `lazy.bundle` for optimized component loading.

| Feature | Usage | Purpose |
|---------|-------|---------|
| Islands | `@island(name: 'stats')` | Isolated update regions |
| Async | `wire:click.async` or `#[Async]` | Non-blocking actions |
| Deferred | `defer` attribute | Load after page render |
| Bundled | `lazy.bundle` | Load multiple together |

### New Directives

- `wire:sort`, `wire:intersect`, `wire:ref`, `.renderless`, `.preserve-scroll` are available for use.
- `data-loading` attribute automatically added to elements triggering network requests.

| Directive | Purpose |
|-----------|---------|
| `wire:sort` | Drag-and-drop sorting |
| `wire:intersect` | Viewport intersection detection |
| `wire:ref` | Element references for JS |
| `.renderless` | Component without rendering |
| `.preserve-scroll` | Preserve scroll position |

## Best Practices

- Always use `wire:key` in loops
- Use `wire:loading` for loading states
- Use `wire:model.live` for instant updates (default is debounced)
- Validate and authorize in actions (treat like HTTP requests)

## Configuration

- `smart_wire_keys` defaults to `true`; new configs: `component_locations`, `component_namespaces`, `make_command`, `csp_safe`.

## Alpine & JavaScript

- `wire:transition` uses browser View Transitions API; `$errors` and `$intercept` magic properties available.
- Non-blocking `wire:poll` and parallel `wire:model.live` updates improve performance.

For interceptors and hooks, see [reference/javascript-hooks.md](reference/javascript-hooks.md).

## Testing

<!-- Testing Example -->
```php
Livewire::test(Counter::class)
    ->assertSet('count', 0)
    ->call('increment')
    ->assertSet('count', 1);
```

## Verification

1. Browser console: Check for JS errors
2. Network tab: Verify Livewire requests return 200
3. Ensure `wire:key` on all `@foreach` loops

## Common Pitfalls

- Missing `wire:key` in loops → unexpected re-rendering
- Expecting `wire:model` real-time → use `wire:model.live`
- Unclosed component tags → syntax errors in v4
- Using deprecated config keys or JS hooks
- Including Alpine.js separately (already bundled in Livewire 4)


sed -n '1,220p' /Users/fabianwesner/Herd/shop/.agents/skills/pest-testing/SKILL.md

SKILL.md

---
name: pest-testing
description: "Use this skill for Pest PHP testing in Laravel projects only. Trigger whenever any test is being written, edited, fixed, or refactored — including fixing tests that broke after a code change, adding assertions, converting PHPUnit to Pest, adding datasets, and TDD workflows. Always activate when the user asks how to write something in Pest, mentions test files or directories (tests/Feature, tests/Unit, tests/Browser), or needs browser testing, smoke testing multiple pages for JS errors, or architecture tests. Covers: test()/it()/expect() syntax, datasets, mocking, browser testing (visit/click/fill), smoke testing, arch(), Livewire component tests, RefreshDatabase, and all Pest 4 features. Do not use for factories, seeders, migrations, controllers, models, or non-test PHP code."
license: MIT
metadata:
  author: laravel
---

# Pest Testing 4

## Documentation

Use `search-docs` for detailed Pest 4 patterns and documentation.

## Basic Usage

### Creating Tests

All tests must be written using Pest. Use `php artisan make:test --pest {name}`.

### Test Organization

- Unit/Feature tests: `tests/Feature` and `tests/Unit` directories.
- Browser tests: `tests/Browser/` directory.
- Do NOT remove tests without approval - these are core application code.

### Basic Test Structure

Pest supports both `test()` and `it()` functions. Before writing new tests, check existing test files in the same directory to match the project's convention. Use `test()` if existing tests use `test()`, or `it()` if they use `it()`.

<!-- Basic Pest Test Example -->
```php
it('is true', function () {
    expect(true)->toBeTrue();
});
```

### Running Tests

- Run minimal tests with filter before finalizing: `php artisan test --compact --filter=testName`.
- Run all tests: `php artisan test --compact`.
- Run file: `php artisan test --compact tests/Feature/ExampleTest.php`.

## Assertions

Use specific assertions (`assertSuccessful()`, `assertNotFound()`) instead of `assertStatus()`:

<!-- Pest Response Assertion -->
```php
it('returns all', function () {
    $this->postJson('/api/docs', [])->assertSuccessful();
});
```

| Use | Instead of |
|-----|------------|
| `assertSuccessful()` | `assertStatus(200)` |
| `assertNotFound()` | `assertStatus(404)` |
| `assertForbidden()` | `assertStatus(403)` |

## Mocking

Import mock function before use: `use function Pest\Laravel\mock;`

## Datasets

Use datasets for repetitive tests (validation rules, etc.):

<!-- Pest Dataset Example -->
```php
it('has emails', function (string $email) {
    expect($email)->not->toBeEmpty();
})->with([
    'james' => 'james@laravel.com',
    'taylor' => 'taylor@laravel.com',
]);
```

## Pest 4 Features

| Feature | Purpose |
|---------|---------|
| Browser Testing | Full integration tests in real browsers |
| Smoke Testing | Validate multiple pages quickly |
| Visual Regression | Compare screenshots for visual changes |
| Test Sharding | Parallel CI runs |
| Architecture Testing | Enforce code conventions |

### Browser Test Example

Browser tests run in real browsers for full integration testing:

- Browser tests live in `tests/Browser/`.
- Use Laravel features like `Event::fake()`, `assertAuthenticated()`, and model factories.
- Use `RefreshDatabase` for clean state per test.
- Interact with page: click, type, scroll, select, submit, drag-and-drop, touch gestures.
- Test on multiple browsers (Chrome, Firefox, Safari) if requested.
- Test on different devices/viewports (iPhone 14 Pro, tablets) if requested.
- Switch color schemes (light/dark mode) when appropriate.
- Take screenshots or pause tests for debugging.

<!-- Pest Browser Test Example -->
```php
it('may reset the password', function () {
    Notification::fake();

    $this->actingAs(User::factory()->create());

    $page = visit('/sign-in');

    $page->assertSee('Sign In')
        ->assertNoJavaScriptErrors()
        ->click('Forgot Password?')
        ->fill('email', 'nuno@laravel.com')
        ->click('Send Reset Link')
        ->assertSee('We have emailed your password reset link!');

    Notification::assertSent(ResetPassword::class);
});
```

### Smoke Testing

Quickly validate multiple pages have no JavaScript errors:

<!-- Pest Smoke Testing Example -->
```php
$pages = visit(['/', '/about', '/contact']);

$pages->assertNoJavaScriptErrors()->assertNoConsoleLogs();
```

### Visual Regression Testing

Capture and compare screenshots to detect visual changes.

### Test Sharding

Split tests across parallel processes for faster CI runs.

### Architecture Testing

Pest 4 includes architecture testing (from Pest 3):

<!-- Architecture Test Example -->
```php
arch('controllers')
    ->expect('App\Http\Controllers')
    ->toExtendNothing()
    ->toHaveSuffix('Controller');
```

## Common Pitfalls

- Not importing `use function Pest\Laravel\mock;` before using mock
- Using `assertStatus(200)` instead of `assertSuccessful()`
- Forgetting datasets for repetitive validation tests
- Deleting tests without approval
- Forgetting `assertNoJavaScriptErrors()` in browser tests


sed -n '1,220p' /Users/fabianwesner/Herd/shop/.agents/skills/fluxui-development/SKILL.md

---
name: fluxui-development
description: "Use this skill for Flux UI development in Livewire applications only. Trigger when working with <flux:*> components, building or customizing Livewire component UIs, creating forms, modals, tables, or other interactive elements. Covers: flux: components (buttons, inputs, modals, forms, tables, date-pickers, kanban, badges, tooltips, etc.), component composition, Tailwind CSS styling, Heroicons/Lucide icon integration, validation patterns, responsive design, and theming. Do not use for non-Livewire frameworks or non-component styling."
license: MIT
metadata:
  author: laravel
---

# Flux UI Development

## Documentation

Use `search-docs` for detailed Flux UI patterns and documentation.

## Basic Usage

This project uses the free edition of Flux UI, which includes all free components and variants but not Pro components.

Flux UI is a component library for Livewire built with Tailwind CSS. It provides components that are easy to use and customize.

Use Flux UI components when available. Fall back to standard Blade components when no Flux component exists for your needs.

<!-- Basic Button -->
```blade
<flux:button variant="primary">Click me</flux:button>
```

## Available Components (Free Edition)

Available: avatar, badge, brand, breadcrumbs, button, callout, checkbox, dropdown, field, heading, icon, input, modal, navbar, otp-input, profile, radio, select, separator, skeleton, switch, text, textarea, tooltip

## Icons

Flux includes [Heroicons](https://heroicons.com/) as its default icon set. Search for exact icon names on the Heroicons site - do not guess or invent icon names.

<!-- Icon Button -->
```blade
<flux:button icon="arrow-down-tray">Export</flux:button>
```

For icons not available in Heroicons, use [Lucide](https://lucide.dev/). Import the icons you need with the Artisan command:

```bash
php artisan flux:icon crown grip-vertical github
```

## Common Patterns

### Form Fields

<!-- Form Field -->
```blade
<flux:field>
    <flux:label>Email</flux:label>
    <flux:input type="email" wire:model="email" />
    <flux:error name="email" />
</flux:field>
```

### Modals

<!-- Modal -->
```blade
<flux:modal wire:model="showModal">
    <flux:heading>Title</flux:heading>
    <p>Content</p>
</flux:modal>
```

## Verification

1. Check component renders correctly
2. Test interactive states
3. Verify mobile responsiveness

## Common Pitfalls

- Trying to use Pro-only components in the free edition
- Not checking if a Flux component exists before creating custom implementations
- Forgetting to use the `search-docs` tool for component-specific documentation
- Not following existing project patterns for Flux usage


Output:
Chunk ID: 2b1f73
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 675
Output:
---
name: fluxui-development
description: "Use this skill for Flux UI development in Livewire applications only. Trigger when working with <flux:*> components, building or customizing Livewire component UIs, creating forms, modals, tables, or other interactive elements. Covers: flux: components (buttons, inputs, modals, forms, tables, date-pickers, kanban, badges, tooltips, etc.), component composition, Tailwind CSS styling, Heroicons/Lucide icon integration, validation patterns, responsive design, and theming. Do not use for non-Livewire frameworks or non-component styling."
license: MIT
metadata:
  author: laravel
---

# Flux UI Development

## Documentation

Use `search-docs` for detailed Flux UI patterns and documentation.

## Basic Usage

This project uses the free edition of Flux UI, which includes all free components and variants but not Pro components.

Flux UI is a component library for Livewire built with Tailwind CSS. It provides components that are easy to use and customize.

Use Flux UI components when available. Fall back to standard Blade components when no Flux component exists for your needs.

<!-- Basic Button -->
```blade
<flux:button variant="primary">Click me</flux:button>
```

## Available Components (Free Edition)

Available: avatar, badge, brand, breadcrumbs, button, callout, checkbox, dropdown, field, heading, icon, input, modal, navbar, otp-input, profile, radio, select, separator, skeleton, switch, text, textarea, tooltip

## Icons

Flux includes [Heroicons](https://heroicons.com/) as its default icon set. Search for exact icon names on the Heroicons site - do not guess or invent icon names.

<!-- Icon Button -->
```blade
<flux:button icon="arrow-down-tray">Export</flux:button>
```

For icons not available in Heroicons, use [Lucide](https://lucide.dev/). Import the icons you need with the Artisan command:

```bash
php artisan flux:icon crown grip-vertical github
```

## Common Patterns

### Form Fields

<!-- Form Field -->
```blade
<flux:field>
    <flux:label>Email</flux:label>
    <flux:input type="email" wire:model="email" />
    <flux:error name="email" />
</flux:field>
```

### Modals

<!-- Modal -->
```blade
<flux:modal wire:model="showModal">
    <flux:heading>Title</flux:heading>
    <p>Content</p>
</flux:modal>
```

## Verification

1. Check component renders correctly
2. Test interactive states
3. Verify mobile responsiveness

## Common Pitfalls

- Trying to use Pro-only components in the free edition
- Not checking if a Flux component exists before creating custom implementations
- Forgetting to use the `search-docs` tool for component-specific documentation
- Not following existing project patterns for Flux usage


Output:
Chunk ID: 8c0a3c
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1275
Output:
---
name: pest-testing
description: "Use this skill for Pest PHP testing in Laravel projects only. Trigger whenever any test is being written, edited, fixed, or refactored — including fixing tests that broke after a code change, adding assertions, converting PHPUnit to Pest, adding datasets, and TDD workflows. Always activate when the user asks how to write something in Pest, mentions test files or directories (tests/Feature, tests/Unit, tests/Browser), or needs browser testing, smoke testing multiple pages for JS errors, or architecture tests. Covers: test()/it()/expect() syntax, datasets, mocking, browser testing (visit/click/fill), smoke testing, arch(), Livewire component tests, RefreshDatabase, and all Pest 4 features. Do not use for factories, seeders, migrations, controllers, models, or non-test PHP code."
license: MIT
metadata:
  author: laravel
---

# Pest Testing 4

## Documentation

Use `search-docs` for detailed Pest 4 patterns and documentation.

## Basic Usage

### Creating Tests

All tests must be written using Pest. Use `php artisan make:test --pest {name}`.

### Test Organization

- Unit/Feature tests: `tests/Feature` and `tests/Unit` directories.
- Browser tests: `tests/Browser/` directory.
- Do NOT remove tests without approval - these are core application code.

### Basic Test Structure

Pest supports both `test()` and `it()` functions. Before writing new tests, check existing test files in the same directory to match the project's convention. Use `test()` if existing tests use `test()`, or `it()` if they use `it()`.

<!-- Basic Pest Test Example -->
```php
it('is true', function () {
    expect(true)->toBeTrue();
});
```

### Running Tests

- Run minimal tests with filter before finalizing: `php artisan test --compact --filter=testName`.
- Run all tests: `php artisan test --compact`.
- Run file: `php artisan test --compact tests/Feature/ExampleTest.php`.

## Assertions

Use specific assertions (`assertSuccessful()`, `assertNotFound()`) instead of `assertStatus()`:

<!-- Pest Response Assertion -->
```php
it('returns all', function () {
    $this->postJson('/api/docs', [])->assertSuccessful();
});
```

| Use | Instead of |
|-----|------------|
| `assertSuccessful()` | `assertStatus(200)` |
| `assertNotFound()` | `assertStatus(404)` |
| `assertForbidden()` | `assertStatus(403)` |

## Mocking

Import mock function before use: `use function Pest\Laravel\mock;`

## Datasets

Use datasets for repetitive tests (validation rules, etc.):

<!-- Pest Dataset Example -->
```php
it('has emails', function (string $email) {
    expect($email)->not->toBeEmpty();
})->with([
    'james' => 'james@laravel.com',
    'taylor' => 'taylor@laravel.com',
]);
```

## Pest 4 Features

| Feature | Purpose |
|---------|---------|
| Browser Testing | Full integration tests in real browsers |
| Smoke Testing | Validate multiple pages quickly |
| Visual Regression | Compare screenshots for visual changes |
| Test Sharding | Parallel CI runs |
| Architecture Testing | Enforce code conventions |

### Browser Test Example

Browser tests run in real browsers for full integration testing:

- Browser tests live in `tests/Browser/`.
- Use Laravel features like `Event::fake()`, `assertAuthenticated()`, and model factories.
- Use `RefreshDatabase` for clean state per test.
- Interact with page: click, type, scroll, select, submit, drag-and-drop, touch gestures.
- Test on multiple browsers (Chrome, Firefox, Safari) if requested.
- Test on different devices/viewports (iPhone 14 Pro, tablets) if requested.
- Switch color schemes (light/dark mode) when appropriate.
- Take screenshots or pause tests for debugging.

<!-- Pest Browser Test Example -->
```php
it('may reset the password', function () {
    Notification::fake();

    $this->actingAs(User::factory()->create());

    $page = visit('/sign-in');

    $page->assertSee('Sign In')
        ->assertNoJavaScriptErrors()
        ->click('Forgot Password?')
        ->fill('email', 'nuno@laravel.com')
        ->click('Send Reset Link')
        ->assertSee('We have emailed your password reset link!');

    Notification::assertSent(ResetPassword::class);
});
```

### Smoke Testing

Quickly validate multiple pages have no JavaScript errors:

<!-- Pest Smoke Testing Example -->
```php
$pages = visit(['/', '/about', '/contact']);

$pages->assertNoJavaScriptErrors()->assertNoConsoleLogs();
```

### Visual Regression Testing

Capture and compare screenshots to detect visual changes.

### Test Sharding

Split tests across parallel processes for faster CI runs.

### Architecture Testing

Pest 4 includes architecture testing (from Pest 3):

<!-- Architecture Test Example -->
```php
arch('controllers')
    ->expect('App\Http\Controllers')
    ->toExtendNothing()
    ->toHaveSuffix('Controller');
```

## Common Pitfalls

- Not importing `use function Pest\Laravel\mock;` before using mock
- Using `assertStatus(200)` instead of `assertSuccessful()`
- Forgetting datasets for repetitive validation tests
- Deleting tests without approval
- Forgetting `assertNoJavaScriptErrors()` in browser tests


sed -n '1,220p' /Users/fabianwesner/Herd/shop/.agents/skills/tailwindcss-development/SKILL.md


sed -n '1,220p' /Users/fabianwesner/Herd/shop/.agents/skills/tailwindcss-development/SKILL.md

---
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


Output:
Chunk ID: 9c014d
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


rg -n "Phase 6|content|settings|theme|navigation|pages|Navigation|Theme|Settings" specs/09-IMPLEMENTATION-ROADMAP.md specs/03-ADMIN-UI.md specs/01-DATABASE-SCHEMA.md specs/05-BUSINESS-LOGIC.md specs/07-SEEDERS-AND-TEST-DATA.md


laravel/framework livewire/livewire livewire/flux pestphp/pest

livewire full page form validation pagination

flux textarea select input checkbox table button

laravel validation array json date unique


rg -n "Phase 6|content|settings|theme|navigation|pages|Navigation|Theme|Settings" specs/09-IMPLEMENTATION-ROADMAP.md specs/03-ADMIN-UI.md specs/01-DATABASE-SCHEMA.md specs/05-BUSINESS-LOGIC.md specs/07-SEEDERS-AND-TEST-DATA.md

rg -n 'Phase 6|content|settings|theme|navigation|pages|Navigation|Theme|Settings' specs/09-IMPLEMENTATION-ROADMAP.md specs/03-ADMIN-UI.md specs/01-DATABASE-SCHEMA.md specs/05-BUSINESS-LOGIC.md specs/07-SEEDERS-AND-TEST-DATA.md

Question: Phase 6|content|settings|theme|navigation|pages|Navigation|Theme|Settings

specs/07-SEEDERS-AND-TEST-DATA.md:20:| 6 | StoreSettingsSeeder | Stores | Inserts per-store JSON settings |
specs/07-SEEDERS-AND-TEST-DATA.md:21:| 7 | TaxSettingsSeeder | Stores | Configures tax mode and rates |
specs/07-SEEDERS-AND-TEST-DATA.md:28:| 14 | ThemeSeeder | Stores | Creates themes with settings |
specs/07-SEEDERS-AND-TEST-DATA.md:29:| 15 | PageSeeder | Stores | Creates content pages |
specs/07-SEEDERS-AND-TEST-DATA.md:30:| 16 | NavigationSeeder | Stores, Collections, Pages | Creates menus linking to collections and pages |
specs/07-SEEDERS-AND-TEST-DATA.md:32:| 18 | SearchSettingsSeeder | Stores | Configures search synonyms and stop words |
specs/07-SEEDERS-AND-TEST-DATA.md:40:    B --> F[StoreSettingsSeeder]
specs/07-SEEDERS-AND-TEST-DATA.md:41:    B --> G[TaxSettingsSeeder]
specs/07-SEEDERS-AND-TEST-DATA.md:53:    B --> N[ThemeSeeder]
specs/07-SEEDERS-AND-TEST-DATA.md:55:    I --> P[NavigationSeeder]
specs/07-SEEDERS-AND-TEST-DATA.md:59:    B --> R[SearchSettingsSeeder]
specs/07-SEEDERS-AND-TEST-DATA.md:631:### 2.22 ThemeFactory
specs/07-SEEDERS-AND-TEST-DATA.md:633:**Model:** Theme
specs/07-SEEDERS-AND-TEST-DATA.md:640:| name | "Default Theme" |
specs/07-SEEDERS-AND-TEST-DATA.md:677:### 2.24 NavigationMenuFactory
specs/07-SEEDERS-AND-TEST-DATA.md:679:**Model:** NavigationMenu
specs/07-SEEDERS-AND-TEST-DATA.md:693:### 2.25 NavigationItemFactory
specs/07-SEEDERS-AND-TEST-DATA.md:695:**Model:** NavigationItem
specs/07-SEEDERS-AND-TEST-DATA.md:701:| menu_id | Creates a new NavigationMenu via its factory |
specs/07-SEEDERS-AND-TEST-DATA.md:831:### 3.6 StoreSettingsSeeder
specs/07-SEEDERS-AND-TEST-DATA.md:833:**Acme Fashion - settings_json contents:**
specs/07-SEEDERS-AND-TEST-DATA.md:842:**Acme Electronics - settings_json contents:**
specs/07-SEEDERS-AND-TEST-DATA.md:853:### 3.7 TaxSettingsSeeder
specs/07-SEEDERS-AND-TEST-DATA.md:1885:### 3.14 ThemeSeeder
specs/07-SEEDERS-AND-TEST-DATA.md:1891:| name | Default Theme |
specs/07-SEEDERS-AND-TEST-DATA.md:1896:**Theme settings (theme_settings row):**
specs/07-SEEDERS-AND-TEST-DATA.md:1919:| name | Default Theme |
specs/07-SEEDERS-AND-TEST-DATA.md:1923:Theme settings:
specs/07-SEEDERS-AND-TEST-DATA.md:1941:**Acme Fashion - 5 content pages:**
specs/07-SEEDERS-AND-TEST-DATA.md:1943:All pages: status = "published", published_at = 3 months ago.
specs/07-SEEDERS-AND-TEST-DATA.md:1947:- body_html content: Three sections with h2 headings - "Our Story" (mission and philosophy), "Our Values" (ethical sourcing, sustainability, fair labor), "Our Team" (Berlin-based designers). Multiple paragraphs of realistic store copy.
specs/07-SEEDERS-AND-TEST-DATA.md:1951:- body_html content: h2 "Frequently Asked Questions" followed by four Q&A pairs using h3/p structure:
specs/07-SEEDERS-AND-TEST-DATA.md:1959:- body_html content: Shipping rates table (Germany standard 4.99/express 9.99, EU 8.99, International 14.99) using h3 and ul/li elements, plus returns policy paragraph (30 days, customer pays return shipping unless defective).
specs/07-SEEDERS-AND-TEST-DATA.md:1963:- body_html content: Standard privacy policy with sections: Information We Collect, How We Use Your Information, Cookies, Contact (privacy@acme-fashion.test). Uses h2/h3/p structure.
specs/07-SEEDERS-AND-TEST-DATA.md:1967:- body_html content: Standard ToS with sections: Orders and Payments (EUR, tax-inclusive), Product Descriptions (color variance disclaimer), Limitation of Liability, Governing Law (Federal Republic of Germany). Uses h2/h3/p structure.
specs/07-SEEDERS-AND-TEST-DATA.md:1971:### 3.16 NavigationSeeder
specs/07-SEEDERS-AND-TEST-DATA.md:2075:### 3.18 SearchSettingsSeeder
specs/03-ADMIN-UI.md:13:The admin layout is a persistent shell that wraps every admin page. It consists of a left sidebar, a top bar, and a main content area.
specs/03-ADMIN-UI.md:19:### 1.2 Sidebar Navigation
specs/03-ADMIN-UI.md:66:|  [bars-3]       Navigation    |
specs/03-ADMIN-UI.md:67:|  [paint-brush]  Themes        |
specs/03-ADMIN-UI.md:71:|  [cog-6-tooth]  Settings      |
specs/03-ADMIN-UI.md:77:#### Navigation Structure
specs/03-ADMIN-UI.md:92:  Pages                          -> admin.pages.index
specs/03-ADMIN-UI.md:93:  Navigation                     -> admin.navigation.index
specs/03-ADMIN-UI.md:94:  Themes                         -> admin.themes.index
specs/03-ADMIN-UI.md:96:Settings                         -> admin.settings.index
specs/03-ADMIN-UI.md:101:Each nav item displays an icon (via Flux icon component) and a text label. The active item receives a highlighted background and bold text. All navigation links use Livewire SPA-style page transitions. Groups are visually separated with Flux separator components.
specs/03-ADMIN-UI.md:108:| Navigation icons | `icon` |
specs/03-ADMIN-UI.md:113:- **Desktop (lg and above):** Sidebar is always visible, fixed left, 256px wide. Main content has a left margin of 256px.
specs/03-ADMIN-UI.md:148:    - Settings (links to /admin/settings)
specs/03-ADMIN-UI.md:173:The main cont…22966 chars truncated… |
specs/09-IMPLEMENTATION-ROADMAP.md:1348:| handles prices-include-tax correctly | tax settings: prices_include_tax=true, rate=1900; item price 11900 (gross) | tax extracted = 1900, subtotal = 10000 | edge case |
specs/09-IMPLEMENTATION-ROADMAP.md:1383:| applies zero tax when no tax settings exist | no tax_settings row for store | tax = 0 | edge case |
specs/09-IMPLEMENTATION-ROADMAP.md:1553:#### tests/Feature/Admin/SettingsTest.php
specs/09-IMPLEMENTATION-ROADMAP.md:1557:| renders the settings page | GET /admin/settings | 200 response, sees settings tabs | happy path |
specs/09-IMPLEMENTATION-ROADMAP.md:1558:| updates general store settings | update store name | store_settings updated | happy path |
specs/09-IMPLEMENTATION-ROADMAP.md:1560:| configures tax settings | set mode=manual, rate=1900, prices_include_tax=true | tax_settings updated | happy path |
specs/09-IMPLEMENTATION-ROADMAP.md:1561:| restricts settings to owner and admin roles | staff user GET /admin/settings | 403 response | authorization |
specs/09-IMPLEMENTATION-ROADMAP.md:1701:| `StoreSettings` | Per-store configuration |
specs/09-IMPLEMENTATION-ROADMAP.md:1709:| `Theme` | Store theme entity |
specs/09-IMPLEMENTATION-ROADMAP.md:1710:| `ThemeFile` | Individual theme file |
specs/09-IMPLEMENTATION-ROADMAP.md:1711:| `ThemeSettings` | Theme configuration |
specs/09-IMPLEMENTATION-ROADMAP.md:1713:| `NavigationMenu` | Navigation menu entity |
specs/09-IMPLEMENTATION-ROADMAP.md:1714:| `NavigationItem` | Individual navigation item |
specs/09-IMPLEMENTATION-ROADMAP.md:1720:| `TaxSettings` | Per-store tax configuration |
specs/09-IMPLEMENTATION-ROADMAP.md:1738:| `SearchSettings` | Per-store search configuration |
specs/09-IMPLEMENTATION-ROADMAP.md:1747:| `Admin/Layout/Sidebar` | Admin sidebar navigation |
specs/09-IMPLEMENTATION-ROADMAP.md:1759:| `Admin/Settings/Index` | Settings tabs |
specs/09-IMPLEMENTATION-ROADMAP.md:1760:| `Admin/Settings/Shipping` | Shipping zone/rate management |
specs/09-IMPLEMENTATION-ROADMAP.md:1761:| `Admin/Settings/Taxes` | Tax settings |
specs/09-IMPLEMENTATION-ROADMAP.md:1763:| `Admin/Themes/Index` | Theme list |
specs/09-IMPLEMENTATION-ROADMAP.md:1764:| `Admin/Themes/Editor` | Theme editor |
specs/09-IMPLEMENTATION-ROADMAP.md:1767:| `Admin/Navigation/Index` | Navigation menu management |
specs/09-IMPLEMENTATION-ROADMAP.md:1769:| `Admin/Search/Settings` | Search settings |
specs/09-IMPLEMENTATION-ROADMAP.md:1815:| `ThemePolicy` | Theme |
specs/09-IMPLEMENTATION-ROADMAP.md:1838:| `UpdateTaxSettingsRequest` | Validate tax settings update |
specs/09-IMPLEMENTATION-ROADMAP.md:1914:| `Admin/SettingsTest` | Admin settings feature tests |
specs/09-IMPLEMENTATION-ROADMAP.md:1979:| `NavigationService` | Menu tree building, URL resolution, caching |
specs/09-IMPLEMENTATION-ROADMAP.md:2051:6. `StoreSettingsSeeder`
specs/09-IMPLEMENTATION-ROADMAP.md:2052:7. `TaxSettingsSeeder`
specs/09-IMPLEMENTATION-ROADMAP.md:2059:14. `ThemeSeeder` - creates themes with files and settings
specs/09-IMPLEMENTATION-ROADMAP.md:2061:16. `NavigationSeeder` - creates navigation menus and items
specs/09-IMPLEMENTATION-ROADMAP.md:2063:18. `SearchSettingsSeeder`
specs/05-BUSINESS-LOGIC.md:41:3. If the store is suspended: return HTTP 403 Forbidden. Admin users can still view settings but cannot perform storefront-affecting mutations.
specs/05-BUSINESS-LOGIC.md:80:products, collections, customers, orders, carts, checkouts, discounts, shipping_zones, themes, pages, navigation_menus, analytics_events, analytics_daily, webhook_subscriptions, inventory_items, search_queries.
specs/05-BUSINESS-LOGIC.md:90:| Manage store settings | Yes | Yes | No | No |
specs/05-BUSINESS-LOGIC.md:95:| Manage themes | Yes | Yes | No | No |
specs/05-BUSINESS-LOGIC.md:195:- Same logic applies to collections and pages.
specs/05-BUSINESS-LOGIC.md:341:- Finds carts where status = `active` AND updated_at < (now - 14 days). The 14-day threshold is configurable via `store_settings`.
specs/05-BUSINESS-LOGIC.md:737:- The TaxCalculationRequest contains: line items (with discounted amounts), shipping amount, shipping address, store tax settings.
specs/05-BUSINESS-LOGIC.md:750:2. Use the tax rate defined in `tax_settings.config_json` for the matched zone, or the global default rate.
specs/05-BUSINESS-LOGIC.md:763:Controlled by `tax_settings.prices_include_tax` (boolean).
specs/05-BUSINESS-LOGIC.md:802:- Fallback behavior (configurable per store in `tax_settings.config_json`):
specs/05-BUSINESS-LOGIC.md:868:- Cost = fixed amount regardless of cart contents.
specs/05-BUSINESS-LOGIC.md:1047:- Configurable timeout: `store_settings.settings_json` key `bank_transfer_cancel_days`, default = 7.
specs/05-BUSINESS-LOGIC.md:1082:- Format: configurable prefix (default: `#`) stored in `store_settings.settings_json` key `order_number_prefix`.
specs/05-BUSINESS-LOGIC.md:1702:| TaxCalculationRequest | lineItems (array), shippingAmount (int), address (Address), taxSettings (object) | Input for tax providers |


Output:
Chunk ID: 04a02d
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 8242
Output:
specs/07-SEEDERS-AND-TEST-DATA.md:20:| 6 | StoreSettingsSeeder | Stores | Inserts per-store JSON settings |
specs/07-SEEDERS-AND-TEST-DATA.md:21:| 7 | TaxSettingsSeeder | Stores | Configures tax mode and rates |
specs/07-SEEDERS-AND-TEST-DATA.md:28:| 14 | ThemeSeeder | Stores | Creates themes with settings |
specs/07-SEEDERS-AND-TEST-DATA.md:29:| 15 | PageSeeder | Stores | Creates content pages |
specs/07-SEEDERS-AND-TEST-DATA.md:30:| 16 | NavigationSeeder | Stores, Collections, Pages | Creates menus linking to collections and pages |
specs/07-SEEDERS-AND-TEST-DATA.md:32:| 18 | SearchSettingsSeeder | Stores | Configures search synonyms and stop words |
specs/07-SEEDERS-AND-TEST-DATA.md:40:    B --> F[StoreSettingsSeeder]
specs/07-SEEDERS-AND-TEST-DATA.md:41:    B --> G[TaxSettingsSeeder]
specs/07-SEEDERS-AND-TEST-DATA.md:53:    B --> N[ThemeSeeder]
specs/07-SEEDERS-AND-TEST-DATA.md:55:    I --> P[NavigationSeeder]
specs/07-SEEDERS-AND-TEST-DATA.md:59:    B --> R[SearchSettingsSeeder]
specs/07-SEEDERS-AND-TEST-DATA.md:631:### 2.22 ThemeFactory
specs/07-SEEDERS-AND-TEST-DATA.md:633:**Model:** Theme
specs/07-SEEDERS-AND-TEST-DATA.md:640:| name | "Default Theme" |
specs/07-SEEDERS-AND-TEST-DATA.md:677:### 2.24 NavigationMenuFactory
specs/07-SEEDERS-AND-TEST-DATA.md:679:**Model:** NavigationMenu
specs/07-SEEDERS-AND-TEST-DATA.md:693:### 2.25 NavigationItemFactory
specs/07-SEEDERS-AND-TEST-DATA.md:695:**Model:** NavigationItem
specs/07-SEEDERS-AND-TEST-DATA.md:701:| menu_id | Creates a new NavigationMenu via its factory |
specs/07-SEEDERS-AND-TEST-DATA.md:831:### 3.6 StoreSettingsSeeder
specs/07-SEEDERS-AND-TEST-DATA.md:833:**Acme Fashion - settings_json contents:**
specs/07-SEEDERS-AND-TEST-DATA.md:842:**Acme Electronics - settings_json contents:**
specs/07-SEEDERS-AND-TEST-DATA.md:853:### 3.7 TaxSettingsSeeder
specs/07-SEEDERS-AND-TEST-DATA.md:1885:### 3.14 ThemeSeeder
specs/07-SEEDERS-AND-TEST-DATA.md:1891:| name | Default Theme |
specs/07-SEEDERS-AND-TEST-DATA.md:1896:**Theme settings (theme_settings row):**
specs/07-SEEDERS-AND-TEST-DATA.md:1919:| name | Default Theme |
specs/07-SEEDERS-AND-TEST-DATA.md:1923:Theme settings:
specs/07-SEEDERS-AND-TEST-DATA.md:1941:**Acme Fashion - 5 content pages:**
specs/07-SEEDERS-AND-TEST-DATA.md:1943:All pages: status = "published", published_at = 3 months ago.
specs/07-SEEDERS-AND-TEST-DATA.md:1947:- body_html content: Three sections with h2 headings - "Our Story" (mission and philosophy), "Our Values" (ethical sourcing, sustainability, fair labor), "Our Team" (Berlin-based designers). Multiple paragraphs of realistic store copy.
specs/07-SEEDERS-AND-TEST-DATA.md:1951:- body_html content: h2 "Frequently Asked Questions" followed by four Q&A pairs using h3/p structure:
specs/07-SEEDERS-AND-TEST-DATA.md:1959:- body_html content: Shipping rates table (Germany standard 4.99/express 9.99, EU 8.99, International 14.99) using h3 and ul/li elements, plus returns policy paragraph (30 days, customer pays return shipping unless defective).
specs/07-SEEDERS-AND-TEST-DATA.md:1963:- body_html content: Standard privacy policy with sections: Information We Collect, How We Use Your Information, Cookies, Contact (privacy@acme-fashion.test). Uses h2/h3/p structure.
specs/07-SEEDERS-AND-TEST-DATA.md:1967:- body_html content: Standard ToS with sections: Orders and Payments (EUR, tax-inclusive), Product Descriptions (color variance disclaimer), Limitation of Liability, Governing Law (Federal Republic of Germany). Uses h2/h3/p structure.
specs/07-SEEDERS-AND-TEST-DATA.md:1971:### 3.16 NavigationSeeder
specs/07-SEEDERS-AND-TEST-DATA.md:2075:### 3.18 SearchSettingsSeeder
specs/03-ADMIN-UI.md:13:The admin layout is a persistent shell that wraps every admin page. It consists of a left sidebar, a top bar, and a main content area.
specs/03-ADMIN-UI.md:19:### 1.2 Sidebar Navigation
specs/03-ADMIN-UI.md:66:|  [bars-3]       Navigation    |
specs/03-ADMIN-UI.md:67:|  [paint-brush]  Themes        |
specs/03-ADMIN-UI.md:71:|  [cog-6-tooth]  Settings      |
specs/03-ADMIN-UI.md:77:#### Navigation Structure
specs/03-ADMIN-UI.md:92:  Pages                          -> admin.pages.index
specs/03-ADMIN-UI.md:93:  Navigation                     -> admin.navigation.index
specs/03-ADMIN-UI.md:94:  Themes                         -> admin.themes.index
specs/03-ADMIN-UI.md:96:Settings                         -> admin.settings.index
specs/03-ADMIN-UI.md:101:Each nav item displays an icon (via Flux icon component) and a text label. The active item receives a highlighted background and bold text. All navigation links use Livewire SPA-style page transitions. Groups are visually separated with Flux separator components.
specs/03-ADMIN-UI.md:108:| Navigation icons | `icon` |
specs/03-ADMIN-UI.md:113:- **Desktop (lg and above):** Sidebar is always visible, fixed left, 256px wide. Main content has a left margin of 256px.
specs/03-ADMIN-UI.md:148:    - Settings (links to /admin/settings)
specs/03-ADMIN-UI.md:173:The main content area sits to the right of the sidebar and below the top bar. Every page renders within this area.
specs/03-ADMIN-UI.md:175:**Breadcrumbs:** Every page includes a Flux breadcrumbs component at the top of the content area. The first item is always "Home" linking to `/admin`. Subsequent items reflect the page hierarchy. Example for product edit: Home > Products > "Blue T-Shirt".
specs/03-ADMIN-UI.md:177:**Layout wrapper:** The content area has consistent padding (larger on desktop, smaller on mobile) and a max-width container centered horizontally.
specs/03-ADMIN-UI.md:198:Dark mode preference is persisted in `localStorage` under the key `theme` with values `light` or `dark`. On page load, the stored preference is applied before first paint to avoid flash of incorrect theme. If no preference is stored, the system preference (`prefers-color-scheme`) is used as default.
specs/03-ADMIN-UI.md:1124:| Text content | `text` |
specs/03-ADMIN-UI.md:1378:## 11. Settings Pages
specs/03-ADMIN-UI.md:1380:### 11.1 General Settings
specs/03-ADMIN-UI.md:1382:**Route:** `GET /admin/settings`
specs/03-ADMIN-UI.md:1384:**Livewire component:** `App\Livewire\Admin\Settings\General`
specs/03-ADMIN-UI.md:1386:**Blade view:** `resources/views/livewire/admin/settings/general.blade.php`
specs/03-ADMIN-UI.md:1400:| `save()` | Validates and saves store settings |
specs/03-ADMIN-UI.md:1413:- Left: Heading "Defaults" + description "Currency, language, and timezone settings."
specs/03-ADMIN-UI.md:1421:### 11.2 Domains Settings
specs/03-ADMIN-UI.md:1423:Domains is a tab within the Settings page (`/admin/settings`), not a separate route. The Settings page has tabs: General, Domains, Shipping, Taxes, Checkout, Notifications.
specs/03-ADMIN-UI.md:1425:**Livewire component:** `App\Livewire\Admin\Settings\Domains`
specs/03-ADMIN-UI.md:1427:**Blade view:** `resources/views/livewire/admin/settings/domains.blade.php`
specs/03-ADMIN-UI.md:1471:### 11.3 Shipping Settings
specs/03-ADMIN-UI.md:1473:**Route:** `GET /admin/settings/shipping`
specs/03-ADMIN-UI.md:1475:**Livewire component:** `App\Livewire\Admin\Settings\Shipping`
specs/03-ADMIN-UI.md:1477:**Blade view:** `resources/views/livewire/admin/settings/shipping.blade.php`
specs/03-ADMIN-UI.md:1588:### 11.4 Tax Settings
specs/03-ADMIN-UI.md:1590:**Route:** `GET /admin/settings/taxes`
specs/03-ADMIN-UI.md:1592:**Livewire component:** `App\Livewire\Admin\Settings\Taxes`
specs/03-ADMIN-UI.md:1594:**Blade view:** `resources/views/livewire/admin/settings/taxes.blade.php`
specs/03-ADMIN-UI.md:1608:| `save()` | Saves tax settings |
specs/03-ADMIN-UI.md:1655:## 12. Themes Management
specs/03-ADMIN-UI.md:1657:### 12.1 Themes List
specs/03-ADMIN-UI.md:1659:**Route:** `GET /admin/themes`
specs/03-ADMIN-UI.md:1661:**Livewire component:** `App\Livewire\Admin\Themes\Index`
specs/03-ADMIN-UI.md:1663:**Blade view:** `resources/views/livewire/admin/themes/index.blade.php`
specs/03-ADMIN-UI.md:1669:| `themes` | `Collection` | All themes for the store |
specs/03-ADMIN-UI.md:1673:| `publishTheme(int $themeId)` | Publishes a theme (sets as active) |
specs/03-ADMIN-UI.md:1674:| `duplicateTheme(int $themeId)` | Creates a copy of the theme |
specs/03-ADMIN-UI.md:1675:| `deleteTheme(int $themeId)` | Deletes a theme |
specs/03-ADMIN-UI.md:1681:| Themes                                                            |
specs/03-ADMIN-UI.md:1687:| | My Theme   v1.0  | | Dark Theme v1.2  | | Minimal    v2.0  |   |
specs/03-ADMIN-UI.md:1696:**Theme grid:** Responsive 3-column grid (1 on mobile, 2 on md, 3 on lg).
specs/03-ADMIN-UI.md:1698:Each theme card contains:
specs/03-ADMIN-UI.md:1699:- **Thumbnail area:** Aspect-video container with theme preview image or placeholder
specs/03-ADMIN-UI.md:1701:  - Theme name (heading, size md) and version text
specs/03-ADMIN-UI.md:1704:  - "Customize" primary button (links to theme editor)
specs/03-ADMIN-UI.md:1712:The published theme card has a blue ring border highlight.
specs/03-ADMIN-UI.md:1714:### 12.2 Theme Editor
specs/03-ADMIN-UI.md:1716:**Route:** `GET /admin/themes/{theme}/editor`
specs/03-ADMIN-UI.md:1718:**Livewire component:** `App\Livewire\Admin\Themes\Editor`
specs/03-ADMIN-UI.md:1720:**Blade view:** `resources/views/livewire/admin/themes/editor.blade.php`
specs/03-ADMIN-UI.md:1726:| `theme` | `Theme` | The theme being edited |
specs/03-ADMIN-UI.md:1727:| `sections` | `array` | List of theme sections from settings schema |
specs/03-ADMIN-UI.md:1729:| `sectionSettings` | `array` | Settings values for the selected section |
specs/03-ADMIN-UI.md:1734:| `mount(Theme $theme)` | Loads theme and its sections |
specs/03-ADMIN-UI.md:1735:| `selectSection(string $sectionKey)` | Changes the selected section and loads its settings |
specs/03-ADMIN-UI.md:1737:| `save()` | Saves all section settings to theme_settings |
specs/03-ADMIN-UI.md:1738:| `publish()` | Publishes the theme |
specs/03-ADMIN-UI.md:1745:| [<- Back to themes]                     [Save]  [Save & publish] |
specs/03-ADMIN-UI.md:1750:| Header     |  +------------------------+ |  Header Settings     |
specs/03-ADMIN-UI.md:1771:- "Back to themes" button (ghost, with left arrow icon) linking to themes index
specs/03-ADMIN-UI.md:1785:**Right panel (320px):** Settings form
specs/03-ADMIN-UI.md:1786:- Shows settings for the selected section
specs/03-ADMIN-UI.md:1799:- When no section is selected: centered text "Select a section to edit its settings."
specs/03-ADMIN-UI.md:1807:**Route:** `GET /admin/pages`
specs/03-ADMIN-UI.md:1811:**Blade view:** `resources/views/livewire/admin/pages/index.blade.php`
specs/03-ADMIN-UI.md:1821:| `pages` | Paginated pages for the current store |
specs/03-ADMIN-UI.md:1832:**Route:** `GET /admin/pages/create` and `GET /admin/pages/{page}/edit`
specs/03-ADMIN-UI.md:1836:**Blade view:** `resources/views/livewire/admin/pages/form.blade.php`
specs/03-ADMIN-UI.md:1845:| `bodyHtml` | `string` | Page body content (HTML) |
specs/03-ADMIN-UI.md:1869:## 14. Navigation Management
specs/03-ADMIN-UI.md:1871:**Route:** `GET /admin/navigation`
specs/03-ADMIN-UI.md:1873:**Livewire component:** `App\Livewire\Admin\Navigation\Index`
specs/03-ADMIN-UI.md:1875:**Blade view:** `resources/views/livewire/admin/navigation/index.blade.php`
specs/03-ADMIN-UI.md:1881:| `menus` | `Collection` | Navigation menus (Main Menu, Footer Menu) |
specs/03-ADMIN-UI.md:1882:| `editingMenu` | `?NavigationMenu` | Menu being edited |
specs/03-ADMIN-UI.md:1905:| Navigation                                                        |
specs/03-ADMIN-UI.md:2209:## 18. Search Settings
specs/03-ADMIN-UI.md:2211:**Route:** `GET /admin/search/settings`
specs/03-ADMIN-UI.md:2213:**Livewire component:** `App\Livewire\Admin\Search\Settings`
specs/03-ADMIN-UI.md:2215:**Blade view:** `resources/views/livewire/admin/search/settings.blade.php`
specs/03-ADMIN-UI.md:2229:| `save()` | Saves synonym and stop word settings |
specs/03-ADMIN-UI.md:2239:| Search Settings                                                   |
specs/03-ADMIN-UI.md:2296:All list pages follow a consistent pattern:
specs/03-ADMIN-UI.md:2307:All form pages follow a consistent pattern:
specs/03-ADMIN-UI.md:2310:3. Left column: primary content fields
specs/03-ADMIN-UI.md:2367:- Semantic HTML: headings hierarchy, landmark regions, lists for navigation
specs/03-ADMIN-UI.md:2389:| Settings saved | "Settings saved" | success |
specs/03-ADMIN-UI.md:2390:| Theme published | "Theme published" | success |
specs/03-ADMIN-UI.md:2392:| Navigation saved | "Navigation saved" | success |
specs/03-ADMIN-UI.md:2402:| `App\Livewire\Admin\Layout\Sidebar` | `livewire.admin.layout.sidebar` | Layout (all pages) |
specs/03-ADMIN-UI.md:2403:| `App\Livewire\Admin\Layout\TopBar` | `livewire.admin.layout.top-bar` | Layout (all pages) |
specs/03-ADMIN-UI.md:2416:| `App\Livewire\Admin\Settings\General` | `livewire.admin.settings.general` | `GET /admin/settings` |
specs/03-ADMIN-UI.md:2417:| `App\Livewire\Admin\Settings\Domains` | `livewire.admin.settings.domains` | Tab within `GET /admin/settings` |
specs/03-ADMIN-UI.md:2418:| `App\Livewire\Admin\Settings\Shipping` | `livewire.admin.settings.shipping` | `GET /admin/settings/shipping` |
specs/03-ADMIN-UI.md:2419:| `App\Livewire\Admin\Settings\Taxes` | `livewire.admin.settings.taxes` | `GET /admin/settings/taxes` |
specs/03-ADMIN-UI.md:2420:| `App\Livewire\Admin\Themes\Index` | `livewire.admin.themes.index` | `GET /admin/themes` |
specs/03-ADMIN-UI.md:2421:| `App\Livewire\Admin\Themes\Editor` | `livewire.admin.themes.editor` | `GET /admin/themes/{theme}/editor` |
specs/03-ADMIN-UI.md:2422:| `App\Livewire\Admin\Pages\Index` | `livewire.admin.pages.index` | `GET /admin/pages` |
specs/03-ADMIN-UI.md:2423:| `App\Livewire\Admin\Pages\Form` | `livewire.admin.pages.form` | `GET /admin/pages/create`, `GET /admin/pages/{page}/edit` |
specs/03-ADMIN-UI.md:2424:| `App\Livewire\Admin\Navigation\Index` | `livewire.admin.navigation.index` | `GET /admin/navigation` |
specs/03-ADMIN-UI.md:2428:| `App\Livewire\Admin\Search\Settings` | `livewire.admin.search.settings` | `GET /admin/search/settings` |
specs/01-DATABASE-SCHEMA.md:139:### store_settings
specs/01-DATABASE-SCHEMA.md:141:Single-row-per-store JSON settings bag.
specs/01-DATABASE-SCHEMA.md:146:| settings_json | TEXT | No | '{}' | - | JSON settings object |
specs/01-DATABASE-SCHEMA.md:367:## Epic 3 - Themes, Storefront, and Localization
specs/01-DATABASE-SCHEMA.md:369:### themes
specs/01-DATABASE-SCHEMA.md:371:Storefront theme definitions per store.
specs/01-DATABASE-SCHEMA.md:377:| name | TEXT | No | - | - | Theme display name |
specs/01-DATABASE-SCHEMA.md:386:- `idx_themes_store_id` on (`store_id`) - FK lookup, listing themes per store
specs/01-DATABASE-SCHEMA.md:387:- `idx_themes_store_status` on (`store_id`, `status`) - Finding published/draft themes per store
specs/01-DATABASE-SCHEMA.md:391:### theme_files
specs/01-DATABASE-SCHEMA.md:393:Individual files belonging to a theme (templates, assets, snippets).
specs/01-DATABASE-SCHEMA.md:398:| theme_id | INTEGER | No | - | FK -> themes(id) ON DELETE CASCADE | Parent theme |
specs/01-DATABASE-SCHEMA.md:399:| path | TEXT | No | - | UNIQUE per (theme_id, path) | File path within theme |
specs/01-DATABASE-SCHEMA.md:406:- `idx_theme_files_theme_path` UNIQUE on (`theme_id`, `path`) - Enforces unique file paths per theme
specs/01-DATABASE-SCHEMA.md:407:- `idx_theme_files_theme_id` on (`theme_id`) - FK lookup, listing files per theme
specs/01-DATABASE-SCHEMA.md:411:### theme_settings
specs/01-DATABASE-SCHEMA.md:413:Single-row JSON configuration per theme.
specs/01-DATABASE-SCHEMA.md:417:| theme_id | INTEGER | No | - | PRIMARY KEY, FK -> themes(id) ON DELETE CASCADE | One-to-one with themes |
specs/01-DATABASE-SCHEMA.md:418:| settings_json | TEXT | No | '{}' | - | JSON settings object |
specs/01-DATABASE-SCHEMA.md:423:### pages
specs/01-DATABASE-SCHEMA.md:425:Static CMS pages (About Us, Contact, etc.).
specs/01-DATABASE-SCHEMA.md:433:| body_html | TEXT | Yes | NULL | - | Rich-text content |
specs/01-DATABASE-SCHEMA.md:441:- `idx_pages_store_handle` UNIQUE on (`store_id`, `handle`) - Unique handle per store for URL routing
specs/01-DATABASE-SCHEMA.md:442:- `idx_pages_store_id` on (`store_id`) - FK lookup, listing pages per store
specs/01-DATABASE-SCHEMA.md:443:- `idx_pages_store_status` on (`store_id`, `status`) - Filtering pages by status
specs/01-DATABASE-SCHEMA.md:447:### navigation_menus
specs/01-DATABASE-SCHEMA.md:462:- `idx_navigation_menus_store_handle` UNIQUE on (`store_id`, `handle`) - Unique handle per store
specs/01-DATABASE-SCHEMA.md:463:- `idx_navigation_menus_store_id` on (`store_id`) - FK lookup, listing menus per store
specs/01-DATABASE-SCHEMA.md:467:### navigation_items
specs/01-DATABASE-SCHEMA.md:469:Individual links within a navigation menu (supports nesting via position).
specs/01-DATABASE-SCHEMA.md:474:| menu_id | INTEGER | No | - | FK -> navigation_menus(id) ON DELETE CASCADE | Parent menu |
specs/01-DATABASE-SCHEMA.md:478:| resource_id | INTEGER | Yes | NULL | - | FK to pages/collections/products (polymorphic) |
specs/01-DATABASE-SCHEMA.md:483:- `idx_navigation_items_menu_id` on (`menu_id`) - FK lookup, listing items per menu
specs/01-DATABASE-SCHEMA.md:484:- `idx_navigation_items_menu_position` on (`menu_id`, `position`) - Ordered item listing
specs/01-DATABASE-SCHEMA.md:492:### search_settings
specs/01-DATABASE-SCHEMA.md:658:### tax_settings
specs/01-DATABASE-SCHEMA.md:1212:    stores ||--|| store_settings : "has"
specs/01-DATABASE-SCHEMA.md:1245:    store_settings {
specs/01-DATABASE-SCHEMA.md:1247:        TEXT settings_json
specs/01-DATABASE-SCHEMA.md:1318:### Epic 3 - Themes, Storefront, and Localization
specs/01-DATABASE-SCHEMA.md:1322:    stores ||--o{ themes : "has"
specs/01-DATABASE-SCHEMA.md:1323:    themes ||--o{ theme_files : "contains"
specs/01-DATABASE-SCHEMA.md:1324:    themes ||--|| theme_settings : "configured by"
specs/01-DATABASE-SCHEMA.md:1325:    stores ||--o{ pages : "has"
specs/01-DATABASE-SCHEMA.md:1326:    stores ||--o{ navigation_menus : "has"
specs/01-DATABASE-SCHEMA.md:1327:    navigation_menus ||--o{ navigation_items : "contains"
specs/01-DATABASE-SCHEMA.md:1329:    themes {
specs/01-DATABASE-SCHEMA.md:1335:    theme_files {
specs/01-DATABASE-SCHEMA.md:1337:        INTEGER theme_id FK
specs/01-DATABASE-SCHEMA.md:1341:    theme_settings {
specs/01-DATABASE-SCHEMA.md:1342:        INTEGER theme_id PK
specs/01-DATABASE-SCHEMA.md:1343:        TEXT settings_json
specs/01-DATABASE-SCHEMA.md:1345:    pages {
specs/01-DATABASE-SCHEMA.md:1352:    navigation_menus {
specs/01-DATABASE-SCHEMA.md:1358:    navigation_items {
specs/01-DATABASE-SCHEMA.md:1484:The application requires specific SQLite PRAGMA settings configured in the Laravel database configuration file (`config/database.php`). These settings must be applied for correct and performant operation.
specs/01-DATABASE-SCHEMA.md:1486:### Required PRAGMA Settings
specs/01-DATABASE-SCHEMA.md:1500:- The `busy_timeout` must be set to `5000` (milliseconds) to handle write contention gracefully.
specs/01-DATABASE-SCHEMA.md:1526:        store_settings
specs/01-DATABASE-SCHEMA.md:1528:        themes
specs/01-DATABASE-SCHEMA.md:1529:        pages
specs/01-DATABASE-SCHEMA.md:1530:        navigation_menus
specs/01-DATABASE-SCHEMA.md:1531:        search_settings
specs/01-DATABASE-SCHEMA.md:1533:        tax_settings
specs/01-DATABASE-SCHEMA.md:1548:        navigation_items
specs/01-DATABASE-SCHEMA.md:1549:        theme_files
specs/01-DATABASE-SCHEMA.md:1550:        theme_settings
specs/01-DATABASE-SCHEMA.md:1586:    stores --> store_settings
specs/01-DATABASE-SCHEMA.md:1588:    stores --> themes
specs/01-DATABASE-SCHEMA.md:1589:    stores --> pages
specs/01-DATABASE-SCHEMA.md:1590:    stores --> navigation_menus
specs/01-DATABASE-SCHEMA.md:1591:    stores --> search_settings
specs/01-DATABASE-SCHEMA.md:1593:    stores --> tax_settings
specs/01-DATABASE-SCHEMA.md:1606:    navigation_menus --> navigation_items
specs/01-DATABASE-SCHEMA.md:1607:    themes --> theme_files
specs/01-DATABASE-SCHEMA.md:1608:    themes --> theme_settings
specs/01-DATABASE-SCHEMA.md:1645:- **Batch 3** (depends on Batch 2): `store_domains`, `store_users`, `store_settings`, `customers`, `themes`, `pages`, `navigation_menus`, `search_settings`, `shipping_zones`, `tax_settings`, `discounts`, `products`, `collections`, `app_installations`, `oauth_clients`
specs/01-DATABASE-SCHEMA.md:1646:- **Batch 4** (depends on Batch 3): `product_options`, `product_variants`, `product_media`, `collection_products`, `customer_addresses`, `carts`, `navigation_items`, `theme_files`, `theme_settings`, `search_queries`, `shipping_rates`, `oauth_tokens`, `webhook_subscriptions`
specs/01-DATABASE-SCHEMA.md:1673:| 1 - Foundation and Multi-Store Tenancy | organizations, stores, store_domains, users, store_users, store_settings | 6 |
specs/01-DATABASE-SCHEMA.md:1675:| 3 - Themes, Storefront, Localization | themes, theme_files, theme_settings, pages, navigation_menus, navigation_items | 6 |
specs/01-DATABASE-SCHEMA.md:1676:| 4 - Search | search_settings, search_queries | 2 |
specs/01-DATABASE-SCHEMA.md:1677:| 5 - Cart, Checkout, Discounts, Shipping, Taxes | carts, cart_lines, checkouts, shipping_zones, shipping_rates, tax_settings, discounts | 7 |
specs/09-IMPLEMENTATION-ROADMAP.md:43:    P3[Phase 3: Themes and Storefront Layout]
specs/09-IMPLEMENTATION-ROADMAP.md:46:    P6[Phase 6: Customer Accounts]
specs/09-IMPLEMENTATION-ROADMAP.md:109:6. `create_store_settings_table` - PK: `store_id`
specs/09-IMPLEMENTATION-ROADMAP.md:123:| Model (with migration, factory, seeder) | `StoreSettings` | Per-store configuration |
specs/09-IMPLEMENTATION-ROADMAP.md:130:| `Store` | `belongsTo(Organization::class)`, `hasMany(StoreDomain::class)`, `belongsToMany(User::class)` through `store_users`, `hasOne(StoreSettings::class)` |
specs/09-IMPLEMENTATION-ROADMAP.md:134:| `StoreSettings` | `belongsTo(Store::class)` |
specs/09-IMPLEMENTATION-ROADMAP.md:176:Applied on: products, collections, customers, orders, carts, checkouts, discounts, shipping_zones, themes, pages, navigation_menus, analytics_events, analytics_daily, webhook_subscriptions, inventory_items, search_queries.
specs/09-IMPLEMENTATION-ROADMAP.md:217:| Policy | `ThemePolicy` | Theme authorization based on store role |
specs/09-IMPLEMENTATION-ROADMAP.md:227:| Manage store settings | Y | Y | N | N |
specs/09-IMPLEMENTATION-ROADMAP.md:236:| Manage themes | Y | Y | N | N |
specs/09-IMPLEMENTATION-ROADMAP.md:349:### Phase 3: Themes, Pages, Navigation, Storefront Layout
specs/09-IMPLEMENTATION-ROADMAP.md:355:1. `create_themes_table` - FK: `store_id`
specs/09-IMPLEMENTATION-ROADMAP.md:356:2. `create_theme_files_table` - FK: `theme_id`
specs/09-IMPLEMENTATION-ROADMAP.md:357:3. `create_theme_settings_table` - PK: `theme_id`
specs/09-IMPLEMENTATION-ROADMAP.md:358:4. `create_pages_table` - FK: `store_id`
specs/09-IMPLEMENTATION-ROADMAP.md:359:5. `create_navigation_menus_table` - FK: `store_id`
specs/09-IMPLEMENTATION-ROADMAP.md:360:6. `create_navigation_items_table` - FK: `menu_id`
specs/09-IMPLEMENTATION-ROADMAP.md:368:| Model (with migration, factory, seeder) | `Theme` | Store theme entity |
specs/09-IMPLEMENTATION-ROADMAP.md:369:| Model (with migration, factory, seeder) | `ThemeFile` | Individual theme file |
specs/09-IMPLEMENTATION-ROADMAP.md:370:| Model (with migration, factory, seeder) | `ThemeSettings` | Theme configuration |
specs/09-IMPLEMENTATION-ROADMAP.md:372:| Model (with migration, factory, seeder) | `NavigationMenu` | Navigation menu entity |
specs/09-IMPLEMENTATION-ROADMAP.md:373:| Model (with migration, factory, seeder) | `NavigationItem` | Individual navigation item |
specs/09-IMPLEMENTATION-ROADMAP.md:379:| `Theme` | `belongsTo(Store)`, `hasMany(ThemeFile)`, `hasOne(ThemeSettings)` |
specs/09-IMPLEMENTATION-ROADMAP.md:380:| `ThemeFile` | `belongsTo(Theme)` |
specs/09-IMPLEMENTATION-ROADMAP.md:381:| `ThemeSettings` | `belongsTo(Theme)` |
specs/09-IMPLEMENTATION-ROADMAP.md:383:| `NavigationMenu` | `belongsTo(Store)`, `hasMany(NavigationItem)` |
specs/09-IMPLEMENTATION-ROADMAP.md:384:| `NavigationItem` | `belongsTo(NavigationMenu)` |
specs/09-IMPLEMENTATION-ROADMAP.md:390:| `ThemeStatus` | `Draft`, `Published` |
specs/09-IMPLEMENTATION-ROADMAP.md:392:| `NavigationItemType` | `Link`, `Page`, `Collection`, `Product` |
specs/09-IMPLEMENTATION-ROADMAP.md:401:| `pages/` | `home.blade.php`, `collection.blade.php`, `product.blade.php`, `cart.blade.php`, `search.blade.php`, `page.blade.php` |
specs/09-IMPLEMENTATION-ROADMAP.md:409:Base layout (`app.blade.php`): header with nav, announcement bar, main content, footer, cart drawer. All with dark mode support via `dark:` prefix.
specs/09-IMPLEMENTATION-ROADMAP.md:411:**ThemeSettings Service:** Singleton registered in `AppServiceProvider`, loads and caches active theme settings for the current store.
specs/09-IMPLEMENTATION-ROADMAP.md:419:| `Storefront\Home` | Dynamic sections based on theme settings |
specs/09-IMPLEMENTATION-ROADMAP.md:429:#### Step 3.5: Navigation Service
specs/09-IMPLEMENTATION-ROADMAP.md:431:**File to create:** `App\Services\NavigationService`
specs/09-IMPLEMENTATION-ROADMAP.md:435:| `buildTree(NavigationMenu $menu): array` | Builds navigation trees from navigation_menus / navigation_items |
specs/09-IMPLEMENTATION-ROADMAP.md:436:| `resolveUrl(NavigationItem $item): string` | Resolves URLs for page, collection, product type items |
specs/09-IMPLEMENTATION-ROADMAP.md:453:6. `create_tax_settings_table` - PK: `store_id`
specs/09-IMPLEMENTATION-ROADMAP.md:467:| Model (with migration, factory, seeder) | `TaxSettings` | Per-store tax configuration |
specs/09-IMPLEMENTATION-ROADMAP.md:479:| `TaxSettings` | `belongsTo(Store)` |
specs/09-IMPLEMENTATION-ROADMAP.md:537:| `calculate(int $amount, TaxSettings $settings, array $address): TaxResult` | Calculates tax per manual rate or provider |
specs/09-IMPLEMENTATION-ROADMAP.md:746:### Phase 6: Customer Accounts
specs/09-IMPLEMENTATION-ROADMAP.md:785:| `Admin\Layout\Sidebar` | Fixed left sidebar (256px desktop, overlay mobile), navigation groups, Flux `brand`, `icon`, `separator` |
specs/09-IMPLEMENTATION-ROADMAP.md:840:| `Admin\Settings\Index` | Tabbed settings: General, Domains, Shipping, Taxes, Checkout, Notifications |
specs/09-IMPLEMENTATION-ROADMAP.md:841:| `Admin\Settings\Shipping` | Shipping zones CRUD, rates CRUD per zone |
specs/09-IMPLEMENTATION-ROADMAP.md:842:| `Admin\Settings\Taxes` | Tax mode toggle, manual rate configuration |
specs/09-IMPLEMENTATION-ROADMAP.md:843:| `Admin\Themes\Index` | Theme cards with Publish/Duplicate/Delete actions |
specs/09-IMPLEMENTATION-ROADMAP.md:844:| `Admin\Themes\Editor` | Left: sections. Center: preview. Right: settings. |
specs/09-IMPLEMENTATION-ROADMAP.md:845:| `Admin\Pages\Index` | Content pages list |
specs/09-IMPLEMENTATION-ROADMAP.md:847:| `Admin\Navigation\Index` | Menu management with drag-and-drop item ordering |
specs/09-IMPLEMENTATION-ROADMAP.md:849:| `Admin\Search\Settings` | Synonyms, stop words, reindex button |
specs/09-IMPLEMENTATION-ROADMAP.md:862:1. `create_search_settings_table` - PK: `store_id`
specs/09-IMPLEMENTATION-ROADMAP.md:864:3. FTS5 virtual table migration (raw SQL) - create `products_fts` virtual table using FTS5 with columns: title, description, vendor, product_type, tags; content synced from `products` table
specs/09-IMPLEMENTATION-ROADMAP.md:957:1. Accessibility audit: skip links on all pages, ARIA labels on interactive elements, focus management in modals
specs/09-IMPLEMENTATION-ROADMAP.md:958:2. Responsive testing: all pages render correctly at sm/md/lg/xl breakpoints
specs/09-IMPLEMENTATION-ROADMAP.md:960:4. Error pages: styled 404 and 503 pages matching the storefront theme
specs/09-IMPLEMENTATION-ROADMAP.md:998:| `tests/Feature/Admin/` | `DashboardTest.php`, `ProductManagementTest.php`, `OrderManagementTest.php`, `DiscountManagementTest.php`, `SettingsTest.php` |
specs/09-IMPLEMENTATION-ROADMAP.md:1348:| handles prices-include-tax correctly | tax settings: prices_include_tax=true, rate=1900; item price 11900 (gross) | tax extracted = 1900, subtotal = 10000 | edge case |
specs/09-IMPLEMENTATION-ROADMAP.md:1383:| applies zero tax when no tax settings exist | no tax_settings row for store | tax = 0 | edge case |
specs/09-IMPLEMENTATION-ROADMAP.md:1553:#### tests/Feature/Admin/SettingsTest.php
specs/09-IMPLEMENTATION-ROADMAP.md:1557:| renders the settings page | GET /admin/settings | 200 response, sees settings tabs | happy path |
specs/09-IMPLEMENTATION-ROADMAP.md:1558:| updates general store settings | update store name | store_settings updated | happy path |
specs/09-IMPLEMENTATION-ROADMAP.md:1560:| configures tax settings | set mode=manual, rate=1900, prices_include_tax=true | tax_settings updated | happy path |
specs/09-IMPLEMENTATION-ROADMAP.md:1561:| restricts settings to owner and admin roles | staff user GET /admin/settings | 403 response | authorization |
specs/09-IMPLEMENTATION-ROADMAP.md:1701:| `StoreSettings` | Per-store configuration |
specs/09-IMPLEMENTATION-ROADMAP.md:1709:| `Theme` | Store theme entity |
specs/09-IMPLEMENTATION-ROADMAP.md:1710:| `ThemeFile` | Individual theme file |
specs/09-IMPLEMENTATION-ROADMAP.md:1711:| `ThemeSettings` | Theme configuration |
specs/09-IMPLEMENTATION-ROADMAP.md:1713:| `NavigationMenu` | Navigation menu entity |
specs/09-IMPLEMENTATION-ROADMAP.md:1714:| `NavigationItem` | Individual navigation item |
specs/09-IMPLEMENTATION-ROADMAP.md:1720:| `TaxSettings` | Per-store tax configuration |
specs/09-IMPLEMENTATION-ROADMAP.md:1738:| `SearchSettings` | Per-store search configuration |
specs/09-IMPLEMENTATION-ROADMAP.md:1747:| `Admin/Layout/Sidebar` | Admin sidebar navigation |
specs/09-IMPLEMENTATION-ROADMAP.md:1759:| `Admin/Settings/Index` | Settings tabs |
specs/09-IMPLEMENTATION-ROADMAP.md:1760:| `Admin/Settings/Shipping` | Shipping zone/rate management |
specs/09-IMPLEMENTATION-ROADMAP.md:1761:| `Admin/Settings/Taxes` | Tax settings |
specs/09-IMPLEMENTATION-ROADMAP.md:1763:| `Admin/Themes/Index` | Theme list |
specs/09-IMPLEMENTATION-ROADMAP.md:1764:| `Admin/Themes/Editor` | Theme editor |
specs/09-IMPLEMENTATION-ROADMAP.md:1767:| `Admin/Navigation/Index` | Navigation menu management |
specs/09-IMPLEMENTATION-ROADMAP.md:1769:| `Admin/Search/Settings` | Search settings |
specs/09-IMPLEMENTATION-ROADMAP.md:1815:| `ThemePolicy` | Theme |
specs/09-IMPLEMENTATION-ROADMAP.md:1838:| `UpdateTaxSettingsRequest` | Validate tax settings update |
specs/09-IMPLEMENTATION-ROADMAP.md:1914:| `Admin/SettingsTest` | Admin settings feature tests |
specs/09-IMPLEMENTATION-ROADMAP.md:1979:| `NavigationService` | Menu tree building, URL resolution, caching |
specs/09-IMPLEMENTATION-ROADMAP.md:2051:6. `StoreSettingsSeeder`
specs/09-IMPLEMENTATION-ROADMAP.md:2052:7. `TaxSettingsSeeder`
specs/09-IMPLEMENTATION-ROADMAP.md:2059:14. `ThemeSeeder` - creates themes with files and settings
specs/09-IMPLEMENTATION-ROADMAP.md:2061:16. `NavigationSeeder` - creates navigation menus and items
specs/09-IMPLEMENTATION-ROADMAP.md:2063:18. `SearchSettingsSeeder`
specs/05-BUSINESS-LOGIC.md:41:3. If the store is suspended: return HTTP 403 Forbidden. Admin users can still view settings but cannot perform storefront-affecting mutations.
specs/05-BUSINESS-LOGIC.md:80:products, collections, customers, orders, carts, checkouts, discounts, shipping_zones, themes, pages, navigation_menus, analytics_events, analytics_daily, webhook_subscriptions, inventory_items, search_queries.
specs/05-BUSINESS-LOGIC.md:90:| Manage store settings | Yes | Yes | No | No |
specs/05-BUSINESS-LOGIC.md:95:| Manage themes | Yes | Yes | No | No |
specs/05-BUSINESS-LOGIC.md:195:- Same logic applies to collections and pages.
specs/05-BUSINESS-LOGIC.md:341:- Finds carts where status = `active` AND updated_at < (now - 14 days). The 14-day threshold is configurable via `store_settings`.
specs/05-BUSINESS-LOGIC.md:737:- The TaxCalculationRequest contains: line items (with discounted amounts), shipping amount, shipping address, store tax settings.
specs/05-BUSINESS-LOGIC.md:750:2. Use the tax rate defined in `tax_settings.config_json` for the matched zone, or the global default rate.
specs/05-BUSINESS-LOGIC.md:763:Controlled by `tax_settings.prices_include_tax` (boolean).
specs/05-BUSINESS-LOGIC.md:802:- Fallback behavior (configurable per store in `tax_settings.config_json`):
specs/05-BUSINESS-LOGIC.md:868:- Cost = fixed amount regardless of cart contents.
specs/05-BUSINESS-LOGIC.md:1047:- Configurable timeout: `store_settings.settings_json` key `bank_transfer_cancel_days`, default = 7.
specs/05-BUSINESS-LOGIC.md:1082:- Format: configurable prefix (default: `#`) stored in `store_settings.settings_json` key `order_number_prefix`.
specs/05-BUSINESS-LOGIC.md:1702:| TaxCalculationRequest | lineItems (array), shippingAmount (int), address (Address), taxSettings (object) | Input for tax providers |