Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Folio Laravel Package

laravel/folio

Laravel Folio is a page-based router for Laravel that maps routes from your filesystem to simplify routing. Define pages as files, reduce route boilerplate, and build apps faster with a clean, convention-driven approach.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require laravel/folio
    php artisan folio:install
    

    This generates the default resources/views/pages directory and config file.

  2. First Route: Create a Blade file at resources/views/pages/about.blade.php. Access it via /about—no manual route definition needed.

  3. Verify: Run php artisan folio:list to see auto-generated routes.

Where to Look First

  • Configuration: config/folio.php (adjust path, domain, or middleware).
  • Commands:
    • folio:install (setup)
    • folio:list (view routes)
    • folio:make (generate a new page file with namespace support).
  • Documentation: Laravel Folio Docs for advanced features like model binding or custom pipelines.

First Use Case

Static Marketing Site:

  • Place all pages in resources/views/pages/ (e.g., home.blade.php, contact.blade.php).
  • Access via /home, /contact without routes/web.php changes.
  • Use php artisan folio:list to debug route conflicts or missing pages.

Implementation Patterns

Core Workflows

  1. File-Based Routing:

    • Convention: resources/views/pages/{slug}.blade.php/{slug}.
    • Example:
      resources/views/
      └── pages/
          ├── about.blade.php       # /about
          ├── blog/
          │   ├── post-1.blade.php  # /blog/post-1
          │   └── index.blade.php   # /blog (implicit index)
      
    • Custom Paths: Configure path in config/folio.php to use resources/views/content/.
  2. Model Binding:

    • Bind routes to Eloquent models by naming files after model slugs (e.g., resources/views/pages/posts/{post}.blade.php).
    • Access the model in the view via $post (injected automatically).
    • Example:
      // routes/web.php (optional, for custom logic)
      Folio::bind('posts', Post::class);
      
  3. Middleware:

    • Apply middleware globally in config/folio.php:
      'middleware' => ['web', 'auth'],
      
    • Override per route via annotations in Blade files:
      @middleware(['guest'])
      
  4. Dynamic Domains:

    • Route to subdomains by prefixing files:
      resources/views/
      └── pages/
          ├── admin/
          │   └── dashboard.blade.php  # admin.example.com/dashboard
          └── blog/
              └── post.blade.php       # blog.example.com/post
      
    • Configure domains in config/folio.php:
      'domains' => [
          'admin' => 'admin.example.com',
          'blog'  => 'blog.example.com',
      ],
      
  5. Nested Routes:

    • Use directories to imply nesting:
      resources/views/pages/
      └── products/
          ├── electronics/
          │   └── laptops.blade.php  # /products/electronics/laptops
          └── index.blade.php        # /products
      

Integration Tips

  • Hybrid Routing: Combine Folio with traditional routes in routes/web.php:
    Route::get('/legacy', function () { ... });
    Folio::mount(); // Mount Folio after legacy routes.
    
  • APIs: Use Folio for admin panels while keeping API routes in routes/api.php.
  • Testing: Use Folio::fake() in tests to mock routes:
    use Laravel\Folio\Facades\Folio;
    
    public function test_page_routing()
    {
        Folio::fake();
        $response = $this->get('/about');
        $response->assertViewIs('pages.about');
    }
    
  • Caching: Run php artisan route:cache to cache Folio routes (works alongside Laravel’s route caching).

Gotchas and Tips

Pitfalls

  1. Route Overlaps:

    • Issue: Files like index.blade.php in nested directories may conflict with parent routes.
    • Fix: Explicitly name routes in Blade files:
      @route(['name' => 'products.index'])
      
    • Debug: Use php artisan folio:list --verbose to inspect route conflicts.
  2. Case Sensitivity:

    • Issue: Windows/Linux path differences can cause routes to fail silently.
    • Fix: Use consistent casing in filenames (e.g., About.blade.php vs. about.blade.php).
  3. Middleware Conflicts:

    • Issue: Global middleware in config/folio.php may override app-wide middleware.
    • Fix: Use unless or only in app/Http/Kernel.php:
      protected $middleware = [
          // ...
          FolioMiddleware::class => ['unless' => ['folio']],
      ];
      
  4. Model Binding Quirks:

    • Issue: Custom model keys (e.g., UUID) may not bind correctly.
    • Fix: Override the binding in FolioServiceProvider:
      Folio::bind('posts', Post::class, 'uuid');
      
  5. Wildcard Directories:

    • Issue: Directories with special characters (e.g., my-page) may break routing.
    • Fix: Use hyphens or underscores in directory names.

Debugging

  • Route Listing: Always start with php artisan folio:list --verbose.
  • View Events: Listen for ViewMatched events to debug unresolved views:
    event(new ViewMatched($view, $route));
    
  • Log Routes: Enable debug logging in config/folio.php:
    'debug' => env('FOLIO_DEBUG', false),
    

Configuration Quirks

  1. Multiple Mount Paths:

    • Use Case: Mount Folio in multiple locations (e.g., resources/views/pages and resources/views/admin).
    • Config:
      'paths' => [
          'pages' => 'resources/views/pages',
          'admin' => 'resources/views/admin',
      ],
      
    • Note: Ensure no path overlaps (e.g., admin/dashboard vs. pages/admin/dashboard).
  2. Custom View Resolver:

    • Use Case: Use a non-Blade template engine (e.g., Inertia.js).
    • Solution: Extend the FolioViewFinder:
      Folio::extend(function ($app) {
          $app->singleton('view.finder', function () {
              return new CustomFolioViewFinder;
          });
      });
      
  3. Terminable Middleware:

    • Use Case: Redirect or terminate requests early (e.g., for auth).
    • Example:
      Folio::terminable(function ($request) {
          if ($request->ip() === '123.123.123.123') {
              abort(403);
          }
      });
      

Extension Points

  1. Custom Route Naming:

    • Override the default naming convention (e.g., pages.{slug}):
      Folio::name(function ($view) {
          return 'custom.'.str_replace('/', '.', $view);
      });
      
  2. Pipeline Extensions:

    • Add middleware to the Folio pipeline via the service container:
      $app->extend('folio.pipeline', function ($pipeline) {
          $pipeline->append(\App\Http\Middleware\CustomMiddleware::class);
          return $pipeline;
      });
      
  3. Dynamic Route Generation:

    • Generate routes programmatically:
      $routes = Folio::getRoutes();
      foreach ($routes as $route) {
          // Process routes (e.g., log, cache, or modify)
      }
      
  4. Event Listeners:

    • Listen for FolioRegistered (after routes are registered) or FolioBooted (after booting):
      Folio::listen('FolioRegistered', function () {
          // Modify routes dynamically
      });
      

Performance Tips

  • Avoid Deep Nesting: Deep directory structures (e.g., a/b/c/d.blade.php) can slow down route resolution.
  • Cache Routes: Use php artisan route:cache in production to improve performance.
  • Lazy Loading: Folio commands (e.g., folio:make) are lazy-loaded by default (v1.1.7+), reducing startup overhead.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport