Setting a 404 error page on Nuxt and adding a sitemap

Posted last year
Return to overview

The basis for this is simple. Simply place a file in the `pages` folder with the name `404.vue` and Nuxt will default to that when hitting that status code.

You can create a Page for it in Contentful to make the contents controlled by the CMS, because that's what a CMS is for! If you use the slug `404` you can update the filter in the `usePagesNav` composable to also exclude that particular slug, next to the `home` slug by updating this line:

'fields.slug[ne]': 'home',

Into this line (using the `not in` operator):

'fields.slug[nin]': 'home,404',

That ensures that a link to a 404 page doesn't show up in the main navigation, which is good. It also hides the reference from the internal Nuxt crawler, which means the page won't be generated. This is bad!

We need to tell Nuxt to generate the page based on the route for us. We do this by adding a reference to the `nuxt.config.ts` file.

We are going to extend the existing options a bit, by adding a `generate` property. That takes in an Array of urls to generate while building. The result of the file looks like this:

export default defineNuxtConfig({ ssr: true, generate: { routes: ['/404'] }, runtimeConfig: { private: { CONTENTFUL_SPACE_ID: process.env.CONTENTFUL_SPACE_ID, CONTENTFUL_ACCESS_TOKEN: process.env.CONTENTFUL_ACCESS_TOKEN, }, } });

Now the 404 route will match the `[slug].vue` page when you access the `/404` url. This will, however, not work for an actual 404, because that will actually be a non existent slug. This will start to make sense on deployment. First you can create a static `404.vue` page in the root of the `pages` directory, with contents like this (we're doing the same as for the homepage):

<script lang="ts"> definePageMeta({ layout: "default", }); </script> <template> <PageBody slug="404" /> </template>

We're doing nothing more than manually passing down the slug manually to the Page component.

In order to make it work on the host (Netlify in this case), we are going to add a redirect that points any 404 status to the static page. Create a `netlify.toml` file in the root of your project (on deployment, Netlify will read the formatted contents and direct the deployment accordingly):

[[redirects]] from = "*" to = "/404" status = 404

That's it! Deployment will come in a later step, but at least we've covered all the possible routes a visitor can come up with!

A static site, like the one we're generating, has a convenient structure for indexing it, because the folder structure is tightly coupled to the urls. You could just read the folders and output it as a structure.

As it happens, I've published a utility package that can help you with that. It should work with any file based website, so not just limited to Nuxt in this case.

Install the package by running:

npm i fs-sitemap-generator --dev

This package exposes a function that you can use to generate a sitemap file. To use it in your build, we're going to create a small executable JavaScript file that will run on the server after deployment. Let's call it `sitemap.js`:

const generateSitemap = require("fs-sitemap-generator"); const DOMAIN = "PLEASE_ADD_YOUR_DOMAIN_HERE"; const IGNORE_FOLDERS = ["_nuxt"]; const SOURCE_FOLDER = "dist"; const OUTPUT_FILE_NAME = "sitemap.xml"; const __init = async () => { generateSitemap( SOURCE_FOLDER, IGNORE_FOLDERS, DOMAIN, `${SOURCE_FOLDER}/${OUTPUT_FILE_NAME}` ); }; __init();

This tells the script to ingest the folders in the `dist` location and build a sitemap based in the structure.

We can add it to the `generate` script in your `package.json` by adding it to the command like so:

// abbreviated from the package.json file "scripts": { // abbreviated ... "generate": "nuxt generate && node sitemap", // more scripts ... } // ... rest of the package.json

This now means you can, from the terminal, check our entire work by running:

npm run generate

This should start to list all the URLs that are configured in the CMS and in the final step generate a sitemap as well. If all checks out, we're going to deploy in the next step!

⚠️ I noticed some changes in behaviour across version of (Release Candidates) of Nuxt, in order for the tutorial to succeed, I've set the version to `3.0.0-rc.4`, please be aware of this!

The code now should resemble this step.

Return to overview