How to Structure Routing in React (Vite + TypeScript) Like a Pro (2026 Guide)

π React Routing Done Right (Vite + TypeScript)#
Letβs be honest.
Most React apps start simple⦠and then routing becomes a mess.
- Guards everywhere
- Duplicate wrappers
- Confusing structure
So in this guide, Iβll show you a clean, scalable routing setup you can actually use in real projects.
π§ The Core Idea#
Instead of thinking:
βWhich page goes where?β
Think:
βWho is allowed to access this route?β
π Folder Structure#
Folder structure is very importaint for scalable applications. If you know better do let me know
src
βββ router
β βββ protected-route.tsx
β βββ auth-route.tsx
β βββ index.tsx
β
βββ components
β βββ ui
β
βββ layouts
β βββ app-layout.tsx
β βββ auth-layout.tsx
β
βββ pages
β βββ login.tsx
β βββ register.tsx
β βββ dashboard.tsx
β βββ home.tsx
β βββ about.tsx
β
βββ Main.tsx
βββ index.css
π Three Types of Routes#
π 1. Public Routes (No Guard)#
Accessible by everyone.
//about/contact
{ path: "/", element: <Home /> }π’ 2. Auth Routes (Only for Logged-Out Users)#
Used for:
/login/register
import { Navigate } from 'react-router-dom';
export default function AuthRoute({ children }: any) {
const isAuthenticated = true; // testing
if (isAuthenticated) {
return <Navigate to="/dashboard" replace />;
}
return children;
}π If user is logged in β redirect to dashboard
π 3. Protected Routes (Only for Logged-In Users)#
Used for:
/dashboard/profile
import { Navigate } from 'react-router-dom';
export default function ProtectedRoute({ children }: any) {
const isAuthenticated = true; // testing
if (!isAuthenticated) {
return <Navigate to="/login" replace />;
}
return children;
}π If user is NOT logged in β redirect to login
π§© Clean Routing Setup#
Hereβs the actual structure π
import { createBrowserRouter } from 'react-router-dom';
import { Login } from '../pages/login';
import { Register } from '../pages/register';
import { Dashboard } from '../pages/dashboard';
import AuthLayout from '../layout/auth-layout';
import AppLayout from '../layout/app-layout';
import { Home } from '../pages/home';
import { AboutPage } from '../pages/about';
import AuthRoute from './auth-route';
import ProtectedRoute from './protected-route';
export const router = createBrowserRouter([
// Public Routes No Guard
{ path: '/', element: <Home /> },
{ path: '/about', element: <AboutPage /> },
// Auth Guarded Routes
{
element: (
<AuthRoute>
<AuthLayout />
</AuthRoute>
),
children: [
{ path: '/login', element: <Login /> },
{ path: '/register', element: <Register /> },
],
},
// PROTECTED Routes
{
element: (
<ProtectedRoute>
<AppLayout />
</ProtectedRoute>
),
children: [{ path: '/dashboard', element: <Dashboard /> }],
},
]);π§± Why Layouts Matter#
Instead of repeating UI everywhere:
- Navbar
- Sidebar
- Auth container
π You define them once using layouts.
Example: App Layout#
function AppLayout() {
return (
<div>
<Sidebar />
<main>
<Outlet />
</main>
</div>
);
}Example: Auth Layout#
function AuthLayout() {
return (
<div className="centered-container">
<Outlet />
</div>
);
}π Route Guards#
AuthRoute#
if (isAuthenticated) {
return <Navigate to="/dashboard" />;
}ProtectedRoute#
if (!isAuthenticated) {
return <Navigate to="/login" />;
}β οΈ Common Mistakes#
β Using "PublicRoute" for everything#
This blocks logged-in users from normal pages like /about.
β Wrapping every route manually#
Leads to messy and repetitive code.
β Mixing layout + auth logic#
Keep them separate.
π§ Mental Model (Remember This)#
| Type | Access | Guard |
|---|---|---|
| Public | Everyone | β None |
| Auth | Logged-out | β AuthRoute |
| Protected | Logged-in | β ProtectedRoute |
β‘ Pro Tips#
- Use route grouping with
<Outlet /> - Keep routes centralized
- Use layouts for UI reuse
- Donβt over-engineer early
π Final Thoughts#
You donβt need file-based routing like Next.js to build scalable apps.
With:
- React Router
- Layouts
- Route guards
π You already have a production-ready system.
π¬ Final Takeaway#
Routing is not about pages.
Itβs about access control + structure.
Get that right early, and your app stays clean forever.