Add RSS subscribe links with icon across blog pages, footer, and head

- Add <.rss_icon> inline SVG component in core_components.ex
- Inject RSS <link> tags into <head> on blog pages for auto-discovery
- Show RSS icon next to blog title on index and tag pages
- Show RSS icon on post pages next to back-link
- Add Subscribe section in footer with links to both feeds
- Wire feed URL through blog controller (index, show, tag actions)

174 tests pass, credo clean.
This commit is contained in:
2026-07-08 17:00:11 +01:00
parent 9238ecb7f3
commit 855b6cb590
7 changed files with 111 additions and 7 deletions
@@ -420,6 +420,31 @@ defmodule FirehoseWeb.CoreComponents do
"""
end
@doc """
Renders an RSS feed icon (inline SVG).
## Examples
<.rss_icon class="size-5" />
"""
attr :class, :string, default: "size-4"
attr :rest, :global
def rss_icon(assigns) do
~H"""
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class={[@class]}
{@rest}
>
<path d="M3.75 3.75v3c0 7.454 6.046 13.5 13.5 13.5h3v-5.25a.75.75 0 0 0-.75-.75h-3a.75.75 0 0 0-.75.75v1.5a8.25 8.25 0 0 1-8.25-8.25h1.5a.75.75 0 0 0 .75-.75v-3a.75.75 0 0 0-.75-.75h-5.25a.75.75 0 0 0-.75.75Z" />
<circle cx="5.25" cy="18.75" r="2.25" />
</svg>
"""
end
## JS Commands
def show(js \\ %JS{}, selector) do
@@ -39,4 +39,30 @@
</div>
</main>
<footer class="border-t border-base-200 px-4 py-8 sm:px-6 lg:px-8">
<div class="mx-auto max-w-2xl space-y-3">
<h3 class="text-sm font-semibold tracking-wide text-base-content/60 uppercase">Subscribe</h3>
<div class="flex flex-wrap gap-4">
<a
href="/api/blog/engineering/feed.xml"
class="inline-flex items-center gap-2 text-sm text-base-content/70 hover:text-primary transition-colors"
target="_blank"
rel="noopener noreferrer"
>
<.rss_icon class="size-4 text-orange-500" />
Engineering Blog
</a>
<a
href="/api/blog/releases/feed.xml"
class="inline-flex items-center gap-2 text-sm text-base-content/70 hover:text-primary transition-colors"
target="_blank"
rel="noopener noreferrer"
>
<.rss_icon class="size-4 text-orange-500" />
Release Notes
</a>
</div>
</div>
</footer>
<.flash_group flash={@flash} />
@@ -41,6 +41,9 @@
<% end %>
<meta name="twitter:card" content={meta.twitter_card} />
<% end %>
<%= for feed <- get_content_for(assigns, :feed_links) do %>
<link rel="alternate" type="application/rss+xml" title={feed.title} href={feed.rss_url} />
<% end %>
</head>
<body>
{@inner_content}