Quick Tip
Make an RSS Atom feed with Phoenix LiveView
On this website, I do have some content and I plan to write some more. I feel that it is time to add an RSS/Atom feed to the posts I have. I think thats a nice feature for the people consuming content through feed readers and some rumors says it helps SEO as well but that could be totally wrong. On the other hand, it can’t hurt. I will to this by using the package Atomex.
First step is adding the package to the mix file
# mix.exs
def deps do
[
{:atomex, "0.4.1"}
]
end
And run
mix deps.get
With the package installed, I need to add a controller and a route.
defmodule FullstackPhoenixWeb.RssController do
use FullstackPhoenixWeb, :controller
alias FullstackPhoenix.Posts
alias Atomex.{Feed, Entry}
@author "Andreas Eriksson"
@email "andreas@fullstackphoenix.com"
def index(conn, _params) do
posts = Posts.list_posts()
feed = build_feed(posts, conn)
conn
|> put_resp_content_type("text/xml")
|> send_resp(200, feed)
end
def build_feed(posts, conn) do
Feed.new(Routes.home_index_url(conn, :index), DateTime.utc_now, "FullstackPhoenix RSS")
|> Feed.author(@author, email: @email)
|> Feed.link(Routes.rss_url(conn, :index), rel: "self")
|> Feed.entries(Enum.map(posts, &get_entry(conn, &1)))
|> Feed.build()
|> Atomex.generate_document()
end
defp get_entry(conn, %{name: name, kind: kind, slug: slug, summary: summary, published_at: published_at}) do
Entry.new(Routes.post_url(conn, :show, kind, slug), DateTime.from_naive!(published_at, "Etc/UTC"), name)
|> Entry.link(Routes.post_url(conn, :show, kind, slug))
|> Entry.author(@author)
|> Entry.content(summary, type: "text")
|> Entry.build()
end
end
Note that I have a list of posts already. That list_posts
function also look for published posts so it wont shuw up in the feed unless it has a published_at
set. I also need to convert the NaiveDateTime to DateTime.
Next step is to add the route to the router so its accessible.
# lib/fullstack_phoenix_web/router.ex
scope "/", FullstackPhoenixWeb do
get "/posts/rss.xml", RssController, :index
end
With the route in place, I need to add the link to the feed in root.html.heex
in the head section of the layout.
<link rel="alternate" type="application/rss+xml" href={Routes.rss_url(@conn, :index)}>
Most feed readers should find the RSS feed if the root url is provided. However, the last part here is to add a link to the feed. I use a RSS icon from Heroicons for this.
<%= link to: Routes.rss_url(@conn, :index) do %>
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 text-primary" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 5c7.18 0 13 5.82 13 13M6 11a7 7 0 017 7m-6 0a1 1 0 11-2 0 1 1 0 012 0z" />
</svg>
<% end %>
And that should be it.