npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

vue-multi-router

v0.1.3

Published

Vue 3 multi router

Downloads

18

Readme

vue-multi-router

Vue 3 Multi Router that allows you to have multiple routers in your application.

npm downloads TypeScript Vue 3 Bundle Size GitHub issues GitHub License CI Coverage codecov Live Demo

Live Demo

🚀 Try the interactive playground

Installation

npm install vue-multi-router

Features

  • Multiple Independent Routers - Run multiple Vue Router instances simultaneously in a single app
  • Context-Based Navigation - Each routing context maintains its own navigation history
  • Browser History Integration - Back/forward buttons work across contexts with proper URL updates
  • Session Persistence - Context states persist across page reloads via SessionStorage or other implementations
  • TypeScript Support - Full type definitions included
  • Composable API - Easy-to-use composables for accessing router state

Motivation

Vue Router is designed around a single-router-per-app model. That works well for most applications, but falls short when your UI needs multiple independent navigation areas — each with its own route, history stack, and back/forward behavior.

Think of:

  • Dashboard applications with several panels, each displaying a different page
  • Desktop-like UIs with floating or tiled windows that navigate independently
  • Tabbed interfaces where each tab has its own browsing history
  • Multi-pane editors (email clients, admin tools) with a sidebar, list, and detail view that all route separately

Without vue-multi-router you'd have to juggle manual <component :is> switching, duplicate router instances with conflicting URL ownership, or complex query-parameter schemes — all of which break browser history and become hard to maintain.

vue-multi-router solves this by letting you wrap any part of your template in a <MultiRouterContext>. Each context gets its own virtual navigation stack while sharing a single set of route definitions and a single browser URL. The library manages history entries so that the browser back/forward buttons work correctly across every context, and state is persisted through page reloads via SessionStorage.

Basic Usage

1. Create Multi Router

// router.ts
import { createMultiRouter } from 'vue-multi-router'
import { createWebHistory } from 'vue-router'

export const multiRouter = createMultiRouter({
  history: createWebHistory(),
  routes: [
    {
      path: '/',
      component: () => import('./views/Layout.vue'),
      children: [
        { path: 'home', component: () => import('./views/Home.vue') },
        { path: 'about', component: () => import('./views/About.vue') },
      ],
    },
  ],
})

2. Install Plugin

// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import { multiRouter } from './router'

const app = createApp(App)
app.use(multiRouter)
app.mount('#app')

3. Define Contexts

<!-- App.vue -->
<template>
  <MultiRouterContext type="main" name="main" default>
    <RouterView />
  </MultiRouterContext>
</template>

<script setup>
import { MultiRouterContext } from 'vue-multi-router'
</script>

MultiRouterContext acts as an activator by default — clicking anywhere inside it activates the context. No extra wrapper needed.

4. Create Additional Contexts

<!-- Panels.vue -->
<template>
  <div v-for="panel in panels" :key="panel.id">
    <MultiRouterContext type="panel" :name="`panel-${panel.id}`" initial-location="/home">
      <RouterView />
    </MultiRouterContext>
  </div>
</template>

API Reference

createMultiRouter(options)

Creates a multi-router instance.

Options:

  • history: RouterHistory - Vue Router history instance
  • routes: RouteRecordRaw[] - Route definitions (same as Vue Router)
  • historyOptions?: MultiRouterHistoryManagerOptions - History management options

Route Meta Options

multiRouterRoot: boolean

Marks a route as the root for context rendering. When a context navigates to a nested route, RouterView inside the context will start rendering from the route marked with multiRouterRoot: true, skipping parent routes.

const routes = [
  {
    path: '/dashboard',
    component: DashboardLayout,
    children: [
      {
        path: 'panels',
        component: PanelsContainer,
        children: [
          {
            path: 'content',
            component: PanelContent,
            meta: { multiRouterRoot: true }, // Context renders from here
          },
        ],
      },
    ],
  },
]

This is useful when contexts are nested inside shared layouts but should render independently from their root component.

<MultiRouterContext>

Component that defines a routing context boundary. By default, it also acts as an activator — clicking inside the context activates it.

Props:

  • type: string - Context type identifier (for debugging/organization)
  • name: string - Unique context identifier
  • location?: string - Force specific location (overrides storage)
  • initial-location?: string - Initial location for new contexts
  • history-enabled?: boolean - Whether to track in browser history (default: true)
  • default?: boolean - Activate by default if no saved context exists
  • activator?: boolean - Whether to activate context on mousedown (default: true). Set to false to opt out of built-in activation behavior
  • prevent-class?: string - CSS class that prevents activation on click, useful if you want to prevent activation on click of a button that destroys the context

To disable the built-in activator:

<MultiRouterContext type="panel" name="panel-1" :activator="false">
  <!-- manage activation manually -->
</MultiRouterContext>

<MultiRouterContextActivator>

Standalone wrapper component that activates context on user interaction. Useful for advanced cases where you need fine-grained control over which element triggers activation, separate from the MultiRouterContext boundary.

Props:

  • prevent-class?: string - CSS class that prevents activation on click
  • as?: string - HTML element to render as wrapper (default: fragment/div)

useMultiRouter()

Composable for accessing multi-router outside a context.

Returns:

  • activeContextKey: ComputedRef<string | undefined> - Currently active context
  • activeHistoryContextKey: ComputedRef<string | undefined> - Context controlling browser URL
  • setActive(contextKey: string, updateHistory?: boolean): void - Activate a context
  • hasContext(contextKey: string): boolean - Check if context exists

useMultiRouterContext()

Composable for use inside a MultiRouterContext.

Returns:

  • manager: useMultiRouter() - MultiRouter manager instance
  • contextKey: string - This context's key
  • isActive: ComputedRef<boolean> - Whether this context is active
  • isHistoryActive: ComputedRef<boolean> - Whether this context controls browser URL
  • activeContextKey: ComputedRef<string> - Currently active context key
  • activeHistoryContextKey: ComputedRef<string> - Currently active history context key
  • historyEnabled: ComputedRef<boolean> - Whether history is enabled for this context
  • activate(updateHistory?: boolean): void - Activate this context
  • setActive(contextKey: string, updateHistory?: boolean): void - Activate a context
  • hasContext(contextKey: string): boolean - Check if context exists

Examples

Cards with Query Parameters

<template>
  <div v-for="card in cards" :key="card.id">
    <MultiRouterContext
      type="card"
      :name="`card-${card.id}`"
      initial-location="/card/content"
      :history-enabled="false"
    >
      <CardContent @close="removeCard(card.id)" />
    </MultiRouterContext>
  </div>
</template>

Accessing Route in Context

<script setup>
import { useRouter, useRoute } from 'vue-router'

const router = useRouter()
const route = useRoute()

// Navigate within this context
function goToPage(path) {
  router.push(path)
}

// Access query params
const searchQuery = computed(() => route.query.q)
</script>

Peer Dependencies

  • vue: ^3.0.0
  • vue-router: ^4.0.0 || ^5.0.0

License

MIT

Development

Running Playground Locally

# Development mode (hot reload)
npm run play

# Production preview
npm run build:playground
npm run preview:playground

Building

# Build library
npm run build

# Build playground for deployment
npm run build:playground

Testing & Quality

# Run all checks
npm run check

# Type checking
npm run ts:check

# Linting
npm run lint

# Formatting
npm run format

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.