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"}

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)

    |> put_resp_content_type("text/xml")
    |> send_resp(200, feed)

  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()

  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()

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

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" />
<% end %>

And that should be it.