Next.js App Router with Server Components
Render icons in Server Components with no JavaScript at all, and reach for client components only where an icon reacts to clicks or morphs between names.
Server Components
import { Icon, Fusion } from 'glyphfox/react/server';
export default function Page() {
return (
<main>
<h1>
<Icon name="home" size={28} className="title-icon" /> Dashboard
</h1>
<Icon name="file+check@tr" variant="duotone" title="Saved" />
<Icon name="bell" animate="shake" trigger="hover" />
<Icon name="menu" morphTo="x" trigger="hover" />
<Fusion icons={['cloud', 'lock']} layout="overlap" />
</main>
);
}glyphfox/react/server exports hook free Icon and Fusion components. They render static SVG during the server render, so nothing is sent to the browser for them, and every icon of the set is available by name. Living states, hover and state morphs travel inside the SVG as CSS.
Client components
'use client';
import { useState } from 'react';
import { HeartIcon, MorphIcon } from 'glyphfox/react';
export function LikeButton() {
const [liked, setLiked] = useState(false);
return (
<button onClick={() => setLiked(!liked)} aria-pressed={liked}>
<HeartIcon animate="pop" trigger="state" active={liked} variant={liked ? 'solid' : 'outline'} />
<MorphIcon name={liked ? 'check' : 'heart'} />
</button>
);
}The modules of glyphfox/react are marked 'use client', so the icon components also work when a Server Component renders them directly: they are server rendered and hydrated. Use them where you need the click trigger, morph tweens or useMorph.
Bundle size
/** @type {import('next').NextConfig} */
export default {
experimental: {
optimizePackageImports: ['glyphfox'],
},
};Each icon is its own module. With optimizePackageImports Next.js rewrites barrel imports to those modules; deep imports such as import { FileIcon } from 'glyphfox/react/icons/file' work everywhere without configuration.
Sprite
npx glyphfox build home search file+check --type sprite --out public/icons
export function SpriteGlyph({ name }: { name: string }) {
return (
<svg width="20" height="20" aria-hidden="true">
<use href={`/icons/sprite.svg#gf-${name}`} />
</svg>
);
}For long lists of static icons, a sprite of just the icons you use keeps the HTML small and caches across pages.