content: Content API giving 404 on generate build

Environment

  • Operating System: Darwin
  • Node Version: v16.18.0
  • Nuxt Version: 3.4.3
  • Nitro Version: 2.4.0
  • Package Manager: yarn@1.22.19
  • Builder: vite
  • User Config: modules
  • Runtime Modules: @nuxt/content@2.6.0
  • Build Modules: -

Reproduction

https://github.com/Tragio/nuxt-content-repro

yarn generate && yarn preview first selects works, and subsequent selects return 404.

yarn dev / yarn build works just fine.

Describe the bug

Nuxt Content with filter works just fine on dev, but as soon I generate the build it stops working properly.

CleanShot 2023-05-10 at 12 41 17

Already tried all solutions provided here: https://github.com/nuxt/content/issues/1798

Additional context

No response

Logs

No response

CC: @farnabaz

About this issue

  • Original URL
  • State: open
  • Created a year ago
  • Reactions: 3
  • Comments: 27 (6 by maintainers)

Most upvoted comments

I’m having similar issues where something like:

[nitro 17:41:40]   ├─ /api/_content/query/2w8OxZpsdg.1692308491351.json (47ms) (Error: [404] Document not found!)

showed up when running pnpm generate. And disabling SSR along with enabling clientDB solves the problem. But this also break the nuxt-image module and I’m not seeing any images or pictures. Any update or ideas on this problem?

For someone interested, we fixed this issue in this way:

  1. create dynamic slug page […slug].vue (https://content.nuxtjs.org/examples/navigation/use-route)
<script setup>
const { path } = useRoute();

const { data } = await useAsyncData(`content-${path}`, () => {
  return queryContent().where({ _path: path }).findOne()
})
</script>

<template>
  <main class="prose text-left">
    <ContentRenderer v-if="data" :value="data" />
  </main>
</template>
  1. Create a module that scan the ‘content’ directory and dynamically incorporates its paths into the prerendering routes
import { defineNuxtModule } from '@nuxt/kit';
import fs from 'fs/promises';
import path from 'path';

async function listFilesInDirectory(directory: string, prefix = '') {
  const entries = await fs.readdir(directory, { withFileTypes: true });

  // Use map() to perform the following actions for each entry in the directory
  const files: any = await Promise.all(entries.map(async (entry) => {
    const fullPath = path.join(directory, entry.name);
    const relativePath = path.join(prefix, entry.name);

    if (entry.isDirectory()) {
      // If the entry is a directory, recursively list the files in it
      return listFilesInDirectory(fullPath, relativePath);
    } else {
      // If the entry is a file, remove the extension, prepend a slash, and remove number and dot prefix
      const ext = path.extname(entry.name);
      const nameWithoutExtension = path.basename(entry.name, ext);
      const nameWithoutNumberPrefix = nameWithoutExtension.replace(/^\d+\.\s/, '');

      // Check if the name ends with 'index', if so, replace it with '/'
      if (nameWithoutNumberPrefix === 'index') {
        return path.join('/', prefix, '/');
      }

      return '/' + path.join(prefix, nameWithoutNumberPrefix);
    }
  }));

  // Flatten the array and return it
  return Array.prototype.concat(...files);
}

export default defineNuxtModule({
  async setup(_moduleOptions, nuxt) {
    const paths = await listFilesInDirectory('./content');
    nuxt.hook('nitro:config', (nitroConfig) => {
      nitroConfig.prerender.routes = nitroConfig.prerender.routes || [];

      nitroConfig.prerender.routes?.push(...paths);
    });
  }
});

I hope this helps, however I don’t think it solves the initial reported problem …

I’m sure the nuxt team is already working on a definitive solution

@Tragio it’s working for me using these settings (note the casing on clientDB)

export default defineNuxtConfig({
  ssr: false,
  content: {
    experimental: {
      clientDB: true
    }
  }
})

But this also break the nuxt-image module

This is pretty much my day-to-day experience with Nuxt. Something always seems to break.

It’s really quite depressing when you’ve put so much work in to craft a website.

But for what i understand we both don’t want to use hybrid mode but just full static. But that doesn’t pre-render component logic?

I somehow get this problem solved, but with different ways in different versions of Nuxt.

In the latest Nuxt 3.7.3, the 404 error should point to a specific file that is missing from your content. Say, for me I have a content/blog directory for holding all the blog posts, and set up a pages/blog/[slug].vue for rendering the blog page and a pages/blog/index.vue to query content in that folder and render a index page. This should work fine in the Nuxt 3.7.3, but for some reason, in earlier versions of Nuxt, you might need want to try one of the two workarounds:

  1. Add a content/blog/index.md as a placeholder and manage to filter that out in pages/blog/index.vue
  2. Move pages/blog/index.vue to pages/blog.vue and also add a placeholder content/blog.md. You only need to make sure that the query path in your pages/blog.vue is set to /blog/ instead of /blog. (Note that this breaks at least in Nuxt 3.7.3 as it will make the child pages not accessible, but works in some earlier verions)

I am facing the same issue with a search page that accepts user input via a text field to perform a search on the contents. The experimental clientDB fixes the issue, but degrades SEO as SSR has to be fully disabled.

It would be great to be able to force using the clientDB per query while still using SSR. I’ll try to get this done for the project I’m working on.

I’m having similar issues where something like:

[nitro 17:41:40]   ├─ /api/_content/query/2w8OxZpsdg.1692308491351.json (47ms) (Error: [404] Document not found!)

showed up when running pnpm generate. And disabling SSR along with enabling clientDB solves the problem. But this also break the nuxt-image module and I’m not seeing any images or pictures. Any update or ideas on this problem?

Have you tried this? https://image.nuxt.com/advanced/static-images

FWIW on Netlify what worked for me was:

  • setting ssr to true
  • changing the Netlify build command to npm run build (vs generate)
  • removing the Netlify NITRO_PREFIX=netlify-edge environment variable

And FWIW Lighthouse performance shot up from mid 60s to 96 (98 on mobile!):

image

Site link here.

If you are facing issues with generating a static HTML file and receiving a 404 error, you need to add one of your routes to the static generation in nuxt.config.ts. After doing this, all files will be generated correctly.

  export default defineNuxtConfig({
    generate: {
      routes: ["/test-route/test"], // one of routes getting 404
    },
   })

Ahh it was a copy-paste issue 😋 for me it is also working. @farnabaz I was about to create a PR, but not sure if nitro.preset: 'service-worker' does anything for the static deployment. If it should be replaced for what is there or added 🤔 maybe would be better for you to update the docs 🙏

defineNuxtConfig({
  ssr: false,
  nitro: {
    preset: 'service-worker'
  }
})

by:

defineNuxtConfig({
  ssr: false,
  content: {
    experimental: {
      clientDB: true
    }
  }
})

You are generating a static website, which means that there will be no APIs. When you change the select input content will execute query and requests server to get the right data, but instead of data it receives 404.

You should enable the experimental clientdb feature to allow the content module to run queries inside the browser

export default defineNuxtConfig({
  content: {
    experimental: {
      clientDb: true
    }
  }
})

Having the same problem as @Tragio this experimental clientdb setting doesn’t fix my problem still getting an 404.