This post was generated by a coding agent, after using the demo skill to make a demo using Rodney and Showboat (thanks Simon Willison). I find it fun and useful to see this, gives some indication of what went in.
There is a note at the bottom about tools used and the number of phases.
As the agent wrote:
Posts in Firehose are markdown files with a date in the filename. Until now, every published post was immediately visible. That changes today: posts with a future date are now hidden from public views until their date arrives.
This was built in a single session using an agentic dev team – 12 issues tracked in beads, executed in three parallel phases, producing 232 tests across the blogex library and Phoenix app.
What changed
Future-dated posts are hidden from public views
The blog index, tag pages, RSS feeds, and Atom feeds now filter out posts where the date is after today. If you schedule a post for next Tuesday, readers won’t see it until then.
But here’s the key design choice: direct URL access still works. If you know the slug, you can view the post. This lets authors share preview links with reviewers before the publish date.
Status banners for authors
When you’re logged in, draft and scheduled posts show a status banner so you always know what state a post is in. Unauthenticated visitors see nothing – no clue the post isn’t “live” yet.
Scheduled posts show a blue banner with the target date:
Draft posts (unpublished) show an amber banner:
Editor dashboard
A new LiveView at /editor/dashboard gives authors a unified view of all non-live content across every blog. Two tabs: drafts and scheduled posts. Scheduled posts show a “days until live” countdown.
The dashboard requires authentication – unauthenticated users are redirected to the login page.
Authentication and registration gating
We added mix phx.gen.auth for session-based authentication with magic links and password login. Login and registration pages are accessible by direct URL only – they’re intentionally not linked from the public navigation.
Registration is gated to a single email via the ALLOWED_REGISTRATION_EMAIL environment variable. Anyone else gets a polite rejection:
When the environment variable isn’t set, registration is disabled entirely. A demo user (demo@example.com) is seeded in dev for local testing.
How it was built
The feature was planned as an Allium specification with surfaces, rules, and domain entities, then broken into 12 beads (issues) across three phases:
- Scheduled posts (5 beads): date filtering in blogex, unfiltered direct access, feed/router verification
- Authentication (3 beads): phx.gen.auth scaffolding, registration gating, dev seed
- Dashboard (4 beads): post visibility helpers, unfiltered registry access, LiveView dashboard, status banners
All 12 beads were executed with parallel agentic workers in isolated git worktrees, then merged and integrated on main. The demo caught one bug (auth check using current_user instead of current_scope) which was fixed before this post.
By the numbers
- 232 tests passing (89 blogex + 143 Phoenix app)
- 12 beads planned, executed, and closed
- 3 phases run with parallel workers
- 0 compiler warnings