src/routes/, keeping them separate from page components.
How the router is set up
There are two files insrc/routes/:
AppRoutes.tsx
Declares the full route tree as a
RouteObject[] array. Import and add routes here.index.tsx
Calls
createBrowserRouter with the route array and exports the router instance used by main.tsx.src/routes/index.tsx
src/routes/index.tsx
createBrowserRouter uses the HTML5 History API for clean URLs (no # hash). The exported router is passed to <RouterProvider> in src/App.tsx, which main.tsx then renders inside <StrictMode>.
The route tree
src/routes/AppRoutes.tsx
Built-in routes
| Path | Component | Description |
|---|---|---|
/ | HomePage | Landing page (index route) |
/features | FeaturesPage | Feature showcase grid |
/about | AboutPage | About page |
Nested routes and <Outlet />
Layout is the parent route at path: '/'. Every page is a child route rendered inside it. React Router replaces <Outlet /> in Layout with whichever child matches the current URL:
src/components/Layout.tsx
- The navbar and footer render once, for every page.
- You only need to write the content inside
<main>in each page component. - Navigating between pages replaces only the
<Outlet />content — the shell stays mounted.
Adding a new route
Register the route in AppRoutes.tsx
Import your page and add a new child route object:
src/routes/AppRoutes.tsx
Link to it from Navigation
Add a new entry to the links array in
src/components/Navigation.tsx so users can reach the new page. See Navigation for the exact pattern.Adding a 404 route
To catch unmatched URLs, add a catch-all route as the last child withpath: '*':
The catch-all child route still renders inside
Layout, so your navbar and footer remain visible on the 404 page. If you want a fully custom error screen, add the errorElement property to the parent route instead.