laravel/wayfinder
Zero‑friction Laravel → TypeScript bridge. Wayfinder auto‑generates fully typed, importable TS functions for your routes and controller actions, letting you call endpoints like normal functions—no hardcoded URLs, parameter guessing, or manual syncing.
composer require laravel/wayfinder
npm install -D @laravel/vite-plugin-wayfinder
vite.config.js):
import { wayfinder } from "@laravel/vite-plugin-wayfinder";
export default defineConfig({
plugins: [
wayfinder(),
// other plugins...
],
});
php artisan wayfinder:generate
resources/js/wayfinder/, resources/js/actions/, resources/js/routes/php artisan wayfinder:generate --path=custom/pathCall a Controller Action Directly:
import { show } from "@/actions/App/Http/Controllers/PostController";
show(1); // Returns { url: "/posts/1", method: "get" }
import { store } from "@/actions/App/Http/Controllers/PostController";
store({ title: "Hello" }); // POST to `/posts`
import { update } from "@/actions/App/Http/Controllers/PostController";
update([1, "published"]); // PATCH to `/posts/1?status=published`
import { show } from "@/actions/App/Http/Controllers/PostController";
show({ slug: "my-post" }); // GET to `/posts/my-post`
import { show } from "@/routes/post"; // Assumes route named `post.show`
show(1); // GET to `/posts/1`
import { index } from "@/actions/App/Http/Controllers/PostController";
index({ page: 1 }, { query: { sort: "desc" } });
// GET to `/posts?page=1&sort=desc`
import { store } from "@/actions/App/Http/Controllers/PostController";
<form {...store.form()}>
{/* Auto-generates action="/posts" method="post" */}
</form>
import StorePostController from "@/actions/App/Http/Controllers/StorePostController";
StorePostController(); // Direct invocation
import { useForm } from "@inertiajs/react";
import { store } from "@/actions/App/Http/Controllers/PostController";
const form = useForm({ title: "Test" });
form.submit(store()); // Auto-resolves to POST `/posts`
import { show } from "@/actions/App/Http/Controllers/PostController";
show.url(1); // "/posts/1"
show.head(1); // { url: "/posts/1", method: "head" }
Reserved Keywords:
delete or import become deleteMethod/importMethod in TypeScript.Blade Views in Routes:
php artisan wayfinder:generate --eager to pre-render views.Query Parameter Conflicts:
mergeQuery may unintentionally override existing URL params.null to remove params:
{ mergeQuery: { page: null } } // Removes `page` from URL
Namespace Collisions:
App\Http\Controllers\Admin\PostController) cause barrel file conflicts.--path to customize output structure.Invokable Controllers:
import { store } from "@/actions/App/Http/Controllers/PostController";
php artisan wayfinder:generate --verbose
resources/js/wayfinder/ for generated files.npm run dev to auto-generate on file changes.wayfinder.config.php:
return [
'paths' => [
'actions' => 'custom/path/actions',
'routes' => 'custom/path/routes',
],
];
WayfinderGenerator service to include middleware in TypeScript definitions.--with-form:
php artisan wayfinder:generate --with-form
url() helpers in controllers to define dynamic defaults:
public function show($id) {
return response()->json(['id' => $id]);
}
// Wayfinder generates: show(1) → `/posts/1`
--skip-actions or --skip-routes to skip generation for specific parts..gitignore:
/resources/js/wayfinder/
/resources/js/actions/
/resources/js/routes/
How can I help you explore Laravel packages today?