Cargando…

Esto está tardando más de lo esperado.

Volver al centro de ayuda

Rutas, layouts y middleware

Dónde se carga cada archivo de rutas, qué corre en cada petición, y cómo encajan páginas, barras laterales y la capa de carga.

Tu primera página necesita tres decisiones: en qué archivo de rutas va, en qué layout se renderiza y qué entrada de la barra lateral la abre. Esta guía responde las tres y lista el middleware que ya corre en cada petición para que no lo agregues dos veces.

Archivos de rutas

bootstrap/app.php conecta los archivos. Laravel carga routes/web.php y routes/api.php por su cuenta; el resto se carga en el callback then: con el middleware, prefijo y nombre de abajo.

Archivo Middleware Prefijo Prefijo de nombre Qué vive ahí
routes/web.php web ninguno ninguno La landing, /features, el centro de ayuda, /locale/{locale}, /logs, /offline y los endpoints de web push
routes/auth.php web ninguno ninguno Inicio de sesión, registro, restablecer contraseña y verificación, /logout, /stop-acting, /privacy, /terms, y el área de cuenta bajo /account con auth y security
routes/admin.php web, auth, security, role:admin admin admin. El dashboard de administración, los CRUD de Laravel Front, categories/{type}, dev y webhook-events
routes/app.php web, auth, security, y ensure.subscribed cuando la facturación está activa app app. El producto. El kit sólo trae el dashboard en /app
routes/api.php api api ninguno POST /api/stripe/webhook, detrás de webhook y log.webhook:stripe
routes/console.php Closures de Artisan y la programación; ve Colas y trabajo programado

La verificación de salud responde en /up.

ensure.subscribed se agrega a /app sólo cuando el paquete de facturación está instalado y BILLING_CORE_ENABLED y BILLING_USER_ENABLED no son false; sin facturación el alias no existe y una persona con sesión llega a /app sin suscripción. Ve Activa planes y facturación.

Agrega tus propias rutas

Las páginas del producto van en routes/app.php; heredan el prefijo /app y el nombre app.. Registra un componente Livewire como página completa:

use App\Livewire\App;

Route::livewire('/orders', App\Orders\Index::class)->name('orders');
Route::livewire('/orders/{order}', App\Orders\Show::class)->name('orders.show');

Eso es /app/orders, con nombre app.orders. config('app.home_route') es /app, el lugar al que /home redirige y en el que aterriza el flujo de inicio de sesión; cámbialo en config/app.php cuando el producto empiece en otro lado. Los CRUD de administración van en routes/admin.php como Route::front('Order'), que registra cada ruta del recurso App\Front\Resources\Order; ve El panel de administración.

Middleware en cada petición web

bootstrap/app.php agrega seis clases al grupo web, en este orden.

Middleware Qué hace
LocaleMiddleware Define el idioma: el locale de la cuenta con sesión, si no la elección en sesión del visitante, si no el primer idioma del navegador que la app publica, si no el de respaldo
RememberLastUrl Guarda en la sesión la URL de cada página GET normal como last_non_livewire_url, que lastUrl() lee y que los reportes de error incluyen
CaptureReferralCode En un GET normal, recuerda un código de referido del query string o lo restaura desde la cookie; ve Referidos
SystemValidations Para una persona con sesión, deja en flash los avisos que el layout muestra arriba de la página; hoy, el PIN faltante cuando config('auth.enable_pin') está activo
TrackingMiddleware Cuando config('features.tracking_enabled') está activo, abre una sesión de seguimiento de visitantes en el primer GET normal o cuando llegan fbclid o utm_campaign
UpdateLastLoggedAt Marca last_logged_at en la cuenta con sesión una vez al día

Todos se saltan las peticiones de actualización de Livewire, así que corren una vez por página, no una vez por interacción.

trustProxies(at: '*') confía en cualquier proxy, así que el esquema y la IP del cliente salen de los encabezados reenviados por el balanceador frente a la app.

Alias

Alias Clase
security App\Http\Middleware\Security: manda a /password/request a quien debe cambiar su contraseña y cierra la sesión de una cuenta bloqueada
role, permission, role_or_permission El middleware de permisos de Spatie; ve Roles y permisos
log.webhook App\Http\Middleware\LogWebhookEvent: guarda cada webhook entrante, su respuesta y su error como una fila; ve Rastros de auditoría y eventos de webhook
webhook VerifyWebhookSignature de Cashier
ensure.subscribed EnsureHasSubscription del paquete de facturación, presente sólo cuando la facturación está activa

App\Http\Middleware\IsPWABuilder está atado sólo a /: cuando APP_PWA está activo y la petición viene de la app móvil empaquetada, redirige a /app en lugar de mostrar la landing.

Convenciones de Livewire

config/livewire.php fija dónde va cada cosa.

