Most avatar components fake it: a colored circle with initials, because finding the real picture is someone else's problem. This one shows the real picture when it exists and falls back to initials when it does not, with no backend.
The component
import { useState } from "react"
type AvatarProps = {
/** e.g. "github/torvalds", "email/jane@stripe.com", "domain/stripe.com" */
lookup: string
name: string
size?: number
}
export function Avatar({ lookup, name, size = 40 }: AvatarProps) {
const [failed, setFailed] = useState(false)
const initials = name
.split(/\s+/)
.map((part) => part[0] ?? "")
.join("")
.slice(0, 2)
.toUpperCase()
if (failed) {
return (
<span
aria-label={name}
style={{
width: size,
height: size,
borderRadius: "50%",
display: "inline-grid",
placeItems: "center",
background: "#e9e4d8",
fontSize: size * 0.4,
fontWeight: 600
}}
>
{initials}
</span>
)
}
return (
<img
src={`https://avatarsapi.com/${lookup}?size=${size * 2}`}
alt={name}
width={size}
height={size}
loading="lazy"
style={{ borderRadius: "50%", objectFit: "cover" }}
onError={() => setFailed(true)}
/>
)
}
Usage:
<Avatar lookup="github/torvalds" name="Linus Torvalds" />
<Avatar lookup="email/jane@stripe.com" name="Jane Doe" />
<Avatar lookup="domain/stripe.com" name="Stripe" size={24} />
Why this works: avatarapi returns a real 404 when nobody has a picture for that Handle, instead of a default silhouette with a 200. So onError fires exactly when there is no real image. Requesting size * 2 keeps it sharp on high-density screens.
Next.js <Image>
If you prefer next/image, allow the host in next.config.js:
module.exports = {
images: {
remotePatterns: [{ protocol: "https", hostname: "avatarsapi.com" }]
}
}
Then swap <img> for <Image> and keep the same onError. Consider unoptimized: avatarapi already resizes (?size=) and caches at the edge, so routing the image through Next's optimizer adds a second fetch and a second cache without making it smaller.
Using a Project key
On a free or paid Project, prefix the path with your publishable key. pk_ keys are safe in client code:
src={`https://avatarsapi.com/p/${process.env.NEXT_PUBLIC_AVATARS_KEY}/${lookup}?size=${size * 2}`}
Free use, anonymous or on a free Project, requires a visible "Avatars by avatarsapi.com" link where the images appear; Starter removes that. Details are in the docs.
Related
- Generated avatar services if you want something prettier than initials.
- All platforms and their Handle formats.
https://avatarsapi.com/github/torvalds in an <img src>. No key, no signup. Read the docs or create a Project.