nuxt / content

The file-based CMS for your Nuxt application, powered by Markdown and Vue components.
https://content.nuxt.com
MIT License
3.15k stars 630 forks source link

`You should use slots` when using components and json files #1154

Open florian-lefebvre opened 2 years ago

florian-lefebvre commented 2 years ago

Environment

Reproduction

Use the content-wind template and create a test.json in /content with one of the 2 following contents:

{
    "title": "Test",
    "description": "a test description"
}

or

{
    "title": "Test",
    "description": "a test description",
    "body": {
        "type": "root",
        "children": [
            {
                "type": "element",
                "tag": "h1",
                "props": {
                    "id": "title"
                },
                "children": [
                    {
                        "type": "text",
                        "value": "title"
                    }
                ]
            }
        ]
    }
}

Then go to http://localhost:3000/test

Describe the bug

I expect the content but I get the following error rendered by the component:

{
  "message": "You should use slots with <ContentRenderer>",
  "value": {
    "_path": "/test",
    "_draft": false,
    "_partial": false,
    "title": "Test",
    "description": "a test description",
    "excerpt": {
      "type": "root",
      "children": [
        {
          "type": "element",
          "tag": "h1",
          "props": {
            "id": "title"
          },
          "children": [
            {
              "type": "text",
              "value": "title"
            }
          ]
        }
      ]
    },
    "body": {
      "type": "root",
      "children": [
        {
          "type": "element",
          "tag": "h1",
          "props": {
            "id": "title"
          },
          "children": [
            {
              "type": "text",
              "value": "title"
            }
          ]
        }
      ],
      "toc": {
        "title": "",
        "searchDepth": 2,
        "depth": 2,
        "links": []
      }
    },
    "_id": "content:2.test.json",
    "_type": "json",
    "_source": "content",
    "_file": "2.test.json",
    "_extension": "json"
  },
  "excerpt": false,
  "tag": "div"
}

Same with ContentDoc

Additional context

No response

Logs

No response

pavlexander commented 2 years ago

Got very similar issue which I think should be grouped with this one.

Config for SPA app nuxt.config.ts

import {defineNuxtConfig} from 'nuxt'

export default defineNuxtConfig({
    ssr: false, // Disable Server Side rendering
    modules: [
        '@nuxt/content'
    ],
    content: {
        // Options
    },
})

index.vue

<template>
  <div class="page-container">
    <div class="card" v-for="post of data">
      <div class="card-header">
        <NuxtLink :to="post._path">Open</NuxtLink>
      </div>
      <div class="card-body">
        <ContentRenderer :value="post"/>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
export default {
  async setup() {
    const {data} = await useAsyncData('blog', () => {
      return queryContent('/').find()
    })

    return {
      data
    }
  }
};
</script>

Following files are present in content directory:

image

When I run npm run dev I get the correct results (except front-matter issue which is discussed in separate topic):

image

When I run npm run generate (to build a static SPA) and then npm run preview

image

i.e. the same error as reported by original author is shown

{
  "message": "You should use slots with <ContentRenderer>",
  "value": "<",
  "excerpt": false,
  "tag": "div"
}

As opposed to original authors's problem - I am using markdown, not a json

I should also note that despite having only a dozen of markdown pages - I see 837 items on the page! Where are they coming from? no idea..

image

image

In network inspector I see a 200 response for:

image

Request URL: http://localhost:3000/api/_content/query/990068364?_params={%22where%22:[{%22_path%22:%22--REGEX+/^%5C%5C//%22}]}&previewToken

Full request:

image

Response is:

image

Not sure how any of this is related to the problem but hopefully it's of some value..

farnabaz commented 2 years ago

@florian-lefebvre Think of JSON files as data store not renderable content files, If you want to render a content you need to create markdown file.

However if you want your own logic and render JSON files too, you have to use slots and create UI for them.

@pavlexander Could you provide a reproduction using nuxt-starter? Also it would better to have in separate issue :)

pavlexander commented 2 years ago

@florian-lefebvre Think of JSON files as data store not renderable content files, If you want to render a content you need to create markdown file.