Ajuste Valor Significado
class_namespace App\Livewire Los componentes son clases bajo app/Livewire/, agrupadas como Admin, App, Auth, Shared y Web
view_path resources/views/livewire Sus vistas reflejan ese árbol
component_layout layouts::app El layout en el que se renderiza un componente de página completa salvo que llame ->layout()
component_namespaces layouts, pages layouts::app es resources/views/layouts/app.blade.php; pages:: apunta a resources/views/pages/
make_command.type class php artisan make:livewire crea una clase más una vista, no un componente de un solo archivo
legacy_model_binding true wire:model="post.title" liga directo a un atributo del modelo
navigate.progress_bar_color #2299dd El color de la barra delgada que se muestra durante wire:navigate

Layouts

resources/views/layouts/base.blade.php es el cascarón HTML: el <head> con el título, el favicon, los assets de Vite y los scripts de WireUI, luego <x-notifications>, <x-dialog>, la capa de carga, la sección content-base y el anfitrión de modales. Los demás layouts lo extienden:

Layout Lo usan
layouts/app.blade.php Cada página con sesión: barra lateral, barra superior con notificaciones, avisos y el menú de la cuenta, migas de pan, mensajes flash y los avisos del sistema
layouts/auth.blade.php Inicio de sesión, registro y los demás formularios de invitado, sin adornos
layouts/web.blade.php La landing y las páginas públicas, con la navegación de marketing
layouts/help.blade.php El centro de ayuda

El layout de la app elige su barra lateral por el primer segmento de la URL: layouts/sidebars/app.blade.php bajo /app, admin.blade.php bajo /admin, account.blade.php bajo /account. Un componente renderiza migas de pan pasándolas al layout:

public function render()
{
    return view('livewire.app.orders.show')->layout('layouts.app', [
        'breadcrumb' => [
            ['label' => __('Orders'), 'url' => '/app/orders'],
            ['label' => $this->order->number],
        ],
    ]);
}

layouts/partials/breadcrumbs.blade.php imprime un enlace de inicio a la raíz de la sección y una entrada por elemento; el último es la página actual y no lleva URL.

Agrega una entrada a la barra lateral

Cada barra lateral renderiza <x-sidebar-menu>, respaldado por App\View\Components\SidebarMenu. Fusiona los elementos que escribes en el archivo Blade con los recursos de Laravel Front de la sección que responden true a showOnMenu() y pasan la política viewAny para la persona con sesión, ordena todo por order y agrupa por menu_group. Los elementos sin grupo forman el bloque sin encabezado de arriba.

Para agregar una página a la barra lateral del producto, edita layouts/sidebars/app.blade.php:

<x-sidebar-menu
    :items="[
        ['name' => 'Dashboard', 'url' => '/app', 'icon' => 'home', 'exact' => true, 'order' => 1],
        ['name' => 'Orders', 'url' => '/app/orders', 'icon' => 'shopping-bag', 'order' => 2],
        ['name' => 'Reports', 'url' => '/app/reports', 'icon' => 'chart-bar', 'menu_group' => 'Analytics', 'show' => auth()->user()->can('viewAny', Report::class)],
    ]"
    :groups="[
        ['name' => 'Analytics', 'order' => 1],
    ]"
/>
Llave Significado
name Pasa por __(), así que agrégalo a lang/
url Se marca activo cuando la URL actual es esa o empieza con ella, salvo que exact sea true
icon Un nombre de Heroicon
order Posición; los elementos sin ella van al final
show Oculta el elemento cuando es false
menu_group Pone el elemento bajo un encabezado plegable; groups ordena los encabezados

Un recurso de Front declara su propio menu_group, menu_order e icon, así que un CRUD aparece en la barra lateral de administración sin tocar el archivo Blade.

La capa de carga

resources/views/components/loading-overlay.blade.php es un spinner de pantalla completa montado una vez en el layout base y controlado por resources/js/app.js. Se muestra solo en la navegación con wire:navigate, en clics a enlaces normales que salen de la página y mientras se envía un formulario con wire:submit. Después de 3 segundos agrega un mensaje y un botón Recargar, para que una petición atorada siempre tenga salida.

Para un botón que no es el envío de un formulario, actívala con el atributo spinner en el elemento que lleva wire:click:

<x-button wire:click="retryPayment" spinner :label="__('Retry payment')" />

Para una subida de archivo, pon spinner en el <input type="file"> mismo, no en el botón que abre el selector, porque la petición arranca en el change del input.

No agregues spinner a campos wire:model.live, filtros, pestañas ni búsquedas: la capa bloquea toda la pantalla y esas interacciones deben sentirse instantáneas.

El cambio de idioma

GET /locale/{locale}, con nombre locale, revisa el código contra las llaves de config('app.languages') y responde 404 a cualquier otro. Para un visitante guarda la elección en la sesión, que LocaleMiddleware lee en la siguiente petición; para una persona con sesión no escribe nada, porque su idioma sale del perfil. En ambos casos redirige de regreso. <x-language-switcher> renderiza un enlace por idioma con locale_url() y sólo para invitados. Ve Idiomas y traducciones.