# Nextjs Dynamic nested paths

**URL:** <https://community.prismic.io/t/nextjs-dynamic-nested-paths/16613>\
**Category:** Developing with Prismic\
**Tags:** nextjs, link-route-resolver, slice-machine\
**Created:** [September 5, 2024, 4:02pm UTC](https://community.prismic.io/t/nextjs-dynamic-nested-paths/16613 "2024-09-05T16:02:41Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![solution.stack99](https://avatars.discourse-cdn.com/v4/letter/s/cab0a1/32.png) [@solution.stack99](https://community.prismic.io/u/solution.stack99)\
**Post date:** [September 5, 2024, 4:02pm UTC](https://community.prismic.io/t/nextjs-dynamic-nested-paths/16613/1 "2024-09-05T16:02:41Z")

</div>

I have nested paths where I want a child page to be a dynamic page so that the content team can add it.

Structure:

```auto
Resources
  - Blog (dynamic page)
     - Blog pages (dynamic page)
  - Getting Started (dynamic page)
     - Pages (dynamic page)
- etc

```

How to set up files under `app/` folder `Page Type` and `link resolver` all together?

Thank you in advance!

---

<div class="post-metadata">

**Author:** ![Phil](https://dub1.discourse-cdn.com/flex013/user_avatar/community.prismic.io/phil/32/14_2.png) [@Phil](https://community.prismic.io/u/Phil)\
**Post date:** [September 9, 2024, 10:32am UTC](https://community.prismic.io/t/nextjs-dynamic-nested-paths/16613/4 "2024-09-09T10:32:33Z")

</div>

To achieve the dynamic page structure with Prismic and Next.js using the new `app` folder, you'll need to set up your routes dynamically while also configuring a link resolver to manage the relationships between pages and the dynamic content in Prismic.

Here’s a step-by-step guide to achieve this:

### 1. **Setting up dynamic routes under the `app` directory**

In the new Next.js 13 `app` folder structure, each folder corresponds to a route. Dynamic routes can be set using square brackets.

- **Dynamic Parent Page (e.g., `blog`)**
  - Create the following structure inside your `app` directory:

```auto
app/
  resources/
    blog/
      [uid]/
        page.js
      page.js
    getting-started/
      [uid]/
        page.js
      page.js

```

  - Each `[uid]` will correspond to the dynamic blog or getting started pages.

### 2. **Creating the dynamic page for blog**

In `app/resources/blog/[uid]/page.js` you can fetch the specific content from Prismic using the uid. Here’s an example:

```javascript
// app/resources/blog/[uid]/page.js

import { createClient } from '../../../prismicio'; // Adjust path according to your prismic setup
import { PrismicRichText } from '@prismicio/react';

export default async function BlogPostPage({ params }) {
  const client = createClient();

  // Fetch the document using the uid
  const blogPost = await client.getByUID('blog_post', params.uid);

  return (
    <div>
      <h1>{blogPost.data.title}</h1>
      <PrismicRichText field={blogPost.data.content} />
    </div>
  );
}

```

This page will dynamically load content based on the `uid` in the URL, using Prismic's `getByUID`.

### 3. **Creating the dynamic parent page (e.g., `blog`)**

In `app/resources/blog/page.js` you can list all the blog posts:

```javascript
// app/resources/blog/page.js

import { createClient } from '../../../prismicio';
import Link from 'next/link';

export default async function BlogPage() {
  const client = createClient();

  // Fetch all blog posts
  const blogPosts = await client.getAllByType('blog_post');

  return (
    <div>
      <h1>Blog</h1>
      <ul>
        {blogPosts.map((post) => (
          <li key={post.id}>
            <Link href={`/resources/blog/${post.uid}`}>
              {post.data.title}
            </Link>
          </li>
        ))}
      </ul>
    </div>
  );
}

```

### 4. **Set up the Link Resolver**

Prismic’s link resolver allows you to manage links between documents. You can create a `link-resolver.js` to manage dynamic paths, especially for content types like `blog_post` or `page`.

```javascript
// link-resolver.js

export const linkResolver = (doc) => {
  if (doc.type === 'blog_post') {
    return `/resources/blog/${doc.uid}`;
  }
  if (doc.type === 'getting_started') {
    return `/resources/getting-started/${doc.uid}`;
  }
  return '/';
};

```

### 5. **Update Prismic Client to use Link Resolver**

You’ll need to integrate the `linkResolver` into the Prismic client setup. Here’s how to do it inside `prismicio.js` (or wherever you’ve set up your Prismic client):

```javascript
import * as prismic from '@prismicio/client';
import { linkResolver } from './link-resolver';

export const createClient = () => {
  const client = prismic.createClient(process.env.NEXT_PUBLIC_PRISMIC_ENDPOINT, {
    accessToken: process.env.PRISMIC_ACCESS_TOKEN,
  });

  // Add the link resolver
  client.linkResolver = linkResolver;

  return client;
};

```

### 6. **Handling additional dynamic paths**

For the `getting-started` and other nested sections, follow the same pattern as with `blog`. Adjust the content types and page structures accordingly.

For example, for a "Getting Started" dynamic page, create the structure:

```auto
app/
  resources/
    getting-started/
      [uid]/
        page.js
      page.js

```

### Recap of Structure:

```auto
app/
  resources/
    blog/
      [uid]/ -> Dynamic blog post page
      page.js -> Blog listing page
    getting-started/
      [uid]/ -> Dynamic getting-started page
      page.js -> Getting started listing page

```

Each dynamic route will correspond to a page type in Prismic, and your `link-resolver` will generate the correct paths.

This structure allows your content team to manage both the parent and child dynamic pages easily within Prismic while maintaining clear routing in Next.js.

---

<div class="post-metadata">

**Author:** ![solution.stack99](https://avatars.discourse-cdn.com/v4/letter/s/cab0a1/32.png) [@solution.stack99](https://community.prismic.io/u/solution.stack99)\
**Post date:** [September 11, 2024, 7:00pm UTC](https://community.prismic.io/t/nextjs-dynamic-nested-paths/16613/5 "2024-09-11T19:00:37Z")

</div>

Thank you for the info.

How about the path in `const routes: prismic.ClientConfig["routes"]` function in `prismicio.ts`? Do you have examples?

---

<div class="post-metadata">

**Author:** ![Phil](https://dub1.discourse-cdn.com/flex013/user_avatar/community.prismic.io/phil/32/14_2.png) [@Phil](https://community.prismic.io/u/Phil)\
**Post date:** [September 12, 2024, 11:51am UTC](https://community.prismic.io/t/nextjs-dynamic-nested-paths/16613/6 "2024-09-12T11:51:09Z")

</div>

Certainly! Here’s an example of a route resolver for Prismic in Next.js. The route resolver is slightly different from the link resolver, as it provides more control over URL generation, especially for nested or more complex URL structures.

### Prismic Route Resolver Example

The `routeResolver` allows you to define more complex paths for your documents, such as when you have nested or hierarchical structures like you described (e.g., `resources/blog/[slug]`).

Here's an example of how you can set up a route resolver for your `blog_post`, `getting_started`, and other content types.

### 1. **Create the Route Resolver**

Create a new file called `route-resolver.js` in your project:

```javascript
// route-resolver.js

export const routeResolver = {
  routes: [
    {
      type: 'blog_post', // Prismic document type
      path: '/resources/blog/:uid', // Route path in Next.js
    },
    {
      type: 'getting_started', // Prismic document type
      path: '/resources/getting-started/:uid', // Route path for getting started pages
    },
    {
      type: 'other_page_type', // Example of another page type
      path: '/resources/:uid', // Another path for dynamic content
    }
  ],
};

```

### 2. **Update the Prismic Client to Use the Route Resolver**

You need to modify your Prismic client configuration to use the `routeResolver`. Update your `prismicio.js` file (or wherever you've set up the Prismic client) to import and use the `routeResolver`.

```javascript
// prismicio.js

import * as prismic from '@prismicio/client';
import { routeResolver } from './route-resolver';

export const createClient = () => {
  const client = prismic.createClient(process.env.NEXT_PUBLIC_PRISMIC_ENDPOINT, {
    accessToken: process.env.PRISMIC_ACCESS_TOKEN,
  });

  // Add the route resolver for more complex routing
  client.routes = routeResolver.routes;

  return client;
};

```

### 3. **Using Route Resolver in Components**

Once the route resolver is set up, you don’t need to manually build the paths using the document `uid` in your components. Instead, Prismic will automatically resolve the correct paths based on the `routes` you defined in the route resolver.

For example, when linking to a document, you can use the `prismicH.asLink` helper function, which will automatically use the correct path defined by the `routeResolver`.

Example in a component that lists blog posts:

```javascript
import Link from 'next/link';
import { asLink } from '@prismicio/helpers'; // Helper from Prismic to resolve links

export default function BlogPostList({ blogPosts }) {
  return (
    <ul>
      {blogPosts.map((post) => (
        <li key={post.id}>
          {/* Use the asLink helper to automatically resolve the correct path */}
          <Link href={asLink(post)}>
            {post.data.title}
          </Link>
        </li>
      ))}
    </ul>
  );
}

```

In this case, the `asLink(post)` will resolve the link using the `routeResolver`, and for a `blog_post` document, it will generate a URL like `/resources/blog/[uid]`.

### 4. **Testing and Deployment**

With the route resolver set up, you can now deploy your Next.js app and test the dynamic routing. When your content team creates a new `blog_post` or `getting_started` page in Prismic, it will automatically generate the correct URL using the route resolver and display the content based on the `uid`.

### Summary

1. Create the `route-resolver.js` file that defines how the routes are resolved based on the document type.
2. Update the Prismic client to use the `routeResolver`.
3. Use Prismic’s `asLink` or `asLinkResolver` functions in your components to automatically resolve URLs based on the defined routes.

This setup ensures that you can handle nested dynamic pages and have complete control over the paths, making it easy for your content team to add new pages.

---

<div class="post-metadata">

**Author:** ![solution.stack99](https://avatars.discourse-cdn.com/v4/letter/s/cab0a1/32.png) [@solution.stack99](https://community.prismic.io/u/solution.stack99)\
**Post date:** [September 12, 2024, 2:31pm UTC](https://community.prismic.io/t/nextjs-dynamic-nested-paths/16613/7 "2024-09-12T14:31:53Z")

</div>

Thank you, @Phil I will try to implement it and get back to you if I am stuck.

Can your team make a video tutorial on YouTube? This is a very complex build and I believe it will benefit most people.

---

<div class="post-metadata">

**Author:** ![Phil](https://dub1.discourse-cdn.com/flex013/user_avatar/community.prismic.io/phil/32/14_2.png) [@Phil](https://community.prismic.io/u/Phil)\
**Post date:** [September 13, 2024, 12:02pm UTC](https://community.prismic.io/t/nextjs-dynamic-nested-paths/16613/8 "2024-09-13T12:02:57Z")

</div>

We already have documentation for this use case:

> **[Define Paths with Next.js](https://prismic.io/docs/define-paths-nextjs)**
>
> This article will show you how to do dynamic routing in your Next.js and Prismic project.

And our Youtube channel has lots of tutorials:  
https://www.youtube.com/embed/jSa_uskwaE0?feature=oembed&wmode=opaque&list=PLUVZjQltoA3zeEDbjyTXbA42We2t9px7z

But I agree a video for directly this case in Next.js would be nice 🙂

---

<div class="post-metadata">

**Author:** ![jplate](https://dub1.discourse-cdn.com/flex013/user_avatar/community.prismic.io/jplate/32/7900_2.png) [@jplate](https://community.prismic.io/u/jplate)\
**Post date:** [October 3, 2024, 10:01pm UTC](https://community.prismic.io/t/nextjs-dynamic-nested-paths/16613/9 "2024-10-03T22:01:42Z")

</div>

Hello @Phil,

Based on the Define Paths link you provided and specifically the [Nested paths](https://prismic.io/docs/define-paths-nextjs#nested-paths) section, what if the blog in the example above wasn't a list page that pulls back all blog\_posts but instead its own page type? How would you route to those pages while still having nested blog\_post page types?

The structure for blog\_post:

```auto
app/
  resources/
    [blog]/
      [uid]/
        page.js -> Dynamic blog post page

```

The route-resolver for blog\_post:

```auto
// route-resolver.js

export const routeResolver = {
  routes: [
    {
      type: 'blog_post', // Prismic document type
      resolvers: {
        blog: 'blog',
      },
      path: '/resources/:blog/:uid', // Route path in Next.js
    }
};

```

---

<div class="post-metadata">

**Author:** ![Ezekiel](https://avatars.discourse-cdn.com/v4/letter/e/848f3c/32.png) [@Ezekiel](https://community.prismic.io/u/Ezekiel)\
**Post date:** [October 4, 2024, 3:10pm UTC](https://community.prismic.io/t/nextjs-dynamic-nested-paths/16613/12 "2024-10-04T15:10:29Z")

</div>

Hi @jplate,

Welcome to the community!

Can you give me a little more information on what you're trying to do, and what's not working? Do you mean if Blog isn't a dynamic page listing the blog\_posts like in the example above? What do you want it to be doing? 🙂

---

<div class="post-metadata">

**Author:** ![jplate](https://dub1.discourse-cdn.com/flex013/user_avatar/community.prismic.io/jplate/32/7900_2.png) [@jplate](https://community.prismic.io/u/jplate)\
**Post date:** [October 4, 2024, 9:18pm UTC](https://community.prismic.io/t/nextjs-dynamic-nested-paths/16613/14 "2024-10-04T21:18:14Z")

</div>

Hello,

Correct, we are wondering if the Blog isn't a dynamic page listing blog\_posts but instead, a page created in Prismic with its own uid and unique page type.

So in theory we are looking for something like:

```auto
app/
  resources/
    [blog]/
      [uid]/page.js -> Dynamic blog post page
      page.js -> Dynamic blog page, not a listing page

```

The route could look like:

```auto
// route-resolver.js

export const routeResolver = {
  routes: [
    {
      type: 'blog', // Prismic document type
      path: '/resources/:blog', // Route path in Next.js
    }
    {
      type: 'blog_post', // Prismic document type
      resolvers: {
        blog: 'blog',
      },
      path: '/resources/:blog/:uid', // Route path in Next.js
    }
};

```

Obviously, this doesn't work as it is written here because the blog page type route is expecting a `:uid` and not a `:blog` resolver. Is there a way with App Routing to nest page types?

---

<div class="post-metadata">

**Author:** ![Ezekiel](https://avatars.discourse-cdn.com/v4/letter/e/848f3c/32.png) [@Ezekiel](https://community.prismic.io/u/Ezekiel)\
**Post date:** [October 11, 2024, 1:44pm UTC](https://community.prismic.io/t/nextjs-dynamic-nested-paths/16613/16 "2024-10-11T13:44:16Z")

</div>

Have you created the content relationship field called `blog` in your `blog_post` documents?

---

<div class="post-metadata">

**Author:** ![jplate](https://dub1.discourse-cdn.com/flex013/user_avatar/community.prismic.io/jplate/32/7900_2.png) [@jplate](https://community.prismic.io/u/jplate)\
**Post date:** [October 11, 2024, 2:27pm UTC](https://community.prismic.io/t/nextjs-dynamic-nested-paths/16613/17 "2024-10-11T14:27:17Z")

</div>

Yes, but how does that help with the blog page type?

If I try to build my project using the path `/resources/:blog` on the blog type, I get this error:  
`[Link resolver error] The following resolvers are missing for page type blog: - blog`

By default, the only variables allowed in the path pattern are `:uid` and `:lang`. So I need a way to point `/resources/:uid` to `/resources/:blog`. Or do I have to add a blog content relationship field to the blog page type and the editor has to select the same page they are editing?

---

<div class="post-metadata">

**Author:** ![Ezekiel](https://avatars.discourse-cdn.com/v4/letter/e/848f3c/32.png) [@Ezekiel](https://community.prismic.io/u/Ezekiel)\
**Post date:** [October 11, 2024, 4:52pm UTC](https://community.prismic.io/t/nextjs-dynamic-nested-paths/16613/19 "2024-10-11T16:52:20Z")

</div>

> [@jplate](#):
>
> Or do I have to add a blog content relationship field to the blog page type and the editor has to select the same page they are editing?

Yes you have to add a `blog` content relationship to the `blog_post` page type in the top of the type. The editor has to then link to a document of the type `blog`.

---

<div class="post-metadata">

**Author:** ![jplate](https://dub1.discourse-cdn.com/flex013/user_avatar/community.prismic.io/jplate/32/7900_2.png) [@jplate](https://community.prismic.io/u/jplate)\
**Post date:** [October 11, 2024, 5:00pm UTC](https://community.prismic.io/t/nextjs-dynamic-nested-paths/16613/20 "2024-10-11T17:00:38Z")

</div>

Nope, that's not what I'm asking. I know I have to add it to the _ **blog\_post** _ page type

Do I have to add a _ **blog** _ content relationship field to the _ **blog** _ page type?

---

<div class="post-metadata">

**Author:** ![Phil](https://dub1.discourse-cdn.com/flex013/user_avatar/community.prismic.io/phil/32/14_2.png) [@Phil](https://community.prismic.io/u/Phil)\
**Post date:** [October 14, 2024, 1:25pm UTC](https://community.prismic.io/t/nextjs-dynamic-nested-paths/16613/22 "2024-10-14T13:25:43Z")

</div>

Hey @jplate ,

I gave @Ezekiel wrong information for this. You don't to add a _ **blog** _ content relationship field to the _ **blog** _ page type.

You just need to update your route resolver as so, the `uid` is unique to each type so it can referenced in each route.

```auto
// route-resolver.js

export const routeResolver = {
  routes: [
    {
      type: 'blog', // Prismic document type
      path: '/resources/:uid', // Route path in Next.js
    }
    {
      type: 'blog_post', // Prismic document type
      resolvers: {
        blog: 'blog',
      },
      path: '/resources/:blog/:uid', // Route path in Next.js
    }
};

```

---

<div class="post-metadata">

**Author:** ![jplate](https://dub1.discourse-cdn.com/flex013/user_avatar/community.prismic.io/jplate/32/7900_2.png) [@jplate](https://community.prismic.io/u/jplate)\
**Post date:** [October 14, 2024, 3:02pm UTC](https://community.prismic.io/t/nextjs-dynamic-nested-paths/16613/23 "2024-10-14T15:02:47Z")

</div>

Hello @Phil

Correct me if I'm wrong, but doesn't that route resolver require the app routing folder structure to look like:

```auto
app/
  resources/
    [blog]/
      [uid]/page.js -> Dynamic blog post page
    [uid]/
      page.js -> Dynamic blog page, not a listing page

```

If done this way, we get an error saying we can't use different slug names for the same dynamic path. Meaning, `[blog]` and `[uid]` can't be used at the same level.

---

<div class="post-metadata">

**Author:** ![Phil](https://dub1.discourse-cdn.com/flex013/user_avatar/community.prismic.io/phil/32/14_2.png) [@Phil](https://community.prismic.io/u/Phil)\
**Post date:** [October 14, 2024, 4:26pm UTC](https://community.prismic.io/t/nextjs-dynamic-nested-paths/16613/24 "2024-10-14T16:26:54Z")

</div>

So you could have the following folder structure:

```auto
app/
  resources/
    [blog]/
      page.js -> Dynamic blog post page
      [uid]/
        page.js -> Dynamic blog page, not a listing page

```

Your route resolver would look like the one I showed you above.

`resources/[blog]/page.js` Would have the follow code:

```auto
export default async function Page({ params }) {
  const client = createClient();
  const page = await client
    .getByUID("blog", params.blog)
    .catch(() => notFound());

  return <SliceZone slices={page.data.slices} components={components} />;
}

export async function generateStaticParams() {
  const client = createClient();

  const pages = await client.getAllByType("blog");

  return pages.map((page) => {
    return { blog: page.uid };
  });
}

```

and `resources/[blog]/page.js/[uid]/page.js` would have the follow code:

```auto
export default async function Page({ params }) {
  const client = createClient();
  const page = await client
    .getByUID("blog_post", params.uid)
    .catch(() => notFound());

  return <SliceZone slices={page.data.slices} components={components} />;
}

export async function generateStaticParams() {
  const client = createClient();

  const pages = await client.getAllByType("blog_post");

  return pages.map((page) => {
    return {
      blog: page.data.blog.uid,
      uid: page.uid,
    }
  })
}

```

Try this out and let me know how it goes.

---

<div class="post-metadata">

**Author:** ![jplate](https://dub1.discourse-cdn.com/flex013/user_avatar/community.prismic.io/jplate/32/7900_2.png) [@jplate](https://community.prismic.io/u/jplate)\
**Post date:** [October 14, 2024, 5:37pm UTC](https://community.prismic.io/t/nextjs-dynamic-nested-paths/16613/25 "2024-10-14T17:37:59Z")

</div>

Thank you, @Phil!

That was the missing link, the parameter on the `[blog]/page.js` needed to be updated from `params.uid` to `params.blog`.

---

<div class="post-metadata">

**Author:** ![developers13](https://dub1.discourse-cdn.com/flex013/user_avatar/community.prismic.io/developers13/32/8447_2.png) [@developers13](https://community.prismic.io/u/developers13)\
**Post date:** [January 23, 2025, 4:07pm UTC](https://community.prismic.io/t/nextjs-dynamic-nested-paths/16613/26 "2025-01-23T16:07:37Z")

</div>

Hi @Phil, trying to implement this and am running into an issue. My question is where is the page.data.blog.uid data coming from in the final page? Do you need to add a field to the final blog page, or query fetchLinks to get the parent uid? My app router path is

`/services/[service_group]/[uid]`

My /services/[service\_group] page.tsx is running fine if I remove the nested /[uid] route

But on the /services/[service\_group]/[uid] page.tsx route, I have no access to data (or uid) of the service\_group type that the service page is linked to (with a Content Relationship group on the parent page).

This is my resolvers code in prismicio.ts

```auto
{
    type: "services",
    path: "/services",
  },
  {
    type: "service_group",
    path: "/services/:uid",
  },
  {
    type: "service",
    resolvers: {
      service_group: "service_group",
    },
    path: "/services/:service_group/:uid",
  },

```

I am getting the following error with the above setup.

```auto
  response: {
    type: 'Link resolver error',
    message: '[Link resolver error] The following resolvers are missing for page type service:\n' +
      '- service'
  }
}

```

Any help much appreciated! Thanks in advance 🙏

---

<div class="post-metadata">

**Author:** ![Ezekiel](https://avatars.discourse-cdn.com/v4/letter/e/848f3c/32.png) [@Ezekiel](https://community.prismic.io/u/Ezekiel)\
**Post date:** [January 30, 2025, 1:03pm UTC](https://community.prismic.io/t/nextjs-dynamic-nested-paths/16613/27 "2025-01-30T13:03:51Z")

</div>

Hi @developers13,

> Do you need to query fetchLinks to get the parent uid?

Yes, I believe this is the case.

Because the error message says the `service` type is missing a resolver, it indicates Prismic doesn’t know how to resolve the `service_group` relation properly. Your `service_group` resolver might not be correctly fetching the `uid` from the `service_group` parent. Since your `service` type has a Content Relationship to `service_group`, you need to explicitly request its `uid` using `fetchLinks` where you're fetching `service` data. This should ensure that `service_group`'s `uid` is then available in `page.data.service_group.uid`.

If this doesn't work out for you, check out the Link Resolver: [Route Resolver - Documentation - Prismic](https://prismic.io/docs/route-resolver#link-resolver). You might be able to use it as well if the structure gets too complex.

Let me know if that helps!
