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.

12 Likes

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.

I gotta look into mdex, that’s a lot of recommendations I’ve gotten now in a short amount of time

We need an org-mode parser in Elixir!