Who this is for. The content modeller at the start of a build, deciding where each kind of content goes. Afterwards you can place a new kind of content with a reason, and recognise the content that needs a custom entity instead.
The questions that decide
| If the content is | Use | Because |
|---|---|---|
| A hub, a landing page or a section that readers navigate | Pages | A tree with nested URLs, breadcrumbs and children, and a layout per page |
| Read in order, each part assuming the last | A book | Units and pages in a fixed order, with page numbers for progress |
| Dated and found by search or browsed newest first | Blog posts | A paged listing by tag, category and author, and an RSS feed |
| A symptom and its answer | FAQ questions | One answer at one URL, listed on every FAQ page where it applies |
| Many items with the same fields, listed, filtered and linked to each other | Custom entity records | A type of your own, with its own listing and detail routes |
This site uses four of the five: the landing pages are pages, the guides are books, the How-to library is a blog and Troubleshooting is FAQ.
A marketing site section
A "Services" section: six offerings, a pricing page and a landing page that introduces them.
Use pages. The section is a tree: the landing page lists its children with getChildren(), the URLs say where each page belongs (/services/consulting), and breadcrumbs come from getAllParents(). Nothing is read in order and nothing is dated. The content is composed by an editor from components, which is what a page layout is for, and each offering can use a different layout if it needs one. (Pages and the page tree)
A structured course
Twelve lessons in four modules, read in order, with a test at the end of each module and a certificate when the course is passed.
Use a book for the lessons and custom entities for everything with state. The lessons are book pages: a fixed order, units for the modules, getPositionInBook() for "lesson 7 of 12", and a contents list from getUnits() and getPages(). But "this learner passed module 2 on 3 March" is not content. It is a record with fields (learner, course, score, pass date) that belongs to no page tree and is read by one person, which is the definition of a custom entity. The tests hang off that record as children, and a job issues the certificate. (Worked example: a course catalogue)
A product knowledge base
Two hundred answers, browsed by product and found by symptom.
Use FAQ. Each answer is a question with one canonical URL. One FAQ page per product area lists the questions that apply to it, and a question that applies to two areas is listed on both without being copied. Tags carry the symptoms and categories the product tree, and /faq/questions/tags/... gives a filtered list for free. A blog would add dates nobody wants; pages would give two hundred leaves of a tree with no listing. (FAQ pages and questions)
When none of them fits
The built-in types are shaped around reading. When the thing you are modelling has its own fields that every instance shares, needs its own listing, and does not belong in the page tree, because its URL should say what it is rather than where it sits, it is a custom entity: stores, people, events, courses, enrolments. When a custom entity beats a page gives the test and three cases.
Two signs that a type was chosen for its free features rather than its shape: blog posts whose dates mean nothing, and pages whose only job is to hold the same five fields as their siblings. Both are custom entities.