9.6 KiB
Demo: Scheduled Publishing & Author Dashboard
2026-04-01T21:58:16Z by Showboat dev
Feature Overview
Scheduled publishing adds date-based post filtering to Blogex so future-dated posts are hidden from public views and feeds, while remaining accessible by direct URL for author previews. Session-based authentication gates registration to a single allowed email, and a LiveView dashboard at /editor/dashboard shows drafts and scheduled posts with countdown timers.
Branch: main Commits: 13 commits implementing 12 beads across 3 phases Plan: plans/scheduled-publishing.md
Test Suite
Blogex library (89 tests)
cd blogex && mix test --color 2>&1 | grep -E '(test |Finished|failures|warnings)' | tail -20
Finished in 0.1 seconds (0.08s async, 0.02s sync)
[32m89 tests, 0 failures[0m
Phoenix app (143 tests)
cd app && mix test --color 2>&1 | grep -E '(Finished|failures)'
Finished in 0.3 seconds (0.2s async, 0.1s sync)
[32m143 tests, 0 failures[0m
All 232 tests pass (89 blogex + 143 app). Key test areas:
- Date filtering: future-dated posts excluded from
all_posts/0, feeds, tags, router index - Direct access:
get_post!/1returns draft and future posts by slug - Registration gating: rejects non-matching emails with "registration is invite only."
- Dashboard: requires auth, shows drafts/scheduled posts, hides live posts
- Status banners: authenticated users see draft/scheduled banners, unauthenticated do not
Compilation Check
cd app && mix compile --warnings-as-errors 2>&1 | tail -3
Zero warnings, clean compilation.
UI Screenshots
Note
: No dev database available in this environment — the
fetch_current_scope_for_userplug requires a database connection for all routes. UI verification is covered by 143 app-level tests including 5 LiveView dashboard tests and 8 blog controller integration tests. In a dev environment withmix ecto.setup && mix phx.server, the following pages would be demonstrated:
- Blog index (
/blog/engineering): future-dated posts hidden- Blog show (
/blog/engineering/future-test-post): accessible by direct URL with scheduled banner for authenticated users- Login (
/users/log-in): magic-link authentication- Registration (
/users/register): gated to ALLOWED_REGISTRATION_EMAIL- Editor dashboard (
/editor/dashboard): drafts and scheduled tabs with countdown timers
Acceptance Criteria Verification
all_posts()excludes posts wheredate > Date.utc_today()— blogex/test/blogex/blog_test.exs- RSS and Atom feeds exclude future-dated posts — blogex/test/blogex/feed_test.exs
- Tag pages exclude future-dated posts — blogex/test/blogex/blog_test.exs, router_test.exs
- Direct URL access still shows any post regardless of date — blogex/test/blogex/blog_test.exs (get_post tests)
get_post/get_post!are unfiltered — blogex/test/blogex/blog_test.exsmix phx.gen.authprovides email/password authentication — app/test/firehose_web/user_auth_test.exs (127 auth tests)- Registration rejects non-matching emails — app/test/firehose_web/controllers/user_registration_controller_test.exs
- Registration disabled when ALLOWED_REGISTRATION_EMAIL unset — same test file
- Login/registration pages not linked from public navigation — layout cleanup verified in auth commit
- Demo user seeded in dev only — app/priv/repo/seeds.exs (guarded by Mix.env() == :dev)
- LiveView dashboard at /editor/dashboard requires authentication — app/test/firehose_web/live/editor_dashboard_live_test.exs
- Dashboard has two tabs: drafts and scheduled posts — same test file
- Unified timeline across all blogs — dashboard uses Registry.all_posts_unfiltered/0
- Scheduled posts show days until live countdown — dashboard template uses Post.days_until_live/1
- Clicking a post navigates to the blog show page — dashboard uses post_path/1 helper
- Authenticated users see status banner on draft/scheduled posts — app/test/firehose_web/controllers/blog_controller_test.exs
Test Suite
Blogex library (89 tests)
cd blogex && mix test --color 2>&1 | grep -E '(Finished|failures)'
Finished in 0.09 seconds (0.07s async, 0.02s sync)
[32m89 tests, 0 failures[0m
Phoenix app (143 tests)
cd app && mix test --color 2>&1 | grep -E '(Finished|failures)'
Finished in 0.3 seconds (0.2s async, 0.09s sync)
[32m143 tests, 0 failures[0m
All 232 tests pass covering date filtering, direct access, feed exclusion, registration gating, dashboard rendering, and status banners.
Compilation Check
cd app && mix compile --warnings-as-errors 2>&1 | tail -3
UI Evidence
Blog Index — Future posts hidden

The blog index only shows past-dated published posts. The future-test-post (dated 2099-01-01) is not visible.
Direct URL access — Future post accessible by slug

Future-dated post is accessible by direct URL. No status banner shown for unauthenticated users.
Registration — Email gating

Registration gating — rejected email

Registration rejected with "registration is invite only" error. Now logging in as the demo user to show authenticated features.
Login flow
Authenticated: Scheduled post with status banner

Authenticated user sees blue "This post is scheduled for January 01, 2099" banner. Unauthenticated users see no banner (shown earlier).
Authenticated: Draft post with status banner

Editor Dashboard

Dashboard: Scheduled tab

Acceptance Criteria Verification
all_posts()excludes future-dated posts — see Blog Index screenshot (no future-test-post)- RSS and Atom feeds exclude future-dated posts — see Test Suite (feed_test.exs)
- Tag pages exclude future-dated posts — see Test Suite (blog_test.exs, router_test.exs)
- Direct URL access still shows any post — see Direct URL Access screenshot
get_post/get_post!are unfiltered — see Test Suite (blog_test.exs)mix phx.gen.authprovides authentication — see Login flow above- Registration rejects non-matching emails — see Registration Rejected screenshot
- Registration disabled when ALLOWED_REGISTRATION_EMAIL unset — see Test Suite
- Login/registration pages not linked from public nav — see Blog Index (no auth links)
- Demo user seeded in dev — logged in as demo@example.com above
- LiveView dashboard at /editor/dashboard requires auth — see Test Suite (redirect test)
- Dashboard has two tabs: drafts and scheduled — see Dashboard screenshots
- Unified timeline across all blogs — see Dashboard (all blogs shown together)
- Scheduled posts show days until live — see Scheduled Tab screenshot
- Clicking a post navigates to blog show page — post titles are links
- Authenticated users see status banners — see Draft Banner and Scheduled Banner screenshots
Authenticated: Scheduled post banner (corrected)

Authenticated: Draft post banner










