Skip to content

File-Based Routing

Kimesh uses file-based routing where routes are automatically generated based on your file structure in the routes directory.

Basic Concept

Every .vue file in your routes directory becomes a route:

FileRoute Path
index.vue/
about.vue/about
blog/index.vue/blog
blog/post.vue/blog/post

Route Types

Index Routes

Files named index.vue render at the parent path:

routes/
├── index.vue         # /
└── blog/
    └── index.vue     # /blog

Page Routes

Regular .vue files create routes at their path:

routes/
├── about.vue         # /about
├── contact.vue       # /contact
└── blog/
    └── archive.vue   # /blog/archive

Layout Routes

When a file has a matching directory, it becomes a layout that wraps child routes:

routes/
├── posts.vue         # Layout for /posts/*
└── posts/
    ├── index.vue     # /posts
    └── $id.vue       # /posts/:id

The posts.vue component wraps all routes in the posts/ directory with shared UI:

template
<!-- posts.vue -->
<template>
  <div class="posts-layout">
    <PostsSidebar />
    <RouterView />
  </div>
</template>

Pathless Layouts

Use _name.vue prefix for layouts that don't add a URL segment:

routes/
├── _auth.vue         # Pathless layout (wraps children, no URL segment)
├── _auth/
│   ├── login.vue     # /login (not /auth/login)
│   └── register.vue  # /register

Pathless layouts can be nested recursively - a pathless layout can contain another pathless layout:

routes/
├── _auth.vue              # Outer pathless layout
├── _auth/
│   ├── _onboarding.vue    # Nested pathless layout
│   ├── _onboarding/
│   │   ├── step1.vue      # /step1 (wrapped by both layouts)
│   │   └── step2.vue      # /step2
│   ├── login.vue          # /login (wrapped by _auth only)
│   └── register.vue       # /register

The route merger recursively collects routes from nested pathless layouts, ensuring proper layer integration.

Group Folders

Use parentheses for organizational grouping without a layout component:

routes/
├── (marketing)/
│   ├── pricing.vue   # /pricing
│   └── features.vue  # /features
├── (app)/
│   ├── dashboard.vue # /dashboard
│   └── settings.vue  # /settings

Unlike pathless layouts, group folders don't create a wrapping component - they only affect file organization.

Dynamic Routes

Use $param prefix for dynamic segments:

routes/
├── users/
│   └── $id.vue       # /users/:id
└── posts/
    └── $slug.vue     # /posts/:slug

Access params in your component:

template
<script setup lang="ts">
import { useRoute } from 'vue-router'

const route = useRoute()
console.log(route.params.id) // "123" for /users/123
</script>

Catch-All Routes

Use $.vue to match any remaining path segments:

routes/
├── docs/
│   └── $.vue         # /docs/* (any path under /docs)
└── $.vue             # /* (global 404)

The matched path is available as route.params.pathMatch.

Route Hierarchy

Routes are nested based on directory structure and layouts:

routes/
├── __root.vue              # Root layout (wraps everything)
├── index.vue               # /
├── _auth.vue               # Pathless auth layout
├── _auth/
│   ├── login.vue           # /login
│   └── register.vue        # /register
├── dashboard.vue           # Layout for /dashboard/*
└── dashboard/
    ├── index.vue           # /dashboard
    └── settings.vue        # /dashboard/settings

The component hierarchy for /dashboard/settings:

__root.vue
  └── dashboard.vue
        └── dashboard/settings.vue

Generated Routes

Kimesh generates a routes.gen.ts file in the .kimesh directory:

ts
// Auto-generated by @kimesh/router-generator
// Do not edit this file manually

export const routes = [
  {
    path: '/',
    component: () => import('../src/routes/__root.vue'),
    children: [
      { path: '', name: 'index', component: () => import('../src/routes/index.vue') },
      { path: 'about', name: 'about', component: () => import('../src/routes/about.vue') },
      {
        path: 'posts',
        component: () => import('../src/routes/posts.vue'),
        children: [
          { path: '', name: 'posts', component: () => import('../src/routes/posts/index.vue') },
          { path: ':id', name: 'posts-id', component: () => import('../src/routes/posts/$id.vue') },
        ],
      },
    ],
  },
]

Released under the MIT License.