Skip to main content

Routing

Maybern uses React Router v6 with type-safe route definitions.

Route Structure

Routes are defined at the feature level:
// features/fund-family/FundFamilyRoutes.tsx
export const fundFamilyRoutes = [
  {
    path: "fund-families",
    element: <FundFamilyLayout />,
    children: [
      { index: true, element: <FundFamilyListPage /> },
      { path: ":fundFamilyId", element: <FundFamilyDetailPage /> },
      { path: ":fundFamilyId/settings", element: <FundFamilySettingsPage /> },
    ],
  },
];

Type-Safe Routes

Routes are generated for type safety:
// Generated in src/gen/routes/
import { routes } from "@/gen/routes";

// Type-safe navigation
navigate(routes.fundFamily.detail({ fundFamilyId: "123" }));

// Type-safe links
<Link to={routes.fundFamily.settings({ fundFamilyId })} />

Route Patterns

Nested Routes

{
  path: "capital-activity",
  element: <CapitalActivityLayout />,
  children: [
    { index: true, element: <CapitalActivityListPage /> },
    {
      path: ":eventId",
      element: <CapitalEventLayout />,
      children: [
        { index: true, element: <CapitalEventPage /> },
        { path: "notices", element: <NoticesPage /> },
      ],
    },
  ],
}

Protected Routes

<Route element={<AuthRequired />}>
  <Route element={<CustomerRequired />}>
    <Route path="/*" element={<AppRoutes />} />
  </Route>
</Route>

Lazy Loading

const FundFamilyPage = lazy(() => import("./FundFamilyPage"));

{
  path: "fund-families",
  element: (
    <Suspense fallback={<PageLoader />}>
      <FundFamilyPage />
    </Suspense>
  ),
}

URL Parameters

// In component
const { fundFamilyId, eventId } = useParams<{
  fundFamilyId: string;
  eventId: string;
}>();

// Type-safe with routes
const params = routes.capitalActivity.event.useParams();

Query Parameters

import { useSearchParams } from "react-router-dom";

function MyComponent() {
  const [searchParams, setSearchParams] = useSearchParams();
  
  const filter = searchParams.get("filter");
  const page = searchParams.get("page");
  
  // Update params
  setSearchParams({ filter: "active", page: "2" });
}

Programmatic

import { useNavigate } from "react-router-dom";

function MyComponent() {
  const navigate = useNavigate();
  
  const handleClick = () => {
    navigate(routes.fundFamily.detail({ fundFamilyId }));
  };
}
import { Link } from "react-router-dom";

<Link to={routes.fundFamily.list()}>
  Fund Families
</Link>

Route Generation

Regenerate routes after changes:
pnpm gen:routes

Best Practices

Always use generated route helpers instead of string paths.
Define routes within feature directories, import into main router.
Use React.lazy for page components to optimize bundle size.
Use URL params/query params for shareable state (filters, selected items).