@void-snippets/react
defineRoute & build()
Route definitions, metadata, search params, and URL construction.
#defineRoute(path, config?)
Defines a single route with a path and optional metadata. Chain .search to declare typed search parameters.
#Metadata fields (config)
| Field | Type | Description |
|---|---|---|
permissions | string[] | Access control identifiers — read via route.handle in your router config. |
breadcrumb | string | Label for breadcrumb navigation. |
title | string | Page title for management. |
meta | Record | Any custom metadata — loader IDs, analytics events, feature flags. |
#.search() — typed search params
Chain immediately after defineRoute(). The generic T declares which search params this route accepts.
typescript
defineRoute('/contacts')
.search<{ page: number; sort?: 'asc' | 'desc'; q?: string }>()Use absolute paths. Write
/dashboard/usersnot${DASHBOARD}/${USERS}. TypeScript extracts path parameter names (:userId) using template literal inference, and concatenated strings cause exponential type-checking in large apps.
#build() — constructing URLs
TypeScript shapes the build() signature based on what the route has.
| Route shape | Signature |
|---|---|
| No params, no search | build() → string |
| Optional-only search | build(options?) → string |
| Required path param | build({ params }) → string |
| Required search key | build({ search }) → string |
typescript
// No arguments — simple route
AppRoutes.dashboard.settings.build()
// → '/dashboard/settings'
// Optional search
AppRoutes.auth.login.build({ search: { redirect: '/dashboard' } })
// → '/auth/login?redirect=%2Fdashboard'
// Required path param
AppRoutes.dashboard.users.detail.build({ params: { userId: '123' } })
// → '/dashboard/users/123'
// Required path param + optional search
AppRoutes.dashboard.users.detail.build({
params: { userId: '123' },
search: { tab: 'settings' },
})
// → '/dashboard/users/123?tab=settings'
// TypeScript catches these at compile time:
AppRoutes.dashboard.users.detail.build() // ❌ params required
AppRoutes.dashboard.users.list.build() // ❌ search.page required
AppRoutes.dashboard.users.list.build({ search: { page: '1' } }) // ❌ page must be number#Wiring React Router
typescript
// router.tsx
import { createBrowserRouter } from 'react-router';
import { AppRoutes } from './routes';
const router = createBrowserRouter([
{
path: AppRoutes.auth.login.path,
element: <LoginPage />,
},
{
path: AppRoutes.dashboard.root.path,
element: <DashboardLayout />,
handle: { title: AppRoutes.dashboard.root.title, breadcrumb: AppRoutes.dashboard.root.breadcrumb },
children: [
{
path: AppRoutes.dashboard.users.list.path,
element: <UsersListPage />,
handle: { permissions: AppRoutes.dashboard.users.list.permissions },
},
],
},
]);#Navigating
tsx
// Programmatic
const navigate = useNavigate();
navigate(AppRoutes.dashboard.users.detail.build({ params: { userId: contact._id } }));
// Link component
<Link to={AppRoutes.auth.login.build({ search: { redirect: location.pathname } })}>
Log in
</Link>