jola

jola

Building a blog with Elixir and Phoenix

Everyone loves a good “how I set up my blog post” blog post, so here’s mine, using Elixir, Phoenix, and NimblePublisher. For added spice it’s running on Dokploy on Hetzner, with bunny.net in front as a CDN.

First Post!

jsonbecker

jsonbecker

Fun! I redid json.blog recently but went the other way– dynamic, using MDex as my markdown processor. Mostly because of some stuff I wanted to do that wouldn’t be as easy with a static site (I was migrating from Hugo). I built some fun stuff on the admin side like book tracking/syncing using Hardcover.app to power the /books route.

My sitemap is hand rolled in a feeds context that I use for RSS and JSONfeed as well:

 @doc """
  Generates sitemap.xml content.

  ## Options

    * `:target_date` - The datetime to use for filtering published posts and page lastmod.
      Defaults to `DateTime.utc_now()`.
  """
  @spec sitemap(keyword()) :: String.t()
  def sitemap(opts \\ []) do
    now = Keyword.get(opts, :target_date, DateTime.utc_now())
    posts = Blog.list_posts(target_date: now)

    # Also include main pages
    pages = [
      %{url: "/", lastmod: now},
      %{url: "/about/", lastmod: now},
      %{url: "/archive/", lastmod: now},
      %{url: "/style-guide/", lastmod: now}
    ]

    """
    <?xml version="1.0" encoding="UTF-8"?>
    <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    #{Enum.map_join(pages, "\n", &sitemap_url/1)}
    #{Enum.map_join(posts, "\n", &sitemap_post_url/1)}
    </urlset>
    """
  end

  defp sitemap_url(%{url: url, lastmod: lastmod}) do
    """
      <url>
        <loc>#{@site_url}#{url}</loc>
        <lastmod>#{DateTime.to_iso8601(lastmod)}</lastmod>
      </url>
    """
  end

  defp sitemap_post_url(post) do
    """
      <url>
        <loc>#{@site_url}#{post.url_path}</loc>
        <lastmod>#{DateTime.to_iso8601(post.published_at)}</lastmod>
      </url>
    """
  end

Some improvements remain, but it’s kind of nice how easy it is to roll your own.

Where Next?

Popular in Blog Posts Top

luckywatcher
Hey all! I just started a blog focused on web development in Elixir. I wrote my first article and thought I’d post it here for the whole...
New
lawik
We all have varying degrees of exposure to Big Tech. Some of it seems fine, stable and can be relied on. Some of it feels like shifting s...
New
StuntProgrammer
Hey there! This is the first article in what I hope will be a nice series about how I built (and am building) Lofi Limo. If you have any ...
New
ErlangSolutions
Hey all, it’s Erlang Solutions. We released loads of Elixir content from our senior developers last week in celebration of ElixirConf US...
New
zachdaniel
In this post I explore the silos that exist in the Elixir ecosystem, the pros and cons, and what we can improve.
New
paulanthonywilson
This is an overview of different ways to try and kill an OTP process (in Elixir) and the behaviour to expect when that happens. I know th...
New
aymanosman
The desire to produce structured logs is common. In this article, I will survey the major approaches one could take to achieve this goal ...
New
AstonJ
Update: How to use the blogs section You can post in one of the Official Blog Posts threads (like this one), or, via Devtalk and a new t...
New
paulanthonywilson
Whatever your Nerves project does, there’s a good chance that it can be enhanced by securely connecting to a Phoenix Server in the cloud;...
New
lawik
Building on other people’s work I bashed things together and suddenly I can know when someone is speaking using Elixir and Membrane.
New

Other popular topics Top

skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 43757 214
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
Lily
In templates/appointment/index.html.eex: &lt;%= for appointment &lt;- @appointments do %&gt; &lt;tr&gt; &lt;td&gt;&lt;%= appoi...
New
komlanvi
Hi everyone, I was playing with phoenix liveView but I run into an issue. I have a form and want to validate each input text when the te...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement