The best way to create components

Hey Dato community,

I’m wondering what the best way is to structure components in your CMS?

I was reading the documentation and saw that Blocks are recommended; however, Relations also look promising. Do you have any best practices to share, or does it depend on the project?

Thanks in advance for your help!

Hi @saprykinse,

Welcome to the Dato forums!

Can you please describe your use case here in more detail (like what you are trying to accomplish on the frontend)? “Components” can have a lot of different meanings…

If you’re trying to model something like a WYSIWYG page builder where you can have, say, a “Hero” component with a background image, a description, and a CTA button, all as one frontend <Hero/> component, then yes, you can model that as a block inside DatoCMS and let your editors use it to compose modular pages via drag-and-drop.

However… the answer isn’t quite that simple (it never is, right? :sweat_smile:)

It not only depends on the particular project, but also what your goals are, both for your frontend and your editors. While that example WYSIWYG page builder block system above is one way to model a schema, it’s not necessarily the “best” (or even most popular) way of doing it. That’s how some customers think of a CMS, especially if they’re coming from the Wordpress / Wix / Squarespace etc worlds.

But in a headless system like ours, there doesn’t necessarily need to be a 1:1 connection between a frontend component and model or block in the CMS. In fact, more often than not, they can be quite different.

Let me give you a contrived example…

Let’s say your frontend is an ecommerce store (like our ecommerce demo that you can play around with), full of different products.

The same product would ideally be only defined one time inside DatoCMS, with all the fields you’d expect: name, price, images, etc.

And on a product page on your frontend, you’d just use those fields normally.

But maybe you also want to mention the product on other pages… like maybe you want to showcase it in a “business casual” collection. Inside DatoCMS, then, you’d make a new schema for that kind of “showcase” page, which can have its own fields (like a title and description). Then maybe it’d link to one or more specific products (via a multiple links field, probably). So far, you don’t need any blocks yet.

But then maybe you also want a blog section where you can write long-form articles, maybe something like a “best of” type of article. But you want your editors to have more editorial control over the page content, being able to intersperse text, images, links to other pages… but also the occasional product. THAT’s when blocks would be useful. You can compose the blog page out of different blocks inside a “structured text” field, which allows your editors to write in a powerful WYSIWYG system that allows allows the use of blocks and linked records. That way they can easily intersperse regular text alongside product links, hero blocks, carousel blocks, etc. Those particular blocks could correspond to frontend components (via our <StructuredText/> helper component for React and its “custom renderers” — they let you define how to a certain block’s schema and fields should be rendered on the frontend).

So in the end, a project would end up with a healthy mix of fields, records, blocks, and links/relationships. They each have a certain purpose and they’re meant to complement each other for different use cases. Most projects use all of them in different ways.

If you’re just exploring DatoCMS, I would recommend playing with our starter projects (Project starters - Free demo projects - Marketplace) to see how a typical project might be hooked up.

If you have a specific kind of project or use case in mind, please also feel free to email us at support@datocms.com (or just post the details here) and we can help you brainstorm through a schema design, if that would help.

Does that answer your concerns? If there’s anything I can clarify, please let me know :slight_smile:

Hi @roger,

Thank you very much for such a detailed response.

I came from the Contentful world and found your CMS to be a step forward in comparison. In Contentful, we used Components (e.g., Hero, Features, FAQ, CTA, Pricing etc) as references. I noticed in your documentation that all these types are described as best used as Blocks.

Do you think using references(links) in Dato is considered a bad practice for these use cases, or are Blocks simply a more powerful solution? Or is it mainly a matter of usability?

Thanks in advance for your response!

The primary difference between a block and a linked record is reusability.

A record has its own independent lifecycle. It exists on its own, and can be linked/referenced from other records. It would make sense to use a record whenever you expect to re-use the same content across several components or pages, like a “Who is Saprykinse?” FAQ entry or a “Join our mailing list!” CTA record that may be present across many other pages/records/components. Having just that one record would simply future updates, so that you can change the FAQ entry or CTA record just once, as a single source of truth, and all the pages that use it will be updated.

Blocks, on the other hand, don’t have their own lives. They are merely ephemeral “sub-fields” within an existing record. If your “FAQ page” record has a bunch of “FAQ entry” blocks within it, no other record is able to link to a single block. They can link to the overall page record, but the block within it is basically set of fields. If you delete the record, all the blocks disappear too.

On which specific doc page or video?

It is probably referring to them that way in the WYSIWYG page builder context, like if you wanted to make a drag-and-drop editor (using structured text) where your editors can add and rearrange heroes/CTAs/etc on a single page. That makes sense in that particular case since those blocks are 1:1 representations of how that one single page would appear on the frontend.

But in other use cases, where a single piece of content is expected to be used in a bunch of places, a record might make more sense.

Do you want to give me an example of a project you might want to build, and I can talk about that use case more specifically? It all just depends on the specific project and model and editor/developer needs. It’s not a case where you must choose either blocks or linked records… they work together in different parts of the same project :slight_smile:


In more complicated setups, a more advanced “hybrid” option is also possible. Let’s say you have some CTAs that would be used in multiple places (like a generic email sign), and others that would be used only on a single page (like a sale for a specific product).

In that case, you might do something like this (just an example):

  • Create a CTA block that has fields for headline, description, button text, and button URL fields

  • Make that block available in your “post” and “page” models, where they would be used as one-offs

  • But also make a new model, “Reusable CTAs”, with a single-block field… that basically just “wraps” the CTA block inside a record, making it essentially reusable (but still keeping the block’s same schema).

    Alternatively, that new model could also just re-create fields of the same name.


Confused yet? Lol, sorry… there isn’t just “one right way” to do any of this. It really depends on your specific needs. I don’t want to overcomplicate things, so the takeaway would probably be this:

  • You can use a block whenever you want a reusable set of fields within one single record, knowing that those blocks won’t be linkable/referenceable from anywhere outside that record
  • If you have a piece of content that will be referenced elsewhere, it should be its own record instead (or a record wrapping a block, as per the “advanced” example)

One noteworthy exception: One technical limit is that each record usually has a 600 block limit by default. Like if you were making a huge page with a lot of entries (say, a product listing page where each product would be its own block) and/or a lot of localizations (which each would need their own set of blocks), it is better to make those 600+ items as separate records instead — just to avoid system limitations. This only matters if you’re using hundreds of blocks per locale, otherwise you generally don’t have to worry about that.

Anyway… if you can share with me more details about what exactly what you’re trying to model (feel free to email us or DM me if it’s private), I can help you think through some possible schema options?

Thank you!

@roger

Thank you for an amazing guide! I think ‘hybrid’ sounds pretty cool. I’m going to dive deeper and explore more by trying different approaches.

Thanks again — cheers! raised_hands:

1 Like