← All @molecule/* packages · App templates
@molecule/app-routing-nextProvider bond · routing · App (browser) · v1.0.1 · Apache-2.0
Next.js App Router provider for molecule.dev
npm install @molecule/app-routing-nextnpm · Source on GitHub · Implements @molecule/app-routing
@molecule/app-routing-next is a provider bond on the app (browser) side: it implements the routing core interface (@molecule/app-routing) with a concrete vendor or library behind it.
Your code calls the core; you wire this provider once at startup. Swapping vendors later is one line in that wiring, not a rewrite.
'use client'
import { useParams, usePathname, useRouter, useSearchParams } from 'next/navigation'
import { useMoleculeRouter } from '@molecule/app-routing-next'
// Mount once near the root layout. useMoleculeRouter recreates + re-bonds on every
// route change (via setRouter in an effect) so location/params stay current and
// @molecule/app-routing's navigate() drives THIS App Router.
export function MoleculeRouterBridge({ children }: { children: React.ReactNode }) {
useMoleculeRouter({
navigation: useRouter(),
pathname: usePathname(),
searchParams: Object.fromEntries(useSearchParams()),
params: useParams(),
})
return children
}Works with: @molecule/app-i18n, @molecule/app-logger, @molecule/app-routing
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
Next.js App Router provider for molecule.dev.
Adapts Next.js App Router navigation to the molecule Router interface from
@molecule/app-routing, so molecule packages and app code can navigate, read
params/query, and register guards without importing next/navigation.
'use client'
import { useParams, usePathname, useRouter, useSearchParams } from 'next/navigation'
import { useMoleculeRouter } from '@molecule/app-routing-next'
// Mount once near the root layout. useMoleculeRouter recreates + re-bonds on every
// route change (via setRouter in an effect) so location/params stay current and
// @molecule/app-routing's navigate() drives THIS App Router.
export function MoleculeRouterBridge({ children }: { children: React.ReactNode }) {
useMoleculeRouter({
navigation: useRouter(),
pathname: usePathname(),
searchParams: Object.fromEntries(useSearchParams()),
params: useParams(),
})
return children
}
provider
npm install @molecule/app-routing-next @molecule/app-i18n @molecule/app-logger @molecule/app-routing react
npm install -D @types/react
MiddlewareGuardRuleMiddleware guard rule configuration.
interface MiddlewareGuardRule {
/**
* Path pattern to match (supports * wildcards).
*/
match: string
/**
* Check function - return true to allow, string to redirect.
*/
check: (request: {
url: string
pathname: string
cookies: { get: (name: string) => { value: string } | undefined }
headers: { get: (name: string) => string | null }
}) => boolean | string | Promise<boolean | string>
}
NavigateOptionsOptions for programmatic navigation (replace vs push, carry state, preserve query/hash).
interface NavigateOptions {
/**
* Replace current history entry instead of pushing.
*/
replace?: boolean
/**
* State to pass with navigation.
*/
state?: unknown
/**
* Preserve current query params.
*/
preserveQuery?: boolean
/**
* Preserve current hash.
*/
preserveHash?: boolean
}
NextNavigationNext.js navigation types (minimal subset to avoid direct next dependency).
interface NextNavigation {
push(href: string, options?: { scroll?: boolean }): void
replace(href: string, options?: { scroll?: boolean }): void
back(): void
forward(): void
refresh(): void
prefetch?(href: string): void
}
NextParamsNext Params interface.
interface NextParams {
[key: string]: string | string[]
}
NextRouterConfigConfiguration options for the Next.js router provider.
interface NextRouterConfig extends RouterConfig {
/**
* Next.js navigation object (from useRouter).
*/
navigation?: NextNavigation
/**
* Current pathname (from usePathname).
*/
pathname?: string
/**
* Current search params (from useSearchParams).
*/
searchParams?: NextSearchParams
/**
* Current dynamic params (from useParams).
*/
params?: NextParams
/**
* Route definitions.
*/
routes?: RouteDefinition[]
}
NextSearchParamsNext Search Params interface.
interface NextSearchParams {
[key: string]: string | string[] | undefined
}
RouteDefinitionRoute configuration entry (path pattern, name, auth requirements, roles, children).
interface RouteDefinition {
/**
* Route path pattern.
*/
path: string
/**
* Route name (for named routes).
*/
name?: string
/**
* Whether the route requires exact matching.
*/
exact?: boolean
/**
* Whether the route requires authentication.
*/
requiresAuth?: boolean
/**
* Required roles/permissions.
*/
roles?: string[]
/**
* Route metadata.
*/
meta?: Record<string, unknown>
/**
* Child routes.
*/
children?: RouteDefinition[]
}
RouteLocationCurrent URL decomposed into pathname, search string, hash, navigation state, and unique key.
interface RouteLocation {
/**
* Current pathname.
*/
pathname: string
/**
* Query string (including leading ?).
*/
search: string
/**
* Hash (including leading #).
*/
hash: string
/**
* State data passed with navigation.
*/
state?: unknown
/**
* Unique key for this location.
*/
key?: string
}
RouteMatchResult of matching a URL against a route pattern (path, params, query string).
interface RouteMatch<Params extends RouteParams = RouteParams> {
/**
* Route path pattern.
*/
path: string
/**
* Matched URL pathname.
*/
pathname: string
/**
* Route parameters.
*/
params: Params
/**
* Whether this is an exact match.
*/
isExact: boolean
}
RouterClient-side router providing navigation, guards, route matching, and history control.
All routing providers must implement this interface.
interface Router {
/**
* Returns the current route location (pathname, search, hash, state).
*/
getLocation(): RouteLocation
/**
* Gets the current route params.
*/
getParams<T extends RouteParams = RouteParams>(): T
/**
* Gets the current query params.
*/
getQuery(): QueryParams
/**
* Gets a specific query parameter.
*/
getQueryParam(key: string): string | undefined
/**
* Gets the current hash.
*/
getHash(): string
/**
* Navigates to a path.
*/
navigate(path: string, options?: NavigateOptions): void
/**
* Navigates to a named route.
*/
navigateTo(
name: string,
params?: RouteParams,
query?: QueryParams,
options?: NavigateOptions,
): void
/**
* Goes back in history.
*/
back(): void
/**
* Goes forward in history.
*/
forward(): void
/**
* Goes to a specific point in history.
*/
go(delta: number): void
/**
* Updates the current query params.
*/
setQuery(params: QueryParams, options?: NavigateOptions): void
/**
* Updates a specific query parameter.
*/
setQueryParam(key: string, value: string | undefined, options?: NavigateOptions): void
/**
* Updates the current hash.
*/
setHash(hash: string, options?: NavigateOptions): void
/**
* Checks if a path matches the current location.
*
* @returns `true` if the path matches the current route.
*/
isActive(path: string, exact?: boolean): boolean
/**
* Matches a path pattern against a pathname.
*/
matchPath<Params extends RouteParams = RouteParams>(
pattern: string,
pathname: string,
): RouteMatch<Params> | null
/**
* Generates a URL from a named route.
*/
generatePath(name: string, params?: RouteParams, query?: QueryParams): string
/**
* Subscribes to route changes.
*/
subscribe(listener: RouteChangeListener): () => void
/**
* Adds a navigation guard.
*/
addGuard(guard: NavigationGuard): () => void
/**
* Registers route definitions.
*/
registerRoutes(routes: RouteDefinition[]): void
/**
* Gets all registered routes.
*/
getRoutes(): RouteDefinition[]
/**
* Destroys the router.
*/
destroy(): void
}
RouterConfigConfiguration options for creating a router instance.
interface RouterConfig {
/**
* Router mode.
*/
mode?: 'history' | 'hash' | 'memory'
/**
* Base path.
*/
basePath?: string
/**
* Initial routes.
*/
routes?: RouteDefinition[]
}
NavigationGuardNavigation guard function invoked before each navigation.
Return false to cancel, a string/path to redirect, or void to allow.
type NavigationGuard = (
to: RouteLocation,
from: RouteLocation | null,
) => GuardResult | Promise<GuardResult>
QueryParamsURL query string parameter map (single values or arrays for repeated keys).
type QueryParams = Record<string, string | string[] | undefined>
RouteChangeListenerCallback invoked on each route change with the new location and the navigation action that triggered it.
type RouteChangeListener = (location: RouteLocation, action: 'push' | 'replace' | 'pop') => void
RouteParamsURL path parameter key-value map extracted from dynamic route segments (e.g. { id: '123' }).
type RouteParams = Record<string, string>
createLinkHref(pathname, query, hash)Creates a Next.js link href with query params.
function createLinkHref(pathname: string, query?: QueryParams, hash?: string): string
pathname — The base path (e.g. '/products').query — Optional query parameters to append as a search string.hash — Optional hash fragment (with or without leading #).Returns: The assembled href string with path, query, and hash.
createMiddlewareGuard(rules)Next.js middleware helper for route guards.
function createMiddlewareGuard(
rules: MiddlewareGuardRule[],
): (request: {
url: string
nextUrl: { pathname: string }
cookies: { get: (name: string) => { value: string } | undefined }
headers: { get: (name: string) => string | null }
}) => Promise<
{ redirect: string; continue?: undefined } | { continue: boolean; redirect?: undefined }
>
rules — Array of guard rules, each with a match pattern (supports * wildcards) and an async check function.Returns: An async middleware function that returns { redirect: string } or { continue: true }.
createNextRouter(config)Creates a Next.js App Router adapter.
function createNextRouter(config?: NextRouterConfig): Router
config — Configuration with Next.js's navigation (from useRouter()), pathname, searchParams, params, and optional routes.Returns: A molecule Router with navigation, guards, query/hash management, and route matching.
dynamicPath(pattern)Creates a reusable path builder for Next.js dynamic routes. Replaces [param] and
[...catchAll] segments with provided values.
function dynamicPath(pattern: string): (params: Record<string, string | string[]>) => string
pattern — A Next.js route pattern with [param] or [...catchAll] segments.Returns: A function that accepts params and returns the resolved path string.
parseCatchAllParams(param)Normalizes a Next.js catch-all route parameter into a string array.
Handles undefined (returns []), a single string, or an existing array.
function parseCatchAllParams(param: string | string[] | undefined): string[]
param — The catch-all param value from Next.js route params.Returns: An array of path segments.
useMoleculeRouter(config)Builds the molecule Router from next/navigation hook values AND bonds it via
@molecule/app-routing's setRouter, so navigate()/getRouter() drive the REAL
App Router (not the core's auto-created fallback that does full-page reloads).
Call it in a 'use client' component near the root layout, passing the values from
useRouter()/usePathname()/useSearchParams()/useParams(). It rebuilds and
re-bonds on every route change so location/params stay current.
function useMoleculeRouter(config: NextRouterConfig): Router
config — The Next.js router config (navigation, pathname, searchParams, params, optional routes) assembled from next/navigation hooks.Returns: The bonded molecule Router.
generatePathGenerates a URL path from a route pattern by substituting named parameters.
const generatePath: (pattern: string, params?: RouteParams) => string
matchPathMatches a route pattern (e.g. /users/:id) against a pathname.
Extracts named parameters from the URL.
const matchPath: <Params extends RouteParams = RouteParams>(
pattern: string,
pathname: string,
exact?: boolean,
) => RouteMatch<Params> | null
parseQueryParses a URL query string (e.g. ?foo=bar&baz=1) into a
QueryParams object. Duplicate keys produce string arrays.
const parseQuery: (search: string) => QueryParams
providerDefault Next.js router provider (basic, no hooks). For full functionality, use
createNextRouter with useRouter/usePathname/useSearchParams/useParams.
const provider: Router
stringifyQuerySerializes a QueryParams object into a query string with leading ?.
Returns an empty string if no parameters are present.
const stringifyQuery: (params: QueryParams) => string
Implements @molecule/app-routing interface.
Setup function to register this provider with the core interface:
import { setRouter } from '@molecule/app-routing'
import { provider } from '@molecule/app-routing-next'
export function setupRoutingNext(): void {
setRouter(provider)
}
Peer dependencies:
@molecule/app-i18n ^1.0.1@molecule/app-logger ^1.0.1@molecule/app-routing ^1.0.1react ^18.0.0 || ^19.0.0@molecule/app-i18n
@molecule/app-logger
@molecule/app-routing
react
Use useMoleculeRouter(...) to bond the router from a 'use client'
component near the root layout (the adapter cannot run in Server Components). It
calls @molecule/app-routing's setRouter in an effect, so molecule packages'
navigate()/getRouter() drive the real App Router.
Do NOT wire the exported provider const in a Next app. It is a no-hooks
fallback: its location is frozen at import time, getParams() is always empty,
and navigate() falls back to window.location.href — a full page reload that
bypasses the App Router.
Forgotten wiring never errors. @molecule/app-routing's getRouter()
auto-creates a plain browser router when nothing is bonded, so molecule packages
keep "working" with full-page reloads — check wiring first when SPA navigation
degrades.
createMiddlewareGuard() (for middleware.ts) returns plain
{ redirect: string } | { continue: true } objects — map them to
NextResponse.redirect(new URL(result.redirect, request.url)) /
NextResponse.next() yourself; returning the guard result directly does nothing.
searchParams must be a plain object — spread the hook value with
Object.fromEntries(useSearchParams()).