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.
`
elixir
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 |> putrespcontent_type("text/xml") |> send_resp(200, feed) end
def build_feed(posts, conn) do Feed.new(Routes.homeindexurl(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 getentry(conn, %{name: name, kind: kind, slug: slug, summary: summary, publishedat: published_at}) do
Entry.new(Routes.posturl(conn, :show, kind, slug), DateTime.fromnaive!(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 listposts
function also look for published posts so it wont shuw up in the feed unless it has a publishedat
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.