---
url: /file-based-routing.md
---
# Getting Started

Vue Router includes a built-in file-based routing plugin. It generates the routes and types automatically from your page components, so you no longer need to maintain a `routes` array manually.

## Setup

Add the plugin to your bundler:

::: code-group

```ts [vite.config.ts]
import VueRouter from 'vue-router/vite'

export default defineConfig({
  plugins: [
    VueRouter({
      // options
    }),
    // ⚠️ Vue must be placed after VueRouter()
    Vue(),
  ],
})
```

```ts [rollup.config.js]
import VueRouter from 'vue-router/unplugin/rollup'

export default {
  plugins: [
    VueRouter({
      // options
    }),
    // ⚠️ Vue must be placed after VueRouter()
    Vue(),
  ],
}
```

```ts [webpack.config.js]
module.exports = {
  /* ... */
  plugins: [require('vue-router/unplugin/webpack')({/* options */})],
}
```

```ts [vue.config.js]
module.exports = {
  configureWebpack: {
    plugins: [require('vue-router/unplugin/webpack')({/* options */})],
  },
}
```

```ts [esbuild.config.js]
import { build } from 'esbuild'
import VueRouter from 'vue-router/unplugin/esbuild'

build({
  plugins: [VueRouter()],
})
```

:::

After adding this plugin, **start the dev server** (usually `npm run dev`) **to generate the first version of the types** at `typed-router.d.ts` which should be added to your `tsconfig.json` along with `"moduleResolution": "Bundler"`. This is what it should look like:

::: code-group

```json{8} [tsconfig.json]
{
  "include": [
    // other files...
    "./typed-router.d.ts" // [!code ++]
  ],
  "compilerOptions": {
    // ...
    "moduleResolution": "Bundler",
    // ...
  }
}
```

```ts [typed-router.d.ts]
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by vue-router. ‼️ DO NOT MODIFY THIS FILE ‼️
// It's recommended to commit this file.
// Make sure to add this file to your tsconfig.json file as an "includes" or "files" entry.

declare module 'vue-router/auto-routes' {
  import type {
    RouteRecordInfo,
    ParamValue,
    ParamValueOneOrMore,
    ParamValueZeroOrMore,
    ParamValueZeroOrOne,
  } from 'vue-router'

  /**
   * Route name map generated by vue-router file-based routing
   */
  export interface RouteNamedMap {
    '/': RouteRecordInfo<
      '/',
      '/',
      Record<never, never>,
      Record<never, never>,
      | never
    >
    '/about': RouteRecordInfo<
      '/about',
      '/about',
      Record<never, never>,
      Record<never, never>,
      | never
    >
    '/users/[id]': RouteRecordInfo<
      '/users/[id]',
      '/users/:id',
      { id: ParamValue<true> },
      { id: ParamValue<false> },
      | never
    >
  }
}
```

:::

### Volar Plugins

To get the best TypeScript experience in Single File Components, add the following Volar plugins to your `tsconfig.json` (or `tsconfig.app.json`):

```jsonc [tsconfig.json]
{
  "vueCompilerOptions": {
    "plugins": [
      "vue-router/volar/sfc-route-blocks",
      "vue-router/volar/sfc-typed-router",
    ],
  },
}
```

* `vue-router/volar/sfc-route-blocks` — enables `<route>` blocks in SFCs for defining per-page route metadata
* `vue-router/volar/sfc-typed-router` — makes `useRoute()` return a typed route based on the current page component, so `route.params` is correctly typed

### Migrating an existing project

Move your page components to `src/pages` and rename them accordingly. Here is an example of migration.
Given the following route configuration:

::: code-group

```ts [src/router.ts]
import { createRouter, createWebHistory } from 'vue-router'
import { routes, handleHotUpdate } from 'vue-router/auto-routes' // [!code ++]

export const router = createRouter({
  history: createWebHistory(),
  routes: [ // [!code --]
    { // [!code --]
      path: '/', // [!code --]
      component: () => import('src/pages/Home.vue'), // [!code --]
    }, // [!code --]
    { // [!code --]
      path: '/users/:id', // [!code --]
      component: () => import('src/pages/User.vue'), // [!code --]
    } // [!code --]
    { // [!code --]
      path: '/about', // [!code --]
      component: () => import('src/pages/About.vue'), // [!code --]
    }, // [!code --]
  ] // [!code --]
  routes, // [!code ++]
})

// This will update routes at runtime without reloading the page
if (import.meta.hot) { // [!code ++]
  handleHotUpdate(router) // [!code ++]
} // [!code ++]
```

```ts{2,5} [main.ts]
import { createApp } from 'vue'
import { router } from './router'
import App from './App.vue'

createApp(App).use(router).mount('#app')
```

:::

* Rename `src/pages/Home.vue` to `src/pages/index.vue`
* Rename `src/pages/User.vue` to `src/pages/users/[id].vue`
* Rename `src/pages/About.vue` to `src/pages/about.vue`

Check the [file conventions](./file-based-routing) guide for more information about the naming conventions.

### From scratch

* Create a `src/pages` folder and add an `index.vue` component to it. This will render your home page at `/`.
* Import the `routes` from `vue-router/auto-routes` and pass them to the `createRouter` function.

::: code-group

```ts{2-3,6-9,12} [src/main.ts]
import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import { routes } from 'vue-router/auto-routes'
import App from './App.vue'

const router = createRouter({
  history: createWebHistory(),
  routes,
})

createApp(App)
  .use(router)
  .mount('#app')
```

```vue [src/pages/index.vue]
<template>
  <h1>Home</h1>
</template>
```

:::

Check the [file conventions](./file-based-routing) guide for more information about the naming conventions.

### Manipulating the routes

You can pass the `routes` to any plugin that needs to add changes to them but note that **these changes will not be reflected in types**. Use [build-time routes instead](./extending-routes) if you want to have types support. Here is an example with [Vitesse starter](https://github.com/antfu-collective/vitesse/blob/main/src/main.ts):

```ts
import { ViteSSG } from 'vite-ssg'
import { setupLayouts } from 'virtual:generated-layouts'
import App from './App.vue'
import type { UserModule } from './types'
import generatedRoutes from '~pages' // [!code --]
import { routes } from 'vue-router/auto-routes' // [!code ++]

import '@unocss/reset/tailwind.css'
import './styles/main.css'
import 'uno.css'

const routes = setupLayouts(generatedRoutes) // [!code --]

// https://github.com/antfu/vite-ssg
export const createApp = ViteSSG(
  App,
  {
    routes, // [!code --]
    routes: setupLayouts(routes), // [!code ++]
    base: import.meta.env.BASE_URL,
  },
  ctx => {
    // install all modules under `modules/`
    Object.values(
      import.meta.glob<{ install: UserModule }>('./modules/*.ts', {
        eager: true,
      })
    ).forEach(i => i.install?.(ctx))
  }
)
```

## ESLint

If you use ESlint, check [the ESlint section](./eslint).
