WEB ATELIER (UDIT) Β· Learning by doing, with theory, practice and shared reflection

Routing & Navigation: The Multi-Page SPA

Draft

URL: https://ruvebal.github.io/web-atelier-udit/lessons/en/react/react-routing/

πŸ“‹ Table of Contents

β€œRouting is the art of making many pages feel like one app.”


🎯 Sprint Goal

By the end of this sprint: Transform your app into a full multi-page experience with clean URLs, protected routes, and smooth navigationβ€”while remaining a single-page application.


πŸ“ Position in Journey

Sprint Focus Your App Grows
5. Fundamentals Components, JSX, Props Component library skeleton
6. Hooks State & effects Interactive components
7. Architecture Global state Connected features
β†’ 8. Routing Navigation Multi-page structure

🧭 Learning Objectives

By the end of this lesson, you will:

  • Set up React Router v6 in your project
  • Create declarative routes with <Routes> and <Route>
  • Navigate programmatically with useNavigate
  • Read URL parameters with useParams and useSearchParams
  • Implement nested routes and layouts with <Outlet>
  • Protect routes based on authentication state

πŸ—οΈ What We’ll Build This Sprint

Route Structure for Your App

// Example route structure:

<Routes>
  {/* Public routes */}
  <Route path="/" element={<Layout />}>
    <Route index element={<Home />} />
    <Route path="about" element={<About />} />
    <Route path="products" element={<ProductList />} />
    <Route path="products/:id" element={<ProductDetail />} />
  </Route>

  {/* Auth routes */}
  <Route path="/login" element={<Login />} />
  <Route path="/register" element={<Register />} />

  {/* Protected routes */}
  <Route element={<ProtectedRoute />}>
    <Route path="/dashboard" element={<Dashboard />} />
    <Route path="/profile" element={<Profile />} />
    <Route path="/settings" element={<Settings />} />
  </Route>

  {/* Catch-all */}
  <Route path="*" element={<NotFound />} />
</Routes>

πŸ”§ Integration Points

Data Source Routing Integration
Laravel API Dynamic routes from API (e.g., /products/:slug)
Hygraph CMS Content-driven routes (blog posts, pages)
Auth State Protected routes check AuthContext

URL as State

// Filters in URL = shareable, bookmarkable UI state

// Instead of:
const [filter, setFilter] = useState('all');

// Use:
const [searchParams, setSearchParams] = useSearchParams();
const filter = searchParams.get('filter') || 'all';

// URL: /products?filter=electronics&sort=price

πŸŽ“ Methodology: Atelier Practice

The Sprint Rhythm

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ DAY 1: Basic Routing                                    β”‚
β”‚   β€’ Set up React Router in your project                 β”‚
β”‚   β€’ Create public routes and layouts                    β”‚
β”‚   β€’ Practice: Navigation between your existing pages    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ DAY 2: Dynamic & Protected Routes                       β”‚
β”‚   β€’ Build product/article detail pages with useParams   β”‚
β”‚   β€’ Implement ProtectedRoute wrapper                    β”‚
β”‚   β€’ Wire to your AuthContext from Sprint 7              β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ DAY 3: Polish & Edge Cases                              β”‚
β”‚   β€’ Add loading states during navigation                β”‚
β”‚   β€’ Handle 404 with a beautiful NotFound page           β”‚
β”‚   β€’ Test: Can users deep-link? Bookmark? Refresh?       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

AI-Assisted Development Protocol

Task AI Role Your Role
Generate route structure Propose based on your app Verify navigation logic
Implement ProtectedRoute Scaffold the wrapper Test edge cases (no token, expired)
Handle nested layouts Show Outlet pattern Apply to your structure
Debug navigation issues Explain common pitfalls Fix and test

πŸ“ Sprint Deliverables

  • 5+ routes covering your app’s main pages
  • Nested layout with shared header/footer
  • Dynamic route with URL parameter (e.g., :id)
  • Protected route requiring authentication
  • 404 page with helpful navigation
  • URL-based filtering on at least one list page
  • Reflection: How does URL state change your UX thinking?

πŸ”— Lesson Navigation

Previous Current Next
State Architecture Routing Backend Integration

πŸ“š Key Concepts Preview

URL state is real state

  • Filters, pagination, and selected entities often belong in the URL.
  • Treat the URL as a shareable snapshot of app state.

Practical patterns

  • Nested layouts: keep nav + shell stable while pages change
  • Protected routes: authorization gate, not just β€œredirect magic”
  • Search params: the simplest persistence for filters

Example: filters as URL state (conceptual)

// Example state you can encode in the URL:
// /products?query=shoes&sort=price&page=2

Reflection (Atelier)

πŸ’­ Which state should be shareable via link? Which state should not? Why?

πŸ’­ What breaks when you refresh the page? What does that reveal about your architecture?

Koan

β€œIf the URL lies, the user will not return.”


β€œA URL is a promise to the user: this address will always show this content.”