Content: Handling results from "deep:true"

Created on 31 Aug 2020  Â·  13Comments  Â·  Source: nuxt/content

(Warning: I've already asked this question in the Reddit Nuxt.js subreddit and I still need help. If this makes my question irrelevant, I understand.)

TL,DR version: Nuxt.js beginner needs guidance on how to fetch from deeper levels with the Content Module, after hours of futile searching for instructions/examples/snippets about that.

If my content directory is structured like this example...

/content
   |_ posts
      |_ 2020
         |_ 02
            |_ post.md
            |_ post2.md

(edit after @benjamincanac's reply reminded me I forgot to mention this)

...and I have this pages structure:

/pages
   |_ posts
      |_ _slug.vue

(end of edit)

...and I use the following in an attempt to fetch from the deepest level...

<template>
  <article>
    <h1>Title = {{ article.title }}</h1>
    <nuxt-content :document="article" />
  </article>
</template>

<script>
  export default {
    async asyncData ({ $content, params, error }) {
      const slug = params.slug || 'index'
      const article = await $content('posts', { deep: true })
      .where({ slug: slug})
      .fetch()

      if (!article) {
        return error({ statusCode: 404, message: 'Article not found' })
      }

      return {
        article
      }
    }
  }
</script>

...how should I then handle the result so that the page appears?

If I do the above and go to http://localhost:3000/_content/posts/2020/02/post2 (note that it's _content rather than content), I see good JSON from the result:

{"title":"post2","date":"2020-08-28T00:00:00.000Z","toc":[],"body":{"type":"root","children":[{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"This is another one."}]}]},"dir":"/posts/2020/02","path":"/posts/2020/02/post2","extension":".md","slug":"post2","createdAt":"2020-08-29T02:16:10.876Z","updatedAt":"2020-08-29T02:16:33.152Z"}

...proving it can "see" the post and, therefore, respects the deep:true, but I get only a 404 if I go to http://localhost:3000/content/posts/2020/02/post2. All the examples I've found in and out of the documentation seem to be for only one level below (in this case) /contents/posts/; I can find none for fetching from a deeper level. It works fine if I put a Markdown file in /content/posts, however, so clearly I'm not handling the deep:true result properly.

Help, please?

question

All 13 comments

Hey @brycewray, it seems that you need to have an _.vue page to match unknown dynamic nested routes, here is the documentation on nuxtjs.org.

And here is a snippet on how to achieve this with content: https://content.nuxtjs.org/snippets#dynamic-routing

Hi, @benjamincanac — and, actually, I do have such a file. Sorry that I forgot to mention that; now have edited the original post to correct that omission. Thanks for jogging my memory, sir.

I would use dir instead of the slug - that will give you the full directory structure. Slugs aren't quite working the way they should be right now, but also a slug is defined as the end of your URL that uniquely identifies the post, and I don't think you'll get a unique slug with your structure. The dir will be unique though.

The other option would be to flatten your structure - this would give you something easier to maintain as well as a good slug:

/content
   |_ posts
      |_ 2020-02-post.md
      |_ 2020-02-post2.md

@davydnorris Thanks. I have reasons for wanting to keep the structure as it is, but duly noted, sir. I appreciate the info.

No problem, then your only real other option is to use dir instead of slug I think.

No problem, then your only real other option is to use dir instead of slug I think.

@davydnorris Would that be _dir — i.e., like _slug.vue — or just dir? (Just looked in the content docs for this and was unable to locate it.)

no this is a property on the content - see https://content.nuxtjs.org/fetching

The fetch operation actually takes a path, not a slug - I made the same mistake myself initially. So in your example above, if you have defined your content structure to be:

/content
   |_ posts
      |_ 2020
         |_ 02
            |_ post.md
            |_ post2.md

and your page structure to be:

/pages
   |_ posts
      |_ _slug.vue

then the URL to retrieve post2 will need to be:
/posts/2020/02/post2

