Skip to content

Commit 967a1df

Browse files
committed
wip
1 parent 88365ca commit 967a1df

5 files changed

Lines changed: 208 additions & 2 deletions

File tree

.github/instructions/laravel-boost.instructions.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ This application is a Laravel application and its main Laravel ecosystems packag
2727
This project has domain-specific skills available. You MUST activate the relevant skill whenever you work in that domain—don't wait until you're stuck.
2828

2929
- `fluxui-development` — 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.
30+
- `livewire-development` — Use for any task or question involving Livewire. Activate if user mentions Livewire, wire: directives, or Livewire-specific concepts like wire:model, wire:click, 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.
3031
- `tailwindcss-development` — Always invoke when the user's message includes 'tailwind' in any form. Also invoke for: building responsive grid layouts (multi-column card grids, product grids), flex/grid page structures (dashboards with sidebars, fixed topbars, mobile-toggle navs), styling UI components (cards, tables, navbars, pricing sections, forms, inputs, badges), adding dark mode variants, fixing spacing or typography, and Tailwind v3/v4 work. The core use case: writing or fixing Tailwind utility classes in HTML templates (Blade, JSX, Vue). Skip for backend PHP logic, database queries, API routes, JavaScript with no HTML/CSS component, CSS file audits, build tool configuration, and vanilla CSS.
3132

3233
## Conventions
@@ -224,6 +225,14 @@ protected function isAccessible(User $user, ?string $path = null): bool
224225

225226
- Casts can and likely should be set in a `casts()` method on a model rather than the `$casts` property. Follow existing conventions from other models.
226227

228+
=== livewire/core rules ===
229+
230+
# Livewire
231+
232+
- Livewire allow to build dynamic, reactive interfaces in PHP without writing JavaScript.
233+
- You can use Alpine.js for client-side interactions instead of JavaScript frameworks.
234+
- Keep state server-side so the UI reflects it. Validate and authorize in actions as you would in HTTP requests.
235+
227236
=== pint/core rules ===
228237

