Set up a blog
Posts are ordinary pages. Grouping them in year folders keeps the tree tidy and gives you a natural archive.
-
Create an
articles/folder with a folder for the current year, and a post in it,articles/2025/hello-world.md:--- title: Hello, world date: 2025-01-01 description: The first post. --- This is my first post.The
dateorders posts in listings, and a date in the future keeps a post out ofbuilduntil that day (see Drafts). -
Give posts a frame with
articles/_layout.jsx. It wraps every page inarticles/, and the root layout wraps the result:(content) => <article class="post"> <h1>{page.title}</h1> <time>{page.date}</time> {content} </article> -
Add the blog's front page,
articles/index.jsx, listing posts by year, newest first. Year folders have no index file of their own, so they're grouping nodes withisDirset and their posts insubpages:data({ title: "Articles", layout: "_layout" }); <h1>Articles</h1> {pages("articles").filter(p => p.isDir).reverse().map(year => <section> <h2>{year.slug}</h2> <ul> {year.subpages.slice().reverse().map(post => <li><time>{post.date}</time> <a href={post.path}>{post.title}</a></li> )} </ul> </section> )}Setting
layout: "_layout"uses only the root layout for this page, since the post layout would add a stray date heading.For a flat list instead, one call reaches every post however it's nested:
{pages("articles/**").reverse().map(post => partial("_partials/card", post))} -
Add a feed.
articles/feed.xml.jsxbuilds/articles/feed.xml; the full template is in Non-HTML pages and feeds . SetsiteURLin your root_defaults.jsxso the feed can build absolute links, and advertise the feed from the root layout's<head>:<link rel="alternate" type="application/rss+xml" title="Articles" href="/articles/feed.xml" /> -
Run
taragen serveand open/articles.