However if you want your own logic and render JSON files too, you have to use slots and create UI for them.

@pavlexander Could you provide a reproduction using nuxt-starter? Also it would better to have in separate issue :)

@farnabaz Yes sure, here it is: https://github.com/nuxt/content/issues/1202 I downloaded the starter codebase from the nuxt-starter template you have mentioned. And then added a bit of code on top until problem was reproducible. You will find details in that link.

stefanfrede commented 2 years ago

For me this problem occurs the moment I update to @nuxt/content@2.0.1.

Then my page breaks and I get the following message:

{
  "message": "You should use slots with <ContentDoc>",
  "slot": "default",
  "data": {
    "_path": "/_hero",
    "_draft": false,
    "_partial": true,
    "title": "Unsichtbare Zahnspange:",
    "subtitle": "Mehr Selbstvertrauen durch gerade Zähne.",
    "description": "Sie sind unzufrieden mit Ihrer Zahnstellung? Mit den unsichtbaren Zahnschienen von Invisalign® ist auch im Erwachsenenalter eine erfolgreiche Behandlung einer Fehlstellung möglich. ",
    "label": "Jetzt Termin ausmachen",
    "_id": "content:_hero.json",
    "_type": "json",
    "_source": "content",
    "_file": "_hero.json",
    "_extension": "json"
  }
}

Here is a link to my repo (sadly not that minimal):

And here is a link to a branch where I just updated to @nuxt/content@2.0.1:

So far I'm unable to figure out the cause and because everything worked fine unitl @nuxt/content@2.0.1 it is just trial and error at the moment.

Every push in the right direction is much appreciated!

farnabaz commented 2 years ago

@stefanfrede This is a known issue in v2.0.1 which is fixed in edge version. It is planned to release next week. Meanwhile you can use edge version to resolve the issue. Just add this to your package.json

"@nuxt/content": "npm:@nuxt/content-edge@latest"

Also in the query inside c-hero you need to remove the argument passed to queryContent

https://github.com/sabinehugo189/sabinehugo/blob/5549862132910056e20555bd3953c19d2f8b68ea/components/c-hero.vue#L62-L65

-  return queryContent('/')
+  return queryContent()
    .where({ _partial: true })
    .only(['title', 'subtitle', 'description', 'label'])
    .findOne();
slav0nic commented 2 years ago

/about endpoint in npx nuxi init content-app -t content app with latest npm:@nuxt/content-edge@latest still return error after yarn generate/preview