229238
# Laravel Pint Code Formatter
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
---
2+
name: livewire-development
3+
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."
4+
license: MIT
5+
metadata:
6+
author: laravel
7+
---
8+
9+
# Livewire Development
10+
11+
## Documentation
12+
13+
Use `search-docs` for detailed Livewire 4 patterns and documentation.
14+
15+
## Basic Usage
16+
17+
### Creating Components
18+
19+
```bash
20+
21+
# Single-file component (default in v4)
22+
23+
php artisan make:livewire create-post
24+
25+
# Multi-file component
26+
27+
php artisan make:livewire create-post --mfc
28+
29+
# Class-based component (v3 style)
30+
31+
php artisan make:livewire create-post --class
32+
33+
# With namespace
34+
35+
php artisan make:livewire Posts/CreatePost
36+
```
37+
38+
### Converting Between Formats
39+
40+
Use `php artisan livewire:convert create-post` to convert between single-file, multi-file, and class-based formats.
41+
42+
### Choosing a Component Format
43+
44+
Before creating a component, check `config/livewire.php` for directory overrides, which change where files are stored. Then, look at existing files in those directories (defaulting to `app/Livewire/` and `resources/views/livewire/`) to match the established convention.
45+
46+
### Component Format Reference
47+
48+
| Format | Flag | Class Path | View Path |
49+
|--------|------|------------|-----------|
50+
| Single-file (SFC) | default || `resources/views/livewire/create-post.blade.php` (PHP + Blade in one file) |
51+
| Multi-file (MFC) | `--mfc` | `app/Livewire/CreatePost.php` | `resources/views/livewire/create-post.blade.php` |
52+
| Class-based | `--class` | `app/Livewire/CreatePost.php` | `resources/views/livewire/create-post.blade.php` |
53+
| View-based | ⚡ prefix || `resources/views/livewire/create-post.blade.php` (Blade-only with functional state) |
54+
55+
Namespaced components map to subdirectories: `make:livewire Posts/CreatePost` creates files at `app/Livewire/Posts/CreatePost.php` and `resources/views/livewire/posts/create-post.blade.php`.
56+
57+
### Single-File Component Example
58+
59+
<!-- Single-File Component Example -->
60+
```php
61+
<?php
62+
use Livewire\Component;
63+
64+
new class extends Component {
65+
public int $count = 0;
66+
67+
public function increment(): void
68+
{
69+
$this->count++;
70+
}
71+
}
72+
?>
73+
74+
<div>
75+
<button wire:click="increment">Count: @{{ $count }}</button>
76+
</div>
77+
```
78+
79+
## Livewire 4 Specifics
80+
81+
### Key Changes From Livewire 3
82+
83+
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.
84+
85+
- 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`.
86+
- `wire:model` now ignores child events by default (use `wire:model.deep` for old behavior); `wire:scroll` renamed to `wire:navigate:scroll`.
87+
- Component tags must be properly closed; `wire:transition` now uses View Transitions API (modifiers removed).
88+
- JavaScript: `$wire.$js('name', fn)``$wire.$js.name = fn`; `commit`/`request` hooks → `interceptMessage()`/`interceptRequest()`.
89+
90+
### New Features
91+
92+
- Component formats: single-file (SFC), multi-file (MFC), view-based components.
93+
- Islands (`@island`) for isolated updates; async actions (`wire:click.async`, `#[Async]`) for parallel execution.
94+
- Deferred/bundled loading: `defer`, `lazy.bundle` for optimized component loading.
95+
96+
| Feature | Usage | Purpose |
97+
|---------|-------|---------|
98+
| Islands | `@island(name: 'stats')` | Isolated update regions |
99+
| Async | `wire:click.async` or `#[Async]` | Non-blocking actions |
100+
| Deferred | `defer` attribute | Load after page render |
101+
| Bundled | `lazy.bundle` | Load multiple together |
102+
103+
### New Directives
104+
105+
- `wire:sort`, `wire:intersect`, `wire:ref`, `.renderless`, `.preserve-scroll` are available for use.
106+
- `data-loading` attribute automatically added to elements triggering network requests.
107+
108+
| Directive | Purpose |
109+
|-----------|---------|
110+
| `wire:sort` | Drag-and-drop sorting |
111+
| `wire:intersect` | Viewport intersection detection |
112+
| `wire:ref` | Element references for JS |
113+
| `.renderless` | Component without rendering |
114+
| `.preserve-scroll` | Preserve scroll position |
115+
116+
## Best Practices
117+
118+
- Always use `wire:key` in loops
119+
- Use `wire:loading` for loading states
120+
- Use `wire:model.live` for instant updates (default is debounced)
121+
- Validate and authorize in actions (treat like HTTP requests)
122+
123+
## Configuration
124+
125+
- `smart_wire_keys` defaults to `true`; new configs: `component_locations`, `component_namespaces`, `make_command`, `csp_safe`.
126+
127+
## Alpine & JavaScript
128+
129+
- `wire:transition` uses browser View Transitions API; `$errors` and `$intercept` magic properties available.
130+
- Non-blocking `wire:poll` and parallel `wire:model.live` updates improve performance.
131+
132+
For interceptors and hooks, see [reference/javascript-hooks.md](reference/javascript-hooks.md).
133+
134+
## Testing
135+
136+
<!-- Testing Example -->
137+
```php
138+
Livewire::test(Counter::class)
139+
->assertSet('count', 0)
140+
->call('increment')
141+
->assertSet('count', 1);
142+
```
143+
144+
## Verification
145+
146+
1. Browser console: Check for JS errors
147+
2. Network tab: Verify Livewire requests return 200
148+
3. Ensure `wire:key` on all `@foreach` loops
149+
150+
## Common Pitfalls
151+
152+
- Missing `wire:key` in loops → unexpected re-rendering
153+
- Expecting `wire:model` real-time → use `wire:model.live`
154+
- Unclosed component tags → syntax errors in v4
155+
- Using deprecated config keys or JS hooks
156+
- Including Alpine.js separately (already bundled in Livewire 4)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Livewire 4 JavaScript Integration
2+
3+
## Interceptor System (v4)
4+
5+
### Intercept Messages
6+
7+
```js
8+
Livewire.interceptMessage(({ component, message, onFinish, onSuccess, onError }) => {
9+
onFinish(() => { /* After response, before processing */ });
10+
onSuccess(({ payload }) => { /* payload.snapshot, payload.effects */ });
11+
onError(() => { /* Server errors */ });
12+
});
13+
```
14+
15+
### Intercept Requests
16+
17+
```js
18+
Livewire.interceptRequest(({ request, onResponse, onSuccess, onError, onFailure }) => {
19+
onResponse(({ response }) => { /* When received */ });
20+
onSuccess(({ response, responseJson }) => { /* Success */ });
21+
onError(({ response, responseBody, preventDefault }) => { /* 4xx/5xx */ });
22+
onFailure(({ error }) => { /* Network failures */ });
23+
});
24+
```
25+
26+
### Component-Scoped Interceptors
27+
28+
```blade
29+
<script>
30+
this.$intercept('save', ({ component, onSuccess }) => {
31+
onSuccess(() => console.log('Saved!'));
32+
});
33+
</script>
34+
```
35+
36+
## Magic Properties
37+
38+
- `$errors` - Access validation errors from JavaScript
39+
- `$intercept` - Component-scoped interceptors

composer.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"laravel/framework": "^12.0",
1515
"laravel/tinker": "^2.10.1",
1616
"livewire/flux": "^2.1.1",
17+
"livewire/livewire": "^4.0",
1718
"pulkitjalan/google-apiclient": "^6.2",
1819
"revolution/laravel-google-sheets": "^7.0"
1920
},
@@ -73,6 +74,7 @@
7374
"npm run build"
7475
],
7576
"lint": "vendor/bin/pint",
76-
"test": "vendor/bin/phpunit"
77+
"test": "vendor/bin/phpunit",
78+
"boost": "@php artisan boost:install --no-interaction --ansi"
7779
}
7880
}

composer.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)