view('app'))->middleware(['auth', 'verified'])->name('dashboard'); // Server-side logout for the SPA's hard navigation (GET /logout). // Intentionally unnamed: the `logout` route name belongs to Fortify's POST /logout, // which the Blade auth forms target via route('logout'). Both can share the /logout // URL (different verbs), but two routes cannot share a name — that breaks route:cache. Route::get('/logout', function (Request $request) { Auth::logout(); $request->session()->invalidate(); $request->session()->regenerateToken(); return redirect('/'); })->middleware('auth'); Route::middleware(['auth'])->prefix('billing')->name('billing.')->group(function () { Route::get('/checkout/{tier}/{cadence}', [BillingController::class, 'checkout'])->name('checkout'); Route::get('/portal', [BillingController::class, 'portal'])->name('portal'); Route::get('/success', [BillingController::class, 'success'])->name('success'); Route::get('/cancel', [BillingController::class, 'cancel'])->name('cancel'); }); // Server-rendered legal pages — must be registered before the SPA catch-all Route::prefix('legal')->name('legal.')->group(function () { Route::view('/privacy', 'legal.privacy')->name('privacy'); Route::view('/terms', 'legal.terms')->name('terms'); Route::view('/refund', 'legal.refund')->name('refund'); Route::view('/cookies', 'legal.cookies')->name('cookies'); }); // SPA catch-all — must be last Route::get('/{any?}', fn () => view('app'))->where('any', '.*')->name('home');