{
  "message": "You should use slots with <ContentDoc>",
  "slot": "default",
  "data": "<!DOCTYPE html>\n<html  data-head-attrs=\"\">\n\n<head >\n  <title>Nuxt Content</title><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><link rel=\"prefetch\" href=\"/api/_content/query/brX4CwCJoQ\"><meta name=\"description\" content=\"This page corresponds to the / route of your website. You can delete it or create another file in the content/ directory.\"><meta name=\"head:count\" content=\"4\"><link rel=\"modulepreload\" href=\"/_nuxt/entry-44d81aa7.mjs\" as=\"script\" crossorigin><link rel=\"modulepreload\" href=\"/_nuxt/_...slug_-37c219b1.mjs\" as=\"script\" crossorigin><link rel=\"modulepreload\" href=\"/_nuxt/ProseH1-b5bf0e08.mjs\" as=\"script\" crossorigin><link rel=\"modulepreload\" href=\"/_nuxt/ProseP-206c1b9a.mjs\" as=\"script\" crossorigin><link rel=\"modulepreload\" href=\"/_nuxt/ProseCodeInline-f25412ff.mjs\" as=\"script\" crossorigin><link rel=\"modulepreload\" href=\"/_nuxt/ProseA-a788d31a.mjs\" as=\"script\" crossorigin><link rel=\"modulepreload\" href=\"/_nuxt/ProseHr-aee51228.mjs\" as=\"script\" crossorigin><link rel=\"prefetch\" as=\"script\" href=\"/_nuxt/ContentList-208a0115.mjs\"><link rel=\"prefetch\" as=\"script\" href=\"/_nuxt/ContentNavigation-6487d949.mjs\"><link rel=\"prefetch stylesheet\" href=\"/_nuxt/ContentNavigation.fb1c1af1.css\"><link rel=\"prefetch stylesheet\" href=\"/_nuxt/ProseCode.c12da1e5.css\"><link rel=\"prefetch\" as=\"script\" href=\"/_nuxt/DocumentDrivenEmpty-d17e6709.mjs\"><link rel=\"prefetch\" as=\"script\" href=\"/_nuxt/DocumentDrivenNotFound-5fffecaa.mjs\"><link rel=\"prefetch\" as=\"script\" href=\"/_nuxt/Markdown-ca798dd2.mjs\"><link rel=\"prefetch\" as=\"script\" href=\"/_nuxt/ProseCode-79edb398.mjs\"><link rel=\"prefetch\" as=\"script\" href=\"/_nuxt/ProseBlockquote-06ab7348.mjs\"><link rel=\"prefetch\" as=\"script\" href=\"/_nuxt/ProseEm-2c23c797.mjs\"><link rel=\"prefetch\" as=\"script\" href=\"/_nuxt/ProseH2-99b8967b.mjs\"><link rel=\"prefetch\" as=\"script\" href=\"/_nuxt/ProseH3-15bba5e3.mjs\"><link rel=\"prefetch\" as=\"script\" href=\"/_nuxt/ProseH4-82d20986.mjs\"><link rel=\"prefetch\" as=\"script\" href=\"/_nuxt/ProseH5-b333c377.mjs\"><link rel=\"prefetch\" as=\"script\" href=\"/_nuxt/ProseH6-68c90136.mjs\"><link rel=\"prefetch\" as=\"script\" href=\"/_nuxt/ProseImg-fb7494b8.mjs\"><link rel=\"prefetch\" as=\"script\" href=\"/_nuxt/ProseLi-b8b7df76.mjs\"><link rel=\"prefetch\" as=\"script\" href=\"/_nuxt/ProseOl-27615e10.mjs\"><link rel=\"prefetch\" as=\"script\" href=\"/_nuxt/ProseStrong-3b4d944f.mjs\"><link rel=\"prefetch\" as=\"script\" href=\"/_nuxt/ProseTable-2a95b8d7.mjs\"><link rel=\"prefetch\" as=\"script\" href=\"/_nuxt/ProseTbody-b408fd71.mjs\"><link rel=\"prefetch\" as=\"script\" href=\"/_nuxt/ProseTd-07406d5e.mjs\"><link rel=\"prefetch\" as=\"script\" href=\"/_nuxt/ProseTh-d9dc6952.mjs\"><link rel=\"prefetch\" as=\"script\" href=\"/_nuxt/ProseThead-c61261e1.mjs\"><link rel=\"prefetch\" as=\"script\" href=\"/_nuxt/ProseTr-52303c2d.mjs\"><link rel=\"prefetch\" as=\"script\" href=\"/_nuxt/ProseUl-3051482a.mjs\"><link rel=\"prefetch\" as=\"script\" href=\"/_nuxt/web-socket-c7d28780.mjs\"><link rel=\"prefetch\" as=\"script\" href=\"/_nuxt/error-component-3c60dd44.mjs\">\n</head>\n\n<body  data-head-attrs=\"\">\n  <div id=\"__nuxt\"><div><main><!--[--><div><h1 id=\"nuxt-content\"><!--[-->Nuxt Content<!--]--></h1><p><!--[-->This page corresponds to the <code><!--[-->/<!--]--></code> route of your website. You can delete it or create another file in the <code><!--[-->content/<!--]--></code> directory.<!--]--></p><p><!--[-->Try to navigate to <a href=\"/about\" class=\"\"><!--[-->/about<!--]--></a>. These 2 pages are rendered by the <code><!--[-->pages/[...slug].vue<!--]--></code> component.<!--]--></p><hr><p><!--[-->Look at the <a href=\"https://content.nuxtjs.org/\" rel=\"nofollow\"><!--[-->Content documentation<!--]--></a> to learn more.<!--]--></p></div><!--]--></main></div></div><script>window.__NUXT__=(function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B){return {data:{\"content-query-1DxZ1vYQk5\":{_path:f,_draft:e,_partial:e,_locale:\"en\",_empty:e,title:i,description:\"This page corresponds to the \\u002F route of your website. You can delete it or create another file in the content\\u002F directory.\",excerpt:{type:k,children:[{type:b,tag:l,props:{id:m},children:[{type:a,value:i}]},{type:b,tag:c,props:{},children:[{type:a,value:n},{type:b,tag:d,props:{},children:[{type:a,value:f}]},{type:a,value:o},{type:b,tag:d,props:{},children:[{type:a,value:p}]},{type:a,value:q}]},{type:b,tag:c,props:{},children:[{type:a,value:r},{type:b,tag:g,props:{href:h},children:[{type:a,value:h}]},{type:a,value:s},{type:b,tag:d,props:{},children:[{type:a,value:t}]},{type:a,value:u}]},{type:b,tag:v,props:{},children:[]},{type:b,tag:c,props:{},children:[{type:a,value:w},{type:b,tag:g,props:{href:x,rel:[y]},children:[{type:a,value:z}]},{type:a,value:A}]}]},body:{type:k,children:[{type:b,tag:l,props:{id:m},children:[{type:a,value:i}]},{type:b,tag:c,props:{},children:[{type:a,value:n},{type:b,tag:d,props:{},children:[{type:a,value:f}]},{type:a,value:o},{type:b,tag:d,props:{},children:[{type:a,value:p}]},{type:a,value:q}]},{type:b,tag:c,props:{},children:[{type:a,value:r},{type:b,tag:g,props:{href:h},children:[{type:a,value:h}]},{type:a,value:s},{type:b,tag:d,props:{},children:[{type:a,value:t}]},{type:a,value:u}]},{type:b,tag:v,props:{},children:[]},{type:b,tag:c,props:{},children:[{type:a,value:w},{type:b,tag:g,props:{href:x,rel:[y]},children:[{type:a,value:z}]},{type:a,value:A}]}],toc:{title:j,searchDepth:B,depth:B,links:[]}},_type:\"markdown\",_id:\"content:index.md\",_source:\"content\",_file:\"index.md\",_extension:\"md\"}},state:{$serror:null},_errors:{},serverRendered:true,config:{public:{content:{base:\"_content\",tags:{p:\"prose-p\",a:\"prose-a\",blockquote:\"prose-blockquote\",\"code-inline\":\"prose-code-inline\",code:\"prose-code\",em:\"prose-em\",h1:\"prose-h1\",h2:\"prose-h2\",h3:\"prose-h3\",h4:\"prose-h4\",h5:\"prose-h5\",h6:\"prose-h6\",hr:\"prose-hr\",img:\"prose-img\",ul:\"prose-ul\",ol:\"prose-ol\",li:\"prose-li\",strong:\"prose-strong\",table:\"prose-table\",thead:\"prose-thead\",tbody:\"prose-tbody\",td:\"prose-td\",th:\"prose-th\",tr:\"prose-tr\"},highlight:e,wsUrl:j,documentDriven:e}},app:{baseURL:f,buildAssetsDir:\"\\u002F_nuxt\\u002F\",cdnURL:j}}}}(\"text\",\"element\",\"p\",\"code-inline\",false,\"\\u002F\",\"a\",\"\\u002Fabout\",\"Nuxt Content\",\"\",\"root\",\"h1\",\"nuxt-content\",\"This page corresponds to the \",\" route of your website. You can delete it or create another file in the \",\"content\\u002F\",\" directory.\",\"Try to navigate to \",\". These 2 pages are rendered by the \",\"pages\\u002F[...slug].vue\",\" component.\",\"hr\",\"Look at the \",\"https:\\u002F\\u002Fcontent.nuxtjs.org\\u002F\",\"nofollow\",\"Content documentation\",\" to learn more.\",2))</script><script type=\"module\" src=\"/_nuxt/entry-44d81aa7.mjs\" crossorigin></script><script type=\"module\" src=\"/_nuxt/_...slug_-37c219b1.mjs\" crossorigin></script><script type=\"module\" src=\"/_nuxt/ProseH1-b5bf0e08.mjs\" crossorigin></script><script type=\"module\" src=\"/_nuxt/ProseP-206c1b9a.mjs\" crossorigin></script><script type=\"module\" src=\"/_nuxt/ProseCodeInline-f25412ff.mjs\" crossorigin></script><script type=\"module\" src=\"/_nuxt/ProseA-a788d31a.mjs\" crossorigin></script><script type=\"module\" src=\"/_nuxt/ProseHr-aee51228.mjs\" crossorigin></script>\n</body>\n\n</html>"
}

