Routing

Jumbo React Vite uses React Router 7 with createBrowserRouter and RouterProvider. The router maps URL prefixes to layout shell components and delegates page-level routes to per-demo route files.

Router setup

The router is created once in src/routes/index.tsx and passed to <RouterProvider> in App.tsx:

tsx
// src/App.tsx
import { RouterProvider } from 'react-router-dom';
import { router } from './routes';
 
function App() {
  return (
    // ... providers ...
    <RouterProvider router={router} />
  );
}

Top-level route structure

Each top-level route maps a URL prefix to a layout shell and uses generateChildRoutes() to attach the page routes as children:

typescript
// src/routes/index.tsx
const routes: RouteObject[] = [
  {
    path: '/',
    element: <StretchedLayout />,
    children: generateChildRoutes(demoRoutes),
  },
  {
    path: '/demo-1',
    element: <Demo1Layout />,
    children: generateChildRoutes(demoRoutes, '/demo-1'),
  },
  {
    path: '/demo-2',
    element: <Demo2Layout />,
    children: generateChildRoutes(demo2Routes, '/demo-2'),
  },
  {
    path: '/demo-3',
    element: <Demo3Layout />,
    children: generateChildRoutes(demo3Routes, '/demo-3'),
  },
  {
    path: '/demo-4',
    element: <Demo4Layout />,
    children: generateChildRoutes(demo4Routes, '/demo-4'),
  },
  {
    path: '/auth',
    element: <SoloLayout />,
    children: generateChildRoutes(authRoutes, '/auth'),
  },
  {
    path: '/extra-pages',
    element: <SoloLayout />,
    children: generateChildRoutes(extraRoutes, '/extra-pages'),
  },
  {
    path: '*',
    element: <NotFound />,
  },
];
 
export const router = createBrowserRouter(routes);

generateChildRoutes()

generateChildRoutes() in src/utilities/helpers/index.tsx prefixes all child paths with a base path, enabling the same page route definitions to be reused across multiple layout prefixes:

typescript
// src/utilities/helpers/index.tsx
export function generateChildRoutes(
  pages: RouteObject[],
  basePath: string = ''
): RouteObject[] {
  return pages.map((page) => ({
    ...page,
    path: `${basePath}${page.path}`,
    children: page.children
      ? generateChildRoutes(page.children, `${basePath}${page.path}/`)
      : [],
  }));
}

For example, the route { path: '/dashboards/misc', element: <MiscPage /> } in demoRoutes becomes /demo-1/dashboards/misc when passed with basePath: '/demo-1'.

Page route files

FileLayout prefixDefault home
src/routes/demo-routes.tsx/ and /demo-1, /demo-4/dashboards/misc
src/routes/demo2-routes.tsx/demo-2Social wall
src/routes/demo3-routes.tsx/demo-3Public profile
src/routes/demo4-routes.tsx/demo-4/dashboards/misc
src/routes/solo-routes.tsx/auth, /extra-pagesLogin

The Page wrapper

Most routes use the Page component to optionally apply a HOC before rendering:

tsx
// src/routes/demo-routes.tsx (excerpt)
{
  path: '/dashboards/misc',
  element: <Page Component={MiscPage} hoc={withAuth} />,
},
tsx
// src/components/Page/Page.tsx
const Page = ({ Component, hoc }: PageProps) => {
  if (hoc) {
    const WrappedComponent = hoc(Component);
    return <WrappedComponent />;
  }
  return <Component />;
};

Route protection with withAuth

withAuth is a HOC that checks authentication state before rendering a page. Unauthenticated users are redirected to /auth/login-1:

typescript
// src/hoc/withAuth.tsx
const withAuth = (Component: React.ComponentType) => {
  return (): React.JSX.Element | null => {
    const { isAuthenticated, loading } = useAuth();
 
    if (loading)          return <Spinner />;
    if (!isAuthenticated) return <Navigate to='/auth/login-1' />;
 
    return <Component />;
  };
};

Pass hoc={withAuth} on every protected route. Auth pages (login, signup) omit the HOC.

Adding a new page

  1. Create the page component

    Add a new file in the appropriate src/pages/<category>/ directory:

    tsx
    // src/pages/dashboards/AnalyticsPage.tsx
    export function AnalyticsPage() {
      return <div>Analytics</div>;
    }
  2. Register the route

    Add an entry to the relevant route file:

    typescript
    // src/routes/demo-routes.tsx
    import { AnalyticsPage } from '@/pages/dashboards/AnalyticsPage';
     
    // Inside the routes array:
    {
      path: '/dashboards/analytics',
      element: <Page Component={AnalyticsPage} hoc={withAuth} />,
    },
  3. Add a nav item (optional)

    Add an entry to the menus file of the layout you want to show it in:

    typescript
    // src/layouts/StretchedLayout/menus.ts
    { label: 'Analytics', path: '/dashboards/analytics' }