nuxt-community/nuxtent-module

Multiple content types path configuration not working as expected

raae opened this issue ยท 19 comments

raae commented

I must have misunderstood something as I cannot get two content types to work together.

I am trying to create both projects and posts with permalinks :slug using the configuration below. I would like the projects to use the page projects/_slug and the posts posts\_slug. However both use posts\_slug giving me a 404 on /project1 as project1 does not exist in the posts collection.

Any help would be much appriciated.

Full example can be found at https://github.com/raae/nuxtent-test.

module.exports = {
  content: [
    [
      'projects',
      {
        permalink: ':slug',
        page: 'projects/_slug',
        isPost: false,
        generate: [
          // for static build
          'get',
          'getAll'
        ]
      }
    ],
    [
      'posts',
      {
        permalink: ':slug',
        page: '/posts/_slug',
        isPost: false,
        generate: [
          // for static build
          'get',
          'getAll'
        ]
      }
    ]
  ]
}
This bug report is available on Nuxt.js community (#c93)

Hi, you should use '/projects/:slug' as projects permalink, and '/posts/:slug' as posts permalink to achieve the behavior you want.
The docs aren't completely up-to-date, including about this topic.

Basically i changed the behavior a few weeks ago, so you could eventually get '/name-of-post' posts url along with '/projects/name-of-project' projects urls for example, thus removing the automatic prefixing of permalinks when having multiple content types.

That's what I figured was the problem -- since they both have same permalink, the one that is registered first overrides the other. @raae Nuxtent overrides page paths so even though you nested the pages correctly, it's the permalink that ends up defining the route's behavior... Try putting posts/:slug and projects/:slug as the permalink, and let us know if that works!

--
Side discussion:
@medfreeman But why is one route ending up as post/_slug if both of them have :slug as the permalink?

Also, this is why I recommended having automatic prefixing of content routes based on their page paths as the default behavior. I think it's what most people would expect. If you define an index route then you'd expect a root level path, but why would you nest a page, e.g. somePath/_slug yet expect a root level path?

The question is: should it be expected that a page found under nestedPath/_slug with permalink :slug be found under nestedPath/slug OR just slug ?

Similarly, should a page under nestedPath/_slug with permalink :year/slug be under nestedPath/2017/slug or 2017/slug? I could see how the latter would be more powerful, but if the user wanted a root level path, why wouldn't the user just set the page under _slug since you can't have more than more dynamic route anyways as they would override each other.

raae commented

So my use case is that I would like to organize the content in different folders and also have them accessible as separate collections through getAll(). But I want both to resolve to <baseUrl>/:slug permalink.

But that might not be possible?

Yes this should be possible with the current implementation. Does putting the permalinks as posts/:slug and projects/:slug not work?

raae commented

Yes, it works. But the permalink are then /posts/post1 and /projects/project1. Not /post1 and /project1. And the path values feel a little weird, see image.

nuxtent_starter

My config is now:

module.exports = {
  content: [
    [
      'projects',
      {
        permalink: 'projects/:slug',
        page: 'projects/_slug',
        isPost: false,
        generate: [
          // for static build
          'get',
          'getAll'
        ]
      }
    ],
    [
      'posts',
      {
        permalink: 'posts/:slug',
        page: '/posts/_slug',
        isPost: false,
        generate: [
          // for static build
          'get',
          'getAll'
        ]
      }
    ]
  ]
}
```

I encountered the same issue - I solved it worked around that by omitting the nesting in the pages directory.

  content: [
    ['writings', {
      permalink: ':year/:slug',
      page: '/_writings',
      generate: [
        'get', 'getAll'
      ]
    }],
    ['projects', {
      permalink: 'projects/:slug',
      isPost: false,
      page: '/_projects',
      generate: [
        'get', 'getAll'
      ]
    }]
  ],

Note that in pages I directly use _projects instead of using a subfolder.

raae commented

If you could point me in the right direction (ie. relevant code) I could give it a try.

Yeah sorry I'm just to busy to look into it this week, but I come here to quickly answer questions :)

If you want to give it a go, the relevant code is at : https://github.com/nuxt-community/nuxtent-module/blob/master/lib/content/build.js#L32

If you have questions feel free to also join our dev slack channel and ask them there

@raae I know this has been open for a while, but I think you might be confusing two things:

  • path : The path used to fetch the item from the content API
  • permalink : The path used by the (user in) the browser

So, in the screenshot above, you have a content entry with:

  • path : /projects/projects/project1 => Use this to fetch from content-api in the page for your dynamic root
  • permalink : /projects/project1 => This is what the user navigates to

This is actually rather handy, because /projects is how the content-api groups all your projects. So in the page that handles the dynamic root for this content type, you simple fetch /projects+permalink from the content api and you'll get the content for the the page the user requested.

And if you wonder, *why can't I just get /content-api/[permalink of the content item] that's because /content-api/[content-group] is also a valid endpoint, one that gives you all that content for that content group. So I guess it's more RESTfull this way.

Just keep in mind that to get stuff from the content api, you fetch: /content-api/[content-group]/[permalink of the content item]

For me, this works as expected and is not a bug. Thoughts?

Note: the terminology I used here (content group and so on) is made up, it's not official

I really don't get those multiple content yes working. I probably tried over 3 hours with different configurations.

Take this simple single content type configuration:

module.exports = {
  api: {
    baseURL: process.env.NODE_ENV === 'production'
      ? 'http:/mywebsite.com'
      : 'http://localhost:3000',
    browserBaseURL: process.env.NODE_ENV === 'production'
      ? 'http://mywebsite.com'
      : 'http://localhost:3000'
  },
  content: {
    page: '/_page',
    permalink: ':slug',
    isPost: false,
    generate: [ // for static build
      'get'
    ],
  }
}

I have several md files in then content folder and in subfolders. They get flattened and stored in the dist folder on nuxt generate.

Good so far.

Now I'm changing this to a content type:

module.exports = {
  api: {
    baseURL: process.env.NODE_ENV === 'production'
      ? 'http://mywebsite.com'
      : 'http://localhost:3000',
    browserBaseURL: process.env.NODE_ENV === 'production'
      ? 'http://mywebsite.com'
      : 'http://localhost:3000'
  },
  content: [
    ['pages', {
      page: '/pages/_page',
      permalink: 'pages/:slug',
      isPost: false,
      generate: [ // for static build
        'get'
      ]
    },
  ]
}

Moving the files to the correct paths and try to generate or run, I always run in 404s or other errors.
Do you have any working example online which is using multiple content types, also with root paths and subfolders?

You use pages/:slug for the permalink, but the subdirectories are not part of the slug. As such, your permalinks don't match your directory structure, which might be causing the 404s.

Try with permalink: '/pages/:section*/:slug', as that should add the directory in there.

There's an example using this here but it's from the nuxtdown fork so you won't be able to just copy-paste it.

But the permalink stuff should be the same though.

You use pages/:slug for the permalink, but the subdirectories are not part of the slug

Not sure what you mean with that. In my understanding, my configuration should match content stored in content/pages, so with pages/:slug as permalink, this would match this structure.

This would mean.
Content: content/pages/my-page.md.
Template: pages/pages/_page.vue
Permalink: mywebsite.com/my-page

What do I misunderstand?

It's the subfolders that are a problem. What you describe above works fine if you have all your markdown in 1 folder, but not if you have subfolders.

So:

/content/pages/my-page.md and /content/pages/subdir/my-page.md have the same slug (my-page).

Your permalinks only include the slug, so the 2pages will end up with the same permalinks. You need to add in the 'sectiin' which is essentially the subdir. The example I linked to above linked this.

Either that, it it's me who misunderstands your issue ๐Ÿ˜‰

I feel like you misunderstand me. I don't have any subfolders in the content/pages folder.
Really, the only thing I did is converting my single content type example above into the multicontent type configuration without adding any other content type. For this I've put my content into content/pages instead of content/ directly, reflected the same structure in pages/ folder to easier relate. The result is always a 404 when trying to access myurl.tld/pages/page-3.

โ”œโ”€โ”€ content/
โ”‚   โ””โ”€โ”€ pages
โ”‚         โ”œโ”€โ”€ page-1.md
โ”‚         โ”œโ”€โ”€ page-2.md
โ”‚         โ””โ”€โ”€ page-3.md
โ””โ”€โ”€ pages/
    โ””โ”€โ”€ pages
          โ””โ”€โ”€ _page.vue

If this is something that is fixed in nuxtdown, fine. But from the readme of nuxtdown, it will only be a temporary repository that is eventually going to be merged back to nuxtent. I would rather love to know how this works in nuxtent and find out where the problem is and directly fix it in nuxtent if a fix is needed.
I still believe I probably doing something wrong and if this is the case, based on the time I invested I also would love to improve the documentation if needed as soon as I understand it.

@renestalder It is a documentation problem and maybe a bug on nuxtent. Nuxtent modifies the route of the component and if configured incorrectly can lead into a really confusing problem.

For now a workaround could be providing a fake page route page: '/unexisting/_slug*'
Another thing that you can try is using the development version, for this you can either clone and link the repo with yarn or use it as a submodule inside your own project.

As i'm looking for bugs I'm using the development branch inside my current projects as a submodule with this config

nuxt.config.js

import nuxtent from './modules/nuxtent/lib/module'
export default {
  modules: [
    './modules/nuxtent/lib/module',
  ],
}

@cesasol Thanks a lot for your input. I then gonna try the development branch. Already saw that there are fixes not available on the released version but wasn't sure if it is safe to try.

Let me know if you need contributors. I really would like to keep this project alive and If I can help instead of developing something from scratch for my Netlify CMS coupled websites I'll do that.

@cesasol With your submodule solution, doesn't Nuxt complain about import statements? How you worked around this? In my understanding, Nuxt v1 doesn't support es modules.

Yes it does, I'm alredy using nuxt-edge on production and so far so good. But for importing the submodule you have to build it (yarn build) and only require it whith './modules/nuxtent'

As for contributing, there are tree ways in wich you can help, first would be input, as we advance on the development for this module sometimes we wonder beteween solution A and B, those discussions are held on gitter, second would be testing and submitting all issues that you encounter, and for the latest would be documentation, right now I'm starting by documenting and rewriting code in a more legible way (smaller files and documented vars/functions).

Another thing, where I work we decide to contribute with this project for the same reason as you, not having to develop a cms for static sites from scratch.