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 (theas
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 valueimport { isFilled } from "@prismicio/client"; if (isFilled.contentRelationship(slice.primary.featured_blog_post)) { // Do something if `featured_blog_post` has a value. }
Examples
Detailed links to other pages
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."
}
}
}