Content Relationship

This article explains what the content relationship field is and how to configure it.

Content writers can link documents through content relationship fields. Developers can fetch data from linked documents.

Content relationships are often used for managing categories, authors, and navigation menus.

Add a content relationship to a content model

  • Open Slice Machine

    In your Prismic project, start Slice Machine to begin editing content models.

    npx start-slicemachine --open
  • Add a content relationship field

    In Slice Machine, navigate to the slice, page type, or custom type you want to modify. Add a content relationship field.

    The label determines the label shown to content writers in the Page Builder. Use an easily understood name.

    The API ID determines the property name in the Document API. Use a short, snake-cased name.

  • (Optional) Allow a subset of document types

    Content relationships can be restricted to a subset of document types. For example, you may want to allow linking only to a Blog Post document.

    Open the field settings and select the allowed document types under the Types field.

Tips

  • Fetch content from linked documents

    The Prismic client’s graphQuery option fetches content from a linked document.

    const home = await client.getByUID("page", "home", {
      graphQuery: `
        page {
          featured_blog_post {
            ...on blog_post {
              title
              description
            }
          }
        }
      `,
    });
    
    // The linked blog post's title.
    const title = home.data.featured_blog_post.data.title;
  • Type fetched fields with TypeScript

    Fields fetched via graphQuery can be typed with TypeScript using a type assertion (the as operator).

    import { Content } from "@prismicio/client";
    
    const featuredBlogPost = home.data
      .featured_blog_post as typeof home.data.featured_blog_post & {
      data: Pick<Content.BlogPostDocument["data"], "title" | "description">;
    };
    
    const title = featuredBlogPost.data.title;
    //    ^ Typed as Content.BlogPostDocument['data']['title']
  • Filter queries by linked documents

    The Prismic client’s filters option can filter queries by a content relationship.

    This example fetches all blog posts from an author with the document ID YksUgRIAACEA-UZD:

    import { filter } from "@prismicio/client";
    
    await client.getAllByType("blog_post", {
      filters: [filter.at("my.blog_post.author", "YksUgRIAACEA-UZD")],
    });
  • Use isFilled.contentRelationship() to check if a content relationship has a value

    import { isFilled } from "@prismicio/client";
    
    if (isFilled.contentRelationship(slice.primary.featured_blog_post)) {
      // Do something if `featured_blog_post` has a value.
    }

Examples

On a marketing page, you could have a list of blog posts with the posts’ titles and descriptions.

  • Add a content relationship field

    On a page type, add a group field called featured_blog_posts containing a content relationship field. Only allow linking Blog Post documents on the content relationship.

  • Query the linked content

    In your API query, use the graphQuery option to retrieve the blog posts’ title and description.

    const page = await client.getByUID("page", "home", {
      graphQuery: `
        page {
          featured_blog_posts {
            blog_post {
              ...on blog_post {
                title
                description
              }
            }
          }
        }
      `,
    });
  • Display the linked content

    Use the page.data.featured_blog_posts array to display each blog post link with its title and description.

Taxonomies

On a blog, you could organize posts by categories.

  • Create a Category custom type

    This type will represent blog post categories. It should be repeatable and have a Name field.

  • Create a Blog Post page type

    This type will represent blog posts. It should be repeatable and have a content relationship field named Category.

    Only allow Category documents on the content relationship field.

  • Query the blog post

    In your API query, use the graphQuery option to retrieve the blog posts’ category name.

    const page = await client.getByUID("blog_post", "my-blog-post", {
      graphQuery: `
        page {
          category {
            ...on category {
              name
            }
          }
        }
      `,
    });
  • Create a category page

    In your API query, use the filters option to query all blog posts for a category.

    This example fetches all blog posts from a category with the document ID YksUgRIAACEA-UZD:

    import { filter } from "@prismicio/client";
    
    const blogPosts = await client.getAllByType("blog_post", {
      filters: [filter.at("my.blog_post.category", "YksUgRIAACEA-UZD")],
    });

Nested menus

On a website, you could build a nested navigation menu.

  • Create a Menu custom type

    This type will represent top-level lists of links. It should be a singleton and have a group field called child_menus containing a content relationship field.

  • Create a Child Menu custom type

    This type will represent a list of links. It should be repeatable and have a group field called links containing a link field.

  • Query the menu

    In your API query, use the graphQuery option to retrieve links from child menus.

    const menu = await client.getSingle("menu", {
      graphQuery: `
        menu {
          child_menus {
            child_menu {
              ...on child_menu {
                links {
                  link
                }
              }
            }
          }
        }
      `,
    });
  • Display the menu

    Use the menu.data.child_menus array to display each list of links.

API response

Here is what a content relationship looks like from the Document API:

{
  "example_content_relationship": {
    "id": "XxnD3REAACYAk_CJ",
    "type": "page",
    "tags": ["music"],
    "slug": "vaporwave",
    "lang": "en",
    "uid": "vaporwave",
    "link_type": "Document",
    "isBroken": false
  }
}

When using the Prismic client’s graphQuery option, fields are added to the data property:

{
  "example_content_relationship": {
    "id": "XxnD3REAACYAk_CJ",
    "type": "page",
    "tags": ["music"],
    "slug": "vaporwave",
    "lang": "en",
    "uid": "vaporwave",
    "link_type": "Document",
    "isBroken": false,
    "data": {
      "title": "Vaporwave",
      "description": "Nostalgic, surreal, dreamy, and retro-futuristic."
    }
  }
}