Missing API Key
Add GRAVATAR_API_KEY to your environment variables
Learn how to handle common errors and implement fallbacks for robust avatar displays.
<GravatarAvatar email="user@example.com" default="identicon" <!-- Show geometric pattern --> size={80}/>Available options:
identicon - Geometric pattern based on email hashmp - Mystery person silhouettemonsterid - Generated monsterwavatar - Generated facesretro - 8-bit arcade-stylerobohash - Generated robotblank - Transparent PNG404 - Return 404 error<GravatarAvatar email="user@example.com" size={80} onError={(e) => { // Fallback to custom avatar e.target.src = '/images/default-avatar.png'; }}/>---import { getProfile, GravatarProfileCard } from 'astro-gravatar';
let profile = null;let error = null;
try { profile = await getProfile('user@example.com', { apiKey: import.meta.env.GRAVATAR_API_KEY });} catch (err) { error = err; console.error('Profile fetch failed:', err);}---
{profile ? ( <GravatarProfileCard email={profile.email} layout="card" avatarSize={100} showName showBio />) : ( <div style="padding: 2rem; background: #fee2e2; border-radius: 0.5rem; border: 1px solid #fca5a5;"> <h3 style="margin: 0 0 0.5rem 0; color: #991b1b;">Profile Not Available</h3> <p style="margin: 0; color: #991b1b;"> {error?.message || 'User profile not found'} </p> </div>)}import { getProfile } from 'astro-gravatar';
async function getProfileWithFallback(email: string) { try { const profile = await getProfile(email); return profile; } catch (error) { // Return minimal profile data return { email, display_name: email.split('@')[0], avatar_url: `https://www.gravatar.com/avatar/${hashEmail(email)}?d=identicon&s=80`, description: null, }; }}import { getProfile } from 'astro-gravatar';
async function fetchWithRetry(email: string, retries = 3): Promise<Profile | null> { try { return await getProfile(email); } catch (error) { if (retries > 0 && error.code === 'rate_limit_exceeded') { const delay = Math.pow(2, 4 - retries) * 1000; // 1s, 2s, 4s await new Promise((resolve) => setTimeout(resolve, delay)); return fetchWithRetry(email, retries - 1); } throw error; }}---import { getProfile } from 'astro-gravatar';
const TIMEOUT_MS = 5000; // 5 seconds
async function getProfileWithTimeout(email: string) { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
try { const profile = await getProfile(email, { apiKey: import.meta.env.GRAVATAR_API_KEY }); clearTimeout(timeoutId); return profile; } catch (error) { clearTimeout(timeoutId); if (error.name === 'AbortError') { throw new Error('Request timeout'); } throw error; }}---function isValidEmail(email: string): boolean { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailRegex.test(email);}
function safeGetAvatarUrl(email: string, options = {}) { if (!isValidEmail(email)) { console.warn('Invalid email provided:', email); // Return default avatar URL return 'https://www.gravatar.com/avatar/default?s=80&d=mp'; }
try { return buildAvatarUrl(email, options); } catch (error) { console.error('Failed to build avatar URL:', error); return 'https://www.gravatar.com/avatar/default?s=80&d=mp'; }}---import GravatarAvatar from 'astro-gravatar';
function validateAvatarProps(props) { if (!props.email || typeof props.email !== 'string') { throw new Error('Valid email is required'); }
if (props.size && (props.size < 1 || props.size > 2048)) { throw new Error('Size must be between 1 and 2048 pixels'); }
return props;}
const avatarProps = validateAvatarProps({ email: 'user@example.com', size: 80, default: 'identicon'});---
<GravatarAvatar {...avatarProps} />Missing API Key
Add GRAVATAR_API_KEY to your environment variables
Invalid Email
Validate email format before using with components
Network Issues
Implement retries and timeout handling
No Profile
Use default avatars and fallback data
// in your Astro layoutexport function handleAvatarError(error: Error) { console.error('Avatar component error:', error);
// Track errors in your analytics if (typeof window !== 'undefined' && window.gtag) { window.gtag('event', 'avatar_error', { error_message: error.message, error_type: error.constructor.name, }); }}---import GravatarAvatar from 'astro-gravatar';
function createFallbackAvatar(email: string, size: number = 80) { const initials = email.split('@')[0] .split('.') .map(part => part[0]?.toUpperCase()) .join('') .slice(0, 2);
return `<div style=" width: ${size}px; height: ${size}px; display: flex; align-items: center; justify-content: center; background: #e5e7eb; border-radius: 50%; font-weight: bold; color: #6b7280; font-size: ${size * 0.4}px; ">${initials}</div>`;}---
<!-- Try Gravatar first, fallback to custom avatar --><GravatarAvatar email="user@example.com" size={80} default="blank" onError={(e) => { e.target.outerHTML = createFallbackAvatar('user@example.com', 80); }}/>import { test, expect } from 'bun:test';import { getProfile, hashEmail, GravatarError } from 'astro-gravatar';
test('handles invalid email gracefully', () => { expect(() => hashEmail('invalid-email')).toThrow();});
test('returns null for non-existent profile', async () => { const profile = await getProfile('nonexistent@example.com'); expect(profile).toBeNull();});
test('throws GravatarError for API errors', async () => { expect.assertions(1); try { await getProfile('user@example.com', { apiKey: 'invalid-key' }); } catch (error) { expect(error).toBeInstanceOf(GravatarError); }});