Skip to content

Migrating from Vue Router ​

FeatureVue RouterKitbag Router
Nested routes✅✅
Named views✅✅
Typed routes✅✅
Typed params🧪 Experimental✅
Navigation guards✅✅
Redirects and aliases✅✅
Data loaders✅✅
Server rendering✅✅
View transitions🟡✅
Dynamic route registration✅❌
Scroll behavior✅❌
File-based routing✅❌
Rejection views❌✅
Async props❌✅
Prefetching❌✅
Typed external routes❌✅

See the Quick Start for installation and TypeScript setup.

Route Configuration ​

Define named routes with createRoute, then attach components with addView. See Routes and Router.

ts
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from './HomeView.vue'

const router = createRouter({
  history: createWebHistory(),
  routes: [{
    name: 'home',
    path: '/',
    component: HomeView,
  }],
})
ts
import { createRoute, createRouter } from '@kitbag/router'
import HomeView from './HomeView.vue'

const home = createRoute({
  name: 'home',
  path: '/',
})
  .addView(HomeView)

const router = createRouter([home], {
  historyMode: 'browser',
})

Child Routes ​

Use a parent reference instead of children. Kitbag joins paths literally: /users + /[id] becomes /users/[id]. Use hoisting for a child with an independent URL.

ts
const routes = [{
  path: '/users',
  children: [{
    name: 'user',
    path: ':id',
    component: UserView,
  }],
}]
ts
const users = createRoute({ path: '/users' })

const user = createRoute({
  parent: users,
  name: 'user',
  path: '/[id]',
})
  .addView(UserView)

const routes = [user]

Props Binding ​

Bind props through addView. Kitbag checks them against the component and requires a getter for required props. See Component Props.

ts
const user = {
  name: 'user',
  path: '/users/:id',
  component: UserView,
  props: (route) => ({ userId: route.params.id }),
}
ts
const user = createRoute({
  name: 'user',
  path: '/users/[id]',
})
  .addView(UserView, {
    props: (route) => ({ userId: route.params.id }),
  })

Named Views ​

Call addView for each component, with a name for named views. See Named Views.

ts
const home = {
  name: 'home',
  path: '/',
  components: {
    default: HomeView,
    sidebar: SidebarView,
  },
}
ts
const home = createRoute({
  name: 'home',
  path: '/',
})
  .addView(HomeView)
  .addView(SidebarView, { name: 'sidebar' })

Pass the route name and params separately. See Navigation.

ts
router.push({
  name: 'user',
  params: { id: '123' },
})

router.replace({
  name: 'user',
  params: { id: '456' },
})
ts
router.push('user', { id: '123' })
router.replace('user', { id: '456' })

Use the resolver callback for typed link destinations. See RouterLink.

vue
<RouterLink :to="{
  name: 'user',
  params: { id: '123' },
}">
  View user
</RouterLink>
vue
<RouterLink :to="(resolve) => resolve('user', { id: '123' })">
  View user
</RouterLink>

View Transitions ​

Vue Router supports view transitions through links. Kitbag also supports router and route defaults, programmatic navigation, transition types, and shared-element helpers. See View Transitions.

vue
<RouterLink to="/about" view-transition>
  About
</RouterLink>
ts
import { createRoute, createRouter } from '@kitbag/router'

const photo = createRoute({
  name: 'photo',
  path: '/photos/[id]',
})

const settings = createRoute({
  name: 'settings',
  path: '/settings',
  viewTransition: false,
})

const router = createRouter([photo, settings], {
  viewTransition: {
    types: ({ to }) => to.name === 'photo' ? ['expand'] : ['fade'],
  },
})

// Uses the router's "expand" transition type.
router.push('photo', { id: '1' })

// Adds "slide-left" for this navigation.
router.push('photo', { id: '2' }, { viewTransition: ['slide-left'] })

// The route opts out of transitions.
router.push('settings')

Reading the Current Route ​

Kitbag exposes query values through URLSearchParams and matched routes through matches. Declared query params are also available in route.params. See Router Route.

ts
import { useRoute } from 'vue-router'

const route = useRoute()

const page = route.query.page
const matches = route.matched
const hash = route.hash // '#comments'
ts
import { useRoute } from '@kitbag/router'

const route = useRoute()

const page = route.query.get('page')
const matches = route.matches
const hash = route.hash // 'comments'

Use context helpers to redirect or cancel navigation. The previous route is available as context.from. See Hooks.

ts
const account = {
  name: 'account',
  path: '/account',
  component: AccountView,
  beforeEnter: () => {
    if (!isSignedIn()) {
      return '/login'
    }
  },
}
ts
const account = createRoute({
  name: 'account',
  path: '/account',
})
  .addView(AccountView)
  .onBeforeRouteEnter((to, context) => {
    if (!isSignedIn()) {
      context.replace('/login')
    }
  })

Typed Params ​

Kitbag parses and validates params using their declared types. Vue Router supports this through its experimental param parsers, which require the experimental router and plugin setup. Both examples expose id as a number for /users/42. See Param Types.

vue
<!-- src/pages/users/[id=int].vue -->
<script setup lang="ts">
const route = useRoute('/users/[id=int]')

route.params.id // 42 (number)
</script>
ts
import { createRoute, useRoute, withParams } from '@kitbag/router'

const user = createRoute({
  name: 'user',
  path: withParams('/users/[id]', {
    id: Number,
  }),
})

// In the component, after registering the route:
const route = useRoute('user')

route.params.id // 42 (number)

Route Regex ​

Validate params with regular expressions using withParams. See Param Types.

ts
const archive = {
  name: 'archive',
  path: '/archive/:date(\\d{2}-\\d{2}-\\d{4})',
}
ts
import { createRoute, withParams } from '@kitbag/router'

const archive = createRoute({
  name: 'archive',
  path: withParams('/archive/[date]', {
    date: /^\d{2}-\d{2}-\d{4}$/,
  }),
})

Repeatable Params ​

Combine a greedy param with arrayOf to read multiple path segments as an array. Both examples match /one/two with chapters ['one', 'two'].

To also match /, use [?chapters*]. Add withDefault for an empty array when the param is missing. See Default Values.

ts
const chapters = {
  name: 'chapters',
  path: '/:chapters+',
}
ts
import { arrayOf, createRoute, withParams } from '@kitbag/router'

const chapters = createRoute({
  name: 'chapters',
  path: withParams('/[chapters*]', {
    chapters: arrayOf([String], { separator: '/' }),
  }),
})

Redirects ​

Use redirectTo for a fixed destination and a before hook for conditional redirects. See Redirects.

ts
const routes = [{
  name: 'new',
  path: '/new',
}, {
  name: 'old',
  path: '/old',
  redirect: { name: 'new' },
}]
ts
const newRoute = createRoute({
  name: 'new',
  path: '/new',
})

const oldRoute = createRoute({
  name: 'old',
  path: '/old',
})
  .redirectTo(newRoute)

const routes = [newRoute, oldRoute]

Aliases ​

Both routers keep the alias URL in the address bar. Kitbag also supports aliases with different params through a transform. See Aliases.

ts
const user = {
  name: 'user',
  path: '/users/:id',
  alias: '/members/:id',
}
ts
const user = createRoute({
  name: 'user',
  path: '/users/[id]',
})
  .addAlias({ path: '/members/[id]' })