Laravel 12 RouteServiceProvider Configuration Tutorial

In this Laravel 12 tutorial titled “laravel 12 RouteServiceProvider configuration tutorial “, you’ll learn how to configure custom route Step by Step with example.

In Laravel 12, the routing system has undergone a significant transformation. The traditional RouteServiceProvider.php file that existed in earlier versions has been completely removed, replaced with a modern, more intuitive configuration system in bootstrap/app.php. This change simplifies route management while providing more control and flexibility for developers.

If you’re upgrading from Laravel 10 or 11, or if you’re new to Laravel 12, this comprehensive guide will walk you through understanding how routes are now configured, customized, and organized in your Laravel 12 applications.

Prerequisites

Before diving into this tutorial, ensure you have:

  • A fresh Laravel 12 installation or an existing Laravel 12 project
  • Basic understanding of Laravel routing concepts (Route::get, Route::post, etc.)

What Happened to RouteServiceProvider?

In Laravel 10 and earlier versions, route configuration was handled through app/Providers/RouteServiceProvider.php.

 public function boot()
    {
     

        $this->routes(function () {
                Route::middleware('web')
                ->prefix('admin')
                ->group(base_path('routes/admin.php'));
        });
    }

While this approach worked, it added an extra layer of abstraction. Developers had to understand service providers, the boot method, and the routes closure—multiple concepts bundled together.

The Laravel 12 Approach

Laravel 12 eliminates this complexity by moving route configuration directly into bootstrap/app.php, where all application setup happens. This is part of Laravel’s broader simplification initiative that began in Laravel 11.

Default configuration in Laravel 12:

<?php

use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {
        //
        ]);
          
    })
    ->withExceptions(function (Exceptions $exceptions) {
        //
    })->create();

Benefits of this approach:

  • All application configuration is in one place
  • Cleaner, more readable code
  • Faster to understand application structure
  • Less boilerplate code
  • Direct access to routing configuration without service provider abstraction

Step 1: Create Your Custom Route File

Let’s create a custom admin route file for managing admin-specific routes.

Create routes/admin.php:

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\LocationController;

Route::get('/show', [LocationController::class, 'show']);
Route::get('/test', [LocationController::class, 'test']);

Read Also : Laravel 12 Restrict/Block User Access from IP Address

Step 2: Register the Route File in bootstrap/app.php

Use the then callback in the withRouting() method:

<?php

use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
         then: function () {
        Route::middleware('web')
            ->prefix('admin')
            ->name('admin.')
            ->group(base_path('routes/admin.php'));
    },
    )
    ->withMiddleware(function (Middleware $middleware) {
          //
    })
    ->withExceptions(function (Exceptions $exceptions) {
        //
    })->create();

What this does:

  • middleware(‘web’): Applies web middleware (session, CSRF protection) to admin routes
  • prefix(‘admin’): All routes get /admin prefix (e.g., /admin/show)
  • name(‘admin.’): All route names get admin. prefix (e.g., admin.show)
  • group(): Loads the admin route file

Now your admin routes are accessible at:

  • http://127.0.0.1:8000/admin/show
  • http://127.0.0.1:8000/admin/test

Step 3: Verify Routes Are Loaded

Run the route list command:

php artisan route:list

You should see your admin routes listed with the /admin prefix:

Laravel 12 RouteServiceProvider Configuration Tutorial
Check Route List

Multiple Custom Route Files

For a larger application, you might want to organize routes by feature or role:

routes/
├── web.php
├── console.php
├── admin.php
├── vendor.php

Register in bootstrap/app.php:

->withRouting(
    web: __DIR__.'/../routes/web.php',
    commands: __DIR__.'/../routes/console.php',
    health: '/up',
    then: function () {
        // Admin routes
        Route::middleware('web')
            ->prefix('admin')
            ->name('admin.')
            ->group(base_path('routes/admin.php'));

        // Vendor routes
        Route::middleware('web')
            ->prefix('vendor')
            ->name('vendor.')
            ->group(base_path('routes/vendor.php'));
    },
)

Read Also : Laravel 12 Database Seeder One to Many Relationship Example

Troubleshooting Common Issues

Issue 1: Custom Routes Not Loading

Problem: You’ve created a custom route file but routes aren’t showing in route:list.

Solution: Ensure you’ve registered the route file in bootstrap/app.php with the then callback:

->withRouting(
    // ... default configuration
    then: function () {
        Route::middleware('web')
            ->prefix('custom')
            ->group(base_path('routes/custom.php'));
    },
)

Then clear the route cache:

php artisan route:clear

Issue 2: Middleware Not Applying

Problem: Routes aren’t respecting the middleware you specified.

Solution: Check that middleware is registered and applied in the correct order:

// Register middleware alias first
->withMiddleware(function (Middleware $middleware) {
    $middleware->alias(['admin' => IsAdmin::class]);
})

// Then use in routes
then: function () {
    Route::middleware('admin')  // Make sure this matches the registered alias
        ->group(base_path('routes/admin.php'));
}

Conclusion

Laravel 12’s approach to route configuration through bootstrap/app.php represents a significant improvement in code organization and developer experience. By eliminating the RouteServiceProvider class, Laravel has made it easier to understand the application bootstrap process at a glance.

key takeaways:

  • All route configuration now happens in bootstrap/app.php
  • Use the withRouting() method to configure web, API, and console routes
  • The then callback allows you to register additional custom route files
  • The using callback provides complete routing control (use with caution)
  • Organize routes into separate files for better maintainability
  • Always cache routes in production for optimal performance
  • As you build more complex Laravel 12 applications, remember that keeping your routes organized and clearly named will make your codebase more maintainable and easier to understand for both you and your team members.

Q1: Can I still use service providers for routing?

In Laravel 12, routing is primarily handled in bootstrap/app.php. However, you can register additional routes in service providers if needed, but it’s not the recommended approach for main route configuration.

Q2: What’s the difference between then and using callbacks?

The then callback registers additional routes alongside the default web and API routes. The using callback takes complete control—you must manually register all routes (but the health check is still available).

Q3: How do I migrate from RouteServiceProvider to the new system?

Move your route registration logic from RouteServiceProvider::boot() method to the then callback in bootstrap/app.php. Replace $this->routes(function() { … }) with the then callback.

Q4: Can I group routes by domain?

Yes! Use the domain() method in your route definitions:
Route::domain(‘api.myapp.com’)
->prefix(‘v1’)
->middleware(‘api’)
->group(function () {
Route::get(‘/posts’, [PostController::class, ‘index’]);
});

Q5: How do I test route registration?

Use the artisan commands:
# List all routes
php artisan route:list
# List only specific routes
php artisan route:list –path=admin