Quorium composes routes, navigation, and module activation from permissions, feature flags, and capability contracts — deterministically. Framework-agnostic core. Adapters for Vue, Quasar, React, Svelte & Framework7.
Quorium combines Quorum — the minimum agreement needed to act — and Core.
A quorum-based runtime that determines what is allowed to exist in a frontend system — based on rules, permissions, and capabilities.
import { defineModule } from '@nextera.one/quorium-core' import { SESSION_TOKEN } from '../core/tokens' export const ProjectsModule = defineModule({ id: 'projects', version: '1.0.0', requires: [SESSION_TOKEN], provides: [PROJECTS_SERVICE_TOKEN], routes: [ { name: 'projects.list', path: '/projects', permission: 'projects.read', nav: { label: 'Projects', icon: 'folder_open', order: 10 } }, { name: 'projects.new', path: '/projects/new', permission: 'projects.write' } ], isEnabled(ctx) { return ctx.enabledModules.has('projects'); }, setup(ctx) { // Wire service via DI — adapter-specific (e.g. ctx.app.provide for Vue) } })
Large frontend applications eventually collapse into structural drift. Quorium introduces runtime composition — your app decides at runtime what is allowed to exist.
if (hasPermission('projects.create')) { router.push('/projects/new') }
const runtime = createRuntime({ modules }) const result = runtime.compose(context) applier.apply(router, result.routes)
A framework-agnostic runtime engine with five concrete responsibilities.
Routes are filtered before registration via
filterRoutesByPermissions(). If the permission is missing, the route does not exist
— not hidden, not guarded,
absent.
Modules only activate when
enabledModules
contains their id. Disabled modules contribute zero
routes, zero navigation, zero state.
Each module declares
requires and
provides via typed
symbols. Missing dependencies surface in
missingCapabilities —
caught before wiring.
Login, logout, or role change triggers
runtime.compose()
again. Old routes are removed. New routes are registered.
Zero page reload.
buildNavigation()
derives navigation items from the composed route specs.
One source of truth — no duplicate menu configuration.
This is the governing principle. Routes, navigation, and modules only exist if explicitly admitted by permissions, flags, and capabilities.
Every module passes through a deterministic pipeline. Core stays pure TypeScript — adapters translate the result into your framework.
id. The runtime
checks
enabledModules —
disabled modules are excluded before any further
processing.
filterRoutesByPermissions()
walks every module's route tree and strips any route
whose
meta.permissions
the current user doesn't hold. The shape of the tree is
preserved.
validateCapabilities()
checks that every
requires token
declared by a module is satisfied by a
provides token from
another. Unsatisfied contracts throw before any adapter
runs.
CompositionResult —
a plain object holding the final route tree, flat
navigation items, capability map, and merged metadata.
No framework code runs here.
CompositionResult
into the exact structures your framework expects.
coreToVueRoutes()
VueRouteApplier
toQuasarDrawerItems()
coreToReactRoutes()
ReactRouteManager
coreToSvelteRoutes()
coreToF7Routes()
F7RouteManager
Two orthogonal systems — one governs what a user can visit, the other governs what a module can depend on.
meta.permissions;
filterRoutesByPermissions()
strips any route the user can't access — before the
adapter ever runs.
provides and what it
requires.
validateCapabilities()
ensures every requirement is satisfied at compose-time —
before any route is registered.
compose() runs.
@nextera.one/quorium-core
— no framework, no side effects.
8 packages. One architecture. Core stays pure TypeScript — adapters bridge to your framework.
Framework-agnostic runtime engine. Module registry, permission filtering, capability validation, deterministic route composition, and navigation generation. Pure TypeScript — zero framework dependency.
Vue Router 4 adapter. Converts
CoreRouteSpec to
RouteRecordRaw,
dynamic route add/remove via
VueRouteApplier, typed
DI with provideToken /
useToken.
Extends the Vue adapter with Quasar-specific helpers. Auto
drawer navigation via
toQuasarDrawerItems(),
capability warning notifications, and group separators.
React Router v6/v7 adapter. Converts
CoreRouteSpec to
RouteObject with
ReactRouteManager for
declarative route recomputation.
Svelte / SvelteKit adapter. Converts to
SvelteRouteRecord
with nested or
flattenSvelteRoutes()
for single-depth routers.
Framework7 adapter. Converts to
F7RouteRecord with
asyncComponent and
F7RouteManager for
mobile-first apps.
Scaffold and validation tool. Commands:
quorium init,
quorium new,
quorium add-route,
quorium validate,
quorium gen.
Optional decorator-based DX.
@QModule and
@QRoute decorators
that generate
CoreModule and
RouteSpec from class
metadata.
# Required — the core runtime engine npm install @nextera.one/quorium-core # Pick your framework adapter (one or more) npm install @nextera.one/quorium-vue # Vue 3 + Vue Router 4 npm install @nextera.one/quorium-quasar # Quasar 2 (extends vue adapter) npm install @nextera.one/quorium-react # React 18/19 + React Router 6/7 npm install @nextera.one/quorium-svelte # Svelte / SvelteKit npm install @nextera.one/quorium-framework7 # Framework7 # Optional tooling npm install @nextera.one/quorium-cli # CLI: init, new, add-route, validate, gen npm install @nextera.one/quorium-decorators # @QModule / @QRoute decorators
Deterministic input → deterministic route tree. Same context always produces the same output.
import { createRuntime, defineModule, buildNavigation } from '@nextera.one/quorium-core' // 1. Define a module with typed CoreModule interface const ProjectsModule = defineModule({ id: 'projects', requires: [SESSION_TOKEN], provides: [PROJECTS_SERVICE_TOKEN], routes: [ { name: 'projects.list', path: '/projects', permission: 'projects.read', nav: { label: 'Projects', icon: 'folder_open', order: 10 } }, { name: 'projects.new', path: '/projects/new', permission: 'projects.write' } ] }) // 2. Create runtime and compose with current context const runtime = createRuntime({ modules: [ProjectsModule] }) const composed = runtime.compose({ permissions: new Set(['projects.read']), enabledModules: new Set(['projects']), capabilities: new Set([SESSION_TOKEN]) }) // 3. CompositionResult — deterministic output composed.routes // CoreRouteSpec[] — permission-filtered composed.activeModules // ['projects'] composed.missingCapabilities // [] — broken contracts surface here // 4. Build navigation from composed routes const navItems = buildNavigation(composed.routes) // [{ name: 'projects.list', path: '/projects', label: 'Projects', icon: 'folder_open' }]
CoreModule,
RuntimeContext,
CompositionResult,
CoreRouteSpec.
The core composes. The adapter applies. Every example below uses real exports from the packages.
import { createRuntime, buildNavigation } from '@nextera.one/quorium-core' import { coreToVueRoutes, VueRouteApplier, runModuleSetups, toQuasarDrawerItems, notifyMissingCapabilities } from '@nextera.one/quorium-quasar' const runtime = createRuntime({ modules }) const applier = new VueRouteApplier() const composed = runtime.compose(context) // Convert to Vue routes & apply const vueRoutes = coreToVueRoutes(composed.routes, resolveComponent) applier.apply(router, vueRoutes) // Run admitted module setup hooks (DI wiring) runModuleSetups(modules, { ...context, app }, composed.activeModules) // Quasar drawer navigation — auto-generated const nav = buildNavigation(composed.routes) const drawerItems = toQuasarDrawerItems(nav) // Surface missing capability warnings via Quasar Notify notifyMissingCapabilities(composed.missingCapabilities, { notify: $q.notify })
import { createRuntime } from '@nextera.one/quorium-core' import { ReactRouteManager, coreToReactRoutes } from '@nextera.one/quorium-react' const runtime = createRuntime({ modules }) const manager = new ReactRouteManager() const composed = runtime.compose(context) // Compute React Router route objects const routeObjects = manager.compute(composed.routes, resolveComponent) // Use with createBrowserRouter or RouterProvider const router = createBrowserRouter(routeObjects)
import { createRuntime } from '@nextera.one/quorium-core' import { coreToSvelteRoutes, flattenSvelteRoutes } from '@nextera.one/quorium-svelte' const runtime = createRuntime({ modules }) const composed = runtime.compose(context) // Nested routes (svelte-routing) const nested = coreToSvelteRoutes(composed.routes, resolveComponent) // Or flat routes (svelte-spa-router) const flat = flattenSvelteRoutes(nested)
Every feature module follows the same governed pattern. API calls, business logic, state, pages, and the module entry point — each in its own layer.
import { defineModule } from '@nextera.one/quorium-core' import type { VueModuleRuntimeContext } from '@nextera.one/quorium-vue' import { SESSION_TOKEN, PROJECTS_SERVICE_TOKEN } from '../../core/tokens' import { ProjectsService } from './services' export const ProjectsModule = defineModule<VueModuleRuntimeContext>({ id: 'projects', version: '1.0.0', requires: [SESSION_TOKEN], provides: [PROJECTS_SERVICE_TOKEN], routes: [ { name: 'projects.list', path: '/projects', permission: 'projects.read', meta: { component: () => import('./pages/ProjectsListPage.vue') }, nav: { label: 'Projects', icon: 'folder_open', order: 10 } }, { name: 'projects.new', path: '/projects/new', permission: 'projects.write', meta: { component: () => import('./pages/ProjectsNewPage.vue') } } ], setup(ctx) { // Wire service into Vue DI — available via useToken(PROJECTS_SERVICE_TOKEN) ctx.app.provide(PROJECTS_SERVICE_TOKEN, new ProjectsService()) } })
Same input always produces the same output. No side effects. No surprises.
No cross-module imports. Dependencies flow through typed capability tokens.
Modules declare requires and provides. Missing tokens are caught before activation.
Routes don't exist unless the permission exists. Not hidden — structurally absent.
Session change → full recomposition. The route tree always reflects current reality.
Every dependency is explicit. Every connection is visible. No implicit global state.
Clarity builds trust. Here's what Quorium does not do.
No buttons, no inputs, no layouts. Use Quasar, Vuetify, MUI, or whatever you want.
Quorium composes routes for your router. Vue Router, React Router, SvelteKit — they still do the routing.
Use Pinia, Zustand, or anything else. Quorium governs structure, not state.
No iframes, no module federation. Quorium works inside a single application.
No webpack config, no vite plugins. Quorium is pure runtime — zero build-time magic.
Nothing more. Admission, composition, and consistency — at runtime. Framework agnostic.
Quorium brings backend-level discipline to frontend composition.
Quorium treats the frontend like a governed system:
Install the packages and compose your first governed runtime in 4 steps.
Install the core runtime and the adapter for your framework.
npm install @nextera.one/quorium-core # Pick your framework adapter npm install @nextera.one/quorium-vue # Vue 3 + Vue Router 4 npm install @nextera.one/quorium-quasar # Quasar 2 (includes vue adapter) npm install @nextera.one/quorium-react # React 18/19 + React Router 6/7 npm install @nextera.one/quorium-svelte # Svelte / SvelteKit npm install @nextera.one/quorium-framework7 # Framework7 # Optional npm install @nextera.one/quorium-cli # CLI scaffolding tool npm install @nextera.one/quorium-decorators # @QModule / @QRoute decorators
Declare routes, permissions, capabilities, and an optional
feature-flag gate using
defineModule().
import { defineModule } from '@nextera.one/quorium-core'
export const ProjectsModule = defineModule({
id: 'projects',
requires: [SESSION_TOKEN],
provides: [PROJECTS_SERVICE_TOKEN],
routes: [
{ name: 'projects.list', path: '/projects', permission: 'projects.read',
nav: { label: 'Projects', icon: 'folder_open', order: 10 } },
{ name: 'projects.new', path: '/projects/new', permission: 'projects.write' }
],
setup(ctx) {
ctx.app.provide(PROJECTS_SERVICE_TOKEN, new ProjectsService())
}
})
Pass the
RuntimeContext —
permissions, enabled modules, and capabilities — and get a
deterministic
CompositionResult.
import { createRuntime } from '@nextera.one/quorium-core'
const runtime = createRuntime({ modules: [ProjectsModule] })
const composed = runtime.compose({
permissions: new Set(['projects.read']),
enabledModules: new Set(['projects']),
capabilities: new Set([SESSION_TOKEN])
})
// composed.routes → permission-filtered CoreRouteSpec[]
// composed.activeModules → ['projects']
// composed.missingCapabilities → []
Use the framework adapter to apply the composed routes.
// Vue / Quasar
import { coreToVueRoutes, VueRouteApplier } from '@nextera.one/quorium-vue'
const applier = new VueRouteApplier()
const vueRoutes = coreToVueRoutes(composed.routes, resolveComponent)
applier.apply(router, vueRoutes)
// React
import { ReactRouteManager } from '@nextera.one/quorium-react'
const manager = new ReactRouteManager()
const routes = manager.compute(composed.routes, resolveComponent)
// Svelte
import { coreToSvelteRoutes } from '@nextera.one/quorium-svelte'
const routes = coreToSvelteRoutes(composed.routes, resolveComponent)
// Role or flag change → recompose → reapply. Done.
Quorium is a framework-agnostic runtime that deterministically composes frontend structure from permissions, feature flags, and capability contracts. Adapters for Vue, Quasar, React, Svelte, and Framework7.