404 with SPA
I have a static site (ssr off) hosted on cloudflare pages. However, I have a problem with my dynamic paths (e.g. pages/apps/[id].vue), they always return 404. They are served fine luckily, but if you inspect network request they have 404 not found as statuscode. How can I fix this?
26 Replies
Hi @Revadike. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
----------------------
When deploying a static Nuxt site (with
Your dynamic routes return 404 because the static host doesn't know to serve
ssr: false
) to Cloudflare Pages, dynamic routes like /apps/[id]
are generated as static HTML files (e.g., /apps/123/index.html
). However, when a user navigates directly to a dynamic route (e.g., /apps/123
), the static host (Cloudflare Pages) may not find a matching file and returns a 404 status, even though the SPA loads and renders the page correctly on the client side.
Why does this happen?
- Static hosts serve files based on the URL path. If a file for the exact path doesn't exist, a 404 is returned.
- In SPA mode, Nuxt expects the static host to serve index.html
for all routes, letting the client-side router handle the actual page rendering.
How to fix this:
You need to configure a "catch-all" or "fallback" so that all unknown routes serve your index.html
file. This allows the SPA router to take over and render the correct page, and ensures the HTTP status is 200 instead of 404.
For Cloudflare Pages, you can do this by adding a _routes.json
or _redirects
file, or by configuring the project settings to serve index.html
for all unmatched routes. Unfortunately, the knowledge sources do not provide the exact file or setting for Cloudflare Pages, but this is the standard approach for static SPA hosting.
Summary:Your dynamic routes return 404 because the static host doesn't know to serve
index.html
for them. Configure a fallback so all routes serve index.html
to fix the 404 status for dynamic SPA routes.
If you need more specific instructions for Cloudflare Pages, the knowledge sources do not contain enough information to provide the exact configuration file or setting required. However, the general solution is as described above.
For more on static hosting and SPA fallback in Nuxt, see the Nuxt deployment documentation.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@172781195329798144> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@kapa.ai There are thousands of id's so pre-generating a html page for each of these is out of the question. With redirects, can users still directly visit /apps/ID pages without being redirected to the website homepage? Or should I use routes? How does that work with dynamic urls?
Let me check the knowledge base for you again. One moment! :books:
----------------------
When using Nuxt with
ssr: false
(SPA mode) and static hosting, you do not need to pre-generate an HTML file for every possible dynamic ID (such as /apps/ID
). Instead, you should configure your static host (e.g., Cloudflare Pages) to serve the main index.html
file for all unknown routes. This allows the Nuxt client-side router to handle dynamic URLs like /apps/ID
and render the correct page, without redirecting users to the homepage or requiring a separate HTML file for each ID.
How it works:
- When a user visits /apps/ID
directly, the static host serves index.html
.
- Nuxt's client-side router reads the URL and loads the correct page/component (e.g., pages/apps/[id].vue
).
- The user sees the correct content for /apps/ID
, not the homepage.
Redirects vs. SPA Fallback:
- A proper SPA fallback (serving index.html
for all unknown routes) is not a redirect to the homepage; it simply allows the SPA to handle routing.
- Users will see the correct dynamic page, not be redirected to /
.
Dynamic URLs:
- Nuxt's file-based routing with dynamic segments (e.g., [id].vue
) works seamlessly in SPA mode as long as the static host is configured to serve index.html
for all routes that aren't actual files. You do not need to pre-generate every possible route, nor do you need to use server-side routes for this use case.
The knowledge sources confirm that in SPA mode (ssr: false
), Nuxt outputs a single index.html
and JavaScript bundles, and you should configure your static host to serve index.html
for all routes to enable client-side routing for dynamic URLs. This is the recommended approach for handling thousands of dynamic IDs without pre-generating each one Static Hosting.
If you need to handle truly dynamic data (e.g., fetching content for each ID), you can do so in your page component using the ID from the route params.
The knowledge sources do not provide the exact Cloudflare Pages configuration, but the general Nuxt approach is as described above.---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
<@172781195329798144> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
I'm not in front of my computer rn but I have a ssr false project on cloudflare with dynamics route that work fine
My guess is you use nuxi generate or something, or other configuration issue
it works fine, but if you inspect the page requests, they return 404 as statuscode, which is undesired.
But that’s correct
How would the server serving the SPA know whether the page can be resolved by Nuxt or not, all without a server running but with a static asset?
magic? 🥹
Works for me (forgot to remove the the ssr false in the routes XD)
maybe cloudflare pages can be configured to fix this
With the normal bulding ofc, not nuxi generate
define works
is your site public?
It's a b2b website but I have dynamic routes to load different properties and they work ^^" ?
Nop :/
I can probably do it on a public website in a few hours ^^
And cloudflare conf is the default nuxt build cloudflare propose
Gotta run, back in an hour or two
My site is public
https://steamkey.trade/app/1085660
as you can see, it "works" fine, but if you inspect network requests, you see it actually has a 404 statuscode
Use a running server is the magic then
I think I’ve explained why the desired result can’t be achieved without having something responding dynamically and “knows how Nuxt will evaluate the requested page”
i suppose hash dynamic routing could fix it
@kapa.ai how can I configure cloudflare pages to do that?
Let me check the knowledge base for you again. One moment! :books:
----------------------
I'm sorry, but the knowledge sources do not contain specific instructions or examples for configuring Cloudflare Pages to serve
index.html
for all unknown routes in a Nuxt SPA deployment. The general approach is described for static hosting with Nuxt, but there are no details about the exact configuration file or settings required for Cloudflare Pages in the provided sources.
If you need more information, you may want to consult the official Cloudflare Pages documentation or Nuxt community discussions for up-to-date guidance on SPA fallback configuration for dynamic routes in Cloudflare Pages deployments.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@172781195329798144> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Cloudflare Docs
Redirects
To apply custom redirects on Cloudflare Pages, declare your redirects in a plain text file called _redirects without a file extension, in the static asset directory of your project. This file will not itself be served as a static asset, but will instead be parsed by Cloudflare Pages and its rules will be applied to static asset responses.
Hash dynamic routing?
Ok so, adding the following to my nuxt config
will disable nuxt generating a 404.html page.
This will cause cloudflare pages to correctly assume it's a SPA:
https://developers.cloudflare.com/pages/configuration/serving-pages/
I now no longer get 404 status when visiting dynamic pages, while still getting an error page for unknown pages (using error.vue and createError method).
The only downside is it's not actually serving these requests with 404 statuscode for unknown pages, but that's still better than how it was before.
I'm back
Never checked but it seems I indeed don't have this issue ?
https://willyou404me.pages.dev/test/44
deploying this :
https://github.com/ribbityfrog/nuxt-base/blob/nossr/nuxt.config.ts
is that the use case you were expecting ?
does your deployment include a 404.html?
Nop
Or maybe it's still being generated if I don't create one ?
The repo is public you can fork and deploy it and add what you want 🙂
The nossr branch, the main one will not compile
well, that was my problem, i had to disable this