Folio is Laravel's answer to file-based routing: instead of declaring every route explicitly in routes/web.php, you place a PHP file (usually a Blade/Volt view) inside a designated pages directory, and the path to that file becomes the URL. It's the same convention Next.js and Nuxt popularized for JavaScript frameworks, applied to Laravel's own routing layer — genuinely useful for content-heavy or page-dominant sites, and unnecessary ceremony for an API or an app that's mostly REST controllers.
How the file-to-URL mapping actually works
After installing Folio (composer require laravel/folio and php artisan folio:install), pages live under resources/views/pages by default. pages/index.blade.php becomes /, pages/contact.blade.php becomes /contact, and nested directories become nested paths: pages/settings/profile.blade.php becomes /settings/profile. There's no separate route file to keep in sync with the view — the file's location on disk is the route.
resources/views/pages/index.blade.php -> /
resources/views/pages/contact.blade.php -> /contact
resources/views/pages/settings/profile.blade.php -> /settings/profile
resources/views/pages/posts/[post].blade.php -> /posts/{post}
Dynamic segments and route model binding
Square-bracket filenames define dynamic route segments, exactly like Next.js's convention. [post].blade.php captures a post parameter, and if that parameter's name matches an Eloquent model type-hinted in the page's <?php ... ?> block or a name() call, Folio performs route model binding automatically — resolving the model instance from the route segment the same way a controller method would.
<?php
use App\Models\Post;
use function Laravel\Folio\{middleware, name};
middleware(['auth']);
name('posts.show');
?>
<x-layout>
<h1>{{ $post->title }}</h1>
<div>{{ $post->body }}</div>
</x-layout>
The middleware() and name() helpers called inside the page file itself replace what would otherwise be route-file configuration — so route('posts.show', $post) works from anywhere in the app exactly as it would for a normally declared named route.
Where Folio sits alongside Inertia and Livewire
Folio is a routing convention, not a rendering approach — it works fine with plain Blade views, and it pairs particularly well with Livewire/Volt's single-file component syntax, since a Folio page and a Volt component can be the same file. It's less commonly paired with Inertia, since Inertia's own routing typically flows through standard Laravel routes that dispatch to page components on the frontend framework's side; combining both means picking which one owns route definition for a given section of the app, rather than using both for the same URLs.
When file-based routing is worth adopting, and when it's not
Folio earns its keep on marketing sites, documentation, dashboards with a large number of mostly-static pages, or any app where the page-to-URL mapping is naturally 1:1 and route files were becoming a long list of nearly identical Route::view() calls. It's a poor fit for an API, or for routes that need heavy custom logic before rendering (complex authorization chains, multi-step wizards) where an explicit controller with clear method boundaries is easier to follow than logic embedded in a page file's PHP block. Standard routes and Folio pages can coexist in the same app — it's not all-or-nothing.
Wrapping up
Folio trades explicit route declarations for a directory convention: the file's path is the URL, dynamic segments use bracket syntax with automatic model binding, and middleware/naming are declared inline in the page rather than in a separate routes file. It's a genuine win for page-heavy, mostly-static sections of an app, and not a replacement for controllers on routes that need real request-handling logic.
Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.