Skip to content

ADR-004: React SPA on Cloudflare Pages

Status: Accepted
Date: 2026-02-01
Deciders: Abdisamed Mohamed
Related ADRs: ADR-002 (Edge-First Architecture)

Context

CepatEdge requires dynamic client-side routing for maintenance request details, user profiles, and administrative interfaces. Traditional static site generators have limitations with dynamic routes, while full server-side frameworks add unnecessary complexity and cost.

The application needs:

  • Dynamic routing (e.g., /maintenance/:id, /users/:id)
  • Client-side navigation
  • Component reusability
  • TypeScript support
  • Minimal operational overhead

Decision

Use React SPA deployed on Cloudflare Pages with client-side routing.

Implementation

Technology Stack

typescript
// Client-side routing with React Router
import { BrowserRouter, Routes, Route } from 'react-router-dom';

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/maintenance/:id" element={<MaintenanceDetail />} />
        <Route path="/users/:id" element={<UserProfile />} />
        <Route path="/admin/*" element={<AdminRoutes />} />
      </Routes>
    </BrowserRouter>
  );
}

Build Configuration

javascript
// vite.config.js - React SPA build for Pages
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  build: {
    outDir: 'dist',
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['react', 'react-dom'],
          router: ['react-router-dom']
        }
      }
    }
  },
  server: {
    port: 3000,
    host: true
  }
})

Deployment

  • Build Command: npm run build (Vite production build)
  • Output Directory: dist/
  • Routing: Client-side routing handles all dynamic paths
  • CDN: Automatic global distribution via Cloudflare Pages

Consequences

Positive

  • Dynamic Routing: Support for /maintenance/:id style routes without server
  • Client-Side Navigation: Fast navigation without page reloads
  • Component Architecture: Reusable React components with TypeScript
  • Zero Server Cost: No server-side rendering overhead
  • Global CDN: Automatic content delivery worldwide

Negative

  • SEO Limitations: No server-side rendering for search engines
  • Initial Load: Larger initial bundle size
  • Hydration: Client-side only, no SSR benefits
  • API Calls: All data fetching happens client-side

Mitigation

  • Static Generation: Critical pages pre-generated where possible
  • Code Splitting: Lazy loading for optimal bundle sizes
  • API Optimization: Efficient data fetching with SWR
  • Service Worker: Offline capabilities for better UX

Alternatives Considered

Next.js with Server Components

  • Pros: Better SEO, streaming, server components
  • Cons: Requires server infrastructure, higher cost, complexity

Next.js Static Export

  • Pros: Familiar framework, good developer experience
  • Cons: Framework overhead, limited customization, build complexity

Traditional React SPA (Vite + Vercel)

  • Pros: Fast development, modern tooling
  • Cons: Regional deployment, potential latency issues

Static Site Generator (Astro, SvelteKit)

  • Pros: Fast builds, good performance
  • Cons: Limited dynamic routing, framework lock-in

Cloudflare Pages Functions

  • Pros: Server-side logic at edge
  • Cons: Additional complexity, cost implications

Performance Benchmarks

Bundle Size

  • Initial Load: <200KB gzipped
  • Lazy Chunks: <50KB per route
  • Total: <500KB for full application

Routing Performance

  • Client Navigation: <50ms
  • Data Fetching: <100ms with caching
  • Page Load: <300ms globally

References

  • Cloudflare Pages Documentation
  • React Router Documentation
  • Vite Build Tool Documentation
  • Performance benchmarks with Lighthouse