You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Configure Cloudflare for DNS, CDN, SSL, and DDoS protection for Laravel apps. Use when setting up domains, adding DNS records, configuring SSL, or enabling Cloudflare features.
Cloudflare DNS & CDN
Cloudflare is the preferred DNS and CDN provider for Laravel apps — free tier covers all essentials.
Cloudflare provides two nameservers — update them at your registrar
Wait for propagation (usually minutes, up to 24h)
DNS Records for a Laravel App
Type
Name
Content
Proxy
A
@
{server-ip}
Proxied ✅
CNAME
www
{appname}.com
Proxied ✅
CNAME
staging
{cloud-staging-url}
DNS only ☁️
Proxied = traffic routes through Cloudflare (DDoS protection, CDN, SSL).
DNS only = direct connection, no Cloudflare features (use for staging/internal).
SSL/TLS
Set SSL mode to Full (strict) in Cloudflare → SSL/TLS → Overview:
Flexible — ⚠️ don't use (insecure, HTTP between Cloudflare and origin)
Full — encrypts to origin with self-signed cert
Full (strict) — ✅ encrypts to origin with valid cert (recommended)
Enable Always Use HTTPS in SSL/TLS → Edge Certificates.
Pointing to Laravel Cloud
CNAME @ {app}.laravel.cloud DNS only
CNAME www {appname}.com Proxied
Laravel Cloud handles its own SSL — use DNS only (grey cloud) for the root record pointing to Cloud.
Pointing to Forge / DigitalOcean
A @ {server-ip} Proxied
Forge provisions SSL via Let's Encrypt — set Cloudflare to Full (strict).
Pointing to Netlify
CNAME @ {app}.netlify.app DNS only
Or use Netlify's DNS proxy with Cloudflare as registrar only.
Git workflow conventions for solo Laravel development. Covers branch naming, commit message format, PR workflow, and common git operations. Use when committing, branching, or managing git workflow.
Git Workflow
Commit Message Format
Use conventional commits with optional scopes:
type(scope): description
feat: add rebuy tracking to tournament page
feat(billing): add Stripe Checkout session
fix: show newsletters without thumbnails on home page
fix(routes): remove redirect that blocked SettingsController
test: expand test suite from 118 to 230 tests
test(e2e): add auth and dashboard tests
docs: add PRD and architecture docs
chore: apply Pint formatting to test files
chore: assign unique vite port
Types
Type
When
feat
New feature or capability
fix
Bug fix
test
Adding or expanding tests
docs
Documentation only
chore
Tooling, formatting, deps, config
refactor
Code restructure without behaviour change
Scopes (optional)
Use the feature area: billing, admin, auth, e2e, seo, api, teams, mcp, ux, embed, routes, tests, ai, etc.
Branch Naming
feat/feature-name
fix/bug-description
test/test-coverage
docs/doc-name
chore/task-name
staging # staging environment branch
main # production branch
Feature branches are created from main and merged back via PR or direct merge.
Typical Workflow
Solo development (most projects)
# Work directly on main for small changes
git add -A && git commit -m "feat: add landing page pricing section"
git push
# Feature branch for larger work
git checkout -b feat/csv-import
# ... work ...
git add -A && git commit -m "feat(customers): CSV import — bulk add customers"
git push -u origin feat/csv-import
# Create PR if needed, or merge directly
git checkout main && git merge feat/csv-import && git push
With staging (production apps)
# Deploy to staging
git checkout staging
git merge main
git push # triggers Laravel Cloud staging deploy# Deploy to production
git checkout main
git push # triggers Laravel Cloud production deploy
Integrate AI features into Laravel apps using the official Laravel AI SDK (laravel/ai). Covers agents, tools, structured output, streaming, embeddings, image generation, audio, transcription, vector stores, and testing. Use when adding AI capabilities to a Laravel application.
Laravel AI SDK
The official first-party Laravel AI package. Supports Anthropic, OpenAI, Gemini, and many other providers.
IMPORTANT: Before implementing, fetch the latest docs:
WebFetch: https://laravel.com/docs/12.x/ai-sdk
The docs are the source of truth — the SDK is actively evolving.
useLaravel\Ai\Contracts\Agent;
useLaravel\Ai\Promptable;
useLaravel\Ai\Attributes\Provider;
useLaravel\Ai\Attributes\Model;
useLaravel\Ai\Enums\Lab;
#[Provider(Lab::Anthropic)]
#[Model('claude-sonnet-4-5-20250514')]
class ReviewResponder implements Agent
{
use Promptable;
publicfunctioninstructions(): string
{
return'You respond to customer reviews on behalf of a business. Be professional, warm, and concise.';
}
}
// Usage$response = (newReviewResponder)->prompt("Write a reply to this 5-star review: \"{$review->content}\"");
echo$response;
usefunctionLaravel\Ai\{agent};
$response = agent(
instructions: 'You are a copywriter.',
tools: [newWebSearch],
)->prompt('Write a tagline for a poker timer app');
Images
useLaravel\Ai\Image;
$image = Image::of('A poker chip on green felt')
->landscape()
->quality('high')
->generate();
$path = $image->store(); // Saves to default disk
Embeddings & Vector Search
useLaravel\Ai\Embeddings;
useIlluminate\Support\Str;
// Generate embeddings$embeddings = Str::of('Laravel is great')->toEmbeddings();
// Vector column in migration
Schema::ensureVectorExtensionExists();
$table->vector('embedding', dimensions: 1536);
// Query similar records$results = Document::query()
->whereVectorSimilarTo('embedding', 'search query')
->limit(10)
->get();
Common SaaS AI Patterns
AI Review Replies
#[Provider(Lab::Anthropic)]
class ReviewReplier implements Agent
{
use Promptable;
publicfunction__construct(privateBusiness$business) {}
publicfunctioninstructions(): string
{
return"Reply on behalf of {$this->business->name}. Be professional and warm.";
}
}
$reply = (newReviewReplier($business))->prompt("Reply to: \"{$review->content}\" ({$review->rating} stars)");
AI Content Generation (DealerDesk pattern)
$description = agent(
instructions: 'You are an automotive copywriter.',
)->prompt("Write a listing for: {$vehicle->year}{$vehicle->make}{$vehicle->model}");
Add web analytics to Laravel applications. Covers Google Analytics 4 (GA4) and Fathom Analytics integration with Inertia/React apps. Use when setting up analytics, tracking events, or discussing analytics tools.
Web Analytics for Laravel
Current Setup
Currently using Fathom Analytics (usefathom.com) — privacy-focused, simple. Considering migrating to Google Analytics 4 for deeper insights.
Fathom: Simple SaaS, privacy-first, don't need deep funnels
GA4: Need conversion funnels, audience segments, ecommerce tracking, or Google Ads integration
Cookie Consent (GA4 only)
If using GA4, you need a cookie consent banner for GDPR/privacy compliance:
// Only load GA after consentfunctioninitGA(){constscript=document.createElement('script');script.src=`https://www.googletagmanager.com/gtag/js?id=${GA_ID}`;script.async=true;document.head.appendChild(script);window.dataLayer=window.dataLayer||[];window.gtag=function(){window.dataLayer.push(arguments);};window.gtag('js',newDate());window.gtag('config',GA_ID);}
Or use GA4's built-in consent mode:
gtag('consent','default',{analytics_storage: 'denied',});// After user consents:gtag('consent','update',{analytics_storage: 'granted',});
Advanced Laravel Cashier patterns for Stripe billing including checkout sessions, customer portal, webhook handling, plan enforcement, and subscription lifecycle. Use when implementing billing, subscriptions, or payment features.
Use Cashier's built-in webhook controller. Only extend if you need custom event handling:
// routes/web.php — Cashier auto-registers, but if needed:
Route::post('/stripe/webhook', [\Laravel\Cashier\Http\Controllers\WebhookController::class, 'handleWebhook']);
For custom handlers, extend the controller:
class StripeWebhookController extends \Laravel\Cashier\Http\Controllers\WebhookController
{
publicfunctionhandleCustomerSubscriptionDeleted(array$payload): Response
{
parent::handleCustomerSubscriptionDeleted($payload);
// Custom cleanup logicreturn$this->successMethod();
}
publicfunctionhandleInvoicePaymentFailed(array$payload): Response
{
// Notify user of failed payment$user = $this->getUserByStripeId($payload['data']['object']['customer']);
if ($user) {
$user->notify(newPaymentFailed());
}
return$this->successMethod();
}
}
Plan Enforcement in Controllers
// In a controller or middlewarepublicfunctionstore(Request$request)
{
$user = $request->user();
$currentCount = $user->items()->count();
if ($user->hasReachedLimit('items', $currentCount)) {
returnback()->with('error', 'You have reached your plan limit. Please upgrade to add more items.');
}
// ... create the item
}
Upgrade Prompt Component (React)
// resources/js/components/upgrade-prompt.tsxinterfaceUpgradePromptProps{feature: string;currentPlan: string;}exportfunctionUpgradePrompt({ feature, currentPlan }: UpgradePromptProps){return(<divclassName="rounded-lg border border-amber-200 bg-amber-50 p-4"><pclassName="text-sm text-amber-800">{feature} is available on Pro and above.
You're currently on the {currentPlan} plan.
</p><Linkhref="/billing"className="mt-2 inline-block text-sm font-medium text-amber-900 underline">
Upgrade now
</Link></div>);}
Manage Laravel Cloud deployments, environments, databases, and infrastructure via the Cloud CLI. Use when deploying to Laravel Cloud, managing environments, viewing logs, or managing Cloud resources.
Laravel Cloud CLI
Installation
gh repo clone laravel/cloud-cli
cd cloud-cli
composer install
Add an alias to your shell config (~/.zshrc, ~/.bashrc, etc.):
Update the api_token field in ~/.config/cloud/config.json to a working token
If all tokens are expired, create a new long-lived token (see above)
Fallback: Use the REST API directly (see section below) — more reliable than the CLI when tokens are flaky.
Repository Setup
cd /path/to/{project}
cloud repo:config # Link repo to Cloud app + environment
This creates a .cloud file in the project root with the app and environment IDs:
{
"id": "app-xxx",
"environment": "env-xxx"
}
These IDs are needed for direct API calls.
Deployment
cloud ship # Guided first-time deployment
cloud deploy # Deploy current branch
cloud deploy:monitor # Watch active deployment
cloud deployment:list # View deployment history
Typical Deploy Workflow
# Push to main and deploy
git push origin main
cloud deploy
# Monitor the deployment
cloud deploy:monitor
Environment Management
cloud environment:list
cloud environment:create
cloud environment:variables # Load env vars from file
cloud environment:logs # Tail logs
Load env vars from .env file
cloud environment:variables # Interactive — loads from .env file
Auto-Injected Variables (DO NOT SET MANUALLY)
Laravel Cloud automatically injects env vars when resources are attached. Never set these manually — doing so overrides the injected values and can break deployments:
Add or configure Filament v3 admin panels in Laravel applications. Use when setting up admin panels, creating Filament resources, or managing superadmin access.
Laravel 12 uses bootstrap/app.php for middleware registration (no Kernel.php). Filament v3 handles its own middleware registration via the panel provider.
Testing Admin Panel
test('admin panel returns 403 for non-superadmin', function () {
$user = User::factory()->create(['is_superadmin' => false]);
$this->actingAs($user)->get('/admin')->assertForbidden();
});
test('admin panel accessible for superadmin', function () {
$admin = User::factory()->create(['is_superadmin' => true, 'email_verified_at' => now()]);
$this->actingAs($admin)->get('/admin')->assertOk();
});
test('admin panel redirects guests to login', function () {
$this->get('/admin')->assertRedirect();
});
Deploy Laravel apps with Laravel Forge on DigitalOcean, AWS, or Linode. Use when setting up VPS hosting, configuring Nginx, managing SSL, queue workers, and deployment scripts. Fallback when Laravel Cloud doesn't suit the project.
Laravel Forge + DigitalOcean
Use Forge when you need full server control or Laravel Cloud doesn't suit the project.
Setup
Create a server in Forge (DigitalOcean recommended)
Connect your GitHub repo
Create a site for your domain
Deployment Script
cd /home/forge/{appname}.com
git pull origin main
composer install --no-dev --optimize-autoloader
npm ci && npm run build
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan queue:restart
SSL
Set up via Forge → Site → SSL → Let's Encrypt (free, auto-renews).
Local Laravel development with Laravel Herd. Use when setting up local dev environments, configuring .test domains, managing PHP versions, or running queue workers locally.
Laravel Herd — Local Development
Laravel Herd provides a zero-config local dev environment for macOS with PHP, Nginx, and database services built in.
Setup
cd /path/to/{project-name}
herd link {appname}
This creates https://{appname}.test with automatic SSL.
Per-Project Vite Ports
Each project needs a unique Vite dev server port to avoid conflicts when running multiple projects simultaneously:
// vite.config.tsexportdefaultdefineConfig({server: {port: 5173,// increment per project: 5174, 5175, etc.},});
Starting Dev Servers
php artisan serve &
npm run dev &
Or use Herd's built-in Nginx (no artisan serve needed when using herd link).
Database
Herd provides MySQL and PostgreSQL. Configure .env:
php artisan queue:work # Process jobs
php artisan schedule:work # Run scheduler locally
PHP Version Management
herd php:list # List installed PHP versions
herd php:use 8.3 # Switch global PHP version
herd isolate 8.2 # Use PHP 8.2 for current project only
Useful Commands
herd open # Open current site in browser
herd edit # Edit Nginx config for current site
herd logs # Tail Nginx logs
herd restart # Restart all services
herd status # Show running services
SSL Certificates
Herd automatically provisions SSL for all .test domains. If a cert is missing:
herd secure {appname} # Manually secure a site
herd unsecure {appname} # Remove SSL
Build Laravel Inertia.js pages with React and TypeScript. Use when creating new pages, components, layouts, or working with Inertia props, forms, and routing in a Laravel React app.
Laravel + Inertia.js + React + TypeScript
Page Structure
Pages live in resources/js/pages/. Each page is a React component that receives props from the Laravel controller.
Infrastructure overview for Laravel apps — which platform to use for local dev, staging, production, DNS, and static sites. Use when deciding where to deploy or how environments are structured.
Infrastructure & Deployment Overview
Environment Stack
Environment
Platform
Domain Pattern
Purpose
Local
Laravel Herd
{appname}.test
Development
Staging
Laravel Cloud
{appname}-staging.laravel.cloud
Pre-production testing
Production
Laravel Cloud
{appname}.com
Live
Platform Decision Tree
New Laravel SaaS project?
├── Yes → Laravel Cloud (staging + production)
│ └── DNS via Cloudflare
│ └── Local dev via Herd
├── Static site?
│ └── Netlify
├── Frontend-only React/Next.js app?
│ └── Vercel (or Netlify)
├── Need full server control?
│ └── Laravel Forge + DigitalOcean
│ └── DNS via Cloudflare
Build interactive Laravel pages with Livewire and Alpine.js. Use when the project uses Livewire instead of Inertia, or when adding Livewire components.
Laravel Livewire + Alpine.js
Some projects use Livewire + Alpine.js instead of Inertia + React. This is the Blade-based interactive stack.
When to Use Livewire vs Inertia
Livewire + Alpine
Inertia + React
Best for
Content sites, admin panels, forms
Complex SPA-like apps
Frontend
Blade + Alpine.js
React + TypeScript
Reactivity
Server-driven (wire:model)
Client-side (useState)
SEO
Better by default (server-rendered)
Needs SSR setup
JS bundle
Minimal
Larger (React)
Default: Inertia + React for new SaaS projects. Livewire for content-heavy sites or when Blade is preferred.
Set up Laravel Nightwatch for error tracking and application monitoring. Use when adding monitoring, error tracking, or performance observability to a Laravel application.
Laravel Nightwatch
Nightwatch is Laravel's first-party application monitoring and error tracking service.
Write comprehensive Pest PHP tests for Laravel applications. Use when adding tests, expanding test coverage, or when the user mentions testing, test suite, or Pest.
Laravel Pest Testing
Conventions
Use Pest PHP syntax (not PHPUnit classes)
Tests go in tests/Feature/ (most tests) and tests/Unit/
Use RefreshDatabase trait for feature tests
Use factories for all test data
Test file naming: {Feature}Test.php (e.g., BillingTest.php, AdminPanelTest.php)
Set up and write Playwright end-to-end tests for Laravel applications. Use when adding E2E tests, browser testing, or when the user mentions Playwright.
Playwright E2E Testing for Laravel
Installation
npm init playwright@latest
Select TypeScript, tests in e2e/, and install browsers.
e2e/
├── global-setup.ts
├── helpers/
│ └── auth.ts
├── auth.spec.ts
├── dashboard.spec.ts
├── misc-pages.spec.ts # smoke tests for all settings/misc pages
├── {feature}.spec.ts # one file per major feature
Test Patterns
Auth flow
test.describe('Auth',()=>{test('landing page loads without auth redirect',async({ page })=>{awaitpage.goto('/');awaitexpect(page).not.toHaveURL(/login/);awaitexpect(page.locator('body')).toBeVisible();});test('dashboard redirects unauthenticated users',async({ page })=>{awaitpage.goto('/dashboard');awaitexpect(page).not.toHaveURL(/dashboard/);});test('e2e login lands on dashboard',async({ page })=>{awaitloginAsE2eUser(page);awaitexpect(page).toHaveURL(/dashboard/);});});
Page smoke test (bulk pattern)
For every auth-gated page, verify it loads without errors:
test.describe('Settings pages',()=>{test.beforeEach(async({ page })=>{awaitloginAsE2eUser(page);});for(constpathof['/settings/billing','/settings/notifications','/settings/integrations']){test(`${path} loads without error`,async({ page })=>{awaitpage.goto(path);awaitexpect(page.locator('body')).not.toContainText('Whoops');awaitexpect(page.locator('body')).not.toContainText('500');});}});
CRUD flow
test('can create and view resource',async({ page })=>{awaitloginAsE2eUser(page);awaitpage.goto('/resources/create');awaitpage.fill('input[name="name"]','Test Resource');awaitpage.click('button[type="submit"]');awaitexpect(page.locator('text=Test Resource')).toBeVisible();});
Form validation
test('shows validation errors for empty required fields',async({ page })=>{awaitloginAsE2eUser(page);awaitpage.goto('/resources/create');awaitpage.click('button[type="submit"]');awaitexpect(page.locator('text=required')).toBeVisible();});
Dashboard with data
test('dashboard shows stats and navigation',async({ page })=>{awaitloginAsE2eUser(page);awaitexpect(page.locator('body')).not.toContainText('Whoops');// Verify seeded data appearsawaitexpect(page.locator('body')).toContainText('E2E Test');// Verify nav links presentawaitexpect(page.locator('body')).toContainText('Dashboard');});
Running Tests
npx playwright test# Run all
npx playwright test auth.spec.ts # Run specific file
npx playwright test --ui # Interactive mode
npx playwright show-report # View HTML report
Common Issues
Inertia 409 version mismatch
Run npm run build to regenerate assets before running tests.
WorkOS redirect on /_e2e/login
Ensure APP_E2E=true is set in .env and the bypass route is registered.
Flaky timeouts
Use workers: 1 and fullyParallel: false for Inertia apps — parallel test runs can cause database conflicts with RefreshDatabase.
Related
For interactive visual auditing (not automated tests), see the laravel-ui-audit skill which uses Playwright MCP browser tools to manually inspect pages.
Generate project documentation including PRD, competitive analysis, OpenAPI spec, internal docs, and deployment guides. Use when the user asks for docs, PRD, competitor analysis, architecture docs, or wants to understand project status.
Laravel Project Documentation
Documentation Structure
Every project should have a docs/ directory with this structure:
docs/
├── PRD.md # Product Requirements Document
├── NEXT_STEPS.md # Prioritised task list / roadmap
├── COMPETITIVE_ANALYSIS.md # Competitor research (optional, recommended)
├── openapi.yaml # OpenAPI 3.1 spec for API endpoints
├── internal/ # Internal-only docs
│ ├── ARCHITECTURE.md # System architecture and key decisions
│ ├── DEPLOYMENT.md # Deployment guide (Forge, Herd, Cloud)
│ └── {FEATURE}_SETUP.md # Setup guides for integrations (Twilio, Stripe, etc.)
└── public/ # Docs visible to end users (optional)
└── API.md # Public API documentation
Research competitors using WebSearch. Structure the analysis as:
# {AppName} — Competitive Analysis**Date:** {date}
## Competitors Researched| Competitor | Positioning | Pricing (USD/mo) ||---|---|---|| {name} | {one-line positioning} | {price range} |## Feature Comparison Table| Feature | Competitor A | Competitor B | {AppName} ||---|---|---|---|| {feature} | Y | N | Y |## 1. Features Competitors Have That {AppName} is MISSING### HIGH PRIORITY#### 1.1 {Feature Name}-**Who has it:** {competitors}
-**What it does:** {description}
-**Why it matters:** {business justification}
-**Gap level:** Critical / High / Medium / Low
## 2. Features {AppName} Has That Competitors DON'T## 3. Pricing Analysis## 4. Recommended Roadmap Based on Gaps
Laravel queues, jobs, scheduling, and failed job handling. Use when creating jobs, setting up schedulers, configuring queue workers, or debugging failed jobs.
Laravel Queues, Jobs & Scheduling
Creating Jobs
php artisan make:job ProcessPayment
// app/Jobs/ProcessPayment.phpclass ProcessPayment implements ShouldQueue
{
use Queueable;
publicint$tries = 3;
publicint$backoff = 60; // seconds between retriespublicint$timeout = 120;
publicfunction__construct(
privateOrder$order,
) {}
publicfunctionhandle(): void
{
// Process the payment
}
publicfunctionfailed(Throwable$exception): void
{
// Notify admin, log error, etc.
Log::error("Payment failed for order {$this->order->id}", [
'error' => $exception->getMessage(),
]);
}
}
Scaffold a new Laravel SaaS application with Inertia.js, React, TypeScript, Tailwind CSS, shadcn/ui, Pest, Filament admin, WorkOS auth, and Stripe billing. Use when creating a new Laravel project or SaaS app from scratch.
Add SEO features to Laravel applications including sitemap, robots.txt, Open Graph meta tags, and structured data. Use when the user mentions SEO, sitemap, robots, meta tags, or social sharing.
Integrate SMS into Laravel applications using Twilio or ClickSend. Use when adding SMS notifications, appointment reminders, two-way messaging, or discussing SMS providers. ClickSend is the Australian alternative.
SMS Integration for Laravel
Provider Choice
Provider
Best for
Pricing
Twilio
Global, feature-rich, two-way SMS
Pay per message (~$0.05 AUD/msg AU)
ClickSend
Australian-based, simpler, good AU rates
Pay per message (~$0.04 AUD/msg AU)
Preference: ClickSend for Australian-focused apps (local support, competitive AU rates). Twilio for apps needing advanced features (programmable voice, WhatsApp, global reach).
ClickSend also supports: email, fax, postcard, MMS, and voice. The API is REST-based and simpler than Twilio's. For basic SMS sending in Australian apps, ClickSend is often the better choice.
Use Playwright MCP browser tools to visually audit and verify UI/UX across a Laravel application. Use when checking frontend design, finding visual bugs, verifying responsive layout, or confirming that pages render correctly after changes.
Laravel UI/UX Audit via Playwright Browser
Use the Playwright MCP browser tools to navigate the running app, take screenshots, inspect the DOM, and verify that every page renders correctly. This catches bugs that unit/feature tests miss: broken layouts, missing elements, console errors, failed asset loading, dark mode issues, and mobile responsiveness problems.
Prerequisites
The Laravel app must be running locally (e.g., via Herd at https://appname.test or php artisan serve at http://localhost:8000)
Determine the base URL before starting
Step 1: Authenticate
Most apps use WorkOS AuthKit with no local login form. Use the dev login bypass:
Navigate to: {baseURL}/_e2e/login?email=e2e@appname.test
— or —
Navigate to: {baseURL}/dev/login
If neither bypass exists, check routes/web.php for a local/testing login route. If none exists, suggest creating one gated to app()->environment('local', 'testing').
Verify: confirm the browser lands on /dashboard after login.
Use Laravel Wayfinder for type-safe TypeScript route and controller action generation. Use when adding routes, creating controllers, or connecting React frontend to Laravel backend routes.
Laravel Wayfinder
Wayfinder generates fully-typed TypeScript functions from your Laravel controllers and routes — no more hardcoded URLs.
Installation
composer require laravel/wayfinder
npm i -D @laravel/vite-plugin-wayfinder
Vite Config
// vite.config.tsimport{wayfinder}from'@laravel/vite-plugin-wayfinder';exportdefaultdefineConfig({plugins: [wayfinder(),// ... other plugins],});
Generated files go in resources/js/wayfinder/. These can be gitignored — they regenerate on every build. The Vite plugin auto-regenerates during development.
Usage in React Components
Importing Actions
// Import specific controller actionsimport{show,update}from'@/actions/App/Http/Controllers/PostController';// URL string onlyshow.url(1);// "/posts/1"// Full route objectshow(1);// { url: "/posts/1", method: "get" }
import{useForm}from'@inertiajs/react';import{store}from'@/actions/App/Http/Controllers/PostController';constform=useForm({name: ''});form.submit(store());// POSTs to /posts
With Query Parameters
import{index}from'@/actions/App/Http/Controllers/PostController';index({query: {page: 2,sort: 'name'}});// { url: "/posts?page=2&sort=name", method: "get" }// Merge with current query paramsindex({mergeQuery: {page: 3}});
Deploy static sites and frontend-only projects to Netlify. Use when deploying marketing sites, documentation, or static HTML/JS projects. Not suitable for full Laravel apps.
Netlify — Static Site Deployment
Netlify is ideal for static sites, marketing pages, and documentation. Not suitable for full Laravel apps (use Laravel Cloud or Forge instead).
[[redirects]]
from = "/old-path"to = "/new-path"status = 301
[[redirects]]
from = "/*"to = "/index.html"status = 200
Deploy Previews
Netlify automatically creates preview URLs for every pull request. Useful for reviewing changes before merging.
Netlify CLI
npm install -g netlify-cli
netlify login
netlify deploy # Deploy to preview URL
netlify deploy --prod # Deploy to production
netlify env:list # List env vars
netlify open # Open site in browser
Deploy frontend-only React, Next.js, or static apps to Vercel. Use when deploying standalone frontends, Next.js apps, or projects needing edge functions. Not suitable for full Laravel apps.
Vercel — Frontend Deployment
Vercel is optimised for React and Next.js projects. Use for standalone frontends or Next.js apps. Not suitable for full Laravel apps (use Laravel Cloud or Forge instead).
Deploy from Git
Go to vercel.com → Add New Project → Import Git Repository
Or use Vercel's nameservers for full DNS management.
Environment Variables
Project → Settings → Environment Variables. Set per environment (Production, Preview, Development).
Vercel CLI
npm install -g vercel
vercel login
vercel # Deploy to preview
vercel --prod # Deploy to production
vercel env list # List env vars
vercel logs # View function logs
Preview Deployments
Every Git branch and PR gets an automatic preview URL. Share with stakeholders before merging.
Edge Functions / API Routes
// app/api/hello/route.ts (Next.js App Router)exportasyncfunctionGET(){returnResponse.json({message: 'Hello from the edge'});}
Deploy as edge functions — runs globally close to users.
When to Use Vercel vs Netlify
Vercel
Netlify
Best for
Next.js, React apps
Static sites, simple SPAs
Next.js
Optimised (made by Vercel)
Works
Edge functions
Yes
Yes
Forms
No
Built-in
Analytics
Built-in (paid)
Limited
When NOT to Use Vercel
Full Laravel apps → use Laravel Cloud or Forge
Apps needing persistent server state → use a VPS
Apps with long-running PHP processes → not supported