Issues with page routes when implementing catch all route with custom slug field

Describe your question/issue in detail

Hello, I'm currently migrating a project from Gatsby to Next.js (Pages Router). The challenge arose around the topic of routing, as currently it's based on the slug field of a page type. This slug can take a form of a simple one like /lorem, but also nested like /lorem/ipsum. So, instead of going the uid route as presented in the documentation, I've implemented generating static paths and pages based on that page.slug field by utlizing filters and it's working well.

The problem starts with setting Prismic page routing. I'm unable to set it up properly, whether with a routes object or with a link resolver.

Impacted feature

PrismicNextLinks are broken.

What steps have you taken to resolve this issue already?

1. Setting up routes object

I've tried adding this to page routes:

{
  type: 'page',
  resolvers: {     
    slug: 'page.slug'
  },
  path: '/:slug',
}

It results with this error that I just can't understand:

Error: [Link resolver error] Invalid resolver slug
It must be a content relationship linked to one and only one custom typ

2. Creating a custom link resolver

I thought that maybe it's not possible to get the page as self in the page route, as the documentation states the resolver is for parents and grandparents. I went for the more advanced use case with link resolver. I've created it like this:

const linkResolver = (doc) => {
  switch (doc.type) {
    case 'page':
      return doc.data.slug || null;
    default:
      return null;
  }
};

The new problem is that doc doesn't have a data key for some reason. In the current Gatsby implementation, it works properly with page.slug being defined in Gatsby plugin config in fetchLinks array.

TypeError: Cannot read properties of undefined (reading 'slug')

Prismic client, when pulling the page in getStaticProps, uses fetchLinks with page.slug in it, but it makes no difference.

Your Role

Software engineer

Hosting provider

Netlify

Hi @bartosz.holubowicz ,

Welcome to the community :slight_smile:

The best option here is to work with the recommended tools for this job:

  • The UID field
  • Content Relationships
  • The route resolver

This will help you achieve exactly what you want otherwise you'll keep hitting the problems listed above.

This document will explain how to do that:

and if you need to convert your slug fields to UIDs you can use the migration API:

Let me know if you have any questions.

Thanks.

Hi @Phil, thanks for the response!

I've looked into the first document for a bit before and I haven't found the solution for my use case. The catch-all paths example doesn't reflect the problem, as the "lorem" part in the example /lorem/ipsum doesn't represent any content for use with a resolver. It all revolves around the fact that UID field isn't able to store the full path with nesting, like /lorem/ipsum - it doesn't accept slashes, so I don't even know how I could use Migration API to achieve that.

With nested paths, which are built by using content relationships to declare the parent document, the route resolver will build the full path for you.

/lorem/ipsum = /content-relationship/uid
https://prismic.io/docs/define-paths-nextjs#nested-paths

const routes = [
  {
    type: 'page',
    resolvers: {
      category: 'category',
    },
    path: '/:category/:uid',
  },
]

I mentioned migration API as a way to bulk update the UID fields with the content of the slug field.

As I've mentioned, the slug to migrate has nothing to do with content relationships - it's nested path is one chunk, like /lorem/ipsum = /slug. If it's not possible to configure it that way, I'll probably go with some refactoring where one can choose a parent page in a page type and use content relationship for it, though I'm worried whether it will complicate the later migration process from one repo to another. Before I do that, I'd like to know whether it's technically possible to do what I've described before - nested paths without content relationships.

Your suggested refactoring is exactly what I'm suggesting; we're agreeing here :sweat_smile: The migration API with some scripting on your side is the way to convert the slug into a content relationship and a uid.

It's not possible to do this using page.slug and route/link resolver or the PrismicNextLink component.

@Phil is there a way to map one field to the UID field? If we had a field for the slug, and the User inputted the value /parent-page/page-slug – is there a way to format the value and set it as the UID value?

@phil.moody So you're saying the slug is a string like /parent-page/page-slug? If so, you'll need to create the /parent-page first, then map /page-slug to the UID field and link the /parent-page as a content relationship and import it with the migration API.

Does that make sense?