> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Presentación de Laravel Wayfinder

> Se explica Laravel Wayfinder, el paquete que sustituye a Ziggy y ha sido adoptado en los starter kits de Inertia. Se presenta en detalle desde el mecanismo para conectar backend Laravel y frontend TypeScript de forma type-safe, las diferencias con Ziggy, la instalación y el uso básico, hasta las funcionalidades de nueva generación que se desarrollan en la rama next.

## ¿Qué es Wayfinder?

**Laravel Wayfinder** es un paquete que conecta backend Laravel y frontend TypeScript con cero fricción. Genera automáticamente funciones TypeScript completamente tipadas a partir de controladores y rutas, con lo que puedes invocar directamente como funciones los endpoints de Laravel desde el código de frontend.

Ya no es necesario hardcodear URLs, gestionar manualmente los parámetros de ruta ni sincronizar a mano los cambios del backend.

<Info>
  Wayfinder está en versión Beta (actualmente v0.1.x). La API puede cambiar antes de la release de v1.0.0. Todos los cambios importantes se registran en el [CHANGELOG](https://github.com/laravel/wayfinder/blob/main/CHANGELOG.md).
</Info>

***

## Diferencias entre Ziggy y Wayfinder

### ¿Qué es Ziggy?

[Ziggy](https://github.com/tighten/ziggy) es un helper de rutas ampliamente usado durante años en el ecosistema Laravel. Publicaba las definiciones de rutas de Laravel al lado JavaScript, y permitía generar URLs con formas como `route('posts.show', { id: 1 })`.

### Por qué se ha sustituido por Wayfinder

Ziggy trata los nombres de rutas y los parámetros como cadenas, por lo que tenía limitaciones de compatibilidad con TypeScript. Los typos en nombres de rutas o los nombres de parámetro incorrectos solo se convierten en errores en tiempo de ejecución.

Wayfinder tiene un diseño TypeScript-first y genera los métodos de controlador como **funciones importables**.

| Elemento              | Ziggy                                    | Wayfinder                                        |
| --------------------- | ---------------------------------------- | ------------------------------------------------ |
| Referencia a rutas    | `route('posts.show', { id: 1 })`         | `import { show } from "@/actions/..."`           |
| Seguridad de tipos    | Definiciones de tipo limitadas           | Tipos TypeScript completos                       |
| Soporte IDE           | Autocompletado débil                     | Autocompletado y verificación de tipos completos |
| Tree-shaking          | Todas las rutas se incluyen en el bundle | Solo las rutas usadas van al bundle              |
| Momento de generación | Se inyectan en runtime                   | Generación estática en tiempo de build           |

En los starter kits de Laravel basados en Inertia (React, Vue, Svelte), Wayfinder se adopta por defecto.

***

## Instalación

### 1. Instala el paquete del lado servidor con Composer

```bash theme={null}
composer require laravel/wayfinder
```

### 2. Instala el plugin de Vite con NPM

```bash theme={null}
npm i -D @laravel/vite-plugin-wayfinder
```

### 3. Añade el plugin a `vite.config.js`

```ts theme={null}
import { wayfinder } from "@laravel/vite-plugin-wayfinder";
import { defineConfig } from "vite";
import laravel from "laravel-vite-plugin";

export default defineConfig({
    plugins: [
        laravel({
            input: ["resources/js/app.ts"],
            refresh: true,
        }),
        wayfinder(),
    ],
});
```

Al añadir el plugin de Vite, mientras el servidor de desarrollo esté arrancado, se regeneran automáticamente los archivos TypeScript cada vez que cambian archivos PHP o de rutas.

***

## Generación del archivo de definiciones TypeScript

Con el comando `wayfinder:generate` se generan los archivos TypeScript.

```bash theme={null}
php artisan wayfinder:generate
```

Por defecto se generan tres directorios bajo `resources/js`.

```
resources/js/
├── actions/         # Funciones de acciones de controlador
│   └── App/Http/Controllers/
│       └── PostController.ts
├── routes/          # Funciones de rutas con nombre
│   └── post.ts
└── wayfinder/       # Archivo de definiciones de tipo
    └── types.ts
```

<Tip>
  Como los archivos generados se regeneran completamente en cada build, se recomienda añadirlos a `.gitignore`. Excluye a la vez los tres directorios `wayfinder`, `actions` y `routes`.
</Tip>

Para cambiar el destino de salida, usa la opción `--path`.

```bash theme={null}
php artisan wayfinder:generate --path=resources/js/api
```

También es posible generar solo las acciones de controlador o solo las rutas.

```bash theme={null}
php artisan wayfinder:generate --skip-actions  # Solo genera rutas
php artisan wayfinder:generate --skip-routes   # Solo genera acciones
```

***

## Uso básico

### Importar y usar acciones

Ejemplo de generación de la URL correspondiente al método `show` de `PostController`.

```ts theme={null}
import { show } from "@/actions/App/Http/Controllers/PostController";

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

Si solo necesitas la URL, usa `.url()`.

```ts theme={null}
show.url(1); // "/posts/1"
```

También puedes indicar un método HTTP concreto.

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

### Cómo pasar parámetros

Las funciones de Wayfinder aceptan parámetros en varios formatos.

```ts theme={null}
import { update } from "@/actions/App/Http/Controllers/PostController";

// Parámetro único
show(1);
show({ id: 1 });

// Varios parámetros
update([1, 2]);
update({ post: 1, author: 2 });
update({ post: { id: 1 }, author: { id: 2 } });
```

Si la ruta especifica un key binding (`/posts/{post:slug}`), puedes usar ese valor.

```ts theme={null}
// Si la ruta es /posts/{post:slug}
show("my-new-post");
show({ slug: "my-new-post" });
```

### Importación de todo el controlador

También puedes importar todo el controlador y llamar a los métodos.

```ts theme={null}
import PostController from "@/actions/App/Http/Controllers/PostController";

PostController.show(1);
PostController.index();
```

<Warning>
  Al importar el controlador entero, el tree-shaking no funciona y todas las acciones se incluyen en el bundle. Importarlas por separado mantiene menor el tamaño final del bundle.
</Warning>

### Controladores de acción única

En los controladores de acción única (Invokable Controller), llamas directamente a la función importada.

```ts theme={null}
import StorePostController from "@/actions/App/Http/Controllers/StorePostController";

StorePostController(); // { url: "/posts", method: "post" }
```

### Importar rutas con nombre

Para acceder por nombre de ruta, usa los archivos bajo `routes/`.

```ts theme={null}
import { show } from "@/routes/post";

// Si el nombre de la ruta es `post.show`
show(1); // { url: "/posts/1", method: "get" }
```

### Parámetros de consulta

Todas las funciones Wayfinder pueden añadir parámetros de consulta con la opción `query`.

```ts theme={null}
import { show } from "@/actions/App/Http/Controllers/PostController";

show(1, { query: { page: 1, sort_by: "name" } });
// { url: "/posts/1?page=1&sort_by=name", method: "get" }
```

Para fusionar con los parámetros de consulta de la URL actual, usa `mergeQuery`.

```ts theme={null}
// URL actual: /posts/1?page=1&sort_by=category&q=shirt

show.url(1, { mergeQuery: { page: 2, sort_by: "name" } });
// "/posts/1?page=2&sort_by=name&q=shirt"

// Para eliminar un parámetro, indica null
show.url(1, { mergeQuery: { sort_by: null } });
// "/posts/1?page=1&q=shirt"
```

### Variante Form

Si vas a usarlo con formularios HTML tradicionales, genera con la opción `--with-form` y usa la variante `.form`.

```bash theme={null}
php artisan wayfinder:generate --with-form
```

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

// Ejemplo con React
const Page = () => (
    <form {...store.form()}>
        {/* <form action="/posts" method="post"> */}
    </form>
);

const EditPage = () => (
    <form {...update.form(1)}>
        {/* <form action="/posts/1?_method=PATCH" method="post"> */}
    </form>
);
```

***

## Combinar Inertia y Wayfinder

Al combinar los helpers de formulario de Inertia con Wayfinder, puedes enviar formularios sin escribir ni una cadena de URL.

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

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

form.submit(store()); // Envía a POST /posts
```

También se puede usar en el componente `Link`.

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

const Nav = () => (
    <Link href={show(1)}>Ver publicación</Link>
);
```

***

## Adopción en los starter kits

Al crear un proyecto nuevo con `laravel new` y elegir React, Vue o Svelte, se te ofrece una configuración con Wayfinder ya configurado automáticamente. El starter kit incluye:

* Paquete Composer `laravel/wayfinder`
* Paquete NPM `@laravel/vite-plugin-wayfinder`
* Configuración del plugin ya presente en `vite.config.js`
* Directorios generados ya añadidos a `.gitignore`

También puedes hacer la introducción manual en proyectos existentes siguiendo los pasos anteriores.

***

## Tratamiento de nombres de método que chocan con palabras reservadas

A los métodos de controlador con el mismo nombre que palabras reservadas de JavaScript como `delete` o `import`, se les añade el sufijo `Method`.

```ts theme={null}
// Si el controlador tiene un método delete
import { deleteMethod } from "@/actions/App/Http/Controllers/PostController";

deleteMethod(1); // { url: "/posts/1", method: "delete" }
```

***

## Estado actual (v0.1.x)

La versión estable actual se ofrece en la rama `v0.1.x`. A fecha de marzo de 2026, la última versión es **v0.1.15**.

### Historial principal de la serie v0.1.x

| Versión | Contenido principal                                                      |
| ------- | ------------------------------------------------------------------------ |
| v0.1.15 | Compatibilidad con Laravel 13, corrección de crash de vistas Blade       |
| v0.1.13 | Mejora de compatibilidad TypeScript strict de los parámetros de consulta |
| v0.1.7  | Soporte para indicar los parámetros de URL por defecto desde el frontend |
| v0.1.6  | Añadido del plugin de Vite                                               |
| v0.1.5  | Soporte de PHP 8.2, soporte de rutas cacheadas                           |
| v0.1.0  | Release inicial                                                          |

***

## Funcionalidades de nueva generación en desarrollo en la rama next

En la rama `next` se está desarrollando la próxima versión, que amplía notablemente las funcionalidades respecto a la actual v0.1.x.

<Warning>
  La rama `next` se puede instalar con la restricción `dev-next`, pero la API puede cambiar mucho. No se recomienda su uso en producción.
</Warning>

```bash theme={null}
composer require laravel/wayfinder:dev-next
```

### Amplio aumento del alcance del TypeScript generado

Mientras que la v0.1.x se centra solo en rutas y acciones de controlador, la próxima versión genera como TypeScript todo lo siguiente.

```mermaid theme={null}
graph TD
    A["Aplicación Laravel"] --> B["wayfinder:generate"]
    B --> C["Routes & Actions<br>Funciones de URL de ruta"]
    B --> D["Form Requests<br>Tipos de validación"]
    B --> E["Eloquent Models<br>Interfaces de modelo"]
    B --> F["PHP Enums<br>Constantes TypeScript"]
    B --> G["Inertia Page Props<br>Tipos de page props"]
    B --> H["Broadcast Channels<br>Tipos de canales"]
    B --> I["Broadcast Events<br>Tipos de payload de eventos"]
    B --> J["Environment Variables<br>Tipos de import.meta.env"]
```

### Generación de tipos TypeScript de Form Request

```php theme={null}
class StorePostRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'title'   => ['required', 'string', 'max:255'],
            'content' => ['required', 'string'],
            'tags'    => ['nullable', 'array'],
            'tags.*'  => ['string'],
        ];
    }
}
```

A partir del Form Request anterior se genera el siguiente tipo.

```ts theme={null}
export type Request = {
    title: string;
    content: string;
    tags?: string[] | null;
};
```

### Generación de tipos de modelos Eloquent

```php theme={null}
class User extends Model
{
    protected $casts = [
        'email_verified_at' => 'datetime',
        'is_admin' => 'boolean',
    ];

    public function posts(): HasMany
    {
        return $this->hasMany(Post::class);
    }
}
```

A partir del modelo anterior se generan los tipos en `types.d.ts`.

```ts theme={null}
export namespace App.Models {
    export type User = {
        id: number;
        name: string;
        email: string;
        email_verified_at: string | null;
        is_admin: boolean;
        posts: App.Models.Post[];
    };
}
```

### Conversión de Enum PHP a TypeScript

```php theme={null}
enum PostStatus: string
{
    case Draft = 'draft';
    case Published = 'published';
    case Archived = 'archived';
}
```

Se generan tanto los tipos como las constantes.

```ts theme={null}
// Definición de tipo (types.d.ts)
export namespace App.Enums {
    export type PostStatus = "draft" | "published" | "archived";
}

// Constantes (App/Enums/PostStatus.ts)
export const Draft = "draft";
export const Published = "published";
export const Archived = "archived";

export const PostStatus = { Draft, Published, Archived } as const;
```

### Cambio del directorio de salida

En v0.1.x se dividía en tres directorios `actions/`, `routes/` y `wayfinder/`, pero en la próxima versión se agrupa bajo `resources/js/wayfinder`.

```
resources/js/wayfinder/
├── App/Http/Controllers/
│   └── PostController.ts    # Funciones de acción (se elimina actions/)
├── routes/
│   └── post.ts              # Rutas con nombre (igual)
├── broadcast-channels.ts    # Canales de broadcast
├── broadcast-events.ts      # Eventos de broadcast
└── types.d.ts               # Todas las definiciones de tipo (cambiado desde types.ts)
```

### Principales cambios de v0.1.x a next

* La ruta de importación cambia de `@/actions/...` a `@/wayfinder/...`
* Las flags `--skip-actions`, `--skip-routes` y `--with-form` se eliminan y pasan al archivo de configuración
* `types.ts` cambia a `types.d.ts`

***

## Conclusión

Laravel Wayfinder es un paquete que rediseña con enfoque TypeScript-first la funcionalidad que ofrecía Ziggy de "referenciar rutas de Laravel desde JavaScript". Con el enfoque de importar y usar las funciones generadas, mejora enormemente la seguridad de tipos, el soporte de IDE y el tree-shaking.

Incluso con la actual v0.1.x ya se logra la referencia type-safe de rutas y acciones de controlador, y se adopta por defecto en los starter kits de Laravel basados en Inertia. En la próxima versión en desarrollo en la rama `next` está previsto que evolucione a una base type-safe más amplia, generando también como TypeScript Form Requests, modelos Eloquent, Enums y page props de Inertia.

<Card title="GitHub de Laravel Wayfinder" icon="github" href="https://github.com/laravel/wayfinder">
  Código fuente, CHANGELOG e issues aquí.
</Card>

<Card title="Vite Plugin Wayfinder" icon="bolt" href="https://github.com/laravel/vite-plugin-wayfinder">
  Detalles de las opciones de configuración del plugin de Vite aquí.
</Card>


## Related topics

- [Presentación del paquete Blaze](/es/blog/blaze-introduction.md)
- [Casos de uso prácticos de Laravel Pennant](/es/blog/laravel-pennant.md)
- [Técnicas prácticas de Laravel Telescope](/es/blog/telescope-introduction.md)
- [Laravel PAO — Herramienta de optimización de salida para agentes de IA](/es/blog/pao-introduction.md)
- [Laravel Chisel — Biblioteca de scripts de post-instalación para starter kits](/es/blog/chisel-introduction.md)
