firehose/investigation/context.md
Firehose Bot fe156ef81e Add Dashboard nav link for authenticated users
- Add conditional "Dashboard" link in navbar that shows when a user is logged in
- Tests verify the link is hidden for unauthenticated users and visible when authenticated
- Investigation reports for Q1 (drafts/scheduled), Q2 (RSS), Q3 (email subs)
2026-07-06 09:11:13 +01:00

3.5 KiB

Codebase Context for Investigation

Project Structure

  • app/ - Phoenix LiveView application with blogs, user auth, editor dashboard
  • blogex/ - Multi-blog engine library (Blogex) with NimblePublisher-based markdown posts

Key Modules

Blog Config (app/lib/firehose/blogs/)

  • Firehose.EngineeringBlog - blog_id: :engineering, base_path: "/blog/engineering"
  • Firehose.ReleaseNotes - blog_id: :release_notes, base_path: "/blog/releases"

Blog Post System (blogex/lib/blogex/)

  • Blogex.Post - struct with fields: id, title, author, body, description, date, blog, image, tags, published
  • Post.visibility(post) returns :draft (published=false), :scheduled (future date), :live
  • Post.days_until_live(post) returns days until scheduled post goes live
  • Posts are compiled at build-time from markdown files in priv/blog/

Blog Module (blogex/lib/blogex/blog.ex)

  • Blogex.Blog - macro that uses NimblePublisher
  • all_posts() - returns published, non-future-dated posts (drafts excluded in prod)
  • unfiltered_posts() - returns ALL posts including drafts and future-dated
  • recent_posts(n) - returns n most recent published posts
  • paginate(page, per_page) - pagination support

Registry (blogex/lib/blogex/registry.ex)

  • Blogex.Registry.all_posts() - all published posts across blogs
  • Blogex.Registry.all_posts_unfiltered() - all posts including drafts/scheduled
  • Blogex.Registry.get_blog!(blog_id) - get blog module by atom

Router (app/lib/firehose_web/router.ex)

  • GET / - PageController.home (homepage with recent posts)
  • GET /blog/:blog_id - BlogController.index (blog listing)
  • GET /blog/:blog_id/:slug - BlogController.show (single post)
  • GET /blog/:blog_id/tag/:tag - BlogController.tag (posts by tag)
  • GET /api/blog/engineering - Blogex.Router (serves HTML+JSON+RSS)
  • GET /api/blog/releases - Blogex.Router (serves HTML+JSON+RSS)
  • LiveView: GET /editor/dashboard - EditorDashboardLive (authenticated)
  • LiveView: GET /microprints - MicroprintsLive

Blogex Router (blogex/lib/blogex/router.ex)

  • Serves at /api/blog/{engineering,releases}
  • GET /feed.xml - RSS 2.0 feed
  • GET /atom.xml - Atom feed
  • These are mounted under /api/blog/* so feeds are at /api/blog/engineering/feed.xml

Blog Controller (app/lib/firehose_web/controllers/blog_controller.ex)

  • Renders blog index, show, and tag pages using Phoenix templates with Blogex.Components
  • Uses the Phoenix layout (app.html.heex) with full UI

Editor Dashboard (app/lib/firehose_web/live/editor_dashboard_live.ex)

  • Authenticated LiveView at /editor/dashboard
  • Shows Drafts and Scheduled posts tabs
  • Uses Blogex.Registry.all_posts_unfiltered()
  • Has a tab switcher between drafts and scheduled
  • Each post shows title, author, date, status

Layout/UI (app/lib/firehose_web/components/layouts/app.html.heex)

  • Navbar with links to: Home, Blog, Releases, QWAN (external), Contact, theme toggle
  • No RSS icon/link visible in nav
  • No link to Editor Dashboard in nav (only accessible via direct URL)

Homepage (app/lib/firehose_web/controllers/page_html/home.html.heex)

  • Shows intro text and recent posts grid (6 most recent across both blogs)

Email/Mailer

  • Firehose.Mailer uses Swoosh with gen_smtp adapter
  • Firehose.Accounts has user registration, login, password change
  • Firehose.Accounts.UserNotifier for email notifications
  • No subscription/newsletter functionality exists

Mix Dependencies

  • phoenix_live_view ~> 1.1.0
  • swoosh ~> 1.16 (email library)
  • gen_smtp ~> 1.0 (SMTP adapter)
  • ecto_sql ~> 3.13, postgrex
  • blogex (path dependency, local)