Structuring content is hard when you’re starting a site or app, whether it’s a company website, an e-commerce app, or a landing page.
In this tutorial, you’ll design a scalable Strapi 5 content page builder using Strapi collection/single types, components, dynamic zones, and relations.
You’ll also see when to use each and how to accelerate with Strapi AI and Vercel v0.
By completing this tutorial, you'll
Content modeling is the process of defining and structuring content so it can be managed, reused, and delivered consistently across different platforms.
In simple terms, it’s about deciding what content you have, what fields it needs, and how it relates to other content.
As Marcelo Lewin, founder of Headless Creator puts it:
What are the benefits of content modeling? Why does it matter? Let's find out in the next section.
Content modeling benefits not only developers, but also editors, designers, and the business as a whole. It creates a shared foundation for how content is structured, stored, and delivered.
For content editors coming from tools like WordPress, content modeling in a headless CMS like Strapi can feel unfamiliar. The key difference lies in how content and presentation are handled.
Editors familiar with traditional CMS tools often ask: “Where’s the page builder?”
The answer: a headless CMS isn’t about static page design. It’s about creating flexible content models that can power any channel, now or in the future.
Where do you start when designing your content model? Let's explore the basics of content modeling in a headless CMS like Strapi.
"A headless CMS is the technology that makes this new way of managing content possible. Content modeling is the practice that ensures that your content's purpose is clear."
Those are the words of Larry Swanson from "Content Strategy Insights".
Content modeling gives purpose, and a headless CMS like Strapi gives it omnichannel delivery.
Strapi 5 is a headless CMS that provides powerful native content modeling features that are ideal for implementing a flexible page builder.
There are 2 different types of models in Strapi: 1. Content-types: For single and multiple entries. E.g., Collection types and Single types. 2. Components: Re-usable content structures in multiple content types.
Let's discuss them further.
A collection type is used for content that can have multiple entries (e.g., “Blog”, “Category”, "FAQ", "Page", etc., where you’ll have many instances).
A single type is used for one-off content pieces that exist only once (e.g., a single “Homepage Settings” or “About Us” content).
Fields are the smallest units of content (often referred to as attributes).
Strapi fields can further be grouped into:
Here are the fields you can find in your Strapi admin panel.
Components in Strapi are collections of fields that serve as reusable building blocks.
Instead of recreating the same fields repeatedly, you bundle them together. For example, an SEO component with metaTitle
, metaDescription
, and image
.
Components can also be nested (a “Button” inside a “Hero Section”). This promotes reuse and consistency.
A Strapi dynamic zone is essentially a special field type that allows an entry to hold a mix of different components and arrange them in any order.
You can think of a Strapi dynamic zone as a placeholder in your content type (like a “Sections” field) where editors can insert any number of predefined components.
In the image below, you can see components Hero
, Features
, Testimonials
, How_It_Works
, Brands
, and Pricing
as components inside the dynamic zone field called dynamic_zone
.
Relations connect content types together. They make content reusable across contexts without duplication.
There are 6 different types of relations in Strapi:
Understanding & using relations without overusing components is very crucial to content modeling.
To learn more about Strapi content models, visit the documentation page for Models.
When modeling content in Strapi, it’s not always obvious whether to use a collection type, a single type, a relation, a component, or a dynamic zone. Here’s a simple guide to help you decide.
In this section, we’ll build a Company Website content model in Strapi 5 using content modeling best practices.
The goal is to design a Company Website content model in Strapi. Here are the key steps:
By following these steps, you’ll get a blueprint for building your own flexible and maintainable page builder.
The diagrams below outline all collection types, single types, components, and dynamic zones:
Collection types, Single Types, Components, and Dynamic Zones
Complete Diagram
For a company website example, we will create the following collection types.
Dynamic zones are what make Strapi feel like a page builder for non-technical editors. Instead of hardcoding fields into every content type, you give editors a flexible toolbox of components they can mix, match, and reorder.
Now, let's design a company website content model in Strapi 5.
There are 3 ways to create content types in Strapi.
schema.json
) for content types in your project’s file structure, like the Category
collection type below:1{
2 "kind": "collectionType",
3 "collectionName": "categories",
4 "info": {
5 "singularName": "category",
6 "pluralName": "categories",
7 "displayName": "Category"
8 },
9 "options": {
10 "draftAndPublish": true
11 },
12 "pluginOptions": {},
13 "attributes": {
14 "name": {
15 "type": "string"
16 },
17 "slug": {
18 "type": "uid",
19 "targetField": "name"
20 },
21 "blogs": {
22 "type": "relation",
23 "relation": "oneToMany",
24 "target": "api::blog.blog",
25 "mappedBy": "category"
26 }
27 }
28}
For this article, we will use the Content-Type Builder in the Strapi admin panel.
The User collection type is automatically created by Strapi. We'll create the remaining collection types.
1.1 Create Country Collection Types
Begin by creating the Country collection type, which holds the fields name
and code
.
To do this: 1. Navigate to Content-Type Builder in the admin panel 2. Click "COLLECTION TYPES +" 3. Enter "Country" as the display name
5. Click "Continue"
6. Add these fields:
name
(Short text) and code
(Short text)
6. Click the "Save" button
You should now have the Country collection type as shown below:
1.2 Create Remaining Collection Types
Proceed to create other collection types.
Follow the same process and create these collection types:
Collection Type | Fields |
---|---|
User | Automatically created by Strapi |
Country | name (Short text), code (Short text) |
State | name (Short text), code (Short text) |
Blog | title (Short text), slug (Short text) body (Rich Text Markdown) banner (Single media) |
Category | name (Short text), slug (UID - set the attached field as name ) |
Tag | name (Short text), slug (UID - set the attached field as name ) |
Page | title (Short text), slug (UID - set the attached field as title ), content (Rich Text markdown). content is the main write-up of the page |
FAQ | question (Short text), answer (Long text) |
FAQ-Category | name (Short text) |
Team-Member | name (Short text), role (Short text), bio (Long text), photo (Media - Single media) |
Feature | title (Short text), description (Long text) linkText (Short text) linkUrl (Short text) icon (Single Media) |
NOTE:
User
comes from the users-permissions plugin; you don’t create it.
You should have the complete collection types created in your Strapi admin panel, as shown in the image below:
Let's move further with creating reusable components. Components require a name and category.
Categorizing components properly is key to keeping your Strapi content model organized and intuitive for editors.
2.1 Create Address Component
streetNumber
(Number), streetName
(Short text, required), city
(Short text, required)This is what the "Address" component should look like:
Proceed to create the other components.
2.2 Create Additional Components
This is a summary of the components you should create:
Component | Category | Icon | Fields |
---|---|---|---|
Address | Shared | 📍 | streetNumber (Number), streetName (Short text), city (Short text), geoLocation (JSON or Coordinates) |
SEO | Global | 🔍 | metaTitle (Short text), metaDescription (Long text), keywords (Long text), canonicalUrl (Short text) |
Footer | Global | 📄 | logo (Media - Single media), copyright (Short text) |
Header | Global | 📄 | logo (Media - Single media) |
Link | Shared | 🌐 | label (Short text), url (Short text) icon (Single Media) |
Single Types in Strapi are meant for singleton content. You should use single types when you only need one entry across the entire system.
Single Type | Fields and Components |
---|---|
GlobalSettings | siteName (Short text), companyName (Short text), logo (Media - Single), |
Later on, we will add components such as a footer
field for the Footer
component, defaultSEO
for the SEO
component, and a few other components.
Here is what the GlobalSettings
single type should look like:
Dynamic Zones in Strapi let you build flexible pages by stacking predefined page section components in any order.
4.1: Create Dynamic Zone Components
Start by creating the components below. Remember to categorize them as dynamic zones.
Component | Category | Icon | Fields |
---|---|---|---|
HeroSection | Dynamic-Zone | 🖼️ | title (Short text), subtitle (Long text), image (Media - Single), ctaText (Short text), ctaUrl (Short text) |
Feature | Dynamic-Zone | ⭐ | title (Short text), description (Long text), icon (Media - Single), linkText (Short text), linkUrl (Short text) |
Testimonial | Dynamic-Zone | 💬 | quote (Long text), authorName (Short text), authorRole (Short text), authorPhoto (Media - Single) |
FAQBlock | Dynamic-Zone | ❓ | title (Short text) |
The title
in the FAQBlock
above represents the title for a FAQ, e.g., “Frequently Asked Questions”, “Need help?”, or “Your Questions Answered”.
Recall that we also have the FAQ
collection type. This means we have to create a relational field between the FAQBlock
component and the FAQ
collection type, as we will see in the section for creating relations in Strapi.
Here is what the components for dynamic zones should look like:
We will add fields sections
and dynamic_zones
to the Page
and Blog
collection types. You can choose to name them based on naming conventions that are preferable to you.
Dynamic Zone | Used In | Components Allowed |
---|---|---|
sections | Page (Collection Type) | HeroSection , Feature , Testimonial , FAQBlock |
dynamic_zone | Blog (Collection Type) | FAQBlock |
In the table above, Blog posts only need the FAQBlock
and don't need hero sections, features, and testimonials.
Later on, as the website grows, you can add more components to the dynamic zones.
5.1 Add Dynamic Zone to Page Collection Type
sections
dynamic-zone
category.This is what the Page
collection type should look like after adding a dynamic zone.
👋 NOTE You can create a dynamic zone on the fly with new components without having to initially create components.
Next, create the dynamic zone for the Blog
collection type.
5.2 Add Dynamic Zone to Blog
Collection Type
dynamic_zone
like we mentioned earlierFAQBlock
component (blog posts don't need hero sections or features)As needs increase, you can add other components to this dynamic zone.
As mentioned earlier, we haven't added relations that should be present inside collection types, single types, components, and dynamic zone components. Let's do that in the next section.
Now, we will add some components we have created to content types where they are needed.
6.1 Add Components to Components
As discussed earlier, the Link
component can be reused inside the Header
, Footer
, CTAs, Social links, or anywhere links are needed. So, let's add the Link
component to the Header
and Footer
components we have created.
Footer
component in the Content-Type Builder.Component
field type.links
and select shared - Link
as a repeatable component.Proceed and do the same for the Header
component.
Component | Fields and Components |
---|---|
Footer | other fields..., links (Component →Link (Repeatable) |
Header | other fields..., links (Component →Link (Repeatable) ) |
6.2 Add Components to Single Types
Add the following components to the GlobalSettings
single type.
These components belong in GlobalSettings
because they represent structured, reusable global content blocks (SEO, footer, header, address, and social links) that ensure consistency and are managed centrally in one place.
Single Type | Fields and Components |
---|---|
GlobalSettings | other fields...,footer (Component → Footer (Not Repeatable)),header (Component → Footer (Not Repeatable)), defaultSeo (Component → SEO (Not Repeatable)), socialLinks (Component → Link (Repeatable)), address (Component → Address (Not Repeatable)) |
6.3 Add Components to Collection Types Add the following components to collection types.
Collection Type | Fields and Components |
---|---|
User | other fields...,address (Component → Address (Not Repeatable)) |
Page | other fields...,seo (Component → SEO (Not Repeatable)) |
Blog | other fields...,seo (Component → SEO (Not Repeatable)) |
Relations connect content types and enable content reuse.
7.1 Create FAQ to FAQ-Category Relation
We will create a field called category
inside the FAQ
collection type that will be a many-to-one relation with FAQ-Category
.
This means that many FAQs belong to one FAQ category.
FAQ
collection typecategory
for the FAQ
collection type.FAQ-Category
as the target relation. Give the FAQ-Category
field name as faqs
(inverse name). This is what the FAQ
and FAQ-Category
should look like:
The FAQ
collection type has a manyToOne
relation with the FAQ-Category
collection type. Whereas, the FAQ-Category
has a oneToMany
relation with the FAQ
collection type.
6.2 Create All Relations Now, create the following relations.
Relations for Collection Types
Source | Field | Target | TypeDescription |
---|---|---|---|
FAQ | category | FAQ-Category (inverse: faqs ) | Many-to-one — many FAQs belong to one FAQ-Category; the FAQ-Category has many FAQs. |
Blog | author | User (inverse: blogs ) | Many-to-one — many Blog posts belong to one User (author); a User has many Blogs. |
Blog | category | Category (inverse: blogs ) | Many-to-one — many Blogs belong to one Category; a Category has many Blogs. |
Blog | tags | Tag (inverse: blogs ) | Many-to-many — many Blogs relate to many Tags; Blogs has and belongs to many Tags. |
Page | features | Feature (no inverse) | manyWay — a Page can have many feaures |
NOTE: Ensure
User
is User (from: users-permissions)
Relations for Components
Source | Field | Target Collection Type | TypeDescription |
---|---|---|---|
Address | state | State | One-way — Address references one State ; no inverse field on State . |
Address | country | Country | One-way — Address references one Country ; no inverse field on Country . |
FAQBlock | faqs | FAQ | Many-way (one-way many) — FAQBlock references many FAQ entries; no inverse field on FAQ . |
The complete content model for the company website example can be found here.
Let's explore some content modeling pitfalls and best practices.
1// BAD
2SEO (Collection Type)
3 - metaTitle
4 - metaDescription
5
6// GOOD
7SEO (Component)
8 - metaTitle
9 - metaDescription
1// BAD: Deep nesting chain
2LandingPage
3 - pricing (Component)
4 - plans (repeatable Component)
5 - services (relation)
6 - link (Component)
If you hit the 2-level limit, reconsider the structure rather than forcing it in schema.json. 6. Optimize API Queries Query only the fields you need. Don’t fetch everything. Use filters, sorting, and population selectively to reduce performance costs.
1// BAD
2GET /api/blogs?populate=*
3
4// GOOD
5GET /api/blogs?populate=author
You can learn how to query, populate, and filter data in Strapi using this tutorial.
1// BAD
2SiteSettings (Collection Type) // multiple entries created by mistake
3
4// GOOD
5SiteSettings (Single Type) // only one global entry
HeroSection
, Testimonial
, FAQBlock
). Keep the set curated and avoid deep nesting inside those components.With AI tools on the rise, can we speed up content modeling and development? The answer is "Yes!".
In the next section, you will use Strapi AI and Vercel v0 to speed up content modeling implementation in Strapi and frontend generation using Vercel v0.
With Strapi AI, which is basically for content modeling, you can build your content structure in minutes.
You can generate a complete content schema with Strapi AI in the following ways:
In this section, we will chat and upload an image of the content model we created earlier in this article.
In this tutorial, you will only upload the image diagram of the content models we have created in this tutorial and ask the Strapi AI to implement it.
Chat with Strapi AI using the following prompt:
1Generate the content types for a company website using the attached images.
Strapi AI will go ahead to automatically create the content types for a company website, as shown in the GIF below.
You can take a step further to customize your content type by chatting with the Strapi AI.
With Vercel v0 you can do a whole lot of amazing things. For example, you can Build a Landing Page with AI and Next.js using v0.
Although this might not be the best approach, we can do it in 3 steps.
Install the Strapi API Documentation plugin from the Strapi plugin marketplace to create an OpenAPI Document and visualize your API with SWAGGER UI on port: http://localhost:1337/documentation/v1.0.0
Visit the v0 by Vercel page at v0.app.
We will ask v0 to create a frontend for the company website using the API documentation link and the image diagrams of the content models.
1Using the following documentation: http://localhost:1337/documentation/v1.0.0
2and content model diagrams attached, create the frontend of a company website.
NOTE The
localhost
server isn't accessible from the v0 environment. You should have a production server so that v0 can access your documentation.
For production usecases, it is recommended to deploy your Strapi app to Strapi cloud as shown below. That way, you can preview your Strapi app live!:
v0 will take a while to create the frontend as shown above.
After successful generation, you can export your code through your console: npx shadcn@latest add <link to project>
or as a ZIP file and customize the frontend to use your Strapi backend!
To learn more, visit the blog post: "Building the Future Web: Best Practices with Strapi, Nextjs, & v0".
Content modeling is the foundation for building scalable projects. By carefully structuring your data using collection types, single types, components, relations, and dynamic zones, you create a model that works for everyone and for the future.
In this tutorial, we walked through creating a complete company website model in Strapi 5. We also explored how Strapi AI can accelerate content modeling and how tools like Vercel v0 can instantly generate a frontend using your content model.
Next Steps:
To learn more about content modeling and how to structure data, watch the video below:
Theodore is a Technical Writer and a full-stack software developer. He loves writing technical articles, building solutions, and sharing his expertise.