Dynamic Pages with optional middle part in URL

Hey everyone I'm struggling to create dynamic routes in Next.js where the middle part is optional.

I have a single custom type which is a distribution page. And I have repeatable custom types which are product pages. This product pages can have categories but they are optional. The category field on the product page is a content relationship field to another custom type which resembles the category.

Unfortunately I can't create this URL structure. I tried it with getStaticPaths from Next.js and the optional catch all routes and the route resolver from prismic.

What I want in the end is:

  • distribution page: /distribution
  • product page: /distribution/product
    or product page with category when the user added this field in prismic: /distribution/category/product

My folder structure looks like this:

/pages
    /distribution
        /[uid].tsx

And my route resolver:

export const routeResolver = {
  routes: [
    {
      type: 'index',
      path: '/',
    },
    {
      type: 'distribution',
      path: '/distribution',
    },
    {
      type: 'product-page',
      path: '/distribution/:category?/:uid',
      resolvers: {
        category: 'category',
      },
    },
  ],
}

And here is my getStaticPaths function:

export async function getStaticPaths() {
  const docs = await Client().query(
    Prismic.Predicates.at('document.type', 'product-page'),
    { lang: '*' }
  )
  return {
    paths: docs.results.map((doc: any) => {
      return {
        params: {
          uid: doc.uid,
          category: doc.data.category.uid,
        },
      }
    }),
    fallback: false,
  }
}

The routing for /distribution and /distribution/:uid works but /distribution/:category/:uid throws a 404.

Thanks in advance for every help, I'm sure this was solved before and I'm just overseeing a small detail!

Hello @marco3

Thank you for reaching out to us.

After looking at your problem, you can have two approaches for the solution:

  1. Make a URL like /distribution/:category/:uid and if the category is not available, you can make a default value for a category and check it in its index.tsx i.e. /distribution/:category/index.tsx. This approach is for handling all products where category is not available.

  2. You can create a file like [...slug.js] under /pages/distribution, which can handle both URLs like /distribution/productand/distribution/category/product`. This approach is called an Optional routes in Nextjs. More information is available in the following links:
    Documentation:Routing: Dynamic Routes | Next.js
    Demo: Next.js Catch All Routes Example - StackBlitz

Thanks,
Priyanka

1 Like

Hey @Priyanka thanks for you quick reply! These are two great solutions, I would like to get the first one to run. I changed my folder structure to

pages
    [distribution]
        [category]
            [uid].tsx
            index.tsx

The URLs /:distribution and /:distribution/:category/:uid work now but I can't get the category default to run so it just shows /:distribution/:uid.

How and where would I check for the category default value? In the getStaticPaths in /:distribution/:category/index.tsx?

Hi @marco3

By keeping the default value, I meant to have a constant value in the case, a category is not available. For example: If the default value is a string default-category, then the URLs will be like:

/distribution1/category1/product1
/distribution1/category2/product2
/distribution2/default-category/product3 (Here Product3 is not having any category)

So in /pages/:distribution/:category/index.tsx, you will apply a check for this value and can do the handling accordingly.

That way you will have the same structure across the site.

Thanks,
Priyanka

1 Like

Thanks, that helped me a lot!

You are welcome @marco3. Let us know if you have any questions.

1 Like