any workaround?

selimok commented 2 years ago

Same problem here after changing to @nuxt/content-edge version 2.1.0-27661776.91d257e.

Steps to reproduce:

There is no problem while testing with npm run dev.

Thanks.

jbierfeldt commented 2 years ago

Having the same issue with version @nuxt/content-edge@2.1.0-27667349.b409f18

Anyone find a workaround yet?

farnabaz commented 2 years ago

This is related to an issue with nuxi preview. https://github.com/nuxt/content/issues1281#issuecomment-1164579970

Instead of running yarn run preview you can run npx serve .output/public

jbierfeldt commented 2 years ago

Instead of running yarn run preview you can run npx serve .output/public

Unfortunately, I am seeing the same error even if I serve .output/public or dist directly.

{
  "message": "You should use slots with <ContentDoc>",
  "slot": "default",
  ...
}

I tried changing my catch-all page so that the <ContentDoc> component uses slots, using the code below, pulled directly from the api page:


<template>
  <main>
    <ContentDoc v-slot="{ doc }">
      <h1>{{ doc.title }}</h1>
      <ContentRenderer :value="doc" />
    </ContentDoc>
  </main>
</template>

After doing this, I'm still getting essentially the same error, but now it is complaining about the lack of slot usage in <ContentRenderer>:

