# Typed Laravel routes in Vue with Wayfinder

> Wayfinder writes a TypeScript function per controller action. The Inertia form takes that function. You do not add a second router.

- URL: https://laravel-vuejs.space/laravel-wayfinder-vue
- Author: Anass Ez-zouaine (https://laravel-vuejs.space/author/anass-ez-zouaine)
- Published: 2026-10-10
- Topics: Laravel, VueJs, Inertia, TypeScript

You rename a route, every form that posted to the old string breaks, and nothing tells you until a user clicks. Wayfinder turns Laravel routes into TypeScript functions, so the build fails instead. Here is how the kit uses it.

> **TL;DR**
>
> -   The starter kit already ships Wayfinder; `npm run dev` regenerates files as routes change.
> -   Import `store` from `@/actions/App/Http/Controllers/PostController` and pass `:action="store()"`. No `method` needed.
> -   `store.url()` is just a string, so a string href is a GET.
> -   Clear a stale `route:cache` before `wayfinder:generate` on deploy.
>
> **What you'll learn**
>
> -   How Wayfinder generates actions from your routes
> -   How to post a form to `store()`
> -   What breaks on deploy and how to avoid it
>
> **Who it's for:** Laravel + Vue developers on the starter kit
>
> **Applies to:** Laravel 13 · Wayfinder · Inertia 3 · Vue 3 · TypeScript

The Vue starter kit already ships Wayfinder. It reads the Laravel routes and writes TypeScript functions for the controller actions. A form then posts to `store()` instead of a string you can typo. This is not Vue Router. Inertia still navigates. Adding a client router beside it is the mistake [the stack guide](https://laravel-vuejs.space/laravel-vue-in-2026) warns about.

Typed props on the page are a separate job: [TypeScript props](https://laravel-vuejs.space/typescript-laravel-vue-pages).

## Generate

The Vite plugin in the kit regenerates the files while `npm run dev` is running. After you add a controller, run the command yourself if the import is missing.

```bash
php artisan wayfinder:generate
```

> **Gotcha: stale route cache on deploy**
>
> The files land in `resources/js/wayfinder`, `resources/js/actions`, and `resources/js/routes`. You can gitignore all three. They are rebuilt. On deploy, generate against the routes you are shipping. A stale `route:cache` from the previous release makes Wayfinder skip new routes, and Vite then fails looking for a file that was never written. Clear that cache before generating. The rest of the build is the [deploy guide](https://laravel-vuejs.space/deploy-laravel-vue).

## The form

**A string you can typo:**

`resources/js/pages/posts/Create.vue`
```vue
<Form action="/posts" method="post">
```

**A generated, typed action:**

`resources/js/pages/posts/Create.vue`
```vue
<Form :action="store()">
```

Import `store` from the file Wayfinder wrote for `PostController`. With the kit’s `@` alias pointing at `resources/js`, that path is the one below. If your generate path differs, import the file that is actually on disk.

`resources/js/pages/posts/Create.vue`
```vue
<script setup lang="ts">
import { Form } from "@inertiajs/vue3";
import { store } from "@/actions/App/Http/Controllers/PostController";
</script>

<template>
  <Form :action="store()">
    <input name="title" />
    <input name="excerpt" />
    <button type="submit">Save</button>
  </Form>
</template>
```

Inertia reads the URL and the HTTP method from the Wayfinder object. You do not also pass `method="post"` unless you are posting to a plain string, which is what the [CRUD guide](https://laravel-vuejs.space/laravel-inertia-vue-crud) does before this page. `store()` with no arguments matches `POST /posts`. An update action that needs the id is `update(post.id)` from the same generated module. Use the function the generator named after the controller method.

> **Heads up: store() vs store.url()**
>
> A `<Link>` infers the method from that same object: `:href="store()"`. `store()` is a POST, so the link is a POST. `store.url()` is only the URL string, and a string href is a GET. Check the generated file before you invent a helper. The generator is the API. This page does not describe a second one.

> **Watch the build catch a rename**
>
> Rename `store` to `save` in `PostController` and its route, then run `php artisan wayfinder:generate` and `npx vue-tsc --noEmit`. The old import now fails type-checking instead of failing in the browser.

## Where this stops

Wayfinder does not validate the body. The form request from [Precognition](https://laravel-vuejs.space/laravel-precognition-vue) still does. It does not know which user may call `update`. That is a [policy](https://laravel-vuejs.space/laravel-vue-policies). A tutorial that says `route()` and Ziggy is the [Ziggy map](https://laravel-vuejs.space/laravel-ziggy-vue). Do not install that package beside these generated functions.

## Recap

- Wayfinder writes one TypeScript function per controller action.
- Pass the function to `<Form>` or `<Link>`; Inertia reads URL and method.
- Regenerate after new routes; clear `route:cache` first on deploy.
- Validation and authorization still live in Laravel.

## FAQ

**Q: Does the Laravel Vue starter kit use Ziggy or Wayfinder?**

Wayfinder. It generates typed functions per controller action; Ziggy is not installed.

**Q: Why is my Wayfinder import missing?**

The file was not generated yet. Run `php artisan wayfinder:generate`, and on deploy clear a stale `route:cache` first.

**Q: Should I commit the Wayfinder generated files?**

You can gitignore `resources/js/wayfinder`, `resources/js/actions` and `resources/js/routes`; they are rebuilt.

## Next steps

- [Ziggy or Wayfinder](https://laravel-vuejs.space/laravel-ziggy-vue)
- [TypeScript props for Laravel + Vue pages](https://laravel-vuejs.space/typescript-laravel-vue-pages)
- [CRUD with Inertia and Vue](https://laravel-vuejs.space/laravel-inertia-vue-crud)

## Sources

- [Laravel Wayfinder on GitHub](https://github.com/laravel/wayfinder)
- [Inertia v3: Forms](https://inertiajs.com/docs/v3/the-basics/forms)
