PHPackages                             laravel/wayfinder - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. laravel/wayfinder

ActiveLibrary[Framework](/categories/framework)

laravel/wayfinder
=================

Generate TypeScript representations of your Laravel actions and routes.

v0.1.15(1mo ago)1.7k4.1M—2.3%106[26 issues](https://github.com/laravel/wayfinder/issues)[12 PRs](https://github.com/laravel/wayfinder/pulls)20MITPHPPHP ^8.2CI passing

Since Apr 2Pushed 2d ago22 watchersCompare

[ Source](https://github.com/laravel/wayfinder)[ Packagist](https://packagist.org/packages/laravel/wayfinder)[ Docs](https://github.com/laravel/wayfinder)[ RSS](/packages/laravel-wayfinder/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (14)Versions (25)Used By (20)

[![Laravel Wayfinder Logo](./art/logo.svg)](./art/logo.svg)

Introduction
------------

[](#introduction)

Laravel Wayfinder bridges your Laravel backend and TypeScript frontend with zero friction. It automatically generates fully-typed, importable TypeScript functions for your controllers and routes — so you can call your Laravel endpoints directly in your client code just like any other function. No more hardcoding URLs, guessing route parameters, or syncing backend changes manually.

Important

Wayfinder is currently in Beta, the API is subject to change prior to the v1.0.0 release. All notable changes will be documented in the [changelog](./CHANGELOG.md).

Note

Want to try the next version of Wayfinder? [You can find the beta here](https://github.com/laravel/wayfinder/tree/next).

Installation
------------

[](#installation)

To get started, install Wayfinder via the Composer package manager:

```
composer require laravel/wayfinder

```

Next, install the [Wayfinder Vite plugin](https://github.com/laravel/vite-plugin-wayfinder) to ensure that your routes are generated during Vite's build step and also whenever your files change while running the Vite's dev server.

First, install the plugin via NPM:

```
npm i -D @laravel/vite-plugin-wayfinder

```

Then, update your application's `vite.config.js` file to watch for changes to your application's routes and controllers:

```
import { wayfinder } from "@laravel/vite-plugin-wayfinder";

export default defineConfig({
    plugins: [
        wayfinder(),
        // ...
    ],
});
```

You can read about all of the plugin's configuration options in the [documentation](https://github.com/laravel/vite-plugin-wayfinder).

Generating TypeScript Definitions
---------------------------------

[](#generating-typescript-definitions)

The `wayfinder:generate` command can be used to generate TypeScript definitions for your routes and controller methods:

```
php artisan wayfinder:generate

```

By default, Wayfinder generates files in three directories (`wayfinder`, `actions`, and `routes`) within `resources/js`, but you can configure the base path:

```
php artisan wayfinder:generate --path=resources/js/wayfinder

```

The `--skip-actions` and `--skip-routes` options may be used to skip TypeScript definition generation for controller methods or routes, respectively:

```
php artisan wayfinder:generate --skip-actions
php artisan wayfinder:generate --skip-routes

```

You can safely `.gitignore` the `wayfinder`, `actions`, and `routes` directories as they are completely re-generated on every build.

### Deploying

[](#deploying)

Wayfinder reads routes from the registered router, so if Laravel boots with a cached route table left over from a previous release, generation will run against those stale routes. Any routes added since the last `route:cache` will be silently missing from the generated `routes/` and `actions/` directories, and Vite will fail with errors like `Could not load resources/js/routes/`.

If your deploy script runs `php artisan optimize` (or `route:cache` directly) at the end of a deploy, run `php artisan route:clear` before regenerating on the next deploy. With the Vite plugin, this needs to happen before `npm run build`, since the plugin invokes `wayfinder:generate` during the build:

```
php artisan route:clear
npm run build
```

Usage
-----

[](#usage)

Wayfinder functions return an object that contains the resolved URL and default HTTP method:

```
import { show } from "@/actions/App/Http/Controllers/PostController";

show(1); // { url: "/posts/1", method: "get" }
```

If you just need the URL, or would like to choose a method from the HTTP methods defined on the server, you can invoke additional methods on the Wayfinder generated function:

```
import { show } from "@/actions/App/Http/Controllers/PostController";

show.url(1); // "/posts/1"
show.head(1); // { url: "/posts/1", method: "head" }
```

Wayfinder functions accept a variety of shapes for their arguments:

```
import { show, update } from "@/actions/App/Http/Controllers/PostController";

// Single parameter action...
show(1);
show({ id: 1 });

// Multiple parameter action...
update([1, 2]);
update({ post: 1, author: 2 });
update({ post: { id: 1 }, author: { id: 2 } });
```

Note

If you are using a JavaScript [reserved word](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#reserved_words) such as `delete` or `import`, as a method in your controller, Wayfinder will rename it to `[method name]Method` (`deleteMethod`, `importMethod`) when generating its functions. This is because these words are not allowed as variable declarations in JavaScript.

If you've specified a key for the parameter binding, Wayfinder will detect this and allow you to pass the value in as a property on an object:

```
import { show } from "@/actions/App/Http/Controllers/PostController";

// Route is /posts/{post:slug}...
show("my-new-post");
show({ slug: "my-new-post" });
```

### Invokable Controllers

[](#invokable-controllers)

If your controller is an invokable controller, you may simply invoke the imported Wayfinder function directly:

```
import StorePostController from "@/actions/App/Http/Controllers/StorePostController";

StorePostController();
```

### Importing Controllers

[](#importing-controllers)

You may also import the Wayfinder generated controller definition and invoke its individual methods on the imported object:

```
import PostController from "@/actions/App/Http/Controllers/PostController";

PostController.show(1);
```

Note

In the example above, importing the entire controller prevents the `PostController` from being tree-shaken, so all `PostController` actions will be included in your final bundle.

### Importing Named Routes

[](#importing-named-routes)

Wayfinder can also generate methods for your application's named routes as well:

```
import { show } from "@/routes/post";

// Named route is `post.show`...
show(1); // { url: "/posts/1", method: "get" }
```

### Multiple Routes To The Same Action

[](#multiple-routes-to-the-same-action)

If two or more routes point at the same controller method, Wayfinder can't tell which URL you meant from the action alone, so the generated export becomes a dictionary keyed by URI instead of a callable:

```
Route::get('clients/{client}/payments', [ClientPaymentsController::class, 'index'])
    ->name('clients.payments.index');

Route::get('clients/{client}/payments-archive', [ClientPaymentsController::class, 'index'])
    ->name('clients.payments.archive');
```

```
import { index } from "@/actions/App/Http/Controllers/ClientPaymentsController";

// `index` is not callable directly — pick the URI you want:
index["/clients/{client}/payments"]({ client: 1 });
```

In most cases it is easier to import the route by name from your generated `routes/` directory instead:

```
import { index } from "@/routes/clients/payments";

index({ client: 1 }); // { url: "/clients/1/payments", method: "get" }
```

### Conventional Forms

[](#conventional-forms)

If your application uses conventional HTML form submissions, Wayfinder can help you out there as well. First, opt into form variants when generating your TypeScript definitions:

```
php artisan wayfinder:generate --with-form
```

Then, you can use the `.form` variant to generate `` object attributes automatically:

```
import { store, update } from "@/actions/App/Http/Controllers/PostController";

const Page = () => (

        {/*  */}
        {/* ... */}

);

const Page = () => (

        {/*  */}
        {/* ... */}

);
```

If your form action supports multiple methods and would like to specify a method, you can invoke additional methods on the `form`:

```
import { store, update } from "@/actions/App/Http/Controllers/PostController";

const Page = () => (

        {/*  */}
        {/* ... */}

);
```

Query Parameters
----------------

[](#query-parameters)

All Wayfinder methods accept an optional, final `options` argument to which you may pass a `query` object. This object can be used to append query parameters onto the resulting URL:

```
import { show } from "@/actions/App/Http/Controllers/PostController";

const options = {
    query: {
        page: 1,
        sort_by: "name",
    },
};

show(1, options); // { url: "/posts/1?page=1&sort_by=name", method: "get" }
show.get(1, options); // { url: "/posts/1?page=1&sort_by=name", method: "get" }
show.url(1, options); // "/posts/1?page=1&sort_by=name"
show.form.head(1, options); // { action: "/posts/1?page=1&sort_by=name&_method=HEAD", method: "get" }
```

You can also merge with the URL's existing parameters by passing a `mergeQuery` object instead:

```
import { show } from "@/actions/App/Http/Controllers/PostController";

// window.location.search = "?page=1&sort_by=category&q=shirt"

const options = {
    mergeQuery: {
        page: 2,
        sort_by: "name",
    },
};

show.url(1, options); // "/posts/1?page=2&sort_by=name&q=shirt"
```

If you would like to remove a parameter from the resulting URL, define the value as `null` or `undefined`:

```
import { show } from "@/actions/App/Http/Controllers/PostController";

// window.location.search = "?page=1&sort_by=category&q=shirt"

const options = {
    mergeQuery: {
        page: 2,
        sort_by: null,
    },
};

show.url(1, options); // "/posts/1?page=2&q=shirt"
```

Wayfinder and Inertia
---------------------

[](#wayfinder-and-inertia)

When using [Inertia](https://inertiajs.com), you can pass the result of a Wayfinder method directly to the `submit` method of `useForm`, it will automatically resolve the correct URL and method:

```
import { useForm } from "@inertiajs/react";
import { store } from "@/actions/App/Http/Controllers/PostController";

const form = useForm({
    name: "My Big Post",
});

form.submit(store()); // Will POST to `/posts`...
```

You may also use Wayfinder in conjunction with Inertia's `Link` component:

```
import { Link } from "@inertiajs/react";
import { show } from "@/actions/App/Http/Controllers/PostController";

const Nav = () => Show me the first post;
```

Contributing
------------

[](#contributing)

Thank you for considering contributing to Wayfinder! You can read the contribution guide [here](.github/CONTRIBUTING.md).

Code of Conduct
---------------

[](#code-of-conduct)

In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct).

Security Vulnerabilities
------------------------

[](#security-vulnerabilities)

Please review [our security policy](https://github.com/laravel/wayfinder/security/policy) on how to report security vulnerabilities.

License
-------

[](#license)

Wayfinder is open-sourced software licensed under the [MIT license](LICENSE.md).

###  Health Score

67

—

FairBetter than 100% of packages

Maintenance94

Actively maintained with recent releases

Popularity71

Solid adoption and visibility

Community48

Growing community involvement

Maturity49

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 66.9% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~23 days

Recently: every ~51 days

Total

16

Last Release

54d ago

PHP version history (2 changes)v0.1.0PHP ^8.3

v0.1.5PHP ^8.2

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/463230?v=4)[Taylor Otwell](/maintainers/taylorotwell)[@taylorotwell](https://github.com/taylorotwell)

---

Top Contributors

[![joetannenbaum](https://avatars.githubusercontent.com/u/2702148?v=4)](https://github.com/joetannenbaum "joetannenbaum (166 commits)")[![timacdonald](https://avatars.githubusercontent.com/u/24803032?v=4)](https://github.com/timacdonald "timacdonald (18 commits)")[![istiak-tridip](https://avatars.githubusercontent.com/u/13367189?v=4)](https://github.com/istiak-tridip "istiak-tridip (11 commits)")[![michaelnabil230](https://avatars.githubusercontent.com/u/46572405?v=4)](https://github.com/michaelnabil230 "michaelnabil230 (7 commits)")[![utsavsomaiya](https://avatars.githubusercontent.com/u/96036522?v=4)](https://github.com/utsavsomaiya "utsavsomaiya (5 commits)")[![pushpak1300](https://avatars.githubusercontent.com/u/31663512?v=4)](https://github.com/pushpak1300 "pushpak1300 (4 commits)")[![taylorotwell](https://avatars.githubusercontent.com/u/463230?v=4)](https://github.com/taylorotwell "taylorotwell (3 commits)")[![pascalbaljet](https://avatars.githubusercontent.com/u/8403149?v=4)](https://github.com/pascalbaljet "pascalbaljet (3 commits)")[![ArthurYdalgo](https://avatars.githubusercontent.com/u/25585428?v=4)](https://github.com/ArthurYdalgo "ArthurYdalgo (2 commits)")[![devajmeireles](https://avatars.githubusercontent.com/u/60591772?v=4)](https://github.com/devajmeireles "devajmeireles (2 commits)")[![emhashef](https://avatars.githubusercontent.com/u/45512247?v=4)](https://github.com/emhashef "emhashef (2 commits)")[![SuperDJ](https://avatars.githubusercontent.com/u/6484766?v=4)](https://github.com/SuperDJ "SuperDJ (2 commits)")[![hosmelq](https://avatars.githubusercontent.com/u/1166143?v=4)](https://github.com/hosmelq "hosmelq (2 commits)")[![nckrtl](https://avatars.githubusercontent.com/u/18613261?v=4)](https://github.com/nckrtl "nckrtl (2 commits)")[![owenconti](https://avatars.githubusercontent.com/u/791222?v=4)](https://github.com/owenconti "owenconti (1 commits)")[![r3Fuze](https://avatars.githubusercontent.com/u/840291?v=4)](https://github.com/r3Fuze "r3Fuze (1 commits)")[![thaqebon](https://avatars.githubusercontent.com/u/29402142?v=4)](https://github.com/thaqebon "thaqebon (1 commits)")[![WendellAdriel](https://avatars.githubusercontent.com/u/11641518?v=4)](https://github.com/WendellAdriel "WendellAdriel (1 commits)")[![aktasumut34](https://avatars.githubusercontent.com/u/61461131?v=4)](https://github.com/aktasumut34 "aktasumut34 (1 commits)")[![y-l-g](https://avatars.githubusercontent.com/u/116063953?v=4)](https://github.com/y-l-g "y-l-g (1 commits)")

---

Tags

phplaravelroutestypescript

###  Code Quality

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/laravel-wayfinder/health.svg)

```
[![Health](https://phpackages.com/badges/laravel-wayfinder/health.svg)](https://phpackages.com/packages/laravel-wayfinder)
```

###  Alternatives

[laravel/ui

Laravel UI utilities and presets.

2.7k134.9M601](/packages/laravel-ui)[laravel/breeze

Minimal Laravel authentication scaffolding with Blade and Tailwind.

3.0k31.3M148](/packages/laravel-breeze)[laravel/cashier

Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services.

2.5k25.9M107](/packages/laravel-cashier)[laravel/boost

Laravel Boost accelerates AI-assisted development by providing the essential context and structure that AI needs to generate high-quality, Laravel-specific code.

3.5k10.6M274](/packages/laravel-boost)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k12.1M99](/packages/laravel-pulse)[laravel/folio

Page based routing for Laravel.

608453.9k27](/packages/laravel-folio)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