{
  "message": "You should use slots with <ContentRenderer>",
  ...
}
acidjazz commented 2 years ago

Getting this on production with the latest nuxt and content

image

If I refresh the page it goes away

r-token commented 2 years ago

I'm seeing the same You should use slots with <ContentRenderer> error when using SSG via nuxt generate and nuxt preview; as well as when deploying static to Netlify & Vercel.

Unlike @acidjazz, though, it does not go away for me if I refresh the page. I'm assuming this is a bug with Nuxt 3's static site generation right now, which is new with RC10

acidjazz commented 2 years ago

Would really be nice if we could figure this issue out - I have client projects launching soon and this is a production blocker

Any work around would also be greatly appreciated @benjamincanac

Triloworld commented 2 years ago

I check and "3.0.0-rc.11" don't fix it either. Scenario:

Use:

Solution for us: We use full document driven approach and error gone (before be use only dynamic page that we have more power to edit). It has something with mingled two way of creating pages (dynamic pages and markdown).

Fallback page (404) not creating in full static mode when declaring custom 404 name and this can be connected to issue as well.

L422Y commented 2 years ago

I modified my ContentRenderer.vue render function as follows and it seems to fix things for me, it appeared the function was expecting an object for ctx.value but was getting an array for whatever reason.

render(ctx) {
    const slots = useSlots();
    const { excerpt, tag } = ctx;
    let { value } = ctx;
    if (!value && slots?.empty) {
      return slots.empty({ value, excerpt, tag, ...this.$attrs });
    }
    if (slots?.default) {
      return slots.default({ value, excerpt, tag, ...this.$attrs });
    }
    if(Array.isArray(value)) {
      value = value.shift()
    }
    if (value && value?._type === "markdown" && value?.body?.children?.length) {
      return h(
          ContentRendererMarkdown,
          {
            value,
            excerpt,
            tag,
            ...this.$attrs
          }
      );
    }
    return h(
      "pre",
      null,
      JSON.stringify({ message: "You should use slots with <ContentRenderer>", value, excerpt, tag }, null, 2)
    );
  }
