Detect the document type dynamically

Hi everyone,

I'm using Prismic with a Next.js project, and I have a situation where:

  • I have documents of different types (page, article_post, and documentation_page).
  • All of them should resolve to the same route structure (i put it in app/[uid]/page.tsx).
  • Each type has its own graphQuery to fetch different fields.

:red_question_mark: The current problem:

  • To detect the document by UID, I have to try/catch and call getByUID multiple times (one per type).
  • In the worst case, this causes 3 API requests before even loading the real content.
  try {
    page = await client.getByUID('page', uid)
  } catch {
    try {
      const graphQuery = `{
          ......
      }`
      page = await client.getByUID('article_post', uid, { graphQuery })
    } catch {
      try {
        const graphQuery = `{
          documentation_page {
           .........
          }
        }`
        page = await client.getByUID('documentation_page', uid, { graphQuery })
      } catch {
        notFound()
      }
    }
  }

  if (!page) {
    notFound()
  }

  switch (page.type) {
    case 'article_post':
      return <ArticlePage page={page} />
    case 'documentation_page':
      return <DocumentationPage page={page} />
    default:
      return <DefaultPage page={page} />
  }

:speech_balloon: What I want to achieve:

  • Find the correct document by UID across multiple types using only 1 API call.
  • Then, based on the type, make 1 additional call with the correct graphQuery.

:books: I checked the Prismic Client v7 docs and know about filter.any("document.type", [...]), but I’m not 100% sure how to combine it perfectly for UID lookup.

I want put it in app/[uid]/page.tsx instead of put it in

  • app/[uid]/page.tsx
  • app/article/[uid]/page.tsx
  • app/docs/[uid]/page.tsx

Question:

  • What’s the best practice to efficiently detect a document by UID across several types?
  • Should I use getFirst, getAll, or maybe a custom filters?
  • Is there an even better strategy (e.g., GraphQL one-shot query)?

Any advice, best practices, or sample code would be super appreciated! :rocket:

Thanks so much :folded_hands:

To avoid multiple getByUID calls, you could use client.get() with filters to search by UID across types in one request:

const page = await client.get({
  filters: [
    `my.document.uid = "${uid}"`,
    `document.type in ["page", "article_post", "documentation_page"]`,
  ],
  pageSize: 1,
});

Although please take into account that the UID is unique per type and per language.
If different types share the same UID, and you’re trying to resolve everything under /[uid], it’s hard to know which document should load. That’s why, in cases like this, it’s actually better to split the routes:
/article/[uid], /docs/[uid], and /[uid].

If you really need to mix content from different types into one page, another option is using Content Relationship fields to pull related documents rather than trying to create a link between them all directly by UID.

1 Like