Router API
Complete API reference for client-side routing and navigation.
Router API
The Manic Router provides a type-safe, zero-config routing system for client-side navigation with built-in code-splitting and View Transitions support.
Router
Root component __MANIC_ROUTES__ wiring
RouterContext
Advanced context consumer integrations
Link
Declarative navigation prefetch
navigate
Programmatic navigation
useRouter
Matched route params context
useQueryParams
Reactive URLSearchParams
preloadRoute
Warm lazy chunks manually
Components
<Link />
Primary component for client-side navigation. Automatically prefetches code chunks on hover.
// @errors: 2322
import React from 'react';
import { Link } from 'manicjs';
export default function Nav() {
return (
<Link to="/posts/123" prefetch={true}>
View Post
</Link>
);
}Props
Prop
Type
Example: Conditional Navigation
import React from 'react';
import { } from 'manicjs';
export function ({ , }: { : string; ?: boolean }) {
return (
<
={`/blog/${}`}
={}
={ ? 'font-bold' : ''}
>
{}
</>
);
}Hooks
useRouter()
Access the router instance for programmatic navigation.
// @errors: 2322
import React from 'react';
import { useRouter } from 'manicjs';
export function LoginButton() {
const router = useRouter();
const handleLogin = async () => {
// ... login logic
router.navigate('/dashboard');
};
return <button onClick={handleLogin}>Login</button>;
}Router API
Prop
Type
Examples
// @errors: 2322
const router = useRouter();
// Push a new entry to history
router.navigate('/posts/456');
// Replace current history entry
router.navigate('/login', { replace: true });
// Check current path
if (router.path === '/') {
// Home page
}
// Access route params
const postId = router.params.id;Route Parameters
Access dynamic route parameters via useRouter().params:
// @errors: 2322
import React from 'react';
import { useRouter, useQueryParams } from 'manicjs';
export default function PostPage() {
const { params } = useRouter();
const slug = params.slug;
return <div>Post: {slug}</div>;
}Usage
import { } from 'manicjs';
// Route: app/routes/blog/[slug].tsx
const { } = ();
const { } = ; // From URL: /blog/my-post
// Route: app/routes/posts/[id]/comments/[commentId].tsx
const { , } = ;
// Route: app/routes/docs/[...path].tsx (catch-all)
const { } = ; // path = "guides/setup/installation"useQueryParams()
Access and update URL search parameters:
import React from 'react';
import { } from 'manicjs';
declare const : any;
declare const : (: string) => void;
export function () {
const = ();
return (
<>
<
={.('q') || ''}
={(: any) => {
const = new ();
.('q', .target.value);
(`?${.()}`);
}}
/>
<>Searching for: {.('q')}</>
</>
);
}API
useQueryParams() returns a standard URLSearchParams object:
class URLSearchParams {
get(key: string): string | null;
getAll(key: string): string[];
has(key: string): boolean;
set(key: string, value: string): void;
delete(key: string): void;
toString(): string;
}Examples
import { } from 'manicjs';
declare function (: string): void;
const = ();
// Read
const = .('q'); // "react"
const = .('page'); // "2"
const = .('tag'); // ["javascript", "react"]
// Check existence
if (.('sort')) {
// Sort param exists
}
// Update URL manually
const = new ();
.('q', 'typescript');
.('page');
(`?${.()}`);Route Manifest
The router relies on an auto-generated manifest at app/~routes.generated.ts. This file is updated automatically by manic dev and manic build.
Never edit app/~routes.generated.ts manually. It is regenerated on every build.
Example Generated Manifest
// app/~routes.generated.ts (auto-generated)
export const routes = [
{
path: '/',
component: null,
loader: () => import('./routes/index.tsx'),
},
{
path: '/blog/:slug',
component: null,
loader: () => import('./routes/blog/[slug].tsx'),
},
{
path: '/docs/:...path',
component: null,
loader: () => import('./routes/docs/[...path].tsx'),
},
];Route Registry Structure
Architecture
Advanced Patterns
Protected Routes
// @errors: 2322
import React from 'react';
import { useRouter, useQueryParams } from 'manicjs';
import { useAuth } from './~hooks/useAuth';
export default function AdminPage() {
const router = useRouter();
const { user } = useAuth();
React.useEffect(() => {
if (!user?.isAdmin) {
router.navigate('/', { replace: true });
}
}, [user, router]);
if (!user?.isAdmin) return null; // Prevent flash
return <div>Admin Panel</div>;
}Search with Query Params
import React from 'react';
import { , } from 'manicjs';
declare function (: string): void;
export default function () {
const = ();
const = ();
const = .('q') || '';
const = (: string) => {
const = new ();
.('q', );
.('page', '1');
(`?${.()}`);
};
return (
<>
< ={} ={(: any) => (.target.value)} />
{/* Results for {searchTerm} */}
</>
);
}Nested Dynamic Routes
// Route: app/routes/posts/[id]/comments/[commentId].tsx
import React from 'react';
import { } from 'manicjs';
export default function () {
const { } = ();
return (
<>
<>Post {.}</>
<>Comment {.}</>
</>
);
}View Transitions
Manic automatically wraps navigation in document.startViewTransition() for smooth page transitions.
import React from 'react';
import { } from 'manicjs';
export default function () {
return (
< ="/about">
About
</>
);
}Disable transitions globally:
import { } from 'manicjs';
(false);Custom transition CSS:
::view-transition-old(root) {
animation: fadeOut 0.3s ease-out;
}
::view-transition-new(root) {
animation: fadeIn 0.3s ease-in;
}Router hooks must be called inside components rendered by the router. Calling them outside a routed component will error.
See routing guide for more patterns and best practices.