SPA Rewrites on Render: Why Single Source of Truth Matters (CRA vs Custom Build)

When deploying Single-Page Applications (SPAs) to platforms like Render, you'll inevitably encounter the concept of "SPA rewrites." But beyond the mechanics of making your routes work, there's a deeper lesson here about configuration management that every developer should internalize: the principle of single source of truth.

What Are SPA Rewrites and Why Do They Matter?

Single-Page Applications built with React, Vue, or similar frameworks have a unique characteristic: they only have one real HTML file, typically index.html. Everything else—routing, page transitions, dynamic content—is handled by JavaScript on the client side.

Here's the problem: When a user visits https://yourapp.com/app/history directly (perhaps they bookmarked it, or clicked a shared link), the web server looks for a file at that path. But there is no /app/history.html file on your server. Without proper configuration, this results in a 404 error.

SPA rewrites solve this by telling the server: "No matter what URL path is requested, always serve index.html and let the client-side router figure out what to display."

This is the bridge between traditional server-side routing and modern client-side routing.

The Two Approaches: CRA vs Custom Build

Create React App (CRA)

With Create React App, the workflow is straightforward:

  1. You commit your source code to version control
  2. Run npm run build to generate a production-ready static site in the build/ folder
  3. Deploy the build/ folder to Render
  4. If you need custom redirects, place a _redirects file in the public/ directory
  5. CRA automatically copies everything from public/ into build/ during the build process
  6. Render reads the _redirects file and applies the rules

Example _redirects file:

/*  /index.html  200

This single line tells Render: "For any path (/*), serve /index.html with a 200 status code."

👇 Click the image below to explore the interactive version with animations

CRA Build Process Diagram

Click to view the complete interactive diagram with spinning animations

Custom Build (Vite, Webpack, or Ejected CRA)

The principle is identical, but you have more control:

  1. Configure your build tool to output static files to a specific directory (often dist/ for Vite, build/ for Webpack)
  2. Ensure your _redirects file ends up in the published folder after the build
  3. Alternatively, skip the file entirely and configure the rewrite rule directly in Render's dashboard

Vite example:

// vite.config.js
export default {
  publicDir: 'public', // Files here are copied to dist/
  build: {
    outDir: 'dist'
  }
}

Place your _redirects file in the public/ folder, and Vite will copy it to dist/ during build.

The Critical Question: Can You Have Both?

Here's where things get interesting. Yes, technically you can configure SPA rewrites both in a _redirects file AND in Render's dashboard settings. Both methods are functionally identical.

But should you?

No. And here's why.

The Principle of Single Source of Truth

In software development, the single source of truth principle states that every piece of knowledge or configuration should exist in exactly one place. When the same information exists in multiple locations, you create opportunities for:

  • Inconsistency: What happens when your _redirects file says one thing and your dashboard says another?
  • Confusion: New team members won't know which configuration is actually being used
  • Maintenance overhead: Updates must be made in multiple places, increasing the chance of errors
  • Debugging nightmares: When something breaks, you'll waste time checking multiple sources to find the culprit

👇 Click the images below to explore the interactive comparison

Multiple Sources Problem Single Source Solution

Click either image to explore the complete interactive comparison

Real-World Scenario

Imagine you're troubleshooting why a specific route isn't working. You check your _redirects file—looks correct. You spend an hour reviewing your React Router configuration. Then you discover someone modified the rewrite rule in the Render dashboard six months ago, and now the two configurations conflict.

This is exactly the kind of technical debt that slows teams down and creates fragile systems.

Best Practices: Pick One and Stick With It

Option 1: Use the _redirects File (Recommended for Most Projects)

Advantages:

  • Configuration lives in version control alongside your code
  • Easy to review in pull requests
  • Portable across different hosting platforms
  • Clear history of changes via Git

How to implement:

  1. Create a _redirects file in your public/ folder
  2. Add the SPA rewrite rule: /* /index.html 200
  3. Ensure your build process copies this file to the output directory
  4. Remove any conflicting rules from the Render dashboard
  5. Document this decision in your README

Option 2: Use Render Dashboard Configuration

Advantages:

  • No need to manage an extra file
  • Centralized configuration for platform-specific settings
  • Easier for non-technical team members to modify

How to implement:

  1. Navigate to your Render service settings
  2. Add the rewrite rule in the "Redirects/Rewrites" section
  3. Delete any _redirects file from your repository
  4. Document this decision in your README

The Golden Rule

Whatever you choose, make it your single source of truth. Delete the other option. Don't leave both in place "just in case." Future you (and your teammates) will thank you.

Beyond Render: A Universal Principle

This lesson extends far beyond SPA rewrites:

  • Environment variables: Use .env files OR a secrets manager, not both
  • API endpoints: Define them in a config file OR environment variables, not scattered throughout your code
  • Styling: Use CSS-in-JS OR separate stylesheets, not a mix (unless architecturally justified)
  • State management: Redux OR Context API for global state, not a hodgepodge of both

Every time you introduce a second source of truth, you're trading short-term convenience for long-term complexity.

Conclusion

SPA rewrites are a simple concept with a powerful lesson embedded within. The technical implementation—whether you use _redirects or dashboard configuration—matters far less than the discipline of maintaining a single source of truth.

In an industry where complexity is the default, simplicity is a competitive advantage. Your future self, your teammates, and anyone who maintains your code will appreciate the clarity that comes from having one, and only one, place to look for critical configuration.

Choose your source of truth wisely. Then commit to it completely.


About OneTechly: We write about real-world development challenges and the patterns that solve them. Follow us for more practical insights on building maintainable, production-ready applications.

Comments

Popular posts from this blog