and the slug parameter you retrieve in your code will actually be /2020/02/post2, which you can pass to your fetch like so:

const article = await $content('posts', params.slug).fetch()

with no where clause required

@davydnorris Thanks. Will give it a try and report back.

Update: Unfortunately, no joy. Tried the particular line both with and without { deep: true } and, either way, still got a 404 whenever I tried to reach http://localhost:3000/posts/2020/02/post2. On the other hand (again, either way), http://localhost:3000/ works fine and, oddly enough, either http://localhost:3000/posts/2020/ or http://localhost:3000/posts/ produces the output of that _slug.vue file, albeit with no fetched data from any of the Markdown files. Also, just for bleeps and giggles, I tried this with both (1.) nuxt and (2.) a combo of nuxt generate and nuxt start — just to be sure that didn’t matter. It didn’t; same results.

@brycewray Have you made a _.vue file? It can't work with _slug.vue. Everything is explained here https://content.nuxtjs.org/snippets#dynamic-routing.

@benjamincanac You’re right, I hadn’t done that. Just did, now, and I finally can see content at the desired URLs. I still need to figure out how to access the content from each Markdown file so (e.g.) {{ article.title }} will produce something other than a blank, but at least I got this far, at last. Thank you!!

I think article is a Array so article.title is undefined. Try article[0].title or print the complete article content with {{ article }}.

@mathe42 Yep, that’s correct. So I guess the _.vue file can’t be used as I’d hoped to use the _slug.vue file. Based on the earlier comments in this discussion, it appears that the functionality isn’t yet where the documentation leads one to believe that it is, so perhaps I’ll just wait a while and watch for further developments in this promising module. In the meantime, I’ll stick with other means of static site generation which are somewhat further down the line on such functionality.

To all who responded: Again, my great thanks.

@brycewray - the functionality is there. I literally just launched my company website and the whole blog system is built on nuxt/content.

I'll be updating the first blog article to describe how I've used Vuetify, NuxtJS and nuxt/content, but have a look
https://www.olivegroveit.com.au

This is the markdown that created the first blog entry, plus the preview cards on the front page, the horizontal blog preview card, and the categories and archive filters:

---
title: And we are live in 3... 2... 1...
author: Davyd Norris
description: Welcome to the new Olive Grove IT web site! Find out how we built it and what's under the hood...
createdAt: 2020-08-30
image: the_grove.jpg
tags:
  - Vue
  - Vuetify
  - NuxtJS
  - nuxt/content
  - IBM Cloud
  - CloudFoundry
---

#### It's been a long time coming!


There's an old saying "The cobbler's children have no shoes", and it's been very true for us. We've been so busy working on
our clients' systems, we've neglected our own! After four years, we finally decided it was high time we did something about it,
so welcome to our new site!

When we set out to build our own site, several things were critical:
  - building a company website is very different to building an application. In some ways they are easier, as there are a lot
fewer moving parts, but on the other hand they are more difficult because there's a lot more content. You have to find the right
words and the right feel that captures your brand
  - we not only wanted the site to be representative of us as a business in terms of culture, we also wanted it to be
representative of the technology we use when we build applications for our clients
  - we are foremost a consulting company, so our knowledge is our brand. We needed a way to share and show that knowledge
  - we wanted the site to be elegant and simple to maintain

Bringing all these elements together was quite a journey, the result of which is before you now, and we are really pleased with
how it turned out.

Over the next couple of weeks we'll expand this article and fill you in on the 3 D's - Design, Development and Deployment, but
for now it's time to launch this baby!

Talk soon!
Was this page helpful?
0 / 5 - 0 ratings

Related issues

mathieunicolas picture mathieunicolas  Â·  4Comments

Haeresis picture Haeresis  Â·  3Comments

LukaszRados picture LukaszRados  Â·  3Comments

adrianschubek picture adrianschubek  Â·  4Comments

haykokalipsis picture haykokalipsis  Â·  4Comments