feat(Laravel Boost & Claude configuration)

This commit is contained in:
2026-02-09 18:22:14 +01:00
parent 3389316aef
commit e88d12e99c
15 changed files with 2043 additions and 1 deletions

View File

@@ -0,0 +1,369 @@
---
name: inertia-react-development
description: >-
Develops Inertia.js v2 React client-side applications. Activates when creating
React pages, forms, or navigation; using <Link>, <Form>, useForm, or router;
working with deferred props, prefetching, or polling; or when user mentions
React with Inertia, React pages, React forms, or React navigation.
---
# Inertia React Development
## When to Apply
Activate this skill when:
- Creating or modifying React page components for Inertia
- Working with forms in React (using `<Form>` or `useForm`)
- Implementing client-side navigation with `<Link>` or `router`
- Using v2 features: deferred props, prefetching, or polling
- Building React-specific features with the Inertia protocol
## Documentation
Use `search-docs` for detailed Inertia v2 React patterns and documentation.
## Basic Usage
### Page Components Location
React page components should be placed in the `resources/js/pages` directory.
### Page Component Structure
<code-snippet name="Basic React Page Component" lang="react">
export default function UsersIndex({ users }) {
return (
<div>
<h1>Users</h1>
<ul>
{users.map(user => <li key={user.id}>{user.name}</li>)}
</ul>
</div>
)
}
</code-snippet>
## Client-Side Navigation
### Basic Link Component
Use `<Link>` for client-side navigation instead of traditional `<a>` tags:
<code-snippet name="Inertia React Navigation" lang="react">
import { Link, router } from '@inertiajs/react'
<Link href="/">Home</Link>
<Link href="/users">Users</Link>
<Link href={`/users/${user.id}`}>View User</Link>
</code-snippet>
### Link with Method
<code-snippet name="Link with POST Method" lang="react">
import { Link } from '@inertiajs/react'
<Link href="/logout" method="post" as="button">
Logout
</Link>
</code-snippet>
### Prefetching
Prefetch pages to improve perceived performance:
<code-snippet name="Prefetch on Hover" lang="react">
import { Link } from '@inertiajs/react'
<Link href="/users" prefetch>
Users
</Link>
</code-snippet>
### Programmatic Navigation
<code-snippet name="Router Visit" lang="react">
import { router } from '@inertiajs/react'
function handleClick() {
router.visit('/users')
}
// Or with options
router.visit('/users', {
method: 'post',
data: { name: 'John' },
onSuccess: () => console.log('Success!'),
})
</code-snippet>
## Form Handling
### Form Component (Recommended)
The recommended way to build forms is with the `<Form>` component:
<code-snippet name="Form Component Example" lang="react">
import { Form } from '@inertiajs/react'
export default function CreateUser() {
return (
<Form action="/users" method="post">
{({ errors, processing, wasSuccessful }) => (
<>
<input type="text" name="name" />
{errors.name && <div>{errors.name}</div>}
<input type="email" name="email" />
{errors.email && <div>{errors.email}</div>}
<button type="submit" disabled={processing}>
{processing ? 'Creating...' : 'Create User'}
</button>
{wasSuccessful && <div>User created!</div>}
</>
)}
</Form>
)
}
</code-snippet>
### Form Component With All Props
<code-snippet name="Form Component Full Example" lang="react">
import { Form } from '@inertiajs/react'
<Form action="/users" method="post">
{({
errors,
hasErrors,
processing,
progress,
wasSuccessful,
recentlySuccessful,
clearErrors,
resetAndClearErrors,
defaults,
isDirty,
reset,
submit
}) => (
<>
<input type="text" name="name" defaultValue={defaults.name} />
{errors.name && <div>{errors.name}</div>}
<button type="submit" disabled={processing}>
{processing ? 'Saving...' : 'Save'}
</button>
{progress && (
<progress value={progress.percentage} max="100">
{progress.percentage}%
</progress>
)}
{wasSuccessful && <div>Saved!</div>}
</>
)}
</Form>
</code-snippet>
### Form Component Reset Props
The `<Form>` component supports automatic resetting:
- `resetOnError` - Reset form data when the request fails
- `resetOnSuccess` - Reset form data when the request succeeds
- `setDefaultsOnSuccess` - Update default values on success
Use the `search-docs` tool with a query of `form component resetting` for detailed guidance.
<code-snippet name="Form with Reset Props" lang="react">
import { Form } from '@inertiajs/react'
<Form
action="/users"
method="post"
resetOnSuccess
setDefaultsOnSuccess
>
{({ errors, processing, wasSuccessful }) => (
<>
<input type="text" name="name" />
{errors.name && <div>{errors.name}</div>}
<button type="submit" disabled={processing}>
Submit
</button>
</>
)}
</Form>
</code-snippet>
Forms can also be built using the `useForm` helper for more programmatic control. Use the `search-docs` tool with a query of `useForm helper` for guidance.
### `useForm` Hook
For more programmatic control or to follow existing conventions, use the `useForm` hook:
<code-snippet name="useForm Hook Example" lang="react">
import { useForm } from '@inertiajs/react'
export default function CreateUser() {
const { data, setData, post, processing, errors, reset } = useForm({
name: '',
email: '',
password: '',
})
function submit(e) {
e.preventDefault()
post('/users', {
onSuccess: () => reset('password'),
})
}
return (
<form onSubmit={submit}>
<input
type="text"
value={data.name}
onChange={e => setData('name', e.target.value)}
/>
{errors.name && <div>{errors.name}</div>}
<input
type="email"
value={data.email}
onChange={e => setData('email', e.target.value)}
/>
{errors.email && <div>{errors.email}</div>}
<input
type="password"
value={data.password}
onChange={e => setData('password', e.target.value)}
/>
{errors.password && <div>{errors.password}</div>}
<button type="submit" disabled={processing}>
Create User
</button>
</form>
)
}
</code-snippet>
## Inertia v2 Features
### Deferred Props
Use deferred props to load data after initial page render:
<code-snippet name="Deferred Props with Empty State" lang="react">
export default function UsersIndex({ users }) {
// users will be undefined initially, then populated
return (
<div>
<h1>Users</h1>
{!users ? (
<div className="animate-pulse">
<div className="h-4 bg-gray-200 rounded w-3/4 mb-2"></div>
<div className="h-4 bg-gray-200 rounded w-1/2"></div>
</div>
) : (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
)}
</div>
)
}
</code-snippet>
### Polling
Automatically refresh data at intervals:
<code-snippet name="Polling Example" lang="react">
import { router } from '@inertiajs/react'
import { useEffect } from 'react'
export default function Dashboard({ stats }) {
useEffect(() => {
const interval = setInterval(() => {
router.reload({ only: ['stats'] })
}, 5000) // Poll every 5 seconds
return () => clearInterval(interval)
}, [])
return (
<div>
<h1>Dashboard</h1>
<div>Active Users: {stats.activeUsers}</div>
</div>
)
}
</code-snippet>
### WhenVisible (Infinite Scroll)
Load more data when user scrolls to a specific element:
<code-snippet name="Infinite Scroll with WhenVisible" lang="react">
import { WhenVisible } from '@inertiajs/react'
export default function UsersList({ users }) {
return (
<div>
{users.data.map(user => (
<div key={user.id}>{user.name}</div>
))}
{users.next_page_url && (
<WhenVisible
data="users"
params={{ page: users.current_page + 1 }}
fallback={<div>Loading more...</div>}
/>
)}
</div>
)
}
</code-snippet>
## Common Pitfalls
- Using traditional `<a>` links instead of Inertia's `<Link>` component (breaks SPA behavior)
- Forgetting to add loading states (skeleton screens) when using deferred props
- Not handling the `undefined` state of deferred props before data loads
- Using `<form>` without preventing default submission (use `<Form>` component or `e.preventDefault()`)
- Forgetting to check if `<Form>` component is available in your Inertia version

