Eliminate Route Guesswork with Laravel Wayfinder

Overview of Type-Safe Routing

Bridging the gap between a PHP backend and a JavaScript frontend often involves manually syncing route names and URLs. This process is fragile and prone to silent failures when a controller method changes or a route is renamed.

solves this by generating fully-typed, importable TypeScript functions for every route and controller action in your
Laravel
application. It ensures your frontend calls remain in sync with your backend without manual overhead.

Prerequisites

To get the most out of this tutorial, you should be comfortable with Laravel 10 or 11 and have a basic understanding of

. Familiarity with
TypeScript
is essential, as the primary benefit of this tool is generating types. You should also have a Laravel project set up with
Vite
for asset bundling.

Key Libraries & Tools

  • Laravel Wayfinder: The core package that transpile PHP routes into TypeScript functions.
  • Inertia.js: A framework for building single-page apps using classic server-side routing.
  • Vite Plugin Run: A utility that triggers the generation command whenever PHP files change.
  • Ziggy: While optional, Wayfinder serves as a type-safe alternative or companion to Ziggy's named routes.

Code Walkthrough: Installation and Automation

First, pull the package into your project using

. Although the tool is in beta, it provides immediate value for React or Vue starters.

composer require laravel/wayfinder

You can manually generate types using php artisan wayfinder:generate. However, to make this truly seamless, integrate it into your vite.config.js using the vite-plugin-run package. This ensures your types update the moment you save a PHP file.

import run from 'vite-plugin-run';

export default defineConfig({
    plugins: [
        run([
            {
                name: 'generate wayfinder',
                run: ['php', 'artisan', 'wayfinder:generate'],
                pattern: ['routes/**/*.php', 'app/Http/Controllers/**/*.php'],
            },
        ]),
    ],
});

Implementing Typed Actions

In a standard Inertia form, you might use form.post(route('login')). With Wayfinder, you switch to the submit method and pass the imported action directly. This removes the need for magic strings.

import { store } from '@/actions/RegisteredUserController';

const { data, setData, submit } = useForm({ /* ... */ });

const submitForm = () => {
    submit(store());
};

Syntax Notes and Best Practices

Wayfinder uses a functional approach. Instead of referencing a route by a string like 'user.store', you import the actual store function. This enables IDE features like "Go to Definition," which takes you straight to the PHP controller. For cleaner imports, configure a Vite alias for your generated routes directory.

Tips & Gotchas

Always check the HTTP method when using the submit helper. Wayfinder understands if an action requires POST, PUT, or DELETE, so you don't have to specify the method manually in your frontend code. If a new route isn't appearing, ensure your Vite watcher is running or trigger a manual generation to refresh the TypeScript definitions.

3 min read