Quick Tip

Make an RSS Atom feed with Phoenix LiveView

atom rss

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.