Skip to content

Vike Router

Routing is at the core of any web application. VHS uses Vike, which provides a powerful and flexible routing system. While it defaults to an intuitive filesystem-based approach, it offers powerful escape hatches for when you need more control.

This guide covers the main ways to define, organize, and protect your routes.

By default, Vike maps the folder structure inside src/pages/ directly to URL routes. The key principle is that folders define the route, and special + files inside them define the route’s behavior.

Vike always ignores the pages/ and index/ directories when creating the URL path.

  • src/pages/index/+Page.tsx/
  • src/pages/about/+Page.tsx/about
  • src/pages/posts/+Page.tsx/posts

To create a route with a dynamic segment, use the @ prefix. This is perfect for things like user profiles or blog posts.

Example: src/pages/users/@userId/+Page.tsx

This route will match URLs like /users/123 and /users/jane-doe. You can access the dynamic parameter in your server logic via the pageContext:

TypeScript
// in a .page.server.tsx or +guard.ts file
import type { PageContext } from 'vike/types';
export function data(pageContext: PageContext) {
// Access the dynamic part of the URL
const userId = pageContext.routeParams.userId;
// ... fetch user data
}

You can group related routes into folders with parentheses (). These folders are ignored in the URL, but they are incredibly useful for applying shared layouts or configurations to a set of pages.

Example:

  • src/pages/(marketing)/about/+Page.tsx/about
  • src/pages/(marketing)/contact/+Page.tsx/contact

Now, you can add a +Layout.tsx or +config.ts inside the (marketing) folder to apply a specific layout or configuration only to the marketing pages.

Sometimes, your desired URL doesn’t match your file structure. For these cases, you can create a +route.ts file to explicitly define the route for all files within that same directory.

The simplest way to override filesystem routing is with a Route String.

src/pages/product-details/+route.ts
// This defines the URL for '/src/pages/product-details/+Page.tsx'
export default '/product/@id'

Now, the URL /product/123 will be handled by the page component in the product-details folder.

For ultimate control, you can export a Route Function. This allows for complex, programmatic logic, such as using regular expressions or integrating third-party routing libraries.

src/pages/product-editor/+route.ts
import type { RouteSync } from 'vike/types'
export const route: RouteSync = (pageContext) => {
// Example: only match if a specific query parameter exists
if (pageContext.urlPathname === '/edit' && pageContext.urlParsed.search.edit_token) {
return { routeParams: { /* ... */ } }
}
return false
}

A common requirement is to protect pages from unauthorized access. Vike handles this elegantly with +guard.ts files. A guard file in a directory applies to all sub-routes within it.

The guard() hook runs on the server before your page is rendered. You can check for user permissions and redirect or deny access by throwing render().

Example: Protecting an admin section.

src/pages/admin/+guard.ts
import { render } from 'vike/abort'
import type { GuardAsync } from 'vike/types'
export const guard: GuardAsync = async (pageContext) => {
// This logic runs on the server
const { user } = pageContext; // Assuming user is available in pageContext
if (!user || !user.isAdmin) {
// Deny access and render the 401 Unauthorized page
throw render(401, "You aren't allowed to access this page.")
}
}

Now, any page inside src/pages/admin/ is protected by this logic.

As we covered previously, you can use other + files to manage all aspects of a route:

  • +Page.tsx: The main SolidJS component for the UI.
  • +config.ts: Sets route-specific configuration like the Layout or title.
  • +Head.tsx: Manages the document <head>.
  • +onPageTransitionStart.ts: Handles client-side navigation lifecycle hooks.
  • _error/+Page.tsx: A special route for handling 404 and 500 errors.