Gravatar is a widely used service for associating profile images with email addresses. If your application doesn't store avatars locally, Gravatar offers a reliable fallback based on the user's email hash. Here's a minimal and idiomatic Elixir module to generate Gravatar URLs.
The helper module
defmodule AvatarHelper do
@moduledoc """
Generates a Gravatar URL based on a user's email.
"""
@gravatar_base_url "https://secure.gravatar.com/avatar"
@default_gravatar_id "00000000000000000000000000000000"
@doc """
Returns the Gravatar URL for the given object.
## Options
* `:size` β image size in pixels (default: 180)
* `:default` β default Gravatar image type if email is missing (default: `"mp"`)
## Examples
iex> AvatarHelper.avatar_url(%{email: "user@example.com"})
"https://secure.gravatar.com/avatar/23463b99b62a72f26ed677cc556c44e8?s=180&d=mp"
"""
def avatar_url(object, opts \\ []) do
size = Keyword.get(opts, :size, 180)
default_image = Keyword.get(opts, :default, "mp")
params = "?s=#{size}&d=#{default_image}"
gravatar_id =
case Map.get(object, :email) do
email when is_binary(email) and email != "" -> md5_hash(email)
_ -> @default_gravatar_id
end
"#{@gravatar_base_url}/#{gravatar_id}#{params}"
end
defp md5_hash(email) do
email
|> String.downcase()
|> then(&:crypto.hash(:md5, &1))
|> Base.encode16(case: :lower)
end
end
Why this approach?
- No local storage checks β Itβs purely Gravatar-based.
- Fallback behavior β If no valid email is present, it uses a default blank hash.
- Customizable β You can pass options like size (
:size
) and default image type (:default
), such as"identicon"
,"retro"
, or"mp"
.
Usage in Phoenix
Use this in a template or LiveView like this:
<img src={AvatarHelper.avatar_path(@user)} alt="User avatar" />
This keeps your app simple and your user avatars globally consistent.
If this post was enjoyable or useful for you, please share it! If you have comments, questions, or feedback, you can email my personal email. To get new posts, subscribe use the RSS feed.