WebGrid blog posts can now live in subfolders, and that change ended up cleaning up more than just file organization.
This release also tightens blog ordering, adds a temporary web toggle for non-public post states, and makes frontmatter validation stricter so broken titles fail during checks instead of slipping through quietly.
What shipped
- Recursive blog loading now supports nested folders under
content/blog/ - Blog routing now supports nested slugs through a catch-all post route
- Blog sorting stays date-first, with same-series same-day posts staying grouped by series order
- The blog index now has a checkbox to reveal draft, private, and archived posts
- Blog frontmatter validation now errors when an unquoted
titlecontains: - Reusable release notes now have a dedicated template file outside the blog feed
Why this matters
Before this change, blog content was effectively trapped in one flat folder, and the minute we started writing Building in Public posts in subfolders the routing assumptions showed up fast.
That also exposed a second problem: the blog flow had a few hidden rules that were too brittle. Sorting behavior mixed date with other grouping assumptions, invalid frontmatter could sneak by because the parser was too permissive, and there was no temporary way to inspect non-public posts in the web UI.
Now the blog system behaves more like an actual publishing system instead of a folder convention that happened to work. Posts can be organized into nested paths, routes match that structure, date stays the primary sort signal, and frontmatter mistakes fail loudly enough to catch before release.
Changelog
Blog subfolders now work end to end
The blog loader now walks nested directories under content/blog/, and post slugs are generated from the relative folder path instead of assuming every file lives at the top level. Routing was updated to a catch-all blog post page so nested content resolves correctly on the site.
Sorting now stays anchored to publish date
The blog flow now treats date as the primary ordering rule. When multiple posts from the same series land on the same day, the series still keeps its internal entry order so grouped posts do not shuffle into nonsense.
Non-public statuses are temporarily visible from the web index
The blog index now includes a checkbox that reveals draft, private, and archived posts. It is a temporary inspection tool, not a final publishing model, but it gives immediate visibility while the longer-term content-status plan is still open.
Frontmatter validation is stricter now
If a blog post uses an unquoted title with :, checks now fail. That is intentional. It catches invalid YAML-like frontmatter before a bad title turns into a parsing edge case later in the build.
Validation snapshot
npm run checkshould fail on invalid blog frontmatter instead of silently accepting it- Blog routes now support nested paths like
building in public/... - The all-status toggle is intentionally temporary and only applies to the blog index for now
The short version
The blog now behaves like a real content system, not a flat-folder accident.