Skip to main content
← All articles
craft cms

Entry types, Matrix, and why Craft 5 quietly out-designed Paragraphs

Entry types, Matrix, and why Craft 5 quietly out-designed Paragraphs

The part of Craft CMS that genuinely impressed me — as someone who's modeled a lot of content in Drupal — is how it handles structured content. Drupal taught me to juggle nodes, paragraphs, blocks, and media, each a separate entity type with its own query API and its own quirks. Craft 5 looked at that pile and made one decision Drupal hasn't: it collapsed almost all of it into a single primitive. Everything is an entry.

The building blocks

Craft 5's content model is three things composed together:

  • Fields — reusable, and (the nice part) with per-layout overrides: the same field can appear in many places, each overriding its label, handle, instructions, required-ness, and width independently. The recommended practice is to build a handful of generic primitive fields named by data type and compose from them, rather than a new field per use.
  • Entry types — in Craft 5 these became global, top-level objects. Define "Article" once and assign it to as many sections and Matrix fields as you like, with no duplication.
  • Field layouts — how fields are arranged on a given entry type.

If you're from Drupal that maps almost one-to-one onto content types and fields — until you hit Matrix.

The Matrix move: blocks are just entries

This is the design choice worth the whole post. Drupal's answer to repeatable structured components is Paragraphs — a separate entity type, with its own API and its own view-mode dance. Craft used to have something similar (a dedicated MatrixBlock element). In the Craft 5 upgrade, they removed it and converted Matrix blocks into ordinary entries. "Block types" are now just entry types. Nested entries are owned by their parent, queryable like any other entry, can have their own field-layout overrides, versioning, even their own URLs.

The templating follows: there's no separate block API, you just query entries by type —

{% for block in entry.pageBuilder.type('imageBlock').all() %}
  {# render an image block #}
{% endfor %}

Same query language, same field layouts, same permissions, same versioning — everywhere. That's real conceptual economy. In Drupal, a nested component is a different kind of thing than the page it sits on; in Craft 5, it's the same kind of thing, all the way down.

Drupal's content model is powerful by accumulation — a dozen entity types you learn one at a time. Craft 5's is clean by design — one primitive, reused. Coming from Paragraphs, "it's just an entry" felt like someone had deleted a category of problems.

Where Craft gives something up

I don't want to write a fan post, so here's the honest other side. Under the hood, Craft moved custom field content into a single JSON content column keyed by field handle (which is exactly what makes cross-context field reuse possible and removes the old per-field column limits). Convenient — but it makes raw-SQL reporting against field values harder than Drupal's per-field tables. You lean on element queries, not SQL, and if you're used to just JOINing a field table for a quick report, that habit's gone.

Two more things a Drupal dev will miss: there's no Views UI — you build listings in Twig, by hand, which is more honest but less point-and-click; and Craft has nothing like Drupal's sprawling contrib field-type and view-mode ecosystem. Paragraphs, for all its clunk, is battle-tested at enormous scale with a huge module ecosystem around it. Craft's model is cleaner; Drupal's is deeper.

The verdict

For the kind of component-driven page building most projects actually do, Craft 5's "everything is an entry" is the better idea, full stop — it's less to learn, less to special-case, and it makes nesting trivial to reason about. Coming from Drupal, the adjustment isn't conceptual (fields and types are fields and types); it's giving up Views and the SQL-shaped reporting reflex, and trusting element queries instead. A week in, I didn't miss them as much as I expected.

Links

BM
Blue Moose
The moose behind Blue Moose. Full-stack PHP developer — Drupal by day, Symfony by night, tests always.