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 then access content from those documents.
Content relationship fields are often used for:
- Connecting a blog post to its author.
- Displaying a testimonial on a landing page.
- Linking a product to its category.
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.
Select the allowed document type
You can restrict the field to a specific document type. For example, you can configure the field to only allow Author documents in an Author field.
In the field’s settings, click the Add type button to select a document type.
You’ll be able to select fields from that document type to include in the API response in the next step.
Select the fields to fetch
If you restrict the field to a specific document type, you can select which fields to include in the API response.
Under the Allowed type section, use the field picker to choose which fields should be included. Up to 2 levels of nested fields can be selected (e.g.
blog
->author
->profession
).The selected fields are included in Slice Machine’s generated TypeScript types.
Display content relationships
Content from a related document can be displayed like any other field. The name of a blog post’s author, for example, can be rendered using the <PrismicText>
component.
Before accessing nested content, use isFilled.contentRelationship()
to ensure the relationship has a document.
{
isFilled.contentRelationship(post.data.author) && (
<p>
Written by <PrismicText field={post.data.author.data?.name} />,
{isFilled.contentRelationship(post.data.author.data?.profession) && (
<PrismicText field={post.data.author.data.profession?.data.name} />
)}
</p>
);
}
Examples
Blog post authors
On a blog, you could have posts that reference their authors along with the author’s profession.
Add a content relationship field
On a Post type, add a content relationship field called
author
. Only allow linking Author documents on the content relationship.Select fields to include
Select the following fields to include in your API response:
name
profession.name
Display the author information
Use the author data in your blog post to display the author’s name and profession.
{ isFilled.contentRelationship(post.data.author) && ( <p> Written by <PrismicText field={post.data.author.data?.name} />, {isFilled.contentRelationship(post.data.author.data?.profession) && ( <PrismicText field={post.data.author.data.profession?.data.name} /> )} </p> ); }
Landing page testimonials
On a landing page, you could feature testimonials from your customers or clients.
Add a content relationship field
On a Landing Page type, add a group field called
testimonials
containing a content relationship field. Only allow linking Testimonial documents on the content relationship.Display the testimonials
Use the testimonial data in your landing page to display quotes with avatars.
<ul> {page.data.testimonials.map( (item) => isFilled.contentRelationship(item.testimonial) && ( <li key={item.testimonial.id}> <PrismicNextImage field={item.testimonial.data?.avatar} /> <PrismicRichText field={item.testimonial.data?.quote} /> </li> ), )} </ul>
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.
Add a content relationship field
On a Post type, add a content relationship field called
category
. Only allow linking Category documents on the content relationship.Display the category
Use the category data in your blog post to display the post’s category.
{ isFilled.contentRelationship(post.data.category) && ( <span>{post.data.category.data?.name}</span> ); }
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 posts = await client.getAllByType("post", { filters: [filter.at("my.post.category", "YksUgRIAACEA-UZD")], });
Nested menus
On a website, you could build a nested navigation menu.
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 and an icon field.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. The content relationship should only allow linking to Child Menu documents.Select fields to include
Select the following fields to include in your API response:
links.link
links.icon
Display the menu
Use the menu data to render your navigation with proper field checking.
<ul> {menu.data.child_menus.map( (item) => isFilled.contentRelationship(item) && ( <li key={item.child_menu.id}> <ul> {item.child_menu.data?.links.map( (linkItem) => isFilled.link(linkItem.link) && ( <li key={linkItem.link.url}> <PrismicNextImage field={linkItem.icon} /> <PrismicNextLink field={linkItem.link} /> </li> ), )} </ul> </li> ), )} </ul>
API response
Here is what a content relationship looks like from the Document API:
{
"author": {
"id": "XxnD3REAACYAk_CJ",
"type": "author",
"tags": [],
"slug": "ada-lovelace",
"lang": "en",
"uid": "ada-lovelace",
"data": {
"name": [
{
"type": "paragraph",
"text": "Ada Lovelace",
"spans": []
}
],
"profession": {
"id": "ZpqX7SFJJKEBl_VK",
"type": "profession",
"tags": [],
"slug": "mathematician",
"lang": "en",
"uid": "mathematician",
"data": {
"name": [
{
"type": "paragraph",
"text": "Mathematician",
"spans": []
}
]
},
"link_type": "Document",
"isBroken": false
}
},
"link_type": "Document",
"isBroken": false
}
}
The data
property’s contents is determined by the selected fields.