Posts are for a blog, news or notices: pages that carry a date and are listed newest first. A post is built from blocks like any other page. It also has a few facts of its own, which are its date, author, excerpt, cover image and tags. Every post is wrapped in a post template, so the title, byline and related posts look the same across the whole blog.
After this chapter you can write and publish a post, show posts on a page, change how every post looks and add a field of your own, such as a subtitle.
/blog by default, so the post “Spring news” becomes /blog/spring-news. Leave Template as it is unless you have made another one.YYYY-MM-DD and separate tags with commas. Fields marked with a star are required, and publishing checks them.A draft appears in no list until it is published. The same panel has the page fields for search results and who may open the post (Search engines). A post without its own description or image uses its excerpt and cover.
The Post list block, in the Posts group, shows the published posts as cards, newest first. The starter blog page has one.
A new post appears in the list as soon as it is published. If you want a card of your own design, use a List of… block with Posts as its Source instead, and build one card from blocks (Pages and blocks).
Each post is drawn inside a post template, which holds everything the posts share. The default has a Post hero with the title and facts, a Post info line with the date, author and tags, a Page content block where the post's own blocks go, and Related posts at the foot.
To give some posts a different frame, press New post template on the Templates tab, build it, and set a post's Template field to it. Post hero, Post info, Post field and Related posts belong in templates. Post list can go on any page.
A site can keep more than the five standard facts. A developer adds a field in site.config.ts. Posts is one entry in the features list, and its fields option takes a function that receives the standard fields and returns the list to use. List a new field after the defaults:
features: [
posts({
fields: (defaults) => [
...defaults,
{ name: 'subtitle', type: 'text', label: 'Subtitle', required: false },
],
}),
],Restart the site. The field now appears in every post's own fields. A field's type is one of text, textarea, richtext, image, date, tags, select (with a list of options), boolean, number or url. Its name starts with a lowercase letter and uses letters, digits and underscores. It cannot be layout, template, title, description, ogImage or noindex.
To show the field, open the post template and add a Post field block. Under Field, pick it by its label. Label puts words before the value, such as “Reading time:”, and Hide when empty removes the block from posts that leave the field blank.
To make a standard field required, or optional, change it as you list the defaults. This example makes the author required:
features: [
posts({
fields: (defaults) =>
defaults.map((f) => (f.name === 'author' ? { ...f, required: true } : f)),
}),
],The date field, named publishedAt, must stay in the list.
Posts live under /blog unless the feature is given another path, such as posts({ path: '/news' }). Choose it before you write posts, because every post's address starts with it.
Posts are an optional feature. A site that was made without them needs one extra package and one entry in its configuration. Install the package:
pnpm add @jamiemcconnell/cms-postsThen import the feature and list it under features in site.config.ts, and restart the site. No migration is needed.
import { posts } from '@jamiemcconnell/cms-posts';
// Inside defineConfig({ ... }):
features: [posts()],