laravel/wayfinder
Generates fully typed, importable TypeScript functions from your Laravel routes and controllers. Call backend endpoints like normal TS functions—no hardcoded URLs or manual syncing. Includes an Artisan generator and Vite plugin for auto-regeneration.
import { show } from "@/actions/PostController").route() helpers with typed, importable functions./posts/{id} vs. /posts/{slug}).✅ Your stack is Laravel + TypeScript/React/Vue: Wayfinder is Laravel-native and assumes a Laravel backend with a modern frontend toolchain (Vite, Inertia, or standalone TS).
✅ You’re tired of API drift: Manual API clients (e.g., OpenAPI) often fall out of sync with backend changes. Wayfinder auto-generates types from your routes/controllers.
✅ You use Inertia.js: Seamless integration with useForm().submit(wayfinderAction()) and Link components.
✅ Your team values DX: Reduces context-switching between frontend/backend by providing IDE-friendly imports (autocomplete, type safety).
✅ You need query parameter control: Supports merging/replacing query params at runtime (e.g., pagination, sorting).
❌ You’re not using Laravel: Wayfinder is Laravel-specific (routes, controllers, Blade). For non-Laravel backends, use OpenAPI/Swagger or tRPC.
❌ Your frontend is vanilla JS: Wayfinder generates TypeScript. For JS-only projects, consider manual route resolvers or fetch-based utilities.
❌ You need WebSocket support: Wayfinder focuses on HTTP routes. For real-time, pair with Laravel Echo or tRPC.
❌ You’re in a monorepo with non-Laravel services: Wayfinder won’t generate clients for Node.js/Go/Python services.
❌ You require strict API versioning: Wayfinder is runtime-generated—not ideal for versioned APIs (use OpenAPI instead).
❌ Your team resists tooling: Wayfinder adds a build step (wayfinder:generate). Teams preferring "no dependencies" may reject it.
"Wayfinder eliminates a $50K/year technical debt sinkhole."
showPost(1) instead of axios.get('/posts/1'))."Wayfinder turns Laravel routes into first-class TypeScript citizens."
import { store } from "@/actions/PostController";
store({ title: "Hello" }); // POSTs to `/posts` with type safety.
useForm().submit(store()) and Link components.show(1, { query: { page: 2 } }); // `/posts/1?page=2`
<form> attributes dynamically:
<form {...update.form(1)}> {/* action="/posts/1?_method=PATCH" */}
--skip-actions to opt-in gradually.wayfinder:generate to your deploy pipeline (mitigated by route:clear)."No more ‘Works on my machine’ API errors."
update({ post: { id: 1 }, author: { id: 2 } }); // `/posts/1?author=2`
<form> attributes with one line:
<form {...store.form()}> {/* action="/posts" method="post" */}
composer require laravel/wayfinder + npm i -D @laravel/vite-plugin-wayfinder.vite.config.js: plugins: [wayfinder()].php artisan wayfinder:generate (or let Vite handle it in dev).import { show } from "@/actions/PostController";
show(1).url; // "/posts/1"
How can I help you explore Laravel packages today?