Next.js Avatar Library – Using DiceBear with Next.js
DiceBear works in every Next.js rendering mode — server components, client components, and the Pages Router. Server-side generation is the default recommendation because it produces zero JavaScript on the client and avoids hydration pitfalls.
You can use DiceBear with Next.js via the JS-Library or the HTTP-API.
App Router
Server component (recommended)
In App Router, components are server components by default. Generate the SVG on the server and inline it as a data URI — no client-side JavaScript is shipped for the avatar.
tsx
// app/components/UserAvatar.tsx
import { Avatar } from '@dicebear/core';
import lorelei from '@dicebear/styles/lorelei.json' with { type: 'json' };
export function UserAvatar({ seed = 'Alice' }: { seed?: string }) {
const dataUri = new Avatar(lorelei, {
seed,
size: 128,
// ... other options
}).toDataUri();
return <img src={dataUri} alt="Avatar" width={128} height={128} />;
}Client component
Mark the file with 'use client' and wrap generation in useMemo so the avatar is only re-derived when the seed changes.
tsx
// app/components/UserAvatarClient.tsx
'use client';
import { useMemo } from 'react';
import { Avatar } from '@dicebear/core';
import lorelei from '@dicebear/styles/lorelei.json' with { type: 'json' };
export function UserAvatarClient({ seed = 'Alice' }: { seed?: string }) {
const dataUri = useMemo(
() =>
new Avatar(lorelei, {
seed,
size: 128,
// ... other options
}).toDataUri(),
[seed],
);
return <img src={dataUri} alt="Avatar" width={128} height={128} />;
}Hydration & idRandomization
idRandomization uses the host's non-seeded RNG, so the server and the client will produce different IDs and React will throw a hydration mismatch warning. Either:
- Generate the avatar in a server component (no hydration) and don't pass the SVG to a client component, or
- Leave
idRandomization: falseand rely on the deterministic IDs.
If you need ID uniqueness across multiple avatars on the same page, render each avatar entirely on the server.
Route handler (avatar endpoint)
Expose DiceBear behind your own URL — useful for caching with custom Cache-Control headers or restricting which seeds are accepted.
ts
// app/api/avatar/[seed]/route.ts
import { Avatar } from '@dicebear/core';
import lorelei from '@dicebear/styles/lorelei.json' with { type: 'json' };
export async function GET(
_request: Request,
{ params }: { params: Promise<{ seed: string }> },
) {
const { seed } = await params;
const svg = new Avatar(lorelei, { seed, size: 128 }).toString();
return new Response(svg, {
headers: {
'Content-Type': 'image/svg+xml',
'Cache-Control': 'public, max-age=31536000, immutable',
},
});
}Pages Router
Pages Router treats every component as client-side by default. Use useMemo exactly like in a plain React app — see the React guide for the canonical pattern. Server-side generation through getServerSideProps or getStaticProps returns the SVG as a prop, avoiding a client bundle hit.
tsx
// pages/profile.tsx
import type { GetServerSideProps } from 'next';
import { Avatar } from '@dicebear/core';
import lorelei from '@dicebear/styles/lorelei.json' with { type: 'json' };
type Props = { avatar: string };
export const getServerSideProps: GetServerSideProps<Props> = async () => {
const avatar = new Avatar(lorelei, { seed: 'Alice', size: 128 }).toDataUri();
return { props: { avatar } };
};
export default function Profile({ avatar }: Props) {
return <img src={avatar} alt="Avatar" width={128} height={128} />;
}With the HTTP API
The HTTP API needs no installation and works in both routers. Use a plain <img> tag — Next.js does not pre-process external SVGs by default.
tsx
export function UserAvatar({ seed = 'Alice' }: { seed?: string }) {
const src = `https://api.dicebear.com/10.x/lorelei/svg?seed=${encodeURIComponent(seed)}&size=128`;
return <img src={src} alt="Avatar" width={128} height={128} />;
}If you want to use next/image with the HTTP API, request a raster format (PNG, WebP, AVIF) — next/image does not optimize SVG sources — and add api.dicebear.com to images.remotePatterns in next.config.js.
js
// next.config.js
module.exports = {
images: {
remotePatterns: [{ protocol: 'https', hostname: 'api.dicebear.com' }],
},
};tsx
import Image from 'next/image';
export function UserAvatar({ seed = 'Alice' }: { seed?: string }) {
const src = `https://api.dicebear.com/10.x/lorelei/png?seed=${encodeURIComponent(seed)}&size=128`;
return <Image src={src} alt="Avatar" width={128} height={128} />;
}