acidjazz commented 2 years ago

Would really be nice if we could figure this issue out - I have client projects launching soon and this is a production blocker

Any work around would also be greatly appreciated @benjamincanac

I found that my issue was dealing with CloudFront and Legacy cache settings - I updated my cache settings to their current version and this solved the problem.

Once I get more detail on what exactly fixed this I'll add more detail here in case anyone else runs into this issue

L422Y commented 2 years ago

I found that my issue was dealing with CloudFront and Legacy cache settings - I updated my cache settings to their current version and this solved the problem.

I too was having issues with CloudFront. Adding an adjusted behavior for /api/* seems to have also helped, but I did a clean node_modules install and lost my modification (posted above) and things stopped working again, once I restored the change, things seem to work as expected (mostly)

tuclicks commented 2 years ago

I would like an option to change the content API to another directory name instead of /api.

niklasfjeldberg commented 2 years ago

I get this error when I am using it with markdown content from Strapi v4. Any updates on the issue?

sami-baadarani commented 2 years ago

I was having this issue with version 2.2.2. Moving the content directory from components directory to the root directory fixed it for me.

nlxdodge commented 1 year ago

Environment

Operating System: Windows_NT
Node Version: v18.12.1
Nuxt Version: 3.0.0
Package Manager: yarn@3.30.0
Builder: vite
User Config: meta, css, modules, build, vite, nitro, app, publicRuntimeConfig, content
Runtime Modules: @nuxt/content@2.3.0, @glidejs/glide: 3.6.0, sass: 1.57.1, sitemap: 7.1.1, include-media: 1.4.10, yarn: 1.22.19

Issue is still happening for me, locally yarn dev works 100% but the static site rending is broken for loading pages.

You can get the same by cloning this repository: https://github.com/nlxdodge/portfolio-nuxt followed by yarn install, yarn dev to see it running locally. And when running npx nuxi generate and putting it on a host.

index.md and index.vue returns: "Document not found, overwrite this content with #not-found slot in ."

In the console I see that it tries to get a file from the /api folder that doesn exist? https://website.nl/api/_content/query/brX4CwCJoQ.1673293917527.json?_params={"first":true,"where":[{"_path":"/"}],"sort":[{"_file":1,"$numeric":true}]}

I checked the remote and it only has /api/_content/cache.1673293917527.json so I am not sure what's wrong now. I checked the cached file contents and it seems to house everything it needs.

bobby169 commented 1 year ago

Getting this on production with the latest nuxt and content

image

If I refresh the page it goes away

had the same problem

SleepiestAdam commented 1 year ago

Same here - doesn't appear if the post is accessed directly, but does appear if the blog post is navigated to.

donfreddy commented 1 year ago

I have the same problem: https://github.com/nuxt/content/issues/2128

mathix420 commented 1 year ago

In my case the issue was fixed thanks to this nuxt.config.ts.

Original one:

  routeRules: {
    "/**": { isr: true },
  },
  nitro: {
    preset: "vercel",
    future: {
      nativeSWR: true,
    },
  },

Fixed version:

  routeRules: {
    "/**": { isr: true },
    "/api/**": { isr: false },
  },
  nitro: {
    preset: "vercel",
    future: {
      nativeSWR: true,
    },
  },
  runtimeConfig: {
    nitro: { envPrefix: "VERCEL_" },
  },

After investigating the issue, I found that api routes where cached incorrectly (without get params, or did not even call the serverless function behind). Idk what the envPrefix does, but without it the isr: false on api routes wasn't working correctly.

Knogobert commented 7 months ago

Getting this on production with the latest nuxt and content

image

If I refresh the page it goes away

had the same problem

If you still have the same problem, it might be fixed now with https://github.com/Knogobert/ntn-boilerplate/pull/214 version 3.0.0