laravel/wayfinder
Generate fully typed TypeScript functions for your Laravel routes and controller methods. Wayfinder lets your frontend call endpoints like normal imports—no hardcoded URLs or manual param syncing. Works with Vite via @laravel/vite-plugin-wayfinder.
Installation:
composer require laravel/wayfinder
npm i -D @laravel/vite-plugin-wayfinder
Update vite.config.js:
import { wayfinder } from "@laravel/vite-plugin-wayfinder";
export default defineConfig({ plugins: [wayfinder()] });
Generate TypeScript Definitions:
php artisan wayfinder:generate
This creates resources/js/wayfinder/, actions/, and routes/ directories (safe to .gitignore).
First Use Case: Import a controller action in your frontend:
import { show } from "@/actions/App/Http/Controllers/PostController";
show(1); // Returns { url: "/posts/1", method: "get" }
Controller Integration:
import { show } from "@/actions/App/Http/Controllers/PostController";
const { url, method } = show(1);
fetch(url, { method });
Route-Based Navigation:
import { show } from "@/routes/post";
const link = <Link href={show(1)}>View Post</Link>;
Form Handling:
.form():
import { store } from "@/actions/App/Http/Controllers/PostController";
<form {...store.form()}>
{/* Auto-generates action="/posts" method="post" */}
</form>
Query Parameters:
show(1, { query: { page: 2 } }); // "/posts/1?page=2"
show(1, { mergeQuery: { page: 2 } }); // Merges with existing URL params
HTTP Method Overrides:
PUT for forms):
update.form.put(1); // Generates `_method=PUT`
Invokable Controllers:
__invoke:
import StorePostController from "@/actions/App/Http/Controllers/StorePostController";
StorePostController(); // Calls the controller's __invoke method
useForm.submit():
form.submit(store()); // Auto-resolves URL/method
const client = {
getPost(id: number) { return show(id); },
createPost(data: Post) { return store(data); }
};
const { show } = await import("@/actions/App/Http/Controllers/PostController");
Route Caching:
route:cache cause missing Wayfinder definitions.php artisan route:clear
php artisan wayfinder:generate
Reserved Words:
delete) are renamed to [method]Method.Multiple Routes to Same Action:
index["/clients/{client}/payments"]({ client: 1 });
Optional Parameters:
0, "") may not bind correctly.show({ id: 1, optionalParam: null }); // Ensures null is passed
Vite Dev Server:
--force:
npm run dev -- --force
resources/js/wayfinder/ for errors.vite.config.js includes the plugin.php artisan route:list to validate backend routes.Custom Paths:
--path flag or config:
php artisan wayfinder:generate --path=custom/path
Skip Generation:
php artisan wayfinder:generate --skip-actions --skip-routes
Form Variants:
--with-form for React/Vue form helpers.Runtime Defaults:
APP_URL) in generated URLs.Query Parameter Handling:
vi.mock("@/actions/App/Http/Controllers/PostController", () => ({
show: () => ({ url: "/mock", method: "get" })
}));
How can I help you explore Laravel packages today?