withRouting( web: __DIR__.'/../routes/web.php', api: __DIR__.'/../routes/api.php', commands: __DIR__.'/../routes/console.php', health: '/up', ) ->withMiddleware(function (Middleware $middleware): void { $middleware->web(append: [ \App\Http\Middleware\HandleInertiaRequests::class, // Runs on every web request; no-ops for guests, redirects authenticated // users who have not finished onboarding (e.g. OAuth users awaiting username). \App\Http\Middleware\EnsureOnboardingComplete::class, ]); $middleware->alias([ 'admin.moderation' => \App\Http\Middleware\EnsureAdminOrModerator::class, 'creator.access' => \App\Http\Middleware\EnsureCreatorAccess::class, 'ensure.onboarding.complete'=> \App\Http\Middleware\EnsureOnboardingComplete::class, 'onboarding' => \App\Http\Middleware\EnsureOnboardingComplete::class, 'normalize.username' => \App\Http\Middleware\NormalizeUsername::class, ]); }) ->withExceptions(function (Exceptions $exceptions): void { // ── 404 / 410 / 403 — web HTML responses only ───────────────────────── $exceptions->render(function ( \Symfony\Component\HttpKernel\Exception\HttpException $e, \Illuminate\Http\Request $request ) { if ($request->expectsJson()) { return null; // Let Laravel produce the default JSON response. } $status = $e->getStatusCode(); // 403 and 401 use their generic Blade views — no extra data needed. if ($status === 403) { return response(view('errors.403', ['message' => $e->getMessage() ?: null]), 403); } if ($status === 401) { return response(view('errors.401'), 401); } if ($status === 410) { return response(view('errors.410'), 410); } // Generic 404 — smart URL-pattern routing to contextual views. if ($status === 404) { return app(\App\Http\Controllers\Web\ErrorController::class) ->handleNotFound($request); } return null; // Fallback to Laravel's default. }); // ── ModelNotFoundException → contextual 404 on web ─────────────────── $exceptions->render(function ( \Illuminate\Database\Eloquent\ModelNotFoundException $e, \Illuminate\Http\Request $request ) { if ($request->expectsJson()) { return null; } return app(\App\Http\Controllers\Web\ErrorController::class) ->handleNotFound($request); }); // ── 500 server errors — log with correlation ID ─────────────────────── $exceptions->render(function ( \Throwable $e, \Illuminate\Http\Request $request ) { if ($request->expectsJson()) { return null; } // Only handle truly unexpected server errors (not HTTP exceptions already handled above). if ($e instanceof \Symfony\Component\HttpKernel\Exception\HttpException) { return null; } // In debug mode let Laravel/Ignition render the full error page. if (config('app.debug')) { return null; } try { $correlationId = app(\App\Services\NotFoundLogger::class)->log500($e, $request); } catch (\Throwable) { $correlationId = 'UNKNOWN'; } return response(view('errors.500', ['correlationId' => $correlationId]), 500); }); })->create();