{"slug": "typed-routes-from-laravel-to-react-with-wayfinder", "title": "★ Typed routes from Laravel to React with Wayfinder", "summary": "Spatie's Laravel Wayfinder package generates typed TypeScript functions for every named route and controller in a Laravel app, letting React frontends call `.url()` on imported functions instead of hardcoding URL strings, according to a post describing its use in the Spatie-built helpdesk There There. The package's Vite plugin watches Laravel routes and controllers during development and regenerates the typed functions on change, so renaming a route parameter or controller in PHP breaks the TypeScript build rather than production. There There, built with Laravel and Inertia, is in private beta with early access applications open at there-there.app.", "body_md": "I've been writing about [There There](https://there-there.app) a lot lately. It's a helpdesk we're building at Spatie, born from two decades of running our own customer support for our open source work and SaaS apps. After all that time being the customer of other helpdesks, we finally started on the one we actually wanted to use.\n\nOur take on AI here is to aim it at the support agent, not the customer. The human owns the conversation. The model makes the reply a little cleaner and a little faster. There There is in private beta, and you can apply for early access at [there-there.app](https://there-there.app).\n\nWe're building There There with Laravel and Inertia. One package we've come to rely on is [Laravel Wayfinder](https://github.com/laravel/wayfinder). It generates typed TypeScript functions for every route and controller in your Laravel app, so the frontend talks to the backend without a single hardcoded URL. This post is about why that matters.\n\nA React codebase quickly fills up with URL strings. Every `fetch`, every form action, every link points to a route by way of a template literal. Then you rename a route in Laravel, or add a required parameter, and nothing breaks at compile time. You find out in production, or when a teammate clicks the wrong thing.\n\nWayfinder fixes this by generating a function per named route. You import it and call `.url()` to build the URL.\n\nHere's a snippet from our team membership toggle.\n\n``` js\nimport {\n    add as addTeamMember,\n    remove as removeTeamMember,\n} from '@/routes/app/settings/workspace/teams/members';\n\nremoveTeamMember.url({ team: team.ulid, user: member.ulid });\naddTeamMember.url({ team: team.ulid, user: member.ulid });\n```\n\nTwo things are worth pointing out. First, the parameters are type-checked. If you rename the `user` route parameter to `member`, TypeScript catches every caller. Second, the route names map cleanly to import paths, so finding them is just autocomplete.\n\nWayfinder also generates a typed function per controller. We use that when we talk to an endpoint via plain `fetch`, outside of an Inertia visit. Here's the retry action for a failed outbound message.\n\n``` python\nimport MessageRetryController from '@/actions/App/Http/Controllers/Tickets/MessageRetryController';\n\nawait fetch(\n    MessageRetryController.url({ ticket: current.ulid, message: message.ulid }),\n    { method: 'POST' },\n);\n```\n\nSame deal. The URL is type-safe, the parameters are checked, and renaming the controller in PHP breaks the TypeScript build rather than production.\n\nTo make all of this work, we hook Wayfinder into Vite. Here's the relevant bit of our `vite.config.js`.\n\n``` js\nimport { wayfinder } from \"@laravel/vite-plugin-wayfinder\";\n\nexport default defineConfig({\n    plugins: [\n        // ...\n        wayfinder(),\n    ],\n});\n```\n\nThe plugin watches your Laravel routes and controllers during development, and regenerates the typed functions whenever something changes. Imports stay in sync with your backend without any manual step.\n\nTODO: screenshot of editor autocomplete showing the parameter shape for a Wayfinder-generated function, or a TypeScript error firing when a parameter is missing.\n\nWayfinder has shaved a whole category of bug off our work. No more grep-the-codebase when a route changes, no more \"why is this fetch returning 404\", no more arguing about trailing slashes. You write the route in Laravel, import it in TypeScript, and the two stay honest with each other.\n\nYou can read more about it in [the Wayfinder repo on GitHub](https://github.com/laravel/wayfinder). And if you'd like to try There There yourself, we're in private beta right now and you can apply for early access at [there-there.app](https://there-there.app).", "url": "https://wpnews.pro/news/typed-routes-from-laravel-to-react-with-wayfinder", "canonical_source": "https://freek.dev/3088-typed-routes-from-laravel-to-react-with-wayfinder", "published_at": "2026-10-09 10:30:14+00:00", "updated_at": "2026-10-09 10:53:43.013914+00:00", "lang": "en", "topics": ["developer-tools"], "entities": ["Spatie", "Laravel Wayfinder", "There There", "Laravel", "Inertia", "React", "TypeScript", "Vite"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/typed-routes-from-laravel-to-react-with-wayfinder", "markdown": "https://wpnews.pro/news/typed-routes-from-laravel-to-react-with-wayfinder.md", "text": "https://wpnews.pro/news/typed-routes-from-laravel-to-react-with-wayfinder.txt", "jsonld": "https://wpnews.pro/news/typed-routes-from-laravel-to-react-with-wayfinder.jsonld"}}