Router
Routes are defined in src/resources/src/router/index.ts using Vue Router with createWebHistory.
ts
import { createRouter, createWebHistory } from "vue-router";
import { setupRouteProgress } from "@/plugins/routeProgress";
import { useAuthStore } from "@/stores/auth";
export const routes = [
{
path: "/",
name: "dashlayout",
component: () => import("@/layouts/Layout/index.vue"),
redirect: { path: "/" },
children: [
{
path: "/",
name: "dashboard",
component: () => import("@/pages/dashboard/index.vue"),
meta: { requiresAuth: true }
},
// Add your authenticated pages here
]
},
{
path: "/login",
name: "authlayout",
component: () => import("@/layouts/AuthLayout.vue"),
children: [
{ path: "/login", name: "login", component: () => import("@/pages/auth/login.vue"), meta: { guestOnly: true } },
{ path: "/register", name: "register", component: () => import("@/pages/auth/register.vue"), meta: { guestOnly: true } },
{ path: "/forget-password", name: "forget-password", component: () => import("@/pages/auth/forgetPassword.vue"), meta: { guestOnly: true } },
{ path: "/reset-password", name: "reset-password", component: () => import("@/pages/auth/resetPassword.vue"), meta: { guestOnly: true } },
{ path: "/verify-email", name: "verify-email", component: () => import("@/pages/auth/verifyEmail.vue"), meta: { guestOnly: true } },
]
}
];
const router = createRouter({
history: createWebHistory(),
routes,
scrollBehavior: (_to, _from, savedPosition) => {
if (savedPosition) return savedPosition;
return { top: 0 };
}
});
setupRouteProgress(router);
router.beforeEach(async (to) => {
const auth = useAuthStore();
await auth.bootstrap();
if (to.meta.requiresAuth && !auth.isAuthenticated) {
return { path: "/login", query: { redirect: to.fullPath } };
}
if (to.meta.guestOnly && auth.isAuthenticated) {
return { path: "/" };
}
return true;
});
export default router;Route structure
Two parent layouts with nested child routes:
dashlayout(/) — Dashboard layout with Sidebar + Header + Footer, wraps all authenticated pagesauthlayout(/login) — Centered card layout for guest-only auth pages
Route meta flags
| Flag | Purpose |
|---|---|
requiresAuth: true | Redirects to /login if unauthenticated |
guestOnly: true | Redirects to / if already authenticated |
Auth guard
Every navigation runs router.beforeEach which:
- Calls
auth.bootstrap()to restore or verify the session - Checks
requiresAuth— redirects to/login?redirect=<path>if not authenticated - Checks
guestOnly— redirects to/if already authenticated
Adding a new page
ts
// Add a route child under "dashlayout"
children: [
{
path: "/posts",
name: "posts",
component: () => import("@/pages/posts/index.vue"),
meta: { requiresAuth: true }
},
]
// Create the page component at src/resources/src/pages/posts/index.vueLazy loading
All page components use dynamic import() so they are code-split per route by Vite.
Route progress bar
setupRouteProgress(router) adds a thin gradient progress bar at the top of the page that animates on navigation start and completes on navigation end.
