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 limit posts, newest first unless sortPosts says 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 least 1 is accepted, never above maxLimit; any other value is ignored and limit is used.
  • /blog/rss.xml?tag=news is 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.
  • lastBuildDate is 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=300 and 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 sends If-Modified-Since with that date, or a later one, gets 304 Not Modified without a body. A date that is not in the HTTP format is ignored, and a feed with no posts has no Last-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. Unlike Last-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 matching If-None-Match (a list or * are accepted, and the W/ prefix is not considered) gets 304 Not Modified.
    • When a reader sends both If-None-Match and If-Modified-Since, only If-None-Match counts, as the HTTP specification says.
    • In both cases the 304 is 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_VERSION of BlogController is 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