Blog plugin
Manages blog posts: listing, tag pages (/blog/tags/{tag}), a date archive (/blog/archive/{archive}) and an RSS feed (/blog/rss.xml).
Configuration (services.yaml)
Enabled under derafu.content.config.plugins.blog:
parameters:
derafu.content.config:
plugins:
blog:
path: 'resources/content/blog'
blogTitle: 'Blog'
postsPerPage: 10
| Option | Type | Default | Description |
|---|---|---|---|
path |
string | resources/content/blog |
Directory scanned for posts, relative to the website root. |
blogTitle |
string | Blog |
Title used for the blog’s own SEO metadata. |
blogDescription |
string | Thoughts, stories, and the latest from our world. |
Description used for the blog’s own SEO metadata. |
blogSidebarCount |
int | 5 |
Number of recent posts shown in the sidebar. |
blogSidebarTitle |
string | Recent posts |
Title of the recent-posts sidebar. |
include |
array of glob patterns | ['**.{markdown,md}'] |
Files considered content, relative to path. |
exclude |
array of glob patterns | [] |
Files excluded even if matched by include. |
postsPerPage |
int | 10 |
Posts per page in the listing. |
showReadingTime |
bool | true |
Whether to show the estimated reading time. |
feedOptions |
array | see below | RSS feed configuration (/blog/rss.xml). |
showLastUpdateAuthor |
bool | true |
Whether to show who last updated the post. |
showLastUpdateTime |
bool | true |
Whether to show when the post was last updated. |
tags |
array of strings, or string | [] |
Predefined tags for the blog. |
onInlineTags |
ignore|log|warn|throw |
warn |
What to do when a post uses a tag that isn’t in the predefined tags list. |
feedOptions
| Option | Type | Default | Description |
|---|---|---|---|
limit |
int | 10 |
Number of posts included in the feed: always the latest ones. |
maxLimit |
int | 50 |
Most posts a reader can ask for with ?limit=. A bigger number is reduced to this one. |
title |
string | Blog of {site} |
Overrides the feed title. By default it is built with the title of the website. |
description |
string | generic text | Overrides the feed description. |
copyright |
string | none | Copyright line of the feed. It is not written unless it is set. |
language |
string | none | Feed language, for example es-CL. It is not written unless it is set. |
sortPosts |
descending|ascending |
descending |
Order in which the posts are listed. The posts in the feed are always the latest ones. |
How the feed is built
- The feed holds the latest
limitposts, newest first unlesssortPostssays otherwise. It is not the whole blog: feed readers keep their own history, so older posts do not need to be in it. - A reader can ask for a different number with
/blog/rss.xml?limit=25. Only a whole number of at least1is accepted, never abovemaxLimit; any other value is ignored andlimitis used. /blog/rss.xml?tag=newsis a feed of the posts with that tag. It is the only filter that can be requested: any other parameter in the URL is ignored.lastBuildDateis the date of the newest post in the feed, so it only changes when a post is published.- The response carries
Cache-Control: public, max-age=300and two validators, so a reader that already has the current feed does not download it again:Last-Modified: the most recent update of any post in the feed (an edit to a post that is already in it counts, not only a new post). A reader that sendsIf-Modified-Sincewith that date, or a later one, gets304 Not Modifiedwithout a body. A date that is not in the HTTP format is ignored, and a feed with no posts has noLast-Modified.ETag(weak): calculated from what the feed is made of, without rendering it: the content of each post in it and their order, the options of the feed, the tag asked for, and the title and URL of the website. UnlikeLast-Modified, it changes when the options of the feed or the title of the website change, and when a post is edited without changing its update date. A reader that sends a matchingIf-None-Match(a list or*are accepted, and theW/prefix is not considered) gets304 Not Modified.- When a reader sends both
If-None-MatchandIf-Modified-Since, onlyIf-None-Matchcounts, as the HTTP specification says. - In both cases the
304is decided before rendering the posts, so it costs almost nothing. - A change in a template or in a translation is not part of the
ETag. When the format of the feed changes in the package,FEED_FORMAT_VERSIONofBlogControlleris raised so readers do not keep an old copy.
- The pages of the blog show a link to the feed in the side menu, and advertise it in the
<head>(<link rel="alternate" type="application/rss+xml">) so feed readers find it by themselves.
Content frontmatter
Blog posts use the generic content frontmatter, with one override:
| Field | Type | Default | Description |
|---|---|---|---|
hide_table_of_contents |
bool | true |
Overrides the generic default of false — blog posts hide the table of contents unless explicitly re-enabled. |
On this page
Last updated on 10/10/2026
by Anonymous