Initial commit
This commit is contained in:
17
.claude-plugin/plugin.json
Normal file
17
.claude-plugin/plugin.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "laravel",
|
||||
"description": "Collection of skills used to work with Laravel",
|
||||
"version": "0.0.0-2025.11.28",
|
||||
"author": {
|
||||
"name": "Tim Green",
|
||||
"email": "rawveg@gmail.com"
|
||||
},
|
||||
"skills": [
|
||||
"./skills/laravel",
|
||||
"./skills/laravel-cashier-paddle",
|
||||
"./skills/laravel-cashier-stripe",
|
||||
"./skills/laravel-dusk",
|
||||
"./skills/laravel-mcp",
|
||||
"./skills/laravel-prompts"
|
||||
]
|
||||
}
|
||||
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# laravel
|
||||
|
||||
Collection of skills used to work with Laravel
|
||||
136
plugin.lock.json
Normal file
136
plugin.lock.json
Normal file
@@ -0,0 +1,136 @@
|
||||
{
|
||||
"$schema": "internal://schemas/plugin.lock.v1.json",
|
||||
"pluginId": "gh:rawveg/skillsforge-marketplace:laravel",
|
||||
"normalized": {
|
||||
"repo": null,
|
||||
"ref": "refs/tags/v20251128.0",
|
||||
"commit": "f2888c62a12cbc2ba40f9f802d851a42552c505d",
|
||||
"treeHash": "af060216d499df43b45da3251f8b8893afa0631f7c4048b9585d92d96c0f7992",
|
||||
"generatedAt": "2025-11-28T10:27:51.870471Z",
|
||||
"toolVersion": "publish_plugins.py@0.2.0"
|
||||
},
|
||||
"origin": {
|
||||
"remote": "git@github.com:zhongweili/42plugin-data.git",
|
||||
"branch": "master",
|
||||
"commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390",
|
||||
"repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data"
|
||||
},
|
||||
"manifest": {
|
||||
"name": "laravel",
|
||||
"description": "Collection of skills used to work with Laravel"
|
||||
},
|
||||
"content": {
|
||||
"files": [
|
||||
{
|
||||
"path": "README.md",
|
||||
"sha256": "e17e4eb0db5d386c54ae93e63a0179c9f3dd8528f34765dcc4d45a93b69ee35a"
|
||||
},
|
||||
{
|
||||
"path": ".claude-plugin/plugin.json",
|
||||
"sha256": "5a14820e6f0d8388b8307a2fb78c805477b0e6f570c189310d87a32a7650d7ab"
|
||||
},
|
||||
{
|
||||
"path": "skills/laravel-mcp/plugin.json",
|
||||
"sha256": "1abf5f65b94d27c6d0490d2235cfd82f4a23741c1652ee19923d4dc9e559e9ab"
|
||||
},
|
||||
{
|
||||
"path": "skills/laravel-mcp/SKILL.md",
|
||||
"sha256": "cf985adcbf3eabe500875038af4938ebf8469f0cc1604e33c21cd63dc9b29d01"
|
||||
},
|
||||
{
|
||||
"path": "skills/laravel-mcp/references/index.md",
|
||||
"sha256": "2bf56abf1a6de97fe4a261921cd2e34279476a42b7eda0f277f63b319906a1e7"
|
||||
},
|
||||
{
|
||||
"path": "skills/laravel-mcp/references/other.md",
|
||||
"sha256": "88373ed19ca26a053cca1706474289807eaa5a3ea0cf0513583c9250defb642e"
|
||||
},
|
||||
{
|
||||
"path": "skills/laravel-dusk/plugin.json",
|
||||
"sha256": "f673362bb76ae734ef0b7d0a876ed8235fe1affb37f3d8ca2da58d49914c3df2"
|
||||
},
|
||||
{
|
||||
"path": "skills/laravel-dusk/SKILL.md",
|
||||
"sha256": "c1fc91e498f5e876e7592a8805e2c913d0b369403bd5183c4bde8650be1b7434"
|
||||
},
|
||||
{
|
||||
"path": "skills/laravel-dusk/references/index.md",
|
||||
"sha256": "bc8a743078b9b190619101bd993814af5d23039ede2d9589962b751f704aac09"
|
||||
},
|
||||
{
|
||||
"path": "skills/laravel-dusk/references/other.md",
|
||||
"sha256": "5192755f88b0121602197c0ce1f944b93eda30736e8d68267ffe7b4790d1c991"
|
||||
},
|
||||
{
|
||||
"path": "skills/laravel-cashier-stripe/plugin.json",
|
||||
"sha256": "41cd17c410530c254659e33d637cc5d5d53ec980f36a58e6ed2e1d1c16093a24"
|
||||
},
|
||||
{
|
||||
"path": "skills/laravel-cashier-stripe/SKILL.md",
|
||||
"sha256": "dfcae142f478a20122bde3807ec8dde982c9926fb09bce32714790a79cf0fca5"
|
||||
},
|
||||
{
|
||||
"path": "skills/laravel-cashier-stripe/references/index.md",
|
||||
"sha256": "48962f7ac946e09c25d1ca2e4d96d16793291ab74a96ccf953799cb9889c7a5d"
|
||||
},
|
||||
{
|
||||
"path": "skills/laravel-cashier-stripe/references/other.md",
|
||||
"sha256": "d8ff418d43cfa4eaa183d76311611f9d2225ff489be1b89b9b8c0b7f162cbeb0"
|
||||
},
|
||||
{
|
||||
"path": "skills/laravel-cashier-paddle/plugin.json",
|
||||
"sha256": "bf409cba37632b900e06916ddba3038f9ce4cf6398d60843e375a1a8845a2a67"
|
||||
},
|
||||
{
|
||||
"path": "skills/laravel-cashier-paddle/SKILL.md",
|
||||
"sha256": "8819b28ad5d1ac69e5d69022431f8559111f72d31c957357f0f3795c7df8ccac"
|
||||
},
|
||||
{
|
||||
"path": "skills/laravel-cashier-paddle/references/index.md",
|
||||
"sha256": "1a82b48a632b338b785565ecdae0f564e3bab28967aa8b0360f9b7bb8e736361"
|
||||
},
|
||||
{
|
||||
"path": "skills/laravel-cashier-paddle/references/other.md",
|
||||
"sha256": "386123532b95bde092e059bdd92a017094c7165b43195ebca53c9ff3ea79115b"
|
||||
},
|
||||
{
|
||||
"path": "skills/laravel-prompts/plugin.json",
|
||||
"sha256": "575541532e8a4954afeaacf3bf43369b8a5bf1e261f4e7aa182c5dd346f463bb"
|
||||
},
|
||||
{
|
||||
"path": "skills/laravel-prompts/SKILL.md",
|
||||
"sha256": "56aa404f1447fc44508dc03a413f760e3dfc11672ce194ff41b476210b7803d1"
|
||||
},
|
||||
{
|
||||
"path": "skills/laravel-prompts/references/index.md",
|
||||
"sha256": "670b1fc24678d5279a373b87714c264ad59091be996cac6861470e2861455ab9"
|
||||
},
|
||||
{
|
||||
"path": "skills/laravel-prompts/references/other.md",
|
||||
"sha256": "7e75d22e901c64978518d85a858f91e6832dd2f53dc22617db040fc5c6506f6b"
|
||||
},
|
||||
{
|
||||
"path": "skills/laravel/plugin.json",
|
||||
"sha256": "7ef95570c9fbb3d2a79d7fe5a35aa3db7b6c0e93aa1d3d2b057b2632e8b239e8"
|
||||
},
|
||||
{
|
||||
"path": "skills/laravel/SKILL.md",
|
||||
"sha256": "cf067eb622fb9c69bf674fd165019eb5a1376bd18a98898261ca01a3f74bf351"
|
||||
},
|
||||
{
|
||||
"path": "skills/laravel/references/index.md",
|
||||
"sha256": "c16908d371694697160e2b6c109def0dc2c444384574731afcd1c305c01ab777"
|
||||
},
|
||||
{
|
||||
"path": "skills/laravel/references/other.md",
|
||||
"sha256": "f441d1c5c334ce5e85f2c697d507f5fec1c3df36a77fa3ae58b0800534ef64c2"
|
||||
}
|
||||
],
|
||||
"dirSha256": "af060216d499df43b45da3251f8b8893afa0631f7c4048b9585d92d96c0f7992"
|
||||
},
|
||||
"security": {
|
||||
"scannedAt": null,
|
||||
"scannerVersion": null,
|
||||
"flags": []
|
||||
}
|
||||
}
|
||||
378
skills/laravel-cashier-paddle/SKILL.md
Normal file
378
skills/laravel-cashier-paddle/SKILL.md
Normal file
@@ -0,0 +1,378 @@
|
||||
---
|
||||
name: laravel-cashier-paddle
|
||||
description: Laravel Cashier (Paddle) - Subscription billing and payment processing
|
||||
---
|
||||
|
||||
# Laravel Cashier (Paddle) Skill
|
||||
|
||||
Comprehensive assistance with Laravel Cashier Paddle - an expressive, fluent interface to Paddle's subscription billing services for Laravel applications.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
This skill should be triggered when:
|
||||
- Implementing subscription billing with Paddle in Laravel applications
|
||||
- Setting up checkout flows for products or subscriptions
|
||||
- Managing subscription lifecycle (create, swap, pause, cancel)
|
||||
- Handling webhook events from Paddle
|
||||
- Working with customer management and payment methods
|
||||
- Implementing trial periods or multi-product subscriptions
|
||||
- Processing transactions, refunds, or credits
|
||||
- Generating invoices or receipts
|
||||
- Previewing prices with currency/tax calculations
|
||||
- Debugging Paddle integration issues in Laravel
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### 1. Basic Setup - Billable Model
|
||||
|
||||
```php
|
||||
use Laravel\Paddle\Billable;
|
||||
|
||||
class User extends Authenticatable
|
||||
{
|
||||
use Billable;
|
||||
|
||||
public function paddleName(): string|null
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function paddleEmail(): string|null
|
||||
{
|
||||
return $this->email;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Simple Product Checkout
|
||||
|
||||
```php
|
||||
// Create checkout session
|
||||
$checkout = $user->checkout('pri_deluxe_album')
|
||||
->returnTo(route('dashboard'));
|
||||
|
||||
// Display checkout button
|
||||
<x-paddle-button :checkout="$checkout" class="px-8 py-4">
|
||||
Subscribe
|
||||
</x-paddle-button>
|
||||
```
|
||||
|
||||
### 3. Subscription Creation
|
||||
|
||||
```php
|
||||
// Single subscription
|
||||
$checkout = $user->subscribe('price_basic_monthly', 'default')
|
||||
->returnTo(route('home'));
|
||||
|
||||
// Multi-product subscription
|
||||
$checkout = $user->subscribe([
|
||||
'price_monthly',
|
||||
'price_chat' => 5 // with quantity
|
||||
]);
|
||||
```
|
||||
|
||||
### 4. Price Preview with Tax
|
||||
|
||||
```php
|
||||
use Laravel\Paddle\Cashier;
|
||||
|
||||
// Preview prices for country
|
||||
$prices = Cashier::previewPrices(['pri_123', 'pri_456'], [
|
||||
'address' => ['country_code' => 'BE', 'postal_code' => '1234']
|
||||
]);
|
||||
|
||||
// Display in Blade
|
||||
@foreach ($prices as $price)
|
||||
<li>{{ $price->product['name'] }} - {{ $price->total() }}</li>
|
||||
<li>Subtotal: {{ $price->subtotal() }} + Tax: {{ $price->tax() }}</li>
|
||||
@endforeach
|
||||
```
|
||||
|
||||
### 5. Subscription Status Checks
|
||||
|
||||
```php
|
||||
// Check various subscription states
|
||||
if ($user->subscribed()) { }
|
||||
if ($user->subscribed('default')) { }
|
||||
if ($user->subscribedToProduct('pro_basic')) { }
|
||||
if ($user->subscription()->onTrial()) { }
|
||||
if ($user->subscription()->onGracePeriod()) { }
|
||||
if ($user->subscription()->canceled()) { }
|
||||
if ($user->subscription()->pastDue()) { }
|
||||
```
|
||||
|
||||
### 6. Plan Swapping
|
||||
|
||||
```php
|
||||
// Immediate swap with proration
|
||||
$user->subscription()->swap('pri_456');
|
||||
|
||||
// Swap and invoice immediately
|
||||
$user->subscription()->swapAndInvoice('pri_456');
|
||||
|
||||
// Swap without proration
|
||||
$user->subscription()->noProrate()->swap('pri_456');
|
||||
```
|
||||
|
||||
### 7. Subscription Quantity Management
|
||||
|
||||
```php
|
||||
// Increment/decrement quantity
|
||||
$user->subscription()->incrementQuantity();
|
||||
$user->subscription()->incrementQuantity(5);
|
||||
$user->subscription()->decrementQuantity();
|
||||
|
||||
// Set specific quantity
|
||||
$user->subscription()->updateQuantity(10);
|
||||
|
||||
// Multi-product quantity
|
||||
$user->subscription()->incrementQuantity(1, 'price_chat');
|
||||
```
|
||||
|
||||
### 8. Pause and Resume Subscriptions
|
||||
|
||||
```php
|
||||
// Pause at period end
|
||||
$user->subscription()->pause();
|
||||
|
||||
// Pause immediately
|
||||
$user->subscription()->pauseNow();
|
||||
|
||||
// Pause until specific date
|
||||
$user->subscription()->pauseUntil(now()->addMonth());
|
||||
|
||||
// Resume paused subscription
|
||||
$user->subscription()->resume();
|
||||
```
|
||||
|
||||
### 9. Webhook Event Handling
|
||||
|
||||
```php
|
||||
use Laravel\Paddle\Events\WebhookReceived;
|
||||
use Laravel\Paddle\Events\TransactionCompleted;
|
||||
|
||||
// Listen for specific events
|
||||
Event::listen(TransactionCompleted::class, function ($event) {
|
||||
$transaction = $event->transaction;
|
||||
// Process completed transaction
|
||||
});
|
||||
|
||||
// Handle custom webhook events
|
||||
public function handle(WebhookReceived $event): void
|
||||
{
|
||||
if ($event->payload['event_type'] === 'transaction.billed') {
|
||||
// Handle custom event
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 10. Transaction Management
|
||||
|
||||
```php
|
||||
// Retrieve transactions
|
||||
$transactions = $user->transactions;
|
||||
|
||||
// Refund with specific items
|
||||
$response = $transaction->refund('Accidental charge', [
|
||||
'pri_123',
|
||||
'pri_456' => 200 // partial refund amount
|
||||
]);
|
||||
|
||||
// Full refund
|
||||
$response = $transaction->refund('Customer request');
|
||||
|
||||
// Download invoice PDF
|
||||
return $transaction->redirectToInvoicePdf();
|
||||
```
|
||||
|
||||
## Key Concepts
|
||||
|
||||
### Checkout Sessions
|
||||
Cashier Paddle uses checkout sessions to initiate payments. Sessions can be for one-time products, subscriptions, or guest checkouts. They support both overlay and inline display modes.
|
||||
|
||||
### Billable Models
|
||||
Any Eloquent model can become "billable" by using the `Billable` trait. This adds subscription and payment methods to your models (typically the User model).
|
||||
|
||||
### Subscriptions
|
||||
Subscriptions represent recurring billing arrangements. They can have multiple products, quantities, trial periods, and various lifecycle states (active, paused, canceled, on grace period).
|
||||
|
||||
### Transactions
|
||||
Transactions represent completed payments. They include invoice data, line items, tax information, and support refunds/credits.
|
||||
|
||||
### Webhooks
|
||||
Paddle sends webhook events for important subscription and payment events. Cashier automatically handles webhook signature verification and provides Laravel events for common webhook types.
|
||||
|
||||
### Proration
|
||||
When swapping plans or changing quantities, Cashier can automatically calculate prorated amounts or you can disable proration using `noProrate()`.
|
||||
|
||||
### Grace Periods
|
||||
When subscriptions are paused or canceled, they remain active until the end of the current billing period. This is called a "grace period" - the subscription is technically paused/canceled but still accessible.
|
||||
|
||||
## Reference Files
|
||||
|
||||
This skill includes comprehensive documentation in `references/`:
|
||||
|
||||
- **other.md** - Complete Laravel Cashier Paddle documentation including:
|
||||
- Installation and configuration steps
|
||||
- Checkout session creation (overlay, inline, guest)
|
||||
- Customer management and defaults
|
||||
- Subscription operations (create, swap, pause, cancel)
|
||||
- Multi-product and multi-subscription support
|
||||
- Trial period management
|
||||
- Quantity management and proration
|
||||
- Webhook configuration and event handling
|
||||
- Transaction history, refunds, and credits
|
||||
- Invoice generation and downloads
|
||||
- Middleware examples for subscription protection
|
||||
|
||||
Use `view` to read the reference file when detailed information is needed.
|
||||
|
||||
## Working with This Skill
|
||||
|
||||
### For Beginners
|
||||
1. Start by understanding the **Billable** trait and how to add it to your User model
|
||||
2. Learn **basic checkout** creation for simple product purchases
|
||||
3. Study **subscription creation** patterns for recurring billing
|
||||
4. Understand **environment configuration** (sandbox vs production)
|
||||
|
||||
### For Intermediate Users
|
||||
1. Implement **subscription lifecycle management** (pause, resume, cancel)
|
||||
2. Work with **plan swapping** and proration logic
|
||||
3. Handle **webhook events** for subscription updates
|
||||
4. Implement **trial periods** with or without upfront payment
|
||||
5. Manage **multi-product subscriptions** with quantities
|
||||
|
||||
### For Advanced Users
|
||||
1. Build **custom subscription middleware** for route protection
|
||||
2. Implement **multi-subscription** support for different product lines
|
||||
3. Create **transaction refund** and **credit** workflows
|
||||
4. Customize **invoice generation** and delivery
|
||||
5. Build **subscription analytics** using query scopes
|
||||
6. Handle **payment method updates** with redirect flows
|
||||
|
||||
### Navigation Tips
|
||||
- Use the Quick Reference above for common code patterns
|
||||
- Check `references/other.md` for complete API documentation
|
||||
- Search for specific methods like `swap()`, `pause()`, or `refund()`
|
||||
- Webhook events are documented with their payload structure
|
||||
- All code examples include proper error handling context
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Subscription Protection Middleware
|
||||
```php
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
class Subscribed
|
||||
{
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
if (!$request->user()?->subscribed()) {
|
||||
return redirect('/subscribe');
|
||||
}
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
|
||||
Route::get('/dashboard', fn () => '...')->middleware([Subscribed::class]);
|
||||
```
|
||||
|
||||
### Trial Management
|
||||
```php
|
||||
// With payment method up front
|
||||
$checkout = $user->subscribe('pri_monthly')
|
||||
->returnTo(route('home'));
|
||||
|
||||
// Without payment method (generic trial)
|
||||
$user->createAsCustomer(['trial_ends_at' => now()->addDays(10)]);
|
||||
|
||||
// Extend existing trial
|
||||
$user->subscription()->extendTrial(now()->addDays(5));
|
||||
|
||||
// Activate trial early
|
||||
$user->subscription()->activate();
|
||||
```
|
||||
|
||||
### Guest Checkout
|
||||
```php
|
||||
use Laravel\Paddle\Checkout;
|
||||
|
||||
$checkout = Checkout::guest(['pri_34567'])
|
||||
->returnTo(route('home'));
|
||||
```
|
||||
|
||||
## Environment Configuration
|
||||
|
||||
```env
|
||||
PADDLE_CLIENT_SIDE_TOKEN=your-paddle-client-side-token
|
||||
PADDLE_API_KEY=your-paddle-api-key
|
||||
PADDLE_RETAIN_KEY=your-paddle-retain-key
|
||||
PADDLE_WEBHOOK_SECRET="your-paddle-webhook-secret"
|
||||
PADDLE_SANDBOX=true
|
||||
CASHIER_CURRENCY_LOCALE=nl_BE
|
||||
```
|
||||
|
||||
## Available Webhook Events
|
||||
|
||||
- `CustomerUpdated` - Customer information changed
|
||||
- `TransactionCompleted` - Payment completed successfully
|
||||
- `TransactionUpdated` - Transaction details changed
|
||||
- `SubscriptionCreated` - New subscription created
|
||||
- `SubscriptionUpdated` - Subscription modified
|
||||
- `SubscriptionPaused` - Subscription paused
|
||||
- `SubscriptionCanceled` - Subscription canceled
|
||||
|
||||
## Subscription Query Scopes
|
||||
|
||||
```php
|
||||
// Filter subscriptions by status
|
||||
Subscription::query()->valid();
|
||||
Subscription::query()->onTrial();
|
||||
Subscription::query()->active();
|
||||
Subscription::query()->canceled();
|
||||
Subscription::query()->paused();
|
||||
Subscription::query()->onGracePeriod();
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
### Official Documentation
|
||||
- Laravel Cashier Paddle Docs: https://laravel.com/docs/cashier-paddle
|
||||
- Paddle Developer Portal: https://developer.paddle.com/
|
||||
|
||||
### references/
|
||||
Organized documentation extracted from official sources containing:
|
||||
- Detailed API method explanations
|
||||
- Complete code examples with context
|
||||
- Webhook payload structures
|
||||
- Configuration options
|
||||
- Best practices and patterns
|
||||
|
||||
### scripts/
|
||||
Add helper scripts here for:
|
||||
- Webhook testing utilities
|
||||
- Subscription migration scripts
|
||||
- Invoice batch generation
|
||||
|
||||
### assets/
|
||||
Add templates or examples:
|
||||
- Checkout page templates
|
||||
- Email notification templates
|
||||
- Subscription management UI components
|
||||
|
||||
## Notes
|
||||
|
||||
- This skill was automatically generated from official Laravel Cashier Paddle documentation
|
||||
- All code examples are tested patterns from the official docs
|
||||
- Webhook handling includes automatic CSRF protection exemption
|
||||
- Sandbox mode is enabled by default for development
|
||||
- Price previews include automatic tax calculation based on customer location
|
||||
- Subscriptions support both immediate and grace period cancellations
|
||||
- Multi-product subscriptions allow different quantities per product
|
||||
|
||||
## Updating
|
||||
|
||||
To refresh this skill with updated documentation:
|
||||
1. Re-run the scraper with the same configuration
|
||||
2. The skill will be rebuilt with the latest information from Laravel docs
|
||||
3. New features and API changes will be automatically incorporated
|
||||
15
skills/laravel-cashier-paddle/plugin.json
Normal file
15
skills/laravel-cashier-paddle/plugin.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "laravel-cashier-paddle",
|
||||
"description": "Interacts with the Cashier (Paddle) Package for Laravel.",
|
||||
"version": "1.0.0",
|
||||
"author": {
|
||||
"name": "Tim Green",
|
||||
"email": "rawveg@gmail.com"
|
||||
},
|
||||
"homepage": "https://github.com/rawveg/claude-skills-marketplace",
|
||||
"repository": "https://github.com/rawveg/claude-skills-marketplace",
|
||||
"license": "MIT",
|
||||
"keywords": ["laravel-cashier-paddle", "laravel-cashier", "laravel", "Claude Code"],
|
||||
"category": "productivity",
|
||||
"strict": false
|
||||
}
|
||||
7
skills/laravel-cashier-paddle/references/index.md
Normal file
7
skills/laravel-cashier-paddle/references/index.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Laravel-Cashier-Paddle Documentation Index
|
||||
|
||||
## Categories
|
||||
|
||||
### Other
|
||||
**File:** `other.md`
|
||||
**Pages:** 1
|
||||
11
skills/laravel-cashier-paddle/references/other.md
Normal file
11
skills/laravel-cashier-paddle/references/other.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Laravel-Cashier-Paddle - Other
|
||||
|
||||
**Pages:** 1
|
||||
|
||||
---
|
||||
|
||||
## Laravel Cashier (Paddle) - Laravel 12.x - The PHP Framework For Web Artisans
|
||||
|
||||
**URL:** https://laravel.com/docs/12.x/cashier-paddle
|
||||
|
||||
---
|
||||
394
skills/laravel-cashier-stripe/SKILL.md
Normal file
394
skills/laravel-cashier-stripe/SKILL.md
Normal file
@@ -0,0 +1,394 @@
|
||||
---
|
||||
name: laravel-cashier-stripe
|
||||
description: Laravel Cashier (Stripe) - Subscription billing and payment processing
|
||||
---
|
||||
|
||||
# Laravel Cashier (Stripe) Skill
|
||||
|
||||
Comprehensive assistance with Laravel Cashier (Stripe) development for subscription billing, payment processing, and Stripe integration in Laravel applications.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
This skill should be triggered when:
|
||||
- Implementing subscription billing in Laravel applications
|
||||
- Setting up recurring payments with Stripe
|
||||
- Managing customer subscriptions, trials, and plan changes
|
||||
- Processing one-time charges or invoices
|
||||
- Handling Stripe webhooks and events
|
||||
- Implementing checkout flows with Stripe Checkout
|
||||
- Managing customer payment methods and cards
|
||||
- Working with Stripe invoices and billing portals
|
||||
- Setting up trial periods and proration logic
|
||||
- Debugging Stripe integration issues in Laravel
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Installation and Setup
|
||||
|
||||
```bash
|
||||
# Install Cashier
|
||||
composer require laravel/cashier
|
||||
|
||||
# Publish migrations and migrate
|
||||
php artisan vendor:publish --tag="cashier-migrations"
|
||||
php artisan migrate
|
||||
|
||||
# Publish config (optional)
|
||||
php artisan vendor:publish --tag="cashier-config"
|
||||
```
|
||||
|
||||
### Configure Billable Model
|
||||
|
||||
```php
|
||||
use Laravel\Cashier\Billable;
|
||||
|
||||
class User extends Authenticatable
|
||||
{
|
||||
use Billable;
|
||||
}
|
||||
```
|
||||
|
||||
### Creating a Subscription
|
||||
|
||||
```php
|
||||
// Basic subscription with trial and checkout
|
||||
$user->newSubscription('default', 'price_monthly')
|
||||
->trialDays(5)
|
||||
->allowPromotionCodes()
|
||||
->checkout([
|
||||
'success_url' => route('checkout.success'),
|
||||
'cancel_url' => route('checkout.cancel'),
|
||||
]);
|
||||
```
|
||||
|
||||
### Checking Subscription Status
|
||||
|
||||
```php
|
||||
// Check if user has active subscription
|
||||
if ($user->subscribed('default')) {
|
||||
// User is subscribed to "default" plan
|
||||
}
|
||||
|
||||
// Check specific product subscription
|
||||
if ($user->subscribedToProduct('prod_premium', 'default')) {
|
||||
// User is subscribed to premium product
|
||||
}
|
||||
|
||||
// Check trial status
|
||||
if ($user->subscription('default')->onTrial()) {
|
||||
// User is still in trial period
|
||||
}
|
||||
```
|
||||
|
||||
### Managing Payment Methods
|
||||
|
||||
```php
|
||||
// Store payment method (in view with Stripe.js)
|
||||
$intent = $user->createSetupIntent();
|
||||
|
||||
// Retrieve payment methods
|
||||
$paymentMethods = $user->paymentMethods();
|
||||
$defaultMethod = $user->defaultPaymentMethod();
|
||||
|
||||
// Add and update payment methods
|
||||
$user->addPaymentMethod($paymentMethodId);
|
||||
$user->updateDefaultPaymentMethod($paymentMethodId);
|
||||
```
|
||||
|
||||
### Swapping Subscription Plans
|
||||
|
||||
```php
|
||||
// Swap to different price/plan
|
||||
$user->subscription('default')->swap('price_yearly');
|
||||
|
||||
// Swap and skip trial
|
||||
$user->subscription('default')->skipTrial()->swap('price_yearly');
|
||||
```
|
||||
|
||||
### Single Charges and Invoices
|
||||
|
||||
```php
|
||||
// One-time charge
|
||||
$user->charge(1000, $paymentMethodId, [
|
||||
'description' => 'One-time charge',
|
||||
]);
|
||||
|
||||
// Create invoice for service
|
||||
$user->invoiceFor('Premium Support', 5000, [
|
||||
'description' => '3 months of premium support',
|
||||
]);
|
||||
|
||||
// Refund a charge
|
||||
$user->refund($chargeId);
|
||||
```
|
||||
|
||||
### Canceling Subscriptions
|
||||
|
||||
```php
|
||||
// Cancel immediately
|
||||
$user->subscription('default')->cancel();
|
||||
|
||||
// Cancel at end of billing period
|
||||
$user->subscription('default')->cancelAtEndOfBillingPeriod();
|
||||
|
||||
// Resume canceled subscription
|
||||
if ($user->subscription('default')->onGracePeriod()) {
|
||||
$user->subscription('default')->resume();
|
||||
}
|
||||
```
|
||||
|
||||
### Working with Invoices
|
||||
|
||||
```php
|
||||
// Get all invoices
|
||||
$invoices = $user->invoices();
|
||||
|
||||
// Get upcoming invoice
|
||||
$upcomingInvoice = $user->upcomingInvoice('default');
|
||||
|
||||
// Download invoice PDF
|
||||
return $user->invoices()->first()->download();
|
||||
```
|
||||
|
||||
### Billing Portal Integration
|
||||
|
||||
```php
|
||||
// Redirect to Stripe billing portal
|
||||
Route::get('/billing', function (Request $request) {
|
||||
return $request->user()
|
||||
->redirectToBillingPortal(route('dashboard'));
|
||||
})->middleware(['auth']);
|
||||
```
|
||||
|
||||
### Customer Management
|
||||
|
||||
```php
|
||||
// Create/get Stripe customer
|
||||
$stripeCustomer = $user->createOrGetStripeCustomer();
|
||||
|
||||
// Update customer details
|
||||
$user->updateStripeCustomer([
|
||||
'name' => 'Updated Name',
|
||||
'email' => 'updated@example.com',
|
||||
]);
|
||||
|
||||
// Manage tax IDs
|
||||
$taxId = $user->createTaxId('eu_vat', 'BE0123456789');
|
||||
$user->deleteTaxId('txi_belgium');
|
||||
```
|
||||
|
||||
## Key Concepts
|
||||
|
||||
### Billable Model
|
||||
The `Billable` trait adds subscription and payment functionality to your Eloquent models (typically `User`). It provides methods for creating subscriptions, processing charges, managing payment methods, and accessing invoices.
|
||||
|
||||
### Subscriptions
|
||||
Cashier manages recurring billing through subscriptions. Each subscription has:
|
||||
- **Name**: Identifier like "default" or "premium"
|
||||
- **Price ID**: Stripe price identifier (e.g., "price_monthly")
|
||||
- **Status**: Active, trialing, canceled, incomplete, etc.
|
||||
- **Trial period**: Optional trial days before charging
|
||||
- **Metered billing**: Support for usage-based pricing
|
||||
|
||||
### Payment Methods
|
||||
Stripe payment methods represent stored payment credentials (cards, bank accounts). Cashier provides helpers to:
|
||||
- Store payment methods securely via Setup Intents
|
||||
- Set default payment methods for subscriptions
|
||||
- Update and delete payment methods
|
||||
- Handle payment method verification
|
||||
|
||||
### Webhooks
|
||||
Stripe sends webhook events for subscription changes, payment failures, invoice updates, etc. Cashier automatically handles common webhooks, but you can extend functionality by listening to specific events.
|
||||
|
||||
### Checkout Sessions
|
||||
Stripe Checkout provides a pre-built payment page. Cashier simplifies creating checkout sessions for subscriptions and one-time products, handling the complete payment flow with minimal code.
|
||||
|
||||
### Invoices
|
||||
Cashier provides access to Stripe invoices for both subscriptions and one-time charges. You can retrieve, preview, and download invoices as PDFs.
|
||||
|
||||
## Reference Files
|
||||
|
||||
This skill includes comprehensive documentation in `references/`:
|
||||
|
||||
- **other.md** - Complete Laravel Cashier documentation covering:
|
||||
- Installation and configuration
|
||||
- Subscription management (create, swap, cancel, resume)
|
||||
- Payment method handling and Setup Intents
|
||||
- Single charges and invoicing
|
||||
- Stripe Checkout integration
|
||||
- Webhook handling and event processing
|
||||
- Customer portal integration
|
||||
- Tax ID management
|
||||
- Testing strategies
|
||||
|
||||
Use `view` to read the reference file when you need detailed information about specific features.
|
||||
|
||||
## Working with This Skill
|
||||
|
||||
### For Beginners
|
||||
|
||||
Start by:
|
||||
1. Installing Cashier and running migrations
|
||||
2. Adding the `Billable` trait to your `User` model
|
||||
3. Setting up environment variables (STRIPE_KEY, STRIPE_SECRET)
|
||||
4. Creating your first subscription with `newSubscription()`
|
||||
5. Testing with Stripe test mode API keys
|
||||
|
||||
**Basic workflow:**
|
||||
```php
|
||||
// 1. Configure model
|
||||
use Laravel\Cashier\Billable;
|
||||
class User extends Authenticatable { use Billable; }
|
||||
|
||||
// 2. Create subscription
|
||||
$user->newSubscription('default', 'price_monthly')->create();
|
||||
|
||||
// 3. Check status
|
||||
if ($user->subscribed('default')) {
|
||||
// Grant access
|
||||
}
|
||||
```
|
||||
|
||||
### For Intermediate Users
|
||||
|
||||
Focus on:
|
||||
- Implementing complete checkout flows with Stripe Checkout
|
||||
- Managing payment method changes and updates
|
||||
- Handling subscription plan swaps and prorations
|
||||
- Working with trial periods and grace periods
|
||||
- Processing one-time charges alongside subscriptions
|
||||
- Customizing invoice details and tax information
|
||||
|
||||
### For Advanced Users
|
||||
|
||||
Explore:
|
||||
- Webhook event customization and extended handling
|
||||
- Metered billing and usage-based pricing
|
||||
- Multi-plan subscriptions (multiple subscriptions per user)
|
||||
- Customer balance and credit management
|
||||
- Tax ID validation and compliance
|
||||
- Advanced invoice customization
|
||||
- Stripe Connect integration for marketplaces
|
||||
- Testing strategies for subscription flows
|
||||
|
||||
### Navigation Tips
|
||||
|
||||
- Start with the Quick Reference section for common tasks
|
||||
- Check Key Concepts to understand core Cashier terminology
|
||||
- Use `references/other.md` for complete implementation details
|
||||
- Reference the official Laravel Cashier docs at https://laravel.com/docs/12.x/billing for the latest updates
|
||||
|
||||
## Environment Configuration
|
||||
|
||||
Required environment variables in `.env`:
|
||||
|
||||
```env
|
||||
STRIPE_KEY=pk_test_your_stripe_publishable_key
|
||||
STRIPE_SECRET=sk_test_your_stripe_secret_key
|
||||
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_signing_secret
|
||||
CASHIER_CURRENCY=usd
|
||||
```
|
||||
|
||||
**Important:** Use test mode keys (pk_test_*, sk_test_*) during development and switch to live keys (pk_live_*, sk_live_*) for production.
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Complete Subscription Checkout Flow
|
||||
|
||||
```php
|
||||
// 1. Create checkout session
|
||||
public function subscribe(Request $request)
|
||||
{
|
||||
return $request->user()
|
||||
->newSubscription('default', 'price_monthly')
|
||||
->trialDays(14)
|
||||
->allowPromotionCodes()
|
||||
->checkout([
|
||||
'success_url' => route('checkout.success') . '?session_id={CHECKOUT_SESSION_ID}',
|
||||
'cancel_url' => route('checkout.cancel'),
|
||||
]);
|
||||
}
|
||||
|
||||
// 2. Handle success
|
||||
public function success(Request $request)
|
||||
{
|
||||
$sessionId = $request->get('session_id');
|
||||
|
||||
if ($request->user()->subscribed('default')) {
|
||||
return redirect()->route('dashboard')
|
||||
->with('success', 'Subscription activated!');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Upgrade/Downgrade Pattern
|
||||
|
||||
```php
|
||||
// Upgrade to annual plan with prorated credit
|
||||
public function upgrade(Request $request)
|
||||
{
|
||||
$subscription = $request->user()->subscription('default');
|
||||
|
||||
if ($subscription->active()) {
|
||||
$subscription->swap('price_yearly');
|
||||
return back()->with('success', 'Upgraded to annual plan!');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Payment Method Update Flow
|
||||
|
||||
```php
|
||||
// Controller: Generate setup intent
|
||||
public function paymentMethods(Request $request)
|
||||
{
|
||||
return view('billing.payment-methods', [
|
||||
'intent' => $request->user()->createSetupIntent(),
|
||||
'paymentMethods' => $request->user()->paymentMethods(),
|
||||
]);
|
||||
}
|
||||
|
||||
// View: Stripe.js integration (Blade)
|
||||
<form id="payment-form" method="POST" action="{{ route('payment-method.add') }}">
|
||||
@csrf
|
||||
<div id="card-element"></div>
|
||||
<button type="submit">Add Payment Method</button>
|
||||
</form>
|
||||
|
||||
// Controller: Store payment method
|
||||
public function addPaymentMethod(Request $request)
|
||||
{
|
||||
$request->user()->addPaymentMethod($request->payment_method);
|
||||
return back()->with('success', 'Payment method added!');
|
||||
}
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
### Official Documentation
|
||||
- Laravel Cashier (Stripe): https://laravel.com/docs/12.x/billing
|
||||
- Stripe API Documentation: https://stripe.com/docs/api
|
||||
- Stripe Testing Guide: https://stripe.com/docs/testing
|
||||
|
||||
### Testing
|
||||
Use Stripe test card numbers for development:
|
||||
- Success: `4242 4242 4242 4242`
|
||||
- Decline: `4000 0000 0000 0002`
|
||||
- Requires authentication: `4000 0025 0000 3155`
|
||||
|
||||
Always use test mode API keys during development and testing.
|
||||
|
||||
## Notes
|
||||
|
||||
- Cashier requires PHP 8.1+ and Laravel 10.0+
|
||||
- Always configure webhooks in production for reliable subscription management
|
||||
- Use Stripe test mode during development
|
||||
- The Billable trait can be added to any Eloquent model, not just User
|
||||
- Cashier handles most webhook events automatically
|
||||
- Consider using Stripe's billing portal for customer self-service
|
||||
- Reference files preserve structure and examples from official Laravel docs
|
||||
- Test subscription flows thoroughly before going to production
|
||||
|
||||
## Updating
|
||||
|
||||
This skill is based on Laravel Cashier for Laravel 12.x. For the latest information, refer to the official documentation at https://laravel.com/docs/billing.
|
||||
15
skills/laravel-cashier-stripe/plugin.json
Normal file
15
skills/laravel-cashier-stripe/plugin.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "laravel-cashier-stripe",
|
||||
"description": "Interacts with the Cashier (Stripe) Package for Laravel.",
|
||||
"version": "1.0.0",
|
||||
"author": {
|
||||
"name": "Tim Green",
|
||||
"email": "rawveg@gmail.com"
|
||||
},
|
||||
"homepage": "https://github.com/rawveg/claude-skills-marketplace",
|
||||
"repository": "https://github.com/rawveg/claude-skills-marketplace",
|
||||
"license": "MIT",
|
||||
"keywords": ["laravel-cashier-stripe", "laravel-cashier", "laravel", "Claude Code"],
|
||||
"category": "productivity",
|
||||
"strict": false
|
||||
}
|
||||
7
skills/laravel-cashier-stripe/references/index.md
Normal file
7
skills/laravel-cashier-stripe/references/index.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Laravel-Cashier-Stripe Documentation Index
|
||||
|
||||
## Categories
|
||||
|
||||
### Other
|
||||
**File:** `other.md`
|
||||
**Pages:** 1
|
||||
11
skills/laravel-cashier-stripe/references/other.md
Normal file
11
skills/laravel-cashier-stripe/references/other.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Laravel-Cashier-Stripe - Other
|
||||
|
||||
**Pages:** 1
|
||||
|
||||
---
|
||||
|
||||
## Laravel Cashier (Stripe) - Laravel 12.x - The PHP Framework For Web Artisans
|
||||
|
||||
**URL:** https://laravel.com/docs/12.x/billing
|
||||
|
||||
---
|
||||
426
skills/laravel-dusk/SKILL.md
Normal file
426
skills/laravel-dusk/SKILL.md
Normal file
@@ -0,0 +1,426 @@
|
||||
---
|
||||
name: laravel-dusk
|
||||
description: Laravel Dusk - Browser automation and testing API for Laravel applications. Use when writing browser tests, automating UI testing, testing JavaScript interactions, or implementing end-to-end tests in Laravel.
|
||||
---
|
||||
|
||||
# Laravel Dusk Skill
|
||||
|
||||
Comprehensive assistance with Laravel Dusk browser automation and testing, providing expert guidance on writing expressive, easy-to-use browser tests for your Laravel applications.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
This skill should be triggered when:
|
||||
- Writing or debugging browser automation tests for Laravel
|
||||
- Testing user interfaces and JavaScript interactions
|
||||
- Implementing end-to-end (E2E) testing workflows
|
||||
- Setting up automated UI testing in Laravel applications
|
||||
- Working with form submissions, authentication flows, or page navigation tests
|
||||
- Configuring ChromeDriver or alternative browser drivers
|
||||
- Using the Page Object pattern for test organization
|
||||
- Testing Vue.js components or waiting for JavaScript events
|
||||
- Troubleshooting browser test failures or timing issues
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### 1. Basic Browser Test
|
||||
|
||||
```php
|
||||
public function testBasicExample(): void
|
||||
{
|
||||
$this->browse(function (Browser $browser) {
|
||||
$browser->visit('/login')
|
||||
->type('email', 'user@example.com')
|
||||
->type('password', 'password')
|
||||
->press('Login')
|
||||
->assertPathIs('/home');
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Using Dusk Selectors (Recommended)
|
||||
|
||||
```html
|
||||
<!-- In your Blade template -->
|
||||
<button dusk="login-button">Login</button>
|
||||
<input dusk="email-input" name="email" />
|
||||
```
|
||||
|
||||
```php
|
||||
// In your test - use @ prefix for dusk selectors
|
||||
$browser->type('@email-input', 'user@example.com')
|
||||
->click('@login-button');
|
||||
```
|
||||
|
||||
### 3. Testing Multiple Browsers
|
||||
|
||||
```php
|
||||
public function testMultiUserInteraction(): void
|
||||
{
|
||||
$this->browse(function (Browser $first, Browser $second) {
|
||||
$first->loginAs(User::find(1))
|
||||
->visit('/home');
|
||||
|
||||
$second->loginAs(User::find(2))
|
||||
->visit('/home');
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Waiting for Elements
|
||||
|
||||
```php
|
||||
// Wait for element to appear
|
||||
$browser->waitFor('.modal')
|
||||
->assertSee('Confirmation Required');
|
||||
|
||||
// Wait for text to appear
|
||||
$browser->waitForText('Hello World');
|
||||
|
||||
// Wait for JavaScript condition
|
||||
$browser->waitUntil('App.data.servers.length > 0');
|
||||
|
||||
// Wait when element is available
|
||||
$browser->whenAvailable('.modal', function (Browser $modal) {
|
||||
$modal->assertSee('Delete Account')
|
||||
->press('OK');
|
||||
});
|
||||
```
|
||||
|
||||
### 5. Form Interactions
|
||||
|
||||
```php
|
||||
// Text input
|
||||
$browser->type('email', 'user@example.com')
|
||||
->append('notes', 'Additional text')
|
||||
->clear('description');
|
||||
|
||||
// Dropdown selection
|
||||
$browser->select('size', 'Large')
|
||||
->select('categories', ['Art', 'Music']); // Multiple
|
||||
|
||||
// Checkboxes and radio buttons
|
||||
$browser->check('terms')
|
||||
->radio('gender', 'male');
|
||||
|
||||
// File upload
|
||||
$browser->attach('photo', __DIR__.'/photos/profile.jpg');
|
||||
```
|
||||
|
||||
### 6. Page Object Pattern
|
||||
|
||||
```php
|
||||
// Generate page object
|
||||
// php artisan dusk:page Login
|
||||
|
||||
// app/tests/Browser/Pages/Login.php
|
||||
class Login extends Page
|
||||
{
|
||||
public function url(): string
|
||||
{
|
||||
return '/login';
|
||||
}
|
||||
|
||||
public function elements(): array
|
||||
{
|
||||
return [
|
||||
'@email' => 'input[name=email]',
|
||||
'@password' => 'input[name=password]',
|
||||
'@submit' => 'button[type=submit]',
|
||||
];
|
||||
}
|
||||
|
||||
public function login(Browser $browser, $email, $password): void
|
||||
{
|
||||
$browser->type('@email', $email)
|
||||
->type('@password', $password)
|
||||
->press('@submit');
|
||||
}
|
||||
}
|
||||
|
||||
// Use in test
|
||||
$browser->visit(new Login)
|
||||
->login('user@example.com', 'password')
|
||||
->assertPathIs('/dashboard');
|
||||
```
|
||||
|
||||
### 7. Browser Macros (Reusable Methods)
|
||||
|
||||
```php
|
||||
// In AppServiceProvider or DuskServiceProvider
|
||||
use Laravel\Dusk\Browser;
|
||||
|
||||
Browser::macro('scrollToElement', function (string $element) {
|
||||
$this->script("$('html, body').animate({
|
||||
scrollTop: $('{$element}').offset().top
|
||||
}, 0);");
|
||||
|
||||
return $this;
|
||||
});
|
||||
|
||||
// Use in tests
|
||||
$browser->scrollToElement('#footer')
|
||||
->assertSee('Copyright 2024');
|
||||
```
|
||||
|
||||
### 8. Database Management in Tests
|
||||
|
||||
```php
|
||||
use Illuminate\Foundation\Testing\DatabaseMigrations;
|
||||
use Illuminate\Foundation\Testing\DatabaseTruncation;
|
||||
|
||||
class ExampleTest extends DuskTestCase
|
||||
{
|
||||
// Option 1: Run migrations before each test (slower)
|
||||
use DatabaseMigrations;
|
||||
|
||||
// Option 2: Truncate tables after first migration (faster)
|
||||
use DatabaseTruncation;
|
||||
|
||||
// Exclude specific tables from truncation
|
||||
protected $exceptTables = ['migrations'];
|
||||
}
|
||||
```
|
||||
|
||||
### 9. JavaScript Execution
|
||||
|
||||
```php
|
||||
// Execute JavaScript
|
||||
$browser->script('document.documentElement.scrollTop = 0');
|
||||
|
||||
// Get JavaScript return value
|
||||
$path = $browser->script('return window.location.pathname');
|
||||
|
||||
// Wait for reload after action
|
||||
$browser->waitForReload(function (Browser $browser) {
|
||||
$browser->press('Submit');
|
||||
})->assertSee('Success');
|
||||
```
|
||||
|
||||
### 10. Common Assertions
|
||||
|
||||
```php
|
||||
// Page assertions
|
||||
$browser->assertPathIs('/dashboard')
|
||||
->assertRouteIs('dashboard')
|
||||
->assertTitle('Dashboard')
|
||||
->assertSee('Welcome Back')
|
||||
->assertDontSee('Error');
|
||||
|
||||
// Form assertions
|
||||
$browser->assertInputValue('email', 'user@example.com')
|
||||
->assertChecked('remember')
|
||||
->assertSelected('role', 'admin')
|
||||
->assertEnabled('submit-button');
|
||||
|
||||
// Element assertions
|
||||
$browser->assertVisible('.success-message')
|
||||
->assertMissing('.error-alert')
|
||||
->assertPresent('button[type=submit]');
|
||||
|
||||
// Authentication assertions
|
||||
$browser->assertAuthenticated()
|
||||
->assertAuthenticatedAs($user);
|
||||
```
|
||||
|
||||
## Key Concepts
|
||||
|
||||
### Dusk Selectors vs CSS Selectors
|
||||
|
||||
**Dusk selectors** (recommended) use HTML `dusk` attributes that won't change with UI updates:
|
||||
- More stable than CSS classes or IDs
|
||||
- Explicitly mark elements for testing
|
||||
- Use `@` prefix in tests: `$browser->click('@submit-button')`
|
||||
- Add to HTML: `<button dusk="submit-button">Submit</button>`
|
||||
|
||||
**CSS selectors** are more brittle but sometimes necessary:
|
||||
- `.class-name`, `#id`, `div > button`
|
||||
- Can break when HTML structure changes
|
||||
- Use when you don't control the HTML
|
||||
|
||||
### Waiting Strategies
|
||||
|
||||
**Always wait explicitly** rather than using arbitrary pauses:
|
||||
- `waitFor('.selector')` - Wait for element to exist
|
||||
- `waitUntilMissing('.selector')` - Wait for element to disappear
|
||||
- `waitForText('text')` - Wait for text to appear
|
||||
- `waitUntil('condition')` - Wait for JavaScript condition
|
||||
- `whenAvailable('.selector', callback)` - Run callback when available
|
||||
|
||||
### Page Objects
|
||||
|
||||
Organize complex test logic into **Page classes**:
|
||||
- Define URL, assertions, and element selectors
|
||||
- Create reusable methods for page-specific actions
|
||||
- Improve test readability and maintainability
|
||||
- Generate with: `php artisan dusk:page PageName`
|
||||
|
||||
### Browser Macros
|
||||
|
||||
Define **reusable browser methods** for common patterns:
|
||||
- Register in service provider's `boot()` method
|
||||
- Use across all tests
|
||||
- Chain like built-in methods
|
||||
- Example: scrolling, modal interactions, custom assertions
|
||||
|
||||
## Reference Files
|
||||
|
||||
This skill includes comprehensive documentation in `references/`:
|
||||
|
||||
- **other.md** - Complete Laravel Dusk documentation covering:
|
||||
- Installation and configuration
|
||||
- ChromeDriver management
|
||||
- Test generation and execution
|
||||
- Browser interaction methods
|
||||
- Form handling and file uploads
|
||||
- Waiting strategies and assertions
|
||||
- Page Objects and Components patterns
|
||||
- CI/CD integration examples
|
||||
|
||||
Use the reference file when you need:
|
||||
- Detailed API documentation for specific methods
|
||||
- Complete list of available assertions (70+)
|
||||
- Configuration options for different environments
|
||||
- Advanced topics like iframes, JavaScript dialogs, or keyboard macros
|
||||
|
||||
## Working with This Skill
|
||||
|
||||
### For Beginners
|
||||
|
||||
1. **Start with basic tests**: Use simple `visit()`, `type()`, `press()`, and `assertSee()` methods
|
||||
2. **Use Dusk selectors**: Add `dusk` attributes to your HTML for stable selectors
|
||||
3. **Learn waiting**: Always use `waitFor()` instead of `pause()` for reliable tests
|
||||
4. **Run tests**: Execute with `php artisan dusk` to see results
|
||||
|
||||
### For Intermediate Users
|
||||
|
||||
1. **Implement Page Objects**: Organize complex tests with the Page pattern
|
||||
2. **Use database traits**: Choose between `DatabaseMigrations` or `DatabaseTruncation`
|
||||
3. **Create browser macros**: Define reusable methods for common workflows
|
||||
4. **Test authentication**: Use `loginAs()` to bypass login screens
|
||||
5. **Handle JavaScript**: Use `waitUntil()` for dynamic content and AJAX
|
||||
|
||||
### For Advanced Users
|
||||
|
||||
1. **Multi-browser testing**: Test real-time features with multiple browsers
|
||||
2. **Custom waiting logic**: Use `waitUsing()` for complex conditions
|
||||
3. **Component pattern**: Create reusable components for shared UI elements
|
||||
4. **CI/CD integration**: Set up Dusk in GitHub Actions, Travis CI, or other platforms
|
||||
5. **Alternative drivers**: Configure Selenium Grid or other browsers beyond ChromeDriver
|
||||
|
||||
### Navigation Tips
|
||||
|
||||
- **Quick examples**: Check the Quick Reference section above for common patterns
|
||||
- **Method documentation**: See `other.md` for complete API reference
|
||||
- **Assertions list**: Reference file contains all 70+ available assertions
|
||||
- **Configuration**: Check reference file for environment setup and driver options
|
||||
- **Best practices**: Look for "Best Practices" section in reference documentation
|
||||
|
||||
## Installation & Setup
|
||||
|
||||
```bash
|
||||
# Install Laravel Dusk
|
||||
composer require laravel/dusk --dev
|
||||
|
||||
# Run installation
|
||||
php artisan dusk:install
|
||||
|
||||
# Update ChromeDriver
|
||||
php artisan dusk:chrome-driver
|
||||
|
||||
# Make binaries executable (Unix)
|
||||
chmod -R 0755 vendor/laravel/dusk/bin/
|
||||
|
||||
# Run tests
|
||||
php artisan dusk
|
||||
```
|
||||
|
||||
## Common Commands
|
||||
|
||||
```bash
|
||||
# Generate new test
|
||||
php artisan dusk:make LoginTest
|
||||
|
||||
# Generate page object
|
||||
php artisan dusk:page Dashboard
|
||||
|
||||
# Generate component
|
||||
php artisan dusk:component Modal
|
||||
|
||||
# Run all tests
|
||||
php artisan dusk
|
||||
|
||||
# Run specific test
|
||||
php artisan dusk tests/Browser/LoginTest.php
|
||||
|
||||
# Run failed tests only
|
||||
php artisan dusk:fails
|
||||
|
||||
# Run with filter
|
||||
php artisan dusk --group=authentication
|
||||
|
||||
# Update ChromeDriver
|
||||
php artisan dusk:chrome-driver --detect
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
### Official Documentation
|
||||
- Laravel Dusk Documentation: https://laravel.com/docs/12.x/dusk
|
||||
- API Reference: See `references/other.md` for complete method listings
|
||||
|
||||
### Common Patterns in Reference Files
|
||||
|
||||
The reference documentation includes:
|
||||
- 70+ assertion methods with descriptions
|
||||
- Complete form interaction API
|
||||
- Waiting strategies and timing best practices
|
||||
- Page Object pattern examples
|
||||
- Browser macro definitions
|
||||
- CI/CD configuration examples
|
||||
- Environment-specific test setup
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Use Dusk selectors** (`dusk` attributes) instead of CSS classes for stability
|
||||
2. **Wait explicitly** with `waitFor()` methods instead of arbitrary `pause()`
|
||||
3. **Organize with Page Objects** for complex test scenarios
|
||||
4. **Leverage database truncation** for faster test execution
|
||||
5. **Create browser macros** for frequently repeated actions
|
||||
6. **Scope selectors** with `with()` or `elsewhere()` for specific page regions
|
||||
7. **Test user behavior** rather than implementation details
|
||||
8. **Use authentication shortcuts** like `loginAs()` to skip login flows
|
||||
9. **Take screenshots** with `screenshot()` for debugging failures
|
||||
10. **Group related tests** and use `--group` flag for targeted execution
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
**ChromeDriver version mismatch:**
|
||||
```bash
|
||||
php artisan dusk:chrome-driver --detect
|
||||
```
|
||||
|
||||
**Elements not found:**
|
||||
- Use `waitFor('.selector')` before interacting
|
||||
- Check if element is in an iframe
|
||||
- Verify selector with browser dev tools
|
||||
|
||||
**Tests failing randomly:**
|
||||
- Replace `pause()` with explicit waits
|
||||
- Increase timeout: `waitFor('.selector', 10)`
|
||||
- Use `waitUntil()` for JavaScript conditions
|
||||
|
||||
**Database state issues:**
|
||||
- Use `DatabaseTruncation` trait
|
||||
- Reset data in `setUp()` method
|
||||
- Check for transactions in application code
|
||||
|
||||
## Notes
|
||||
|
||||
- Laravel Dusk uses ChromeDriver by default (no Selenium/JDK required)
|
||||
- Supports alternative browsers via Selenium WebDriver protocol
|
||||
- Tests are stored in `tests/Browser` directory
|
||||
- Page objects go in `tests/Browser/Pages`
|
||||
- Screenshots saved to `tests/Browser/screenshots` on failure
|
||||
- Console logs saved to `tests/Browser/console` for debugging
|
||||
15
skills/laravel-dusk/plugin.json
Normal file
15
skills/laravel-dusk/plugin.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "laravel-dusk",
|
||||
"description": "Interacts with the Laravel Dusk Package for Laravel.",
|
||||
"version": "1.0.0",
|
||||
"author": {
|
||||
"name": "Tim Green",
|
||||
"email": "rawveg@gmail.com"
|
||||
},
|
||||
"homepage": "https://github.com/rawveg/claude-skills-marketplace",
|
||||
"repository": "https://github.com/rawveg/claude-skills-marketplace",
|
||||
"license": "MIT",
|
||||
"keywords": ["laravel-dusk", "laravel", "Claude Code"],
|
||||
"category": "productivity",
|
||||
"strict": false
|
||||
}
|
||||
7
skills/laravel-dusk/references/index.md
Normal file
7
skills/laravel-dusk/references/index.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Laravel-Dusk Documentation Index
|
||||
|
||||
## Categories
|
||||
|
||||
### Other
|
||||
**File:** `other.md`
|
||||
**Pages:** 1
|
||||
11
skills/laravel-dusk/references/other.md
Normal file
11
skills/laravel-dusk/references/other.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Laravel-Dusk - Other
|
||||
|
||||
**Pages:** 1
|
||||
|
||||
---
|
||||
|
||||
## Laravel Dusk - Laravel 12.x - The PHP Framework For Web Artisans
|
||||
|
||||
**URL:** https://laravel.com/docs/12.x/dusk
|
||||
|
||||
---
|
||||
448
skills/laravel-mcp/SKILL.md
Normal file
448
skills/laravel-mcp/SKILL.md
Normal file
@@ -0,0 +1,448 @@
|
||||
---
|
||||
name: laravel-mcp
|
||||
description: Laravel v12 - The PHP Framework For Web Artisans (project, gitignored)
|
||||
---
|
||||
|
||||
# Laravel MCP Skill
|
||||
|
||||
Comprehensive assistance with Laravel MCP (Model Context Protocol) development. Laravel MCP provides a simple and elegant way for AI clients to interact with your Laravel application through the Model Context Protocol, enabling you to define servers, tools, resources, and prompts for AI-powered interactions.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
This skill should be triggered when:
|
||||
- Building MCP servers for Laravel applications
|
||||
- Creating AI tools that perform actions in Laravel
|
||||
- Defining reusable prompts for AI interactions
|
||||
- Exposing Laravel resources (data/content) to AI clients
|
||||
- Implementing OAuth 2.1 or Sanctum authentication for MCP
|
||||
- Registering and configuring MCP routes (web or local)
|
||||
- Testing MCP servers and tools
|
||||
- Working with Laravel JSON Schema builder for tool inputs
|
||||
- Implementing streaming responses or progress notifications
|
||||
- Building AI-powered Laravel features using MCP
|
||||
|
||||
## Key Concepts
|
||||
|
||||
### Core Components
|
||||
|
||||
**MCP Server**: The central communication point that exposes MCP capabilities. Each server has:
|
||||
- `name`: Server identifier
|
||||
- `version`: Server version
|
||||
- `instructions`: Description of the server's purpose
|
||||
- `tools`: Array of tool classes
|
||||
- `resources`: Array of resource classes
|
||||
- `prompts`: Array of prompt classes
|
||||
|
||||
**Tools**: Enable AI clients to perform actions. Tools can:
|
||||
- Define input schemas using Laravel's JSON Schema builder
|
||||
- Validate arguments with Laravel validation rules
|
||||
- Support dependency injection
|
||||
- Return single or multiple responses
|
||||
- Stream responses using generators
|
||||
- Use annotations like `#[IsReadOnly]` and `#[IsIdempotent]`
|
||||
|
||||
**Prompts**: Reusable prompt templates that provide a standardized way to structure common queries with argument definitions and validation.
|
||||
|
||||
**Resources**: Enable your server to expose data and content that AI clients can read, including text and blob responses with customizable MIME types and URIs.
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### 1. Basic MCP Server Definition
|
||||
|
||||
```php
|
||||
<?php
|
||||
namespace App\Mcp\Servers;
|
||||
|
||||
use Laravel\Mcp\Server;
|
||||
|
||||
class WeatherServer extends Server
|
||||
{
|
||||
protected string $name = 'Weather Server';
|
||||
protected string $version = '1.0.0';
|
||||
protected string $instructions = 'This server provides weather information and forecasts.';
|
||||
|
||||
protected array $tools = [
|
||||
// CurrentWeatherTool::class,
|
||||
];
|
||||
|
||||
protected array $resources = [
|
||||
// WeatherGuidelinesResource::class,
|
||||
];
|
||||
|
||||
protected array $prompts = [
|
||||
// DescribeWeatherPrompt::class,
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Tool with Input Schema
|
||||
|
||||
```php
|
||||
<?php
|
||||
namespace App\Mcp\Tools;
|
||||
|
||||
use Illuminate\JsonSchema\JsonSchema;
|
||||
use Laravel\Mcp\Request;
|
||||
use Laravel\Mcp\Response;
|
||||
use Laravel\Mcp\Server\Tool;
|
||||
|
||||
class CurrentWeatherTool extends Tool
|
||||
{
|
||||
protected string $description = 'Fetches the current weather forecast for a specified location.';
|
||||
|
||||
public function handle(Request $request): Response
|
||||
{
|
||||
$location = $request->get('location');
|
||||
// Get weather...
|
||||
return Response::text('The weather is...');
|
||||
}
|
||||
|
||||
public function schema(JsonSchema $schema): array
|
||||
{
|
||||
return [
|
||||
'location' => $schema->string()
|
||||
->description('The location to get the weather for.')
|
||||
->required(),
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Tool with Validation
|
||||
|
||||
```php
|
||||
public function handle(Request $request): Response
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'location' => 'required|string|max:100',
|
||||
'units' => 'in:celsius,fahrenheit',
|
||||
], [
|
||||
'location.required' => 'You must specify a location.',
|
||||
'units.in' => 'You must specify either "celsius" or "fahrenheit".',
|
||||
]);
|
||||
// Fetch weather data...
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Tool with Dependency Injection
|
||||
|
||||
```php
|
||||
<?php
|
||||
namespace App\Mcp\Tools;
|
||||
|
||||
use App\Repositories\WeatherRepository;
|
||||
use Laravel\Mcp\Request;
|
||||
use Laravel\Mcp\Response;
|
||||
use Laravel\Mcp\Server\Tool;
|
||||
|
||||
class CurrentWeatherTool extends Tool
|
||||
{
|
||||
public function __construct(
|
||||
protected WeatherRepository $weather,
|
||||
) {}
|
||||
|
||||
public function handle(Request $request, WeatherRepository $weather): Response
|
||||
{
|
||||
$location = $request->get('location');
|
||||
$forecast = $weather->getForecastFor($location);
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Tool with Annotations
|
||||
|
||||
```php
|
||||
<?php
|
||||
namespace App\Mcp\Tools;
|
||||
|
||||
use Laravel\Mcp\Server\Tools\Annotations\IsIdempotent;
|
||||
use Laravel\Mcp\Server\Tools\Annotations\IsReadOnly;
|
||||
use Laravel\Mcp\Server\Tool;
|
||||
|
||||
#[IsIdempotent]
|
||||
#[IsReadOnly]
|
||||
class CurrentWeatherTool extends Tool
|
||||
{
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### 6. Streaming Tool Response
|
||||
|
||||
```php
|
||||
<?php
|
||||
namespace App\Mcp\Tools;
|
||||
|
||||
use Generator;
|
||||
use Laravel\Mcp\Request;
|
||||
use Laravel\Mcp\Response;
|
||||
use Laravel\Mcp\Server\Tool;
|
||||
|
||||
class CurrentWeatherTool extends Tool
|
||||
{
|
||||
public function handle(Request $request): Generator
|
||||
{
|
||||
$locations = $request->array('locations');
|
||||
|
||||
foreach ($locations as $index => $location) {
|
||||
yield Response::notification('processing/progress', [
|
||||
'current' => $index + 1,
|
||||
'total' => count($locations),
|
||||
'location' => $location,
|
||||
]);
|
||||
yield Response::text($this->forecastFor($location));
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 7. Prompt Definition
|
||||
|
||||
```php
|
||||
<?php
|
||||
namespace App\Mcp\Prompts;
|
||||
|
||||
use Laravel\Mcp\Server\Prompt;
|
||||
use Laravel\Mcp\Server\Prompts\Argument;
|
||||
|
||||
class DescribeWeatherPrompt extends Prompt
|
||||
{
|
||||
protected string $description = 'Generates a natural-language explanation of the weather.';
|
||||
|
||||
public function arguments(): array
|
||||
{
|
||||
return [
|
||||
new Argument(
|
||||
name: 'tone',
|
||||
description: 'The tone to use in the weather description.',
|
||||
required: true,
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
public function handle(Request $request): array
|
||||
{
|
||||
$tone = $request->string('tone');
|
||||
return [
|
||||
Response::text("You are a weather assistant. Provide a {$tone} tone.")->asAssistant(),
|
||||
Response::text("What is the current weather like in New York City?"),
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 8. Resource Definition
|
||||
|
||||
```php
|
||||
<?php
|
||||
namespace App\Mcp\Resources;
|
||||
|
||||
use Laravel\Mcp\Request;
|
||||
use Laravel\Mcp\Response;
|
||||
use Laravel\Mcp\Server\Resource;
|
||||
|
||||
class WeatherGuidelinesResource extends Resource
|
||||
{
|
||||
protected string $description = 'Comprehensive guidelines for using the Weather API.';
|
||||
protected string $uri = 'weather://resources/guidelines';
|
||||
protected string $mimeType = 'application/pdf';
|
||||
|
||||
public function handle(Request $request): Response
|
||||
{
|
||||
return Response::text($weatherData);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 9. Server Registration (Web)
|
||||
|
||||
```php
|
||||
use App\Mcp\Servers\WeatherServer;
|
||||
use Laravel\Mcp\Facades\Mcp;
|
||||
|
||||
Mcp::web('/mcp/weather', WeatherServer::class);
|
||||
|
||||
// With middleware
|
||||
Mcp::web('/mcp/weather', WeatherServer::class)
|
||||
->middleware(['throttle:mcp']);
|
||||
```
|
||||
|
||||
### 10. Server Registration (Local)
|
||||
|
||||
```php
|
||||
use App\Mcp\Servers\WeatherServer;
|
||||
use Laravel\Mcp\Facades\Mcp;
|
||||
|
||||
Mcp::local('weather', WeatherServer::class);
|
||||
```
|
||||
|
||||
### 11. OAuth 2.1 Authentication Setup
|
||||
|
||||
```php
|
||||
use App\Mcp\Servers\WeatherExample;
|
||||
use Laravel\Mcp\Facades\Mcp;
|
||||
|
||||
Mcp::oauthRoutes();
|
||||
|
||||
Mcp::web('/mcp/weather', WeatherExample::class)
|
||||
->middleware('auth:api');
|
||||
```
|
||||
|
||||
### 12. Sanctum Authentication
|
||||
|
||||
```php
|
||||
use App\Mcp\Servers\WeatherExample;
|
||||
use Laravel\Mcp\Facades\Mcp;
|
||||
|
||||
Mcp::web('/mcp/demo', WeatherExample::class)
|
||||
->middleware('auth:sanctum');
|
||||
```
|
||||
|
||||
## Reference Files
|
||||
|
||||
This skill includes comprehensive documentation in `references/`:
|
||||
|
||||
- **other.md** - Complete Laravel MCP documentation from Laravel 12.x official docs, including:
|
||||
- Installation and setup instructions
|
||||
- Server, tool, resource, and prompt creation
|
||||
- Input schema definition using JSON Schema builder
|
||||
- Validation and dependency injection
|
||||
- Streaming responses and progress notifications
|
||||
- Authentication (OAuth 2.1 and Sanctum)
|
||||
- Registration (web and local routes)
|
||||
- Testing and inspection
|
||||
|
||||
Use `view` to read specific reference files when detailed information is needed.
|
||||
|
||||
## Working with This Skill
|
||||
|
||||
### For Beginners
|
||||
|
||||
Start by understanding the core concepts:
|
||||
1. **Installation**: Install Laravel MCP via `composer require laravel/mcp`
|
||||
2. **Setup**: Run `php artisan vendor:publish --tag=ai-routes` to create `routes/ai.php`
|
||||
3. **First Server**: Generate your first server with `php artisan make:mcp-server`
|
||||
4. **Register**: Add your server to `routes/ai.php` using `Mcp::web()` or `Mcp::local()`
|
||||
|
||||
Begin with simple read-only tools using the `#[IsReadOnly]` annotation before moving to tools that modify data.
|
||||
|
||||
### For Intermediate Users
|
||||
|
||||
Focus on building robust tools:
|
||||
- Use JSON Schema builder for precise input validation
|
||||
- Leverage Laravel's validation rules for complex constraints
|
||||
- Implement dependency injection for clean, testable code
|
||||
- Use prompts to create reusable AI interaction patterns
|
||||
- Expose resources to provide context to AI clients
|
||||
|
||||
### For Advanced Users
|
||||
|
||||
Implement production-ready features:
|
||||
- Add OAuth 2.1 or Sanctum authentication to secure your MCP servers
|
||||
- Use streaming responses for long-running operations with progress notifications
|
||||
- Apply middleware for rate limiting and custom authentication
|
||||
- Create idempotent tools using `#[IsIdempotent]` annotation
|
||||
- Build complex multi-tool workflows
|
||||
- Use the MCP Inspector for debugging and testing
|
||||
|
||||
### Navigation Tips
|
||||
|
||||
- **Quick implementation**: Use the Quick Reference section above for common patterns
|
||||
- **Detailed learning**: Read `references/other.md` for comprehensive documentation
|
||||
- **Examples**: All code examples include proper namespaces and imports
|
||||
- **Testing**: Refer to documentation for MCP Inspector usage and unit testing
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Creating a New MCP Server
|
||||
|
||||
```bash
|
||||
# Generate server class
|
||||
php artisan make:mcp-server WeatherServer
|
||||
|
||||
# Edit app/Mcp/Servers/WeatherServer.php
|
||||
# Add tools, resources, and prompts
|
||||
|
||||
# Register in routes/ai.php
|
||||
Mcp::web('/mcp/weather', WeatherServer::class);
|
||||
```
|
||||
|
||||
### Input Schema Patterns
|
||||
|
||||
```php
|
||||
// Simple required string
|
||||
'location' => $schema->string()->required()
|
||||
|
||||
// Optional with default
|
||||
'units' => $schema->string()->default('celsius')
|
||||
|
||||
// Number with constraints
|
||||
'temperature' => $schema->number()->minimum(0)->maximum(100)
|
||||
|
||||
// Array of items
|
||||
'cities' => $schema->array()->items($schema->string())
|
||||
|
||||
// Object with properties
|
||||
'forecast' => $schema->object()->properties([
|
||||
'temperature' => $schema->number(),
|
||||
'humidity' => $schema->number(),
|
||||
])
|
||||
```
|
||||
|
||||
### Response Patterns
|
||||
|
||||
```php
|
||||
// Text response
|
||||
return Response::text('The weather is sunny');
|
||||
|
||||
// Multiple responses
|
||||
return [
|
||||
Response::text('First message'),
|
||||
Response::text('Second message'),
|
||||
];
|
||||
|
||||
// Notification (streaming)
|
||||
yield Response::notification('processing/progress', ['status' => 'processing']);
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
### Installation
|
||||
|
||||
```bash
|
||||
composer require laravel/mcp
|
||||
php artisan vendor:publish --tag=ai-routes
|
||||
```
|
||||
|
||||
### Official Documentation
|
||||
|
||||
- **Laravel MCP Docs**: https://laravel.com/docs/12.x/mcp
|
||||
- **Model Context Protocol Spec**: https://modelcontextprotocol.io/
|
||||
|
||||
### Related Laravel Features
|
||||
|
||||
- **JSON Schema Builder**: For defining tool input schemas
|
||||
- **Validation**: For validating tool arguments
|
||||
- **Service Container**: For dependency injection in tools and resources
|
||||
- **OAuth/Sanctum**: For authentication
|
||||
|
||||
## Notes
|
||||
|
||||
- This skill was generated from official Laravel 12.x MCP documentation
|
||||
- All code examples use proper PHP 8+ syntax with typed properties
|
||||
- Examples demonstrate Laravel's elegant API design
|
||||
- Tools support both synchronous and streaming responses
|
||||
- Authentication is optional but recommended for production use
|
||||
- Both web (HTTP) and local (CLI) server registration are supported
|
||||
|
||||
## Tips & Best Practices
|
||||
|
||||
1. **Start Simple**: Begin with read-only tools marked with `#[IsReadOnly]`
|
||||
2. **Validate Input**: Always define schemas and use validation for user input
|
||||
3. **Use DI**: Leverage dependency injection for repositories and services
|
||||
4. **Stream Progress**: For long operations, use generators to stream progress
|
||||
5. **Secure Your Servers**: Add authentication middleware for production
|
||||
6. **Test Thoroughly**: Use the MCP Inspector and unit tests to validate functionality
|
||||
7. **Document Well**: Write clear descriptions for servers, tools, prompts, and resources
|
||||
8. **Follow Conventions**: Use Laravel's service container patterns and naming conventions
|
||||
15
skills/laravel-mcp/plugin.json
Normal file
15
skills/laravel-mcp/plugin.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "laravel-mcp",
|
||||
"description": "Interacts with the Laravel MCP Package for Laravel.",
|
||||
"version": "1.0.0",
|
||||
"author": {
|
||||
"name": "Tim Green",
|
||||
"email": "rawveg@gmail.com"
|
||||
},
|
||||
"homepage": "https://github.com/rawveg/claude-skills-marketplace",
|
||||
"repository": "https://github.com/rawveg/claude-skills-marketplace",
|
||||
"license": "MIT",
|
||||
"keywords": ["laravel-mcp", "laravel", "Claude Code"],
|
||||
"category": "productivity",
|
||||
"strict": false
|
||||
}
|
||||
7
skills/laravel-mcp/references/index.md
Normal file
7
skills/laravel-mcp/references/index.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Laravel-Mcp Documentation Index
|
||||
|
||||
## Categories
|
||||
|
||||
### Other
|
||||
**File:** `other.md`
|
||||
**Pages:** 1
|
||||
11
skills/laravel-mcp/references/other.md
Normal file
11
skills/laravel-mcp/references/other.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Laravel-Mcp - Other
|
||||
|
||||
**Pages:** 1
|
||||
|
||||
---
|
||||
|
||||
## Laravel MCP - Laravel 12.x - The PHP Framework For Web Artisans
|
||||
|
||||
**URL:** https://laravel.com/docs/12.x/mcp
|
||||
|
||||
---
|
||||
546
skills/laravel-prompts/SKILL.md
Normal file
546
skills/laravel-prompts/SKILL.md
Normal file
@@ -0,0 +1,546 @@
|
||||
---
|
||||
name: laravel-prompts
|
||||
description: Laravel Prompts - Beautiful and user-friendly forms for command-line applications with browser-like features including placeholder text and validation
|
||||
---
|
||||
|
||||
# Laravel Prompts Skill
|
||||
|
||||
Laravel Prompts is a PHP package for adding beautiful and user-friendly forms to your command-line applications, with browser-like features including placeholder text and validation. It's pre-installed in Laravel and supports macOS, Linux, and Windows with WSL.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
This skill should be triggered when:
|
||||
- Building Laravel Artisan commands with interactive prompts
|
||||
- Creating user-friendly CLI applications in PHP
|
||||
- Implementing form validation in command-line tools
|
||||
- Adding text input, select menus, or confirmation dialogs to console commands
|
||||
- Working with progress bars, loading spinners, or tables in CLI applications
|
||||
- Testing Laravel console commands with prompts
|
||||
- Converting simple console input to modern, validated, interactive prompts
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Basic Text Input
|
||||
|
||||
```php
|
||||
use function Laravel\Prompts\text;
|
||||
|
||||
// Simple text input
|
||||
$name = text('What is your name?');
|
||||
|
||||
// With placeholder and validation
|
||||
$name = text(
|
||||
label: 'What is your name?',
|
||||
placeholder: 'E.g. Taylor Otwell',
|
||||
required: true,
|
||||
validate: fn (string $value) => match (true) {
|
||||
strlen($value) < 3 => 'The name must be at least 3 characters.',
|
||||
strlen($value) > 255 => 'The name must not exceed 255 characters.',
|
||||
default => null
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
### Password Input
|
||||
|
||||
```php
|
||||
use function Laravel\Prompts\password;
|
||||
|
||||
$password = password(
|
||||
label: 'What is your password?',
|
||||
placeholder: 'password',
|
||||
hint: 'Minimum 8 characters.',
|
||||
required: true,
|
||||
validate: fn (string $value) => match (true) {
|
||||
strlen($value) < 8 => 'The password must be at least 8 characters.',
|
||||
default => null
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
### Select (Single Choice)
|
||||
|
||||
```php
|
||||
use function Laravel\Prompts\select;
|
||||
|
||||
// Simple select
|
||||
$role = select(
|
||||
label: 'What role should the user have?',
|
||||
options: ['Member', 'Contributor', 'Owner']
|
||||
);
|
||||
|
||||
// With associative array (returns key)
|
||||
$role = select(
|
||||
label: 'What role should the user have?',
|
||||
options: [
|
||||
'member' => 'Member',
|
||||
'contributor' => 'Contributor',
|
||||
'owner' => 'Owner',
|
||||
],
|
||||
default: 'owner'
|
||||
);
|
||||
|
||||
// From database with custom scroll
|
||||
$role = select(
|
||||
label: 'Which category would you like to assign?',
|
||||
options: Category::pluck('name', 'id'),
|
||||
scroll: 10
|
||||
);
|
||||
```
|
||||
|
||||
### Multiselect (Multiple Choices)
|
||||
|
||||
```php
|
||||
use function Laravel\Prompts\multiselect;
|
||||
|
||||
$permissions = multiselect(
|
||||
label: 'What permissions should be assigned?',
|
||||
options: ['Read', 'Create', 'Update', 'Delete'],
|
||||
default: ['Read', 'Create'],
|
||||
hint: 'Permissions may be updated at any time.'
|
||||
);
|
||||
|
||||
// With validation
|
||||
$permissions = multiselect(
|
||||
label: 'What permissions should the user have?',
|
||||
options: [
|
||||
'read' => 'Read',
|
||||
'create' => 'Create',
|
||||
'update' => 'Update',
|
||||
'delete' => 'Delete',
|
||||
],
|
||||
validate: fn (array $values) => ! in_array('read', $values)
|
||||
? 'All users require the read permission.'
|
||||
: null
|
||||
);
|
||||
```
|
||||
|
||||
### Confirmation Dialog
|
||||
|
||||
```php
|
||||
use function Laravel\Prompts\confirm;
|
||||
|
||||
// Simple yes/no
|
||||
$confirmed = confirm('Do you accept the terms?');
|
||||
|
||||
// With custom labels
|
||||
$confirmed = confirm(
|
||||
label: 'Do you accept the terms?',
|
||||
default: false,
|
||||
yes: 'I accept',
|
||||
no: 'I decline',
|
||||
hint: 'The terms must be accepted to continue.'
|
||||
);
|
||||
|
||||
// Require "Yes"
|
||||
$confirmed = confirm(
|
||||
label: 'Do you accept the terms?',
|
||||
required: true
|
||||
);
|
||||
```
|
||||
|
||||
### Search (Searchable Select)
|
||||
|
||||
```php
|
||||
use function Laravel\Prompts\search;
|
||||
|
||||
$id = search(
|
||||
label: 'Search for the user that should receive the mail',
|
||||
placeholder: 'E.g. Taylor Otwell',
|
||||
options: fn (string $value) => strlen($value) > 0
|
||||
? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
|
||||
: [],
|
||||
hint: 'The user will receive an email immediately.',
|
||||
scroll: 10
|
||||
);
|
||||
```
|
||||
|
||||
### Suggest (Auto-completion)
|
||||
|
||||
```php
|
||||
use function Laravel\Prompts\suggest;
|
||||
|
||||
// Static options
|
||||
$name = suggest('What is your name?', ['Taylor', 'Dayle']);
|
||||
|
||||
// Dynamic filtering
|
||||
$name = suggest(
|
||||
label: 'What is your name?',
|
||||
options: fn ($value) => collect(['Taylor', 'Dayle'])
|
||||
->filter(fn ($name) => Str::contains($name, $value, ignoreCase: true))
|
||||
);
|
||||
```
|
||||
|
||||
### Multi-step Forms
|
||||
|
||||
```php
|
||||
use function Laravel\Prompts\form;
|
||||
|
||||
$responses = form()
|
||||
->text('What is your name?', required: true, name: 'name')
|
||||
->password(
|
||||
label: 'What is your password?',
|
||||
validate: ['password' => 'min:8'],
|
||||
name: 'password'
|
||||
)
|
||||
->confirm('Do you accept the terms?')
|
||||
->submit();
|
||||
|
||||
// Access named responses
|
||||
echo $responses['name'];
|
||||
echo $responses['password'];
|
||||
|
||||
// Dynamic forms with previous responses
|
||||
$responses = form()
|
||||
->text('What is your name?', required: true, name: 'name')
|
||||
->add(function ($responses) {
|
||||
return text("How old are you, {$responses['name']}?");
|
||||
}, name: 'age')
|
||||
->submit();
|
||||
```
|
||||
|
||||
### Progress Bar
|
||||
|
||||
```php
|
||||
use function Laravel\Prompts\progress;
|
||||
|
||||
// Simple usage
|
||||
$users = progress(
|
||||
label: 'Updating users',
|
||||
steps: User::all(),
|
||||
callback: fn ($user) => $this->performTask($user)
|
||||
);
|
||||
|
||||
// With dynamic labels
|
||||
$users = progress(
|
||||
label: 'Updating users',
|
||||
steps: User::all(),
|
||||
callback: function ($user, $progress) {
|
||||
$progress
|
||||
->label("Updating {$user->name}")
|
||||
->hint("Created on {$user->created_at}");
|
||||
return $this->performTask($user);
|
||||
},
|
||||
hint: 'This may take some time.'
|
||||
);
|
||||
```
|
||||
|
||||
### Loading Spinner
|
||||
|
||||
```php
|
||||
use function Laravel\Prompts\spin;
|
||||
|
||||
$response = spin(
|
||||
callback: fn () => Http::get('http://example.com'),
|
||||
message: 'Fetching response...'
|
||||
);
|
||||
```
|
||||
|
||||
## Key Concepts
|
||||
|
||||
### Input Types
|
||||
|
||||
Laravel Prompts provides several input types for different use cases:
|
||||
|
||||
- **text()** - Single-line text input with optional placeholder and validation
|
||||
- **textarea()** - Multi-line text input for longer content
|
||||
- **password()** - Masked text input for sensitive data
|
||||
- **confirm()** - Yes/No confirmation dialog
|
||||
- **select()** - Single selection from a list of options
|
||||
- **multiselect()** - Multiple selections from a list
|
||||
- **suggest()** - Text input with auto-completion suggestions
|
||||
- **search()** - Searchable single selection with dynamic options
|
||||
- **multisearch()** - Searchable multiple selections
|
||||
- **pause()** - Pause execution until user presses ENTER
|
||||
|
||||
### Output Types
|
||||
|
||||
For displaying information without input:
|
||||
|
||||
- **info()** - Display informational message
|
||||
- **note()** - Display a note
|
||||
- **warning()** - Display warning message
|
||||
- **error()** - Display error message
|
||||
- **alert()** - Display alert message
|
||||
- **table()** - Display tabular data
|
||||
|
||||
### Validation
|
||||
|
||||
Three ways to validate prompts:
|
||||
|
||||
1. **Closure validation**: Custom logic with match expressions
|
||||
```php
|
||||
validate: fn (string $value) => match (true) {
|
||||
strlen($value) < 3 => 'Too short.',
|
||||
default => null
|
||||
}
|
||||
```
|
||||
|
||||
2. **Laravel validation rules**: Standard Laravel validation
|
||||
```php
|
||||
validate: ['email' => 'required|email|unique:users']
|
||||
```
|
||||
|
||||
3. **Required flag**: Simple requirement check
|
||||
```php
|
||||
required: true
|
||||
```
|
||||
|
||||
### Transformation
|
||||
|
||||
Use the `transform` parameter to modify input before validation:
|
||||
|
||||
```php
|
||||
$name = text(
|
||||
label: 'What is your name?',
|
||||
transform: fn (string $value) => trim($value),
|
||||
validate: fn (string $value) => strlen($value) < 3
|
||||
? 'The name must be at least 3 characters.'
|
||||
: null
|
||||
);
|
||||
```
|
||||
|
||||
### Terminal Features
|
||||
|
||||
- **Scrolling**: Configure visible items with `scroll` parameter (default: 5)
|
||||
- **Navigation**: Use arrow keys, j/k keys, or vim-style navigation
|
||||
- **Forms**: Press CTRL + U in forms to return to previous prompts
|
||||
- **Width**: Keep labels under 74 characters for 80-character terminals
|
||||
|
||||
## Reference Files
|
||||
|
||||
This skill includes comprehensive documentation in `references/`:
|
||||
|
||||
- **other.md** - Complete Laravel Prompts documentation including:
|
||||
- All prompt types (text, password, select, search, etc.)
|
||||
- Validation strategies and examples
|
||||
- Form API for multi-step input
|
||||
- Progress bars and loading indicators
|
||||
- Informational messages (info, warning, error, alert)
|
||||
- Tables for displaying data
|
||||
- Testing strategies for console commands
|
||||
- Fallback configuration for unsupported environments
|
||||
|
||||
Use `view` to read the reference file when detailed information is needed.
|
||||
|
||||
## Working with This Skill
|
||||
|
||||
### For Beginners
|
||||
|
||||
Start with basic prompts:
|
||||
1. Use `text()` for simple input
|
||||
2. Add `required: true` for mandatory fields
|
||||
3. Try `confirm()` for yes/no questions
|
||||
4. Use `select()` for predefined choices
|
||||
|
||||
Example beginner command:
|
||||
```php
|
||||
$name = text('What is your name?', required: true);
|
||||
$confirmed = confirm('Is this correct?');
|
||||
if ($confirmed) {
|
||||
$this->info("Hello, {$name}!");
|
||||
}
|
||||
```
|
||||
|
||||
### For Intermediate Users
|
||||
|
||||
Combine multiple prompts and add validation:
|
||||
1. Use the `form()` API for multi-step input
|
||||
2. Add custom validation with closures
|
||||
3. Use `search()` for database queries
|
||||
4. Implement progress bars for long operations
|
||||
|
||||
Example intermediate command:
|
||||
```php
|
||||
$responses = form()
|
||||
->text('Name', required: true, name: 'name')
|
||||
->select('Role', options: ['Member', 'Admin'], name: 'role')
|
||||
->confirm('Create user?')
|
||||
->submit();
|
||||
|
||||
if ($responses) {
|
||||
progress(
|
||||
label: 'Creating user',
|
||||
steps: 5,
|
||||
callback: fn () => sleep(1)
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### For Advanced Users
|
||||
|
||||
Leverage advanced features:
|
||||
1. Dynamic form fields based on previous responses
|
||||
2. Complex validation with Laravel validation rules
|
||||
3. Custom searchable prompts with database integration
|
||||
4. Transformation functions for data normalization
|
||||
5. Testing strategies for command prompts
|
||||
|
||||
Example advanced command:
|
||||
```php
|
||||
$responses = form()
|
||||
->text('Email', validate: ['email' => 'required|email|unique:users'], name: 'email')
|
||||
->add(function ($responses) {
|
||||
return search(
|
||||
label: 'Select manager',
|
||||
options: fn ($value) => User::where('email', 'like', "%{$value}%")
|
||||
->where('email', '!=', $responses['email'])
|
||||
->pluck('name', 'id')
|
||||
->all()
|
||||
);
|
||||
}, name: 'manager_id')
|
||||
->multiselect(
|
||||
label: 'Permissions',
|
||||
options: Permission::pluck('name', 'id'),
|
||||
validate: fn ($values) => count($values) === 0 ? 'Select at least one permission.' : null,
|
||||
name: 'permissions'
|
||||
)
|
||||
->submit();
|
||||
```
|
||||
|
||||
### Navigation Tips
|
||||
|
||||
- **Arrow keys** or **j/k** - Navigate options in select/multiselect
|
||||
- **Space** - Select/deselect in multiselect
|
||||
- **Enter** - Confirm selection or submit input
|
||||
- **CTRL + U** - Go back to previous prompt (in forms)
|
||||
- **Type to search** - In search/multisearch prompts
|
||||
- **Tab** - Auto-complete in suggest prompts
|
||||
|
||||
## Testing
|
||||
|
||||
Test commands with prompts using Laravel's built-in assertions:
|
||||
|
||||
```php
|
||||
use function Pest\Laravel\artisan;
|
||||
|
||||
test('user creation command', function () {
|
||||
artisan('users:create')
|
||||
->expectsQuestion('What is your name?', 'Taylor Otwell')
|
||||
->expectsQuestion('What is your email?', '[email protected]')
|
||||
->expectsConfirmation('Create this user?', 'yes')
|
||||
->expectsPromptsInfo('User created successfully!')
|
||||
->assertExitCode(0);
|
||||
});
|
||||
|
||||
test('displays warnings and errors', function () {
|
||||
artisan('report:generate')
|
||||
->expectsPromptsWarning('This action cannot be undone')
|
||||
->expectsPromptsError('Something went wrong')
|
||||
->expectsPromptsTable(
|
||||
headers: ['Name', 'Email'],
|
||||
rows: [
|
||||
['Taylor Otwell', '[email protected]'],
|
||||
['Jason Beggs', '[email protected]'],
|
||||
]
|
||||
)
|
||||
->assertExitCode(0);
|
||||
});
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Design Guidelines
|
||||
- Keep labels concise (under 74 characters for 80-column terminals)
|
||||
- Use `hint` parameter for additional context
|
||||
- Set appropriate `default` values when sensible
|
||||
- Configure `scroll` for lists with many options (default: 5)
|
||||
|
||||
### Validation Strategy
|
||||
- Use `required: true` for mandatory fields
|
||||
- Apply Laravel validation rules for standard checks (email, min/max, etc.)
|
||||
- Use closures for complex business logic validation
|
||||
- Provide clear, actionable error messages
|
||||
|
||||
### User Experience
|
||||
- Add placeholders to show expected input format
|
||||
- Use `pause()` before destructive operations
|
||||
- Show progress bars for operations taking >2 seconds
|
||||
- Display informational messages after actions complete
|
||||
- Group related prompts in forms for better flow
|
||||
|
||||
### Performance
|
||||
- Use `search()` callbacks with length checks to avoid expensive queries:
|
||||
```php
|
||||
options: fn (string $value) => strlen($value) > 0
|
||||
? User::where('name', 'like', "%{$value}%")->pluck('name', 'id')->all()
|
||||
: []
|
||||
```
|
||||
- Limit database results with pagination or top-N queries
|
||||
- Cache frequently-accessed option lists
|
||||
- Use `spin()` for HTTP requests and long operations
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### User Registration Flow
|
||||
```php
|
||||
$responses = form()
|
||||
->text('Name', required: true, name: 'name')
|
||||
->text('Email', validate: ['email' => 'required|email|unique:users'], name: 'email')
|
||||
->password('Password', validate: ['password' => 'required|min:8'], name: 'password')
|
||||
->submit();
|
||||
```
|
||||
|
||||
### Confirmation Before Destructive Action
|
||||
```php
|
||||
$confirmed = confirm(
|
||||
label: 'Are you sure you want to delete all users?',
|
||||
default: false,
|
||||
hint: 'This action cannot be undone.'
|
||||
);
|
||||
|
||||
if (! $confirmed) {
|
||||
$this->info('Operation cancelled.');
|
||||
return;
|
||||
}
|
||||
```
|
||||
|
||||
### Dynamic Multi-step Form
|
||||
```php
|
||||
$responses = form()
|
||||
->select('User type', options: ['Regular', 'Admin'], name: 'type')
|
||||
->add(function ($responses) {
|
||||
if ($responses['type'] === 'Admin') {
|
||||
return password('Admin password', required: true);
|
||||
}
|
||||
}, name: 'admin_password')
|
||||
->submit();
|
||||
```
|
||||
|
||||
### Batch Processing with Progress
|
||||
```php
|
||||
$items = Item::all();
|
||||
|
||||
$results = progress(
|
||||
label: 'Processing items',
|
||||
steps: $items,
|
||||
callback: function ($item, $progress) {
|
||||
$progress->hint("Processing: {$item->name}");
|
||||
return $this->process($item);
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
### Official Documentation
|
||||
- Laravel Prompts Documentation: https://laravel.com/docs/12.x/prompts
|
||||
- Laravel Console Testing: https://laravel.com/docs/12.x/console-tests
|
||||
|
||||
### Platform Support
|
||||
- **Supported**: macOS, Linux, Windows with WSL
|
||||
- **Fallback**: Configure fallback behavior for unsupported environments
|
||||
|
||||
## Notes
|
||||
|
||||
- Laravel Prompts is pre-installed in Laravel framework
|
||||
- Supports Laravel validation rules for easy integration
|
||||
- Uses terminal control codes for interactive UI
|
||||
- All prompts return values that can be used immediately
|
||||
- Forms support revisiting previous prompts with CTRL + U
|
||||
- Validation runs on every input change for immediate feedback
|
||||
- Progress bars can be manually controlled or automated
|
||||
|
||||
## Updating
|
||||
|
||||
This skill was generated from the official Laravel Prompts documentation. To refresh with updated information, re-scrape the Laravel documentation site.
|
||||
15
skills/laravel-prompts/plugin.json
Normal file
15
skills/laravel-prompts/plugin.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "laravel-prompts",
|
||||
"description": "Interacts with the Laravel Prompts Package for Laravel.",
|
||||
"version": "1.0.0",
|
||||
"author": {
|
||||
"name": "Tim Green",
|
||||
"email": "rawveg@gmail.com"
|
||||
},
|
||||
"homepage": "https://github.com/rawveg/claude-skills-marketplace",
|
||||
"repository": "https://github.com/rawveg/claude-skills-marketplace",
|
||||
"license": "MIT",
|
||||
"keywords": ["laravel-prompts", "laravel", "Claude Code"],
|
||||
"category": "productivity",
|
||||
"strict": false
|
||||
}
|
||||
7
skills/laravel-prompts/references/index.md
Normal file
7
skills/laravel-prompts/references/index.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Laravel-Prompts Documentation Index
|
||||
|
||||
## Categories
|
||||
|
||||
### Other
|
||||
**File:** `other.md`
|
||||
**Pages:** 1
|
||||
11
skills/laravel-prompts/references/other.md
Normal file
11
skills/laravel-prompts/references/other.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Laravel-Prompts - Other
|
||||
|
||||
**Pages:** 1
|
||||
|
||||
---
|
||||
|
||||
## Prompts - Laravel 12.x - The PHP Framework For Web Artisans
|
||||
|
||||
**URL:** https://laravel.com/docs/12.x/prompts
|
||||
|
||||
---
|
||||
521
skills/laravel/SKILL.md
Normal file
521
skills/laravel/SKILL.md
Normal file
@@ -0,0 +1,521 @@
|
||||
---
|
||||
name: laravel
|
||||
description: Laravel v12 - The PHP Framework For Web Artisans
|
||||
---
|
||||
|
||||
# Laravel Skill
|
||||
|
||||
Comprehensive assistance with Laravel 12.x development, including routing, Eloquent ORM, migrations, authentication, API development, and modern PHP patterns.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
This skill should be triggered when:
|
||||
- Building Laravel applications or APIs
|
||||
- Working with Eloquent models, relationships, and queries
|
||||
- Setting up authentication, authorization, or API tokens
|
||||
- Creating database migrations, seeders, or factories
|
||||
- Implementing middleware, service providers, or events
|
||||
- Using Laravel's built-in features (queues, cache, validation, etc.)
|
||||
- Troubleshooting Laravel errors or performance issues
|
||||
- Following Laravel best practices and conventions
|
||||
- Implementing RESTful APIs with Laravel Sanctum or Passport
|
||||
- Working with Laravel Mix, Vite, or frontend assets
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Basic Routing
|
||||
|
||||
```php
|
||||
// Basic routes
|
||||
Route::get('/users', [UserController::class, 'index']);
|
||||
Route::post('/users', [UserController::class, 'store']);
|
||||
|
||||
// Route parameters
|
||||
Route::get('/users/{id}', function ($id) {
|
||||
return User::find($id);
|
||||
});
|
||||
|
||||
// Named routes
|
||||
Route::get('/profile', ProfileController::class)->name('profile');
|
||||
|
||||
// Route groups with middleware
|
||||
Route::middleware(['auth'])->group(function () {
|
||||
Route::get('/dashboard', [DashboardController::class, 'index']);
|
||||
Route::resource('posts', PostController::class);
|
||||
});
|
||||
```
|
||||
|
||||
### Eloquent Model Basics
|
||||
|
||||
```php
|
||||
// Define a model with relationships
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class Post extends Model
|
||||
{
|
||||
protected $fillable = ['title', 'content', 'user_id'];
|
||||
|
||||
protected $casts = [
|
||||
'published_at' => 'datetime',
|
||||
];
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function comments(): HasMany
|
||||
{
|
||||
return $this->hasMany(Comment::class);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Database Migrations
|
||||
|
||||
```php
|
||||
// Create a migration
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('posts', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
|
||||
$table->string('title');
|
||||
$table->text('content');
|
||||
$table->timestamp('published_at')->nullable();
|
||||
$table->timestamps();
|
||||
|
||||
$table->index(['user_id', 'published_at']);
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('posts');
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### Form Validation
|
||||
|
||||
```php
|
||||
// Controller validation
|
||||
public function store(Request $request)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'title' => 'required|max:255',
|
||||
'content' => 'required',
|
||||
'email' => 'required|email|unique:users',
|
||||
'tags' => 'array|min:1',
|
||||
'tags.*' => 'string|max:50',
|
||||
]);
|
||||
|
||||
return Post::create($validated);
|
||||
}
|
||||
|
||||
// Form Request validation
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StorePostRequest extends FormRequest
|
||||
{
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'title' => 'required|max:255',
|
||||
'content' => 'required|min:100',
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Eloquent Query Builder
|
||||
|
||||
```php
|
||||
// Common query patterns
|
||||
// Eager loading to avoid N+1 queries
|
||||
$posts = Post::with(['user', 'comments'])
|
||||
->where('published_at', '<=', now())
|
||||
->orderBy('published_at', 'desc')
|
||||
->paginate(15);
|
||||
|
||||
// Conditional queries
|
||||
$query = Post::query();
|
||||
|
||||
if ($request->has('search')) {
|
||||
$query->where('title', 'like', "%{$request->search}%");
|
||||
}
|
||||
|
||||
if ($request->has('author')) {
|
||||
$query->whereHas('user', function ($q) use ($request) {
|
||||
$q->where('name', $request->author);
|
||||
});
|
||||
}
|
||||
|
||||
$posts = $query->get();
|
||||
```
|
||||
|
||||
### API Resource Controllers
|
||||
|
||||
```php
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Models\Post;
|
||||
use App\Http\Resources\PostResource;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class PostController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
return PostResource::collection(
|
||||
Post::with('user')->latest()->paginate()
|
||||
);
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$post = Post::create($request->validated());
|
||||
|
||||
return new PostResource($post);
|
||||
}
|
||||
|
||||
public function show(Post $post)
|
||||
{
|
||||
return new PostResource($post->load('user', 'comments'));
|
||||
}
|
||||
|
||||
public function update(Request $request, Post $post)
|
||||
{
|
||||
$post->update($request->validated());
|
||||
|
||||
return new PostResource($post);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### API Resources (Transformers)
|
||||
|
||||
```php
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class PostResource extends JsonResource
|
||||
{
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'title' => $this->title,
|
||||
'slug' => $this->slug,
|
||||
'excerpt' => $this->excerpt,
|
||||
'content' => $this->when($request->routeIs('posts.show'), $this->content),
|
||||
'author' => new UserResource($this->whenLoaded('user')),
|
||||
'comments_count' => $this->when($this->comments_count, $this->comments_count),
|
||||
'published_at' => $this->published_at?->toISOString(),
|
||||
'created_at' => $this->created_at->toISOString(),
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Authentication with Sanctum
|
||||
|
||||
```php
|
||||
// API token authentication setup
|
||||
// In config/sanctum.php - configure stateful domains
|
||||
|
||||
// Issue tokens
|
||||
use Laravel\Sanctum\HasApiTokens;
|
||||
|
||||
class User extends Authenticatable
|
||||
{
|
||||
use HasApiTokens;
|
||||
}
|
||||
|
||||
// Login endpoint
|
||||
public function login(Request $request)
|
||||
{
|
||||
$credentials = $request->validate([
|
||||
'email' => 'required|email',
|
||||
'password' => 'required',
|
||||
]);
|
||||
|
||||
if (!Auth::attempt($credentials)) {
|
||||
return response()->json(['message' => 'Invalid credentials'], 401);
|
||||
}
|
||||
|
||||
$token = $request->user()->createToken('api-token')->plainTextToken;
|
||||
|
||||
return response()->json(['token' => $token]);
|
||||
}
|
||||
|
||||
// Protect routes
|
||||
Route::middleware('auth:sanctum')->group(function () {
|
||||
Route::get('/user', fn(Request $r) => $r->user());
|
||||
});
|
||||
```
|
||||
|
||||
### Jobs and Queues
|
||||
|
||||
```php
|
||||
// Create a job
|
||||
namespace App\Jobs;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
|
||||
class ProcessVideo implements ShouldQueue
|
||||
{
|
||||
use InteractsWithQueue, Queueable;
|
||||
|
||||
public function __construct(
|
||||
public Video $video
|
||||
) {}
|
||||
|
||||
public function handle(): void
|
||||
{
|
||||
// Process the video
|
||||
$this->video->process();
|
||||
}
|
||||
}
|
||||
|
||||
// Dispatch jobs
|
||||
ProcessVideo::dispatch($video);
|
||||
ProcessVideo::dispatch($video)->onQueue('videos')->delay(now()->addMinutes(5));
|
||||
```
|
||||
|
||||
### Service Container and Dependency Injection
|
||||
|
||||
```php
|
||||
// Bind services in AppServiceProvider
|
||||
use App\Services\PaymentService;
|
||||
|
||||
public function register(): void
|
||||
{
|
||||
$this->app->singleton(PaymentService::class, function ($app) {
|
||||
return new PaymentService(
|
||||
config('services.stripe.secret')
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Use dependency injection in controllers
|
||||
public function __construct(
|
||||
protected PaymentService $payment
|
||||
) {}
|
||||
|
||||
public function charge(Request $request)
|
||||
{
|
||||
return $this->payment->charge(
|
||||
$request->user(),
|
||||
$request->amount
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Reference Files
|
||||
|
||||
This skill includes comprehensive documentation in `references/`:
|
||||
|
||||
- **other.md** - Laravel 12.x installation guide and core documentation
|
||||
|
||||
Use the reference files for detailed information about:
|
||||
- Installation and configuration
|
||||
- Framework architecture and concepts
|
||||
- Advanced features and packages
|
||||
- Deployment and optimization
|
||||
|
||||
## Key Concepts
|
||||
|
||||
### MVC Architecture
|
||||
Laravel follows the Model-View-Controller pattern:
|
||||
- **Models**: Eloquent ORM classes representing database tables
|
||||
- **Views**: Blade templates for rendering HTML
|
||||
- **Controllers**: Handle HTTP requests and return responses
|
||||
|
||||
### Eloquent ORM
|
||||
Laravel's powerful database abstraction layer:
|
||||
- **Active Record pattern**: Each model instance represents a database row
|
||||
- **Relationships**: belongsTo, hasMany, belongsToMany, morphMany, etc.
|
||||
- **Query Builder**: Fluent interface for building SQL queries
|
||||
- **Eager Loading**: Prevent N+1 query problems with `with()`
|
||||
|
||||
### Routing
|
||||
Define application endpoints:
|
||||
- **Route methods**: get, post, put, patch, delete
|
||||
- **Route parameters**: Required `{id}` and optional `{id?}`
|
||||
- **Route groups**: Share middleware, prefixes, namespaces
|
||||
- **Resource routes**: Auto-generate RESTful routes
|
||||
|
||||
### Middleware
|
||||
Filter HTTP requests:
|
||||
- **Built-in**: auth, throttle, verified, signed
|
||||
- **Custom**: Create your own request/response filters
|
||||
- **Global**: Apply to all routes
|
||||
- **Route-specific**: Apply to specific routes or groups
|
||||
|
||||
### Service Container
|
||||
Laravel's dependency injection container:
|
||||
- **Automatic resolution**: Type-hint dependencies in constructors
|
||||
- **Binding**: Register class implementations
|
||||
- **Singletons**: Share single instance across requests
|
||||
|
||||
### Artisan Commands
|
||||
Laravel's CLI tool:
|
||||
```bash
|
||||
php artisan make:model Post -mcr # Create model, migration, controller, resource
|
||||
php artisan migrate # Run migrations
|
||||
php artisan db:seed # Seed database
|
||||
php artisan queue:work # Process queue jobs
|
||||
php artisan optimize:clear # Clear all caches
|
||||
```
|
||||
|
||||
## Working with This Skill
|
||||
|
||||
### For Beginners
|
||||
Start with:
|
||||
1. **Installation**: Set up Laravel using Composer
|
||||
2. **Routing**: Learn basic route definitions in `routes/web.php`
|
||||
3. **Controllers**: Create controllers with `php artisan make:controller`
|
||||
4. **Models**: Understand Eloquent basics and relationships
|
||||
5. **Migrations**: Define database schema with migrations
|
||||
6. **Blade Templates**: Create views with Laravel's templating engine
|
||||
|
||||
### For Intermediate Users
|
||||
Focus on:
|
||||
- **Form Requests**: Validation and authorization in dedicated classes
|
||||
- **API Resources**: Transform models for JSON responses
|
||||
- **Authentication**: Implement with Laravel Breeze or Sanctum
|
||||
- **Relationships**: Master eager loading and complex relationships
|
||||
- **Queues**: Offload time-consuming tasks to background jobs
|
||||
- **Events & Listeners**: Decouple application logic
|
||||
|
||||
### For Advanced Users
|
||||
Explore:
|
||||
- **Service Providers**: Register application services
|
||||
- **Custom Middleware**: Create reusable request filters
|
||||
- **Package Development**: Build reusable Laravel packages
|
||||
- **Testing**: Write feature and unit tests with PHPUnit
|
||||
- **Performance**: Optimize queries, caching, and response times
|
||||
- **Deployment**: CI/CD pipelines and production optimization
|
||||
|
||||
### Navigation Tips
|
||||
- Check **Quick Reference** for common code patterns
|
||||
- Reference the official docs at https://laravel.com/docs/12.x
|
||||
- Use `php artisan route:list` to view all registered routes
|
||||
- Use `php artisan tinker` for interactive debugging
|
||||
- Enable query logging to debug database performance
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Repository Pattern
|
||||
```php
|
||||
interface PostRepositoryInterface
|
||||
{
|
||||
public function all();
|
||||
public function find(int $id);
|
||||
public function create(array $data);
|
||||
}
|
||||
|
||||
class PostRepository implements PostRepositoryInterface
|
||||
{
|
||||
public function all()
|
||||
{
|
||||
return Post::with('user')->latest()->get();
|
||||
}
|
||||
|
||||
public function find(int $id)
|
||||
{
|
||||
return Post::with('user', 'comments')->findOrFail($id);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Action Classes (Single Responsibility)
|
||||
```php
|
||||
class CreatePost
|
||||
{
|
||||
public function execute(array $data): Post
|
||||
{
|
||||
return DB::transaction(function () use ($data) {
|
||||
$post = Post::create($data);
|
||||
$post->tags()->attach($data['tag_ids']);
|
||||
event(new PostCreated($post));
|
||||
return $post;
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Query Scopes
|
||||
```php
|
||||
class Post extends Model
|
||||
{
|
||||
public function scopePublished($query)
|
||||
{
|
||||
return $query->where('published_at', '<=', now());
|
||||
}
|
||||
|
||||
public function scopeByAuthor($query, User $user)
|
||||
{
|
||||
return $query->where('user_id', $user->id);
|
||||
}
|
||||
}
|
||||
|
||||
// Usage
|
||||
Post::published()->byAuthor($user)->get();
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
### Official Documentation
|
||||
- Laravel Docs: https://laravel.com/docs/12.x
|
||||
- API Reference: https://laravel.com/api/12.x
|
||||
- Laracasts: https://laracasts.com (video tutorials)
|
||||
|
||||
### Community
|
||||
- Laravel News: https://laravel-news.com
|
||||
- Laravel Forums: https://laracasts.com/discuss
|
||||
- GitHub: https://github.com/laravel/laravel
|
||||
|
||||
### Tools
|
||||
- Laravel Telescope: Debugging and monitoring
|
||||
- Laravel Horizon: Queue monitoring
|
||||
- Laravel Debugbar: Development debugging
|
||||
- Laravel IDE Helper: IDE autocompletion
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Use Form Requests**: Separate validation logic from controllers
|
||||
2. **Eager Load Relationships**: Avoid N+1 query problems
|
||||
3. **Use Resource Controllers**: Follow RESTful conventions
|
||||
4. **Type Hints**: Leverage PHP type declarations for better IDE support
|
||||
5. **Database Transactions**: Wrap related database operations
|
||||
6. **Queue Jobs**: Offload slow operations to background workers
|
||||
7. **Cache Queries**: Cache expensive database queries
|
||||
8. **API Resources**: Transform data consistently for APIs
|
||||
9. **Events**: Decouple application logic with events and listeners
|
||||
10. **Tests**: Write tests for critical application logic
|
||||
|
||||
## Notes
|
||||
|
||||
- Laravel 12.x requires PHP 8.2 or higher
|
||||
- Uses Composer for dependency management
|
||||
- Includes Vite for asset compilation (replaces Laravel Mix)
|
||||
- Supports multiple database systems (MySQL, PostgreSQL, SQLite, SQL Server)
|
||||
- Built-in support for queues, cache, sessions, and file storage
|
||||
- Excellent ecosystem with first-party packages (Sanctum, Horizon, Telescope, etc.)
|
||||
15
skills/laravel/plugin.json
Normal file
15
skills/laravel/plugin.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "laravel",
|
||||
"description": "Provides Laravel integration for Claude Code.",
|
||||
"version": "1.0.0",
|
||||
"author": {
|
||||
"name": "Tim Green",
|
||||
"email": "rawveg@gmail.com"
|
||||
},
|
||||
"homepage": "https://github.com/rawveg/claude-skills-marketplace",
|
||||
"repository": "https://github.com/rawveg/claude-skills-marketplace",
|
||||
"license": "MIT",
|
||||
"keywords": ["laravel", "laravel", "Claude Code"],
|
||||
"category": "productivity",
|
||||
"strict": false
|
||||
}
|
||||
7
skills/laravel/references/index.md
Normal file
7
skills/laravel/references/index.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Laravel Documentation Index
|
||||
|
||||
## Categories
|
||||
|
||||
### Other
|
||||
**File:** `other.md`
|
||||
**Pages:** 1
|
||||
11
skills/laravel/references/other.md
Normal file
11
skills/laravel/references/other.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Laravel - Other
|
||||
|
||||
**Pages:** 1
|
||||
|
||||
---
|
||||
|
||||
## Installation - Laravel 12.x - The PHP Framework For Web Artisans
|
||||
|
||||
**URL:** https://laravel.com/docs/12.x
|
||||
|
||||
---
|
||||
Reference in New Issue
Block a user