cloudflare / cloudflare/templates

🐛 BUG: Routing Conflict in vite-react-template: SPA Fallback Intercepts API Routes on Direct Navigation

Open
#409 0 comments 2 reactions 0 assignees View on GitHub
bug
Dominant language
TypeScript
Stars
2.1k
Forks
1k
Avg merge
17h 44m
Merged PRs (30d)
10

Description

### Which template does this pertain to?

vite-react-template

### What versions are you using?

wrangler: ^4.7.0, vite: ^6.1.0, @cloudflare/vite-plugin: ^1.0.2, hono: ^4.7.5, react: ^19.0.0 (Node.js: unknown, C3: unknown)

### What operating system and version are you using?

Mac OS 15.1.1 (24B91)

### Please provide a link to a minimal reproduction (optional)

_No response_

### Describe the Bug

**Repository:** cloudflare/templates
**Template:** vite-react-template ([link](https://github.com/cloudflare/templates/tree/staging/vite-react-template))

**Problem Description:**

When using the `vite-react-template`, even with its default configuration, a routing conflict occurs when attempting to directly navigate to server-side API routes (e.g., using Hono within the Worker) via the browser address bar or redirects. The platform's routing logic, intended to support Single Page Application (SPA) behavior, appears to intercept these navigation requests before the Worker script can handle them.

The standard setup from the template involves:
1. Using Vite with `@cloudflare/vite-plugin`.
2. Defining API routes (e.g., `/api/*`) within the Hono application (`src/index.ts` or similar, configured as `main` in `wrangler.json`).
3. The default `wrangler.json` (or one configured with `"assets": { "not_found_handling": "single-page-application" }`) attempts to handle SPA routing for non-asset paths.

The issue arises because the mechanism handling SPA fallbacks (likely related to `not_found_handling: "single-page-application"`) intercepts requests with `Sec-Fetch-Mode: navigate` *before* the Worker script runs if the path doesn't match a static asset. This means attempts to directly navigate to an API endpoint (e.g., typing `/api/some-route` in the browser, clicking an external link, or being redirected from an OAuth provider) result in the SPA's `index.html` being served, bypassing the Hono API handler.

Programmatic `fetch` requests from the loaded SPA to `/api/*` routes work correctly, as they typically use a different `Sec-Fetch-Mode` (like `cors`) and are routed to the Worker.

**Use Case / Impact:**

This breaks critical server-side functionality that relies on direct browser interaction with API routes, most notably:

* **OAuth Callbacks:** Redirects from identity providers (e.g., Google, GitHub) land on `/api/auth/callback/...` via browser navigation and are incorrectly served `index.html`.
* **Server-Initiated Redirects:** Any server-side logic that needs to redirect the browser to an API endpoint for processing before potentially redirecting again.

**Steps to Reproduce (Conceptual):**

1. Initialize a project using `npm create cloudflare@latest -- --template=cloudflare/templates/vite-react-template`.
2. In the Hono application (`src/index.ts` or `src/server/server.ts`), define a simple API route: `app.get('/api/test', (c) => c.text('API OK'));`
3. Build and deploy (`npm run build`, `npx wrangler deploy`) using the default `wrangler.json` or one explicitly configured for SPA fallback.
4. Attempt to navigate directly to `https:///api/test` in a web browser.

**Expected Behavior:**

The browser should display the text "API OK" served by the Hono route handler.

**Actual Behavior:**

The SPA's `index.html` is served, and the browser likely shows the SPA's root page or a client-side 404 error. This occurs even with the default template configuration.

**Troubleshooting / Workarounds Attempted:**

1. **Modifying `wrangler.json` `assets`:** Explicitly configuring the `assets` section with various combinations of `not_found_handling` (`"single-page-application"`, `"404-page"`, `"404"`) and `run_worker_first` (`true`/`false`). Removing the `assets` section entirely was also attempted.
* Setting `not_found_handling: "404"` allows API routes to be hit correctly on navigation, but breaks the SPA fallback. It requires manually implementing the SPA fallback within Hono using `env.ASSETS.fetch('/index.html')`, adding complexity.
* Setting `run_worker_first: true` (with `not_found_handling: "single-page-application"` and a valid `assets` config including `directory` and `binding`) *should* theoretically work according to docs, but requires adding a final catch-all route `app.get('*', (c) => c.env.ASSETS.fetch(c.req.raw))` to the Hono app to delegate back to the asset handler. This delegation step isn't present in the template and wasn't immediately obvious. Even with this setup, achieving consistent behavior felt unreliable during testing.
2. **Modifying Headers:** Considered intercepting requests in Hono to change `Sec-Fetch-Mode`, but understood this is not possible as the platform routing happens *before* the Worker executes.

**Question / Suggestion:**

What is the canonical/recommended way to configure the `vite-react-template` (or any Worker+Vite+Hono SPA setup) to correctly handle both SPA fallbacks *and* direct browser navigation to API routes (like OAuth callbacks)?

Is the combination of `run_worker_first: true`, `not_found_handling: "single-page-application"`, a valid `assets` config (with `directory`, `binding`), AND a final Hono catch-all route `app.get('*', (c) => c.env.ASSETS.fetch(c.req.raw))` the intended pattern?

If so, could the template be updated to include this necessary catch-all delegation route in the Hono setup, or could the documentation provide clearer guidance on this specific interaction? The current template structure seems prone to this routing conflict when used for full-stack applications requiring navigable API endpoints.

**Environment (Please fill in your versions):**

* `wrangler`: ^4.7.0
* `@cloudflare/vite-plugin`: ^1.0.2
* `vite`: ^6.1.0
* `hono`: ^4.7.5
* `react`: ^19.0.0
* `node`: [e.g., 20.x.x]

Thank you for providing these templates!

### Please provide any relevant error logs

_No response_

Contributor guide

Open the contributing guide

Research direction

Start in the vite-react-template's wrangler.json and the Hono entry point mentioned as src/index.ts or src/server/server.ts. Reproduce direct navigation to /api/test after deployment, then compare it with an SPA route and a programmatic fetch. Done means the API response is served on direct navigation while SPA fallback behavior remains intact.

Written by the indexing model from the issue text.

Assessment

Tech stack
react, typescript, vite
Domain
backend-api-design, web-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.