
Single Page Applications like React expect the server to always return index.html and let the client-side router take over. On Cloudflare Workers you can do that without custom code as long as wrangler.toml is set up correctly. This post shows the minimal configuration and why two options are essential for SPAs.
The SPA problem on the edge
A deployed SPA usually contains compiled assets plus one index.html. Deep links like /dashboard/settings should load the same index.html and let the client router render the view. Without a rewrite you get 404s because the edge tries to find a physical file dashboard/settings that does not exist.
The two crucial wrangler.toml flags
Cloudflare added built-in SPA handling. Set both options in your wrangler.toml:
1# wrangler.toml
2name = "my-react-app"
3compatibility_date = "2024-11-01" # this is specific to your project
4
5[assets]
6# Forces URLs like /app/ to become /app/ so relative links stay correct
7html_handling = "force-trailing-slash"
8
9# Always return your SPA shell (index.html) for unknown routes
10not_found_handling = "single-page-application"
html_handling = "force-trailing-slash"ensures that HTML requests end with a trailing slash. That keeps relative asset links like"./static/js/main.js"valid and avoids mixed path resolution, especially when users paste URLs without the slash.not_found_handling = "single-page-application"tells the Worker runtime to serve your SPA entry point instead of a 404 for any route that is not a real asset. This is the key to make deep links work.
Verify your deployment
- Build the React app:
npm run build. - Deploy:
wrangler deploy. - Open deep links directly (e.g.,
/settings/profile). If everything is configured, the page loads without 404 and the client router renders the correct view.
Troubleshooting
- Still getting 404? Check that
not_found_handlingis set tosingle-page-applicationand that theassetssection is under the root ofwrangler.toml. - CSS or JS missing? Trailing slashes might be the issue. Keep
html_handling = "force-trailing-slash"so relative paths resolve correctly. - Mixed content or wrong base path? Ensure your React build uses relative asset paths (the default for
create-react-app) and that your Worker domain matches thehomepagesetting if you changed it.
Takeaway
Two lines in wrangler.toml are enough to make React (and any SPA) work on Cloudflare Workers without custom rewrites:
html_handling = "force-trailing-slash"not_found_handling = "single-page-application"
Set them once, deploy and your SPA will be correctly served for every deep link.
Related articles

Jan 04, 2026 · 2 min read
Automate Pull Request Comments with GitHub Actions
When working with Pull Requests (PRs) in GitHub, it is often helpful to provide immediate feedback or relevant information directly in the …

Jul 14, 2025 · 4 min read
Scheduled Builds for Cloudflare Deployments with GitHub Actions
Static site generators like Hugo do not have a built-in mechanism to automatically publish content–such as blog posts–at a specific time. If …

Mar 17, 2026 · 15 min read
GitHub Copilot - Custom Agents for Full-Stack Teams: A Practical Operating Model for .NET, React and Azure
GitHub Copilot custom agents allow teams to define specialized AI assistants, each with its own role, tool access and behavioral boundaries. …
Let's Work Together
Looking for an experienced Platform Architect or Engineer for your next project? Whether it's cloud migration, platform modernization or building new solutions from scratch - I'm here to help you succeed.

Comments