Quick Tip

Make an RSS Atom feed with Phoenix LiveView

atomrss

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.

Phoenix Bolerplate

Generate a Phoenix Boilerplate and save hours on your next project.

6715 downloads
Try now
OR

SAAS Starter Kit

Get started and save time and resources by using the SAAS Starter Kit built with Phoenix and LiveView.

Subscribe for $39/mo to geat ahead!

Learn More