Nuxt error page for Netlify
written on April 9, 2024Netlify and Nuxt combined is a good choice for fast prototyping or even final web applications. I recently tried to
find the easiest way to have a proper 404
page generated by Nuxt for Netlify deployments. As it was a bit of up and
down and delicate configurations, I document it here to my future self how to do it.
Setup
In short, I'm using the Nuxt v3 (currently 3.11.0
), Nuxt content module v2 (currently 2.12.1
) and deploying to
Netlify. I use the command npm run build
as recommended instead of older generate command and use the netlify-static
preset (by setting SERVER_PRESET = "netlify-static"
env var) so that the server side does not consume netlify function
calls.
My goal was to:
- have a custom error page for all kinds of error, even though technically seen we are only dealing with 400s in this setup and probably only 404, 403 and 401
- use that same page for Netlify's error page (meaning to render same page for
404.html
) - use that same page for client side errors (when something goes wrong after hydration, for example while navigating beyond first page)
- finally (as always) to have the least configuration or changes for this to work
Context
Netlify does pickup a file named 404.html
if such exists and shows that for errors.
Nuxt itself has a default error page even though I wanted to change this due to other reasons, but functionally seen this was already given.
Also, Nuxt content does generate the static 404.html
file in default setup, however the file was showing an empty
page when site was "built" using that mentioned preset and not that Nuxt error page. This proved to be major part of
the problem.
In dev mode (npm run dev
) it was working all fine.
Solution
In order to have a custom error page, one should create error.vue
and customize it. You can follow the great tutorial
here to understand it in details.
Next step is to configure the nitro prerenderer (which Nuxt is using to generate static files) to also crawl and render
the 404.html
page. This is done by adding/changing the following section in nuxt.config.ts
(or its equivalent .js
file):
// nuxt.config.ts
export default defineNuxtConfig({
//... other config options
nitro: {
preset: 'netlify-static', // this can be ommited if set as env variable
prerender: {
crawlLinks: true,
routes: [
'/',
'/404.html' // this enforces the crawling
]
}
},
//... other config options
})
Up until here one can build and deploy to Netlify and will see his/her custom error page in cases of not found paths. However, one small piece is still missing. Now if in any page you have a logic that can still be triggered on client side and result in an error case, you will not see the error page. In fact, I was just seeing the error in console and nothing changed on the UI, totally missing the error situation as an end user.
As an example of such a case, let say on each page's setup you want to do an API call and if it returns an error, you want to show an error. You want this call to be done on client side (not at generation/build time). A simplified example would look like:
<!-- pages/somepage.vue -->
<script setup lang="ts">
const {data, error} = await doSomethingAsync(/*...*/)
if (error.value || !data.value) {
throw createError({
fatal: true, // this is the highlight of the show!
statusCode: 404,
statusMessage: 'Product Not Found'
})
}
</script>
Using createError
is documented on Nuxt docs but what is important
here is adding fatal: true,
as otherwise this error will not redirect to error page.
Having all these in place, the build results and Netlify play well together and you will see your custom error page even in case of (fatal!) client side errors.