🎉 First commit
This commit is contained in:
72
.cursor/skills/fluxui-development/SKILL.md
Normal file
72
.cursor/skills/fluxui-development/SKILL.md
Normal file
@@ -0,0 +1,72 @@
|
||||
---
|
||||
name: fluxui-development
|
||||
description: >-
|
||||
Develops UIs with Flux UI Free components. Activates when creating buttons, forms, modals,
|
||||
inputs, dropdowns, checkboxes, or UI components; replacing HTML form elements with Flux;
|
||||
working with flux: components; or when the user mentions Flux, component library, UI components,
|
||||
form fields, or asks about available Flux components.
|
||||
---
|
||||
|
||||
# Flux UI Development
|
||||
|
||||
## When to Apply
|
||||
|
||||
Activate this skill when:
|
||||
|
||||
- Creating UI components or pages
|
||||
- Working with forms, modals, or interactive elements
|
||||
- Checking available Flux components
|
||||
|
||||
## 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.
|
||||
|
||||
<code-snippet name="Basic Button" lang="blade">
|
||||
<flux:button variant="primary">Click me</flux:button>
|
||||
</code-snippet>
|
||||
|
||||
## 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
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Form Fields
|
||||
|
||||
<code-snippet name="Form Field" lang="blade">
|
||||
<flux:field>
|
||||
<flux:label>Email</flux:label>
|
||||
<flux:input type="email" wire:model="email" />
|
||||
<flux:error name="email" />
|
||||
</flux:field>
|
||||
</code-snippet>
|
||||
|
||||
### Modals
|
||||
|
||||
<code-snippet name="Modal" lang="blade">
|
||||
<flux:modal wire:model="showModal">
|
||||
<flux:heading>Title</flux:heading>
|
||||
<p>Content</p>
|
||||
</flux:modal>
|
||||
</code-snippet>
|
||||
|
||||
## 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
|
||||
163
.cursor/skills/livewire-development/SKILL.md
Normal file
163
.cursor/skills/livewire-development/SKILL.md
Normal file
@@ -0,0 +1,163 @@
|
||||
---
|
||||
name: livewire-development
|
||||
description: >-
|
||||
Develops reactive Livewire 4 components. Activates when creating, updating, or modifying
|
||||
Livewire components; working with wire:model, wire:click, wire:loading, or any wire: directives;
|
||||
adding real-time updates, loading states, or reactivity; debugging component behavior;
|
||||
writing Livewire tests; or when the user mentions Livewire, component, counter, or reactive UI.
|
||||
---
|
||||
|
||||
# Livewire Development
|
||||
|
||||
## When to Apply
|
||||
|
||||
Activate this skill when:
|
||||
|
||||
- Creating or modifying Livewire components
|
||||
- Using wire: directives (model, click, loading, sort, intersect)
|
||||
- Implementing islands or async actions
|
||||
- Writing Livewire component tests
|
||||
|
||||
## Documentation
|
||||
|
||||
Use `search-docs` for detailed Livewire 4 patterns and documentation.
|
||||
|
||||
## Basic Usage
|
||||
|
||||
### Creating Components
|
||||
|
||||
<code-snippet name="Component Creation Commands" lang="bash">
|
||||
|
||||
# Single-file component (default in v4)
|
||||
|
||||
{{ $assist->artisanCommand('make:livewire create-post') }}
|
||||
|
||||
# Multi-file component
|
||||
|
||||
{{ $assist->artisanCommand('make:livewire create-post --mfc') }}
|
||||
|
||||
# Class-based component (v3 style)
|
||||
|
||||
{{ $assist->artisanCommand('make:livewire create-post --class') }}
|
||||
|
||||
# With namespace
|
||||
|
||||
{{ $assist->artisanCommand('make:livewire Posts/CreatePost') }}
|
||||
|
||||
</code-snippet>
|
||||
|
||||
### Converting Between Formats
|
||||
|
||||
Use `php artisan livewire:convert create-post` to convert between single-file, multi-file, and class-based formats.
|
||||
|
||||
### Component Format Reference
|
||||
|
||||
| Format | Flag | Structure |
|
||||
|--------|------|-----------|
|
||||
| Single-file (SFC) | default | PHP + Blade in one file |
|
||||
| Multi-file (MFC) | `--mfc` | Separate PHP class, Blade, JS, tests |
|
||||
| Class-based | `--class` | Traditional v3 style class |
|
||||
| View-based | ⚡ prefix | Blade-only with functional state |
|
||||
|
||||
### Single-File Component Example
|
||||
|
||||
<code-snippet name="Single-File Component Example" lang="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>
|
||||
|
||||
</code-snippet>
|
||||
|
||||
## 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; 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
|
||||
|
||||
<code-snippet name="Testing Example" lang="php">
|
||||
|
||||
Livewire::test(Counter::class)
|
||||
->assertSet('count', 0)
|
||||
->call('increment')
|
||||
->assertSet('count', 1);
|
||||
|
||||
</code-snippet>
|
||||
|
||||
## 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)
|
||||
@@ -0,0 +1,39 @@
|
||||
# Livewire 4 JavaScript Integration
|
||||
|
||||
## Interceptor System (v4)
|
||||
|
||||
### Intercept Messages
|
||||
|
||||
```js
|
||||
Livewire.interceptMessage(({ component, message, onFinish, onSuccess, onError }) => {
|
||||
onFinish(() => { /* After response, before processing */ });
|
||||
onSuccess(({ payload }) => { /* payload.snapshot, payload.effects */ });
|
||||
onError(() => { /* Server errors */ });
|
||||
});
|
||||
```
|
||||
|
||||
### Intercept Requests
|
||||
|
||||
```js
|
||||
Livewire.interceptRequest(({ request, onResponse, onSuccess, onError, onFailure }) => {
|
||||
onResponse(({ response }) => { /* When received */ });
|
||||
onSuccess(({ response, responseJson }) => { /* Success */ });
|
||||
onError(({ response, responseBody, preventDefault }) => { /* 4xx/5xx */ });
|
||||
onFailure(({ error }) => { /* Network failures */ });
|
||||
});
|
||||
```
|
||||
|
||||
### Component-Scoped Interceptors
|
||||
|
||||
```blade
|
||||
<script>
|
||||
this.$intercept('save', ({ component, onSuccess }) => {
|
||||
onSuccess(() => console.log('Saved!'));
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
## Magic Properties
|
||||
|
||||
- `$errors` - Access validation errors from JavaScript
|
||||
- `$intercept` - Component-scoped interceptors
|
||||
174
.cursor/skills/pest-testing/SKILL.md
Normal file
174
.cursor/skills/pest-testing/SKILL.md
Normal file
@@ -0,0 +1,174 @@
|
||||
---
|
||||
name: pest-testing
|
||||
description: >-
|
||||
Tests applications using the Pest 4 PHP framework. Activates when writing tests, creating unit or feature
|
||||
tests, adding assertions, testing Livewire components, browser testing, debugging test failures,
|
||||
working with datasets or mocking; or when the user mentions test, spec, TDD, expects, assertion,
|
||||
coverage, or needs to verify functionality works.
|
||||
---
|
||||
|
||||
# Pest Testing 4
|
||||
|
||||
## When to Apply
|
||||
|
||||
Activate this skill when:
|
||||
|
||||
- Creating new tests (unit, feature, or browser)
|
||||
- Modifying existing tests
|
||||
- Debugging test failures
|
||||
- Working with browser testing or smoke testing
|
||||
- Writing architecture tests or visual regression tests
|
||||
|
||||
## 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
|
||||
|
||||
<code-snippet name="Basic Pest Test Example" lang="php">
|
||||
|
||||
it('is true', function () {
|
||||
expect(true)->toBeTrue();
|
||||
});
|
||||
|
||||
</code-snippet>
|
||||
|
||||
### 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()`:
|
||||
|
||||
<code-snippet name="Pest Response Assertion" lang="php">
|
||||
|
||||
it('returns all', function () {
|
||||
$this->postJson('/api/docs', [])->assertSuccessful();
|
||||
});
|
||||
|
||||
</code-snippet>
|
||||
|
||||
| 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.):
|
||||
|
||||
<code-snippet name="Pest Dataset Example" lang="php">
|
||||
|
||||
it('has emails', function (string $email) {
|
||||
expect($email)->not->toBeEmpty();
|
||||
})->with([
|
||||
'james' => 'james@laravel.com',
|
||||
'taylor' => 'taylor@laravel.com',
|
||||
]);
|
||||
|
||||
</code-snippet>
|
||||
|
||||
## 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.
|
||||
|
||||
<code-snippet name="Pest Browser Test Example" lang="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);
|
||||
});
|
||||
|
||||
</code-snippet>
|
||||
|
||||
### Smoke Testing
|
||||
|
||||
Quickly validate multiple pages have no JavaScript errors:
|
||||
|
||||
<code-snippet name="Pest Smoke Testing Example" lang="php">
|
||||
|
||||
$pages = visit(['/', '/about', '/contact']);
|
||||
|
||||
$pages->assertNoJavascriptErrors()->assertNoConsoleLogs();
|
||||
|
||||
</code-snippet>
|
||||
|
||||
### 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):
|
||||
|
||||
<code-snippet name="Architecture Test Example" lang="php">
|
||||
|
||||
arch('controllers')
|
||||
->expect('App\Http\Controllers')
|
||||
->toExtendNothing()
|
||||
->toHaveSuffix('Controller');
|
||||
|
||||
</code-snippet>
|
||||
|
||||
## 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
|
||||
Reference in New Issue
Block a user