Open wouter-muller opened 3 years ago
What would also solve my problem is to be able to add some kind add permalink
or slugurl
to the frontmatter of each blog post, so that decides what the URL becomes. But i tried adding this, and it didn't do anything...
@wouter-muller
I guess you are confused by the way Nuxt Content Theme Doc generates routes.
Indeed, Nuxt Content Theme Doc generates routes (i.e. URLs) in the way you described:
content/articles/subfolder-one/blog-post-one.md -> localhost:3000/articles/subfolder-one/blog-post-one content/articles/subfolder-two/blog-post-two.md -> localhost:3000/articles/subfolder-two/blog-post-two
However, if you Nuxt Content module directly, it's up to you how directory structure under content
corresponds to routes.
If you want to show the content of blog-post-one.md
with the URL /articles/_slug
, assuming that _slug
is set subfolder-one
, then you would be able to achieve that in 2 ways:
$content()
method for it to fetch blog-post-one.md
subfolder-one
directory and filter out the one you want.I guess these are not what you wanted.
To represent URL structure you described, you have to define 2 URL params.
That is, /articles/subfolder-one/blog-post-one
is a case of /articles/:category/:slug
, and pages
directory is:
- pages/
- - _category/
- - - _slug.vue
In this way, you can fetch the exact article at _slug.vue
.
export default {
async asyncData({ $content, params }) {
const { category, slug } = params
const article = await $content("articles", category, slug).fetch()
return { article }
},
}
By the way, you might not know the depth of nested directories in advance.
In that case, you can let Nuxt to render all articles with _.vue
file at any level in pages
directory.
Actually, this is how Nuxt Content Theme Docs realizes flexibility:
To recap, you might want to read these official resources.
https://content.nuxtjs.org/fetching#contentpath-options https://nuxtjs.org/docs/2.x/features/file-system-routing/ https://nuxtjs.org/docs/2.x/features/file-system-routing/#unknown-dynamic-nested-routes
Indeed, Nuxt Content Theme Doc generates routes (i.e. URLs) in the way you described:
content/articles/subfolder-one/blog-post-one.md -> localhost:3000/articles/subfolder-one/blog-post-one content/articles/subfolder-two/blog-post-two.md -> localhost:3000/articles/subfolder-two/blog-post-two
However, if you Nuxt Content module directly, it's up to you how directory structure under content corresponds to routes.
Let me correct.
This description was wrong, because I explained that this magic is done by _.vue
file in the latter part.
So Nuxt Content Theme Doc does not generates the routes actually.
It just accepts all the possibilities.
@wouter-muller
As you want your URLs to correspond to your Content
folder structure, best option will be to create a _.vue
page. You can follow these easy steps 😋
_.vue
page, fetch the current postdata() {
return {
pathMatch: '',
post: null,
}
},
async fetch() {
this.pathMatch = this.$route.params.pathMatch.endsWith("/")
? this.$route.params.pathMatch
: `${this.$route.params.pathMatch}/`;
this.posts = await this.$content({ deep: true })
.where({
path: {
$regex: [
this.pathMatch.slice(0, this.pathMatch.length - 1) + "$",
"gi"
]
}
})
.fetch();
this.post = this.posts[0];
}
Here, initially I have converted pathMatch because of the trailing slash. However, it is up to you how to want to handle it.
where
query, you have to ignore the last character, i.e. the slash (This is what I have did).where
query becomes even simpler without slice
and all. Just write this.$route.params.pathMatch
inside the $regex
key. Also, Note:
{deep: true}
option in the above code. If you want to fetch anything from deep inside your Content folder, this should be set. param
inside the this.$route object
to match with your current post. I found pathMatch
to be apt; some may find some other key to be apt like fullPath
(but that also includes the hash inside the URL, so I chose pathMatch
). 😁This is very easy. Just write anywhere in your HTML, <nuxt-content :document="post"></nuxt-content>
. That's it 😄
See here https://github.com/nuxt/content/issues/819#issuecomment-823220748
Nuxt will generate your posts' pages automatically (magically), but it will only do so if you have the link of the current post written somewhere in your entire app. And the best way to do this is to show a list of your posts, i.e. an index of blog posts. Now, how you want to show this list is up to you.
You can choose a list of all the posts' links on one single page. This works if you have a simple blog.
blog
page inside the pages
folder. {deep:true}
option. nuxt-link
to post.slug
.OR You can show only the children posts' links inside a parent post. This is better if you have a deeply nested Content structure with thousands of md files.
{deep: true}
and fetch only the children posts based on where: {dir: this.post.path}
nuxt-link
to post.slug
.You may use the md file name as the slug
. If you want to keep your file name anything and your URL something else, you may add in your each md file blog post a new key slugurl
or something like that.
Now, when you fetch all your posts, you may display them using v-for with nuxt-link pointing to post.slugurl
inside of post.slug
.
Note that, now when you click on any of the post using the above links, you will go the current post, but it won't show any contents of that current post. This is because now, current post's $route.params.pathMatch
will not be equal to the current post's path
used in where
. (This is logical because path
comes from the Content folder's sub-folders structure, whereas $route.params.pathMatch
comes from the URL.) So, basically your where
query won't work with the above code now.
Quick Solution? So, better to keep your filenames equal to the URL to want for SEO.
But, what if you still want to keep them different? So, how to fetch the contents of the current post then?
Here, you will have to try some try some other permutation or combination which makes you fetch the current post more easily 😊.
You can use something like, where: {slugurl: this.$route.params.slugurl}
. This will work perfectly, provided all your md files have a unique slugurl, which is logical, isn't it? 😋
If you have limited and diverse blogposts, your slugurls will definitely will be different.
But let's say you have thousands of blogposts arranged month-wise into hundreds of folders, and you can practically only scroll and check a single folder to verify the blog's slugurl's uniqueness. Then, in such cases it is better to finetune the where
query with dir
key, so that only blogposts inside a certain folder are fetched, i.e. only fetch sibling posts from a folder, and not all the thousand posts.
data()
e.g. urlWithoutSlugurl
and postSlugurl
. website.com/articles/subfolderone/abcGoodSEOlink
, then
this.urlWithoutSlugurl
will be website.com/articles/subfolderone
and postSlugurl
will be abcGoodSEOlink
.where({
$and: [{ dir: this.urlWithoutSlugurl }, { slugurl: this.postSlugurl }]
})
Side note: If you don't want to use a _.vue
page, you can create some nested dynamic pages like _slugurl.vue
(but how many levels nested? and what if you later change your Content structure? so better to create _.vue
page 😁).
However, if you still choose to have a simple dynamic page (not _.vue
), then your fetch logic will need to be altered. You can see here https://github.com/nuxt/content/issues/822#issuecomment-799894393
Hope all this helps. 💛
Hello everyone,
I am struggling with the following:
I am rebuilding a Wordpress blog site to a Nuxt site with the content module. What i can not figure out is how to have the URL's match the folder structure of my content folder. So let's say my
content
folder is like this:These blog posts should be mapped like this:
content/articles/subfolder-one/blog-post-one.md
->localhost:3000/articles/subfolder-one/blog-post-one
content/articles/subfolder-two/blog-post-two.md
->localhost:3000/articles/subfolder-two/blog-post-two
So far i can only make blog posts work if they are in the
content
folder, not in a subfolder. If i try to access a blog post inside a subfolder i get this error:In my
nuxt.config.js
i only added thecontent
to the list of modules, like this:My
pages/articles/_slug.vue
looks like this:I would really appreciate if someone could help me out here, I am quite new to both Nuxt and the content module, but have been using Vue for a few years.