View File

@@ -0,0 +1,124 @@
---
name: tailwindcss-development
description: >-
Styles applications using Tailwind CSS v4 utilities. Activates when adding styles, restyling components,
working with gradients, spacing, layout, flex, grid, responsive design, dark mode, colors,
typography, or borders; or when the user mentions CSS, styling, classes, Tailwind, restyle,
hero section, cards, buttons, or any visual/UI changes.
---
# Tailwind CSS Development
## When to Apply
Activate this skill when:
- Adding styles to components or pages
- Working with responsive design
- Implementing dark mode
- Extracting repeated patterns into components
- Debugging spacing or layout issues
## 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:
<code-snippet name="CSS-First Config" lang="css">
@theme {
--color-brand: oklch(0.72 0.11 178);
}
</code-snippet>
### Import Syntax
In Tailwind v4, import Tailwind with a regular CSS `@import` statement instead of the `@tailwind` directives used in v3:
<code-snippet name="v4 Import Syntax" lang="diff">
- @tailwind base;
- @tailwind components;
- @tailwind utilities;
+ @import "tailwindcss";
</code-snippet>
### 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:
<code-snippet name="Gap Utilities" lang="html">
<div class="flex gap-8">
<div>Item 1</div>
<div>Item 2</div>
</div>
</code-snippet>
## 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:
<code-snippet name="Dark Mode" lang="html">
<div class="bg-white dark:bg-gray-900 text-gray-900 dark:text-white">
Content adapts to color scheme
</div>
</code-snippet>
## Common Patterns
### Flexbox Layout
<code-snippet name="Flexbox Layout" lang="html">
<div class="flex items-center justify-between gap-4">
<div>Left content</div>
<div>Right content</div>
</div>
</code-snippet>
### Grid Layout
<code-snippet name="Grid Layout" lang="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>
</code-snippet>
## 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

View File

@@ -0,0 +1,89 @@
---
name: wayfinder-development
description: >-
Activates whenever referencing backend routes in frontend components. Use when
importing from @/actions or @/routes, calling Laravel routes from TypeScript,
or working with Wayfinder route functions.
---
# Wayfinder Development
## When to Apply
Activate whenever referencing backend routes in frontend components:
- Importing from `@/actions/` or `@/routes/`
- Calling Laravel routes from TypeScript/JavaScript
- Creating links or navigation to backend endpoints
## Documentation
Use `search-docs` for detailed Wayfinder patterns and documentation.
## Quick Reference
### Generate Routes
Run after route changes if Vite plugin isn't installed:
php artisan wayfinder:generate --no-interaction
For form helpers, use `--with-form` flag:
php artisan wayfinder:generate --with-form --no-interaction
### Import Patterns
<code-snippet name="Controller Action Imports" lang="typescript">
// Named imports for tree-shaking (preferred)...
import { show, store, update } from '@/actions/App/Http/Controllers/PostController'
// Named route imports...
import { show as postShow } from '@/routes/post'
</code-snippet>
### Common Methods
<code-snippet name="Wayfinder Methods" lang="typescript">
// Get route object...
show(1) // { url: "/posts/1", method: "get" }
// Get URL string...
show.url(1) // "/posts/1"
// Specific HTTP methods...
show.get(1)
store.post()
update.patch(1)
destroy.delete(1)
// Form attributes for HTML forms...
store.form() // { action: "/posts", method: "post" }
// Query parameters...
show(1, { query: { page: 1 } }) // "/posts/1?page=1"
</code-snippet>
## Wayfinder + Inertia
Use Wayfinder with the `<Form>` component:
<code-snippet name="Wayfinder Form (React)" lang="typescript">
<Form {...store.form()}><input name="title" /></Form>
</code-snippet>
## Verification
1. Run `php artisan wayfinder:generate` to regenerate routes if Vite plugin isn't installed
2. Check TypeScript imports resolve correctly
3. Verify route URLs match expected paths
## Common Pitfalls
- Using default imports instead of named imports (breaks tree-shaking)
- Forgetting to regenerate after route changes
- Not using type-safe parameter objects for route model binding