DEV Community

Kamran Khan
Kamran Khan

Posted on

My App.jsx is a route map, not a component

My App.jsx contains zero markup. No layout, no styling, no UI logic — just a route tree. That is deliberate. Every starter kit I've inherited buried auth checks and nav state inside components, so debugging a "why can I see this page" question meant grep-hunting through three files. I moved all of it into the route tree, where one file answers it.

<BrowserRouter basename={basename}>
  <Routes>
    <Route path="/login" element={<Login />} />
    <Route path="/register" element={<Register />} />
    <Route
      element={
        <ProtectedRoute>
          <Layout />
        </ProtectedRoute>
      }
    >
      <Route index element={<Dashboard />} />
      <Route
        path="/users"
        element={
          <AdminRoute>
            <Users />
          </AdminRoute>
        }
      />
    </Route>
    <Route path="/home" element={<Navigate to="/" replace />} />
    <Route path="/404" element={<NotFound />} />
    <Route path="*" element={<NotFound />} />
  </Routes>
</BrowserRouter>
Enter fullscreen mode Exit fullscreen mode

The trick is the parent route with an element but no path: ProtectedRoute wraps Layout, and both Dashboard and Users nest inside. Any page that needs a login lives in that subtree, which means the auth gate is applied structurally — there's no per-page if (!user) redirect to forget. The Users page gets one more layer, AdminRoute, for the role check. Login and Register stay outside the subtree entirely; they're public by omission, which is the kind of default I trust more than a default that needs an exception.

Two small details I kept because they save real headaches:

basename. The router basename comes from Vite's BASE_URL (the base build option), so the app works at a domain root and under a sub-path like a GitHub Pages demo link. Without this, the client-side router and the deployed base URL disagree and every deep link breaks.

The /home redirect. Clients always ask for a /home route that nobody built. A one-line <Navigate to="/" replace /> settles it forever — a redirect entry costs nothing and removes a whole category of "page not found" support questions.

Everything else — the sidebar, the header, the logout button — belongs to Layout, which is just another component rendered through the route tree. App.jsx stays a map; components stay components. When someone asks "who can see /users?", the answer is one nesting level in one file.


This structure ships in my Laravel + React SaaS Starter Kit ($19 one-time) — the full route tree above plus ProtectedRoute and AdminRoute, ready to extend with your own pages.

Top comments (0)