Skip to content

Router Setup

12.1.1. createRouter Configuration

  • The router instance must be created using createRouter and createWebHistory.
  • Hash mode (createWebHashHistory) must not be used. All projects must use History mode.
  • The router configuration file must be located at src/router/index.ts.
typescript
// src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
import type { RouteRecordRaw } from 'vue-router'
import { routes } from './routes'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes,
  scrollBehavior(_to, _from, savedPosition) {
    return savedPosition ?? { top: 0 }
  },
})

export default router

12.1.2. Route Definition Structure

  • The route array must be defined with the RouteRecordRaw[] type.
  • Each route must specify the path, name, component, and meta properties.
  • The name property is required and is used for programmatic navigation.
  • The meta property defines authentication requirements, permissions, page titles, and other metadata.
typescript
// src/router/routes.ts
import type { RouteRecordRaw } from 'vue-router'

export const routes: RouteRecordRaw[] = [
  {
    path: '/',
    name: 'Home',
    component: () => import('@/views/HomeView.vue'),
    meta: { title: 'Home', requiresAuth: false },
  },
  {
    path: '/users',
    name: 'UserList',
    component: () => import('@/views/user/UserListView.vue'),
    meta: { title: 'User List', requiresAuth: true, roles: ['admin'] },
  },
  {
    path: '/users/:id',
    name: 'UserDetail',
    component: () => import('@/views/user/UserDetailView.vue'),
    meta: { title: 'User Detail', requiresAuth: true },
  },
]
  • The meta type must be defined via vue-router module augmentation.
typescript
// src/router/types.ts
import 'vue-router'

declare module 'vue-router' {
  interface RouteMeta {
    title: string
    requiresAuth: boolean
    roles?: string[]
  }
}

12.1.3. Nested Routes

  • Pages that share a layout must be organized as nested routes (children).
  • The parent route's component must include a <RouterView />.
  • The parent route must either omit the name property or define a redirect to prevent direct access.
typescript
// src/router/routes.ts (nested route example)
{
  path: '/settings',
  component: () => import('@/layouts/SettingsLayout.vue'),
  redirect: { name: 'SettingsProfile' },
  children: [
    {
      path: 'profile',
      name: 'SettingsProfile',
      component: () => import('@/views/settings/ProfileView.vue'),
      meta: { title: 'Profile Settings', requiresAuth: true },
    },
    {
      path: 'security',
      name: 'SettingsSecurity',
      component: () => import('@/views/settings/SecurityView.vue'),
      meta: { title: 'Security Settings', requiresAuth: true },
    },
  ],
}
vue
<!-- src/layouts/SettingsLayout.vue -->
<template>
  <div class="settings-layout">
    <SettingsSidebar />
    <main>
      <RouterView />
    </main>
  </div>
</template>

12.1.4. Router Registration

  • The router must be registered by calling app.use(router) in main.ts.
  • router.isReady() must be used to mount the app only after the initial navigation is complete.
  • The router must be registered after Pinia, because guards need access to Stores.
typescript
// src/main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'

const app = createApp(App)

app.use(createPinia())
app.use(router)

router.isReady().then(() => {
  app.mount('#app')
})
ItemRule
Router modecreateWebHistory required
Route typeRouteRecordRaw[] must be specified
name propertyRequired for all leaf routes
meta typeType safety ensured via module augmentation
Registration orderRouter must be registered after Pinia
Mount timingMount after router.isReady() resolves

TIENIPIA QUALIFIED STANDARD