Directus is an increasingly popular headless CMS that provides developers with a powerful platform to manage their content using various relational database capabilities. One of the key aspects of content management is the ability to link related content, which can enhance user experience and SEO by providing contextually relevant articles or multimedia content links. This article will serve as a detailed guide on how to add and manage related content in Directus.
As a modern touch, we'll also mention a sophisticated feature used by Wisp CMS, which employs AI to automatically suggest related articles. To learn more about these advanced capabilities, you can visit Wisp Related Blog Post Feature.
Understanding Relationships in Directus
Before diving into the step-by-step guide, it is crucial to understand the types of relationships that Directus supports and how they can be utilized to create an effective data model.
Types of Relationships in DirectusMany-to-One (M2O):
Definition: Multiple items in the parent collection link to one item in a related collection.
Example: Cities belong to a country, but a country can have many cities.
Configuration: Add a foreign key field in the parent collection (e.g.,
country_id
in cities).Usage Note: An M2O relationship requires just one column within the parent table.
One-to-Many (O2M):
Definition: The same relationship as M2O, but viewed from the perspective of the related collection.
Example: From the country perspective, it can list all its cities.
Configuration: Create an O2M alias field to access items from the parent collection.
Usage Note: Configuring an O2M creates a field, which lets us access related items.
One-to-One (O2O):
Definition: One item from the parent collection links to one item in the related collection.
Example: Each country has one capital city.
Configuration: Achieved by configuring an M2O to store unique values.
Usage Note: Directus does not include a dedicated O2O relationship type or Interface.
Many-to-Many (M2M):
Definition: Both collections can have multiple relationships, necessitating a junction table.
Example: Recipes can have multiple ingredients, and ingredients can belong to multiple recipes.
Configuration: Create an M2M alias field and a junction collection to store relationships.
Usage Note: A M2M relationship is stored within an additional table, called a junction table.
Many-to-Any (M2A):
Definition: Links items from the parent collection to any item in any collection.
Example: Page builders that combine various content types (text, images, videos).
Configuration: Includes a matrix field to store collection names.
Usage Note: A M2A relationship allows linking items from the parent collection to any item in any collection in the database.
Translations (O2M):
Definition: Designed specifically for handling translations.
Configuration: Creates a junction collection for translations along with an alias field.
Example: Articles can have translations for different languages.
Usage Note: It is called the Translations O2M because we interact with the Translations O2M alias field.
Step-by-Step Guide to Adding Related Content
Mapping Your Data ModelBefore creating relationships, you need to map out your data model. Identify the types of blocks or sections that you wish to relate. Common sections include:
Hero Block: A block that contains a headline, an image, and a call to action.
Card Group Block: A collection of content cards that link to other content like blog posts.
Rich Text Block: Block containing formatted text or HTML content.
Example Data Model Breakdown:
Hero Block Fields:
id
(uuid)headline
(String)content
(Text)buttons
(JSON)
Card Group Block Fields:
id
(uuid)headline
(String)content
(Text)group_type
(String)
Create the Hero Block Collection:
Navigate to the Content module.
Click on "Create Collection".
Name it
hero_block
.Add fields like
id
,headline
,content
, andbuttons
.
Create the Card Group Block Collection:
Similarly, create a collection named
card_group_block
.Add fields such as
id
,headline
,content
, andgroup_type
.
Create the Rich Text Block Collection:
Create another collection named
rich_text_block
.Add fields including
id
,headline
, andcontent
.
In most cases, you'll want to configure Many-To-Any (M2A) relationships to link different types of content blocks.
Steps to Configure M2A Relationships:
Create the M2A Field:
In the
pages
collection (or equivalent where you want to use related blocks), create a new M2A field namedblocks
.Set up the related collections to include
hero_block
,card_group_block
, andrich_text_block
.
Linking Content:
Navigate to the data entries of the
pages
collection.While creating or editing a page, add blocks via the
blocks
field, choosing from the created collections.
Managing related content involves linking articles or other content entities, making them easier to associate and manage.
Adding Items to Collections:
Populate the
hero_block
,card_group_block
, andrich_text_block
collections with relevant content entries.
Associating Related Articles:
While adding a new article or blog post, use the M2A field
blocks
to add related content items from the created collections.
Example: If you have a blog post about "Healthy Recipes", you could link a Hero Block with a catchy headline, a Card Group Block displaying various recipe links, and a Rich Text Block detailing nutritional information.
Fetching Related Content Using Directus APIFetching related content can be done efficiently using the Directus API.
Sample API Request:
import { createDirectus, rest, readItems } from '@directus/sdk';
const directus = createDirectus('https://directus.example.com').with(rest());
const slug = 'the-ultimate-guide-to-rabbits';
const pages = await directus.request(readItems('pages', {
filter: { slug: { _eq: slug } },
fields: ['*', { blocks: ['*', { item: { block_hero: ['*'], block_cardgroup: ['*'], block_richtext: ['*'] } }]}],
limit: 1,
}));
This request fetches the page details, including the nested related content blocks.
Managing Content Translations
Managing translations is also essential for providing a multi-lingual content experience. Directus offers a structured way to handle translations.
Steps for Managing Content TranslationsCreate the Languages Collection:
Navigate to the Data Model settings.
Create a new collection named
languages
with fieldscode
,name
, anddirection
.
Create the Articles Collection:
Create a collection
articles
with initial fields likeid
,status
,image
,author
, anddate_published
.
Create the Content Translations Collection:
Create a junction collection
content_translations
with fields for each translatable attribute (title
,slug
,summary
,content
).Ensure this collection links to both
languages
andarticles
.
Example API Fetching:
const pages = await directus.request(readItems('articles', {
deep: { translations: { _filter: { _and: [{ languages_code: { _eq: 'en' } }, { slug: { _eq: slug } }] } } },
fields: ['*', { translations: ['*'] }],
limit: 1,
}));
This fetches the content in the desired language, facilitating multi-lingual content management.
Conclusion
Adding and managing related content in Directus involves understanding the relationship types and configuring them effectively within your data model. In this article, we outlined how to create and manage relationships, specifically using Many-To-Any (M2A) relationships and handling translations.
Directus's flexible nature allows comprehensive content management systems to cater to various needs. However, for those looking to simplify the process further, tools like Wisp CMS, which employ AI to automatically suggest related articles, provide an advanced solution.