Angular 20 has arrived with exciting new features like improved hybrid rendering, experimental zoneless change detection, and enhanced performance optimizations. Today, we’ll explore how to integrate ngx-avatar-2, a powerful avatar component library, into your shiny new Angular 20 application.
Whether you’re building a social platform, admin dashboard, or any application that displays user profiles, having a robust avatar system is crucial. Let’s dive into how ngx-avatar makes this incredibly simple while providing enterprise-grade reliability.
What is ngx-avatar?

ngx-avatar-2 is a universal avatar component for Angular that automatically fetches user avatars from multiple sources with an intelligent fallback system. Think of it as your Swiss Army knife for avatar management in your Angular applications – it handles everything from social media profile pictures to custom initials, all with zero configuration.
A Brief History
The original ngx-avatar package was created by Haithem Mosbahi and served the Angular community well for many years. However, when the package was abandoned and no longer maintained, many projects (including mine) still depended on this crucial functionality. That’s when I decided to fork the project and create ngx-avatar-2, taking on the responsibility of maintaining and modernizing it for the Angular community.
Since Angular 15, I’ve been actively maintaining ngx-avatar-2, ensuring it stays compatible with each new Angular release, adding modern features, and keeping it aligned with Angular’s best practices. The library has evolved significantly from its original form, now featuring standalone component support, improved performance, and compatibility with Angular 20’s latest innovations.
Why ngx-avatar Stands Out
- Smart Fallback System: If Facebook fails, try Google. If Google fails, try Gravatar. If all else fails, generate beautiful initials.
- Angular 20 Ready: Built with standalone components, OnPush change detection, and modern Angular patterns
- Zero Configuration: Works out of the box with sensible defaults
- Highly Customizable: Control every aspect when you need to
Quick Start: Your First Avatar in 60 Seconds
Step 1: Installation
npm install ngx-avatar-2
Step 2: Setup Standalone Components
// main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { provideHttpClient } from '@angular/common/http';
import { AppComponent } from './app/app.component';
bootstrapApplication(AppComponent, {
providers: [
provideHttpClient(), // Required for external avatar sources
]
});
Step 3: And start using it!
// user-profile.component.ts
import { Component } from '@angular/core';
import { AvatarComponent } from 'ngx-avatar-2';
@Component({
selector: 'app-user-profile',
standalone: true,
imports: [AvatarComponent],
template: `
<div class="profile-header">
<ngx-avatar
name="John Doe"
size="100"
[round]="true">
</ngx-avatar>
<h2>John Doe</h2>
</div>
`,
styles: [`
.profile-header {
display: flex;
align-items: center;
gap: 20px;
padding: 20px;
}
`]
})
export class UserProfileComponent {}
That’s it! You now have a beautiful avatar that will display the initials “JD” with a randomly generated background color.

Real-World Examples: Building a Team Dashboard
Let’s create a more realistic example – a team member dashboard that showcases different avatar sources:

// team-dashboard.component.ts
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AvatarComponent } from 'ngx-avatar-2';
interface TeamMember {
name: string;
email?: string;
githubId?: string;
profileImage?: string;
role: string;
}
@Component({
selector: 'app-team-dashboard',
standalone: true,
imports: [CommonModule, AvatarComponent],
template: `
<div class="team-grid">
@for (member of teamMembers; track member.name) {
<div class="member-card">
<ngx-avatar
[name]="member.name"
[gravatarId]="member.email"
[githubId]="member.githubId"
[src]="member.profileImage"
size="80"
[round]="true"
borderColor="#3b82f6"
(clickOnAvatar)="onAvatarClick($event, member)">
</ngx-avatar>
<h3>{{ member.name }}</h3>
<p>{{ member.role }}</p>
</div>
}
</div>
`,
styles: [`
.team-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 24px;
padding: 24px;
}
.member-card {
background: white;
border-radius: 12px;
padding: 20px;
text-align: center;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
transition: transform 0.2s;
}
.member-card:hover {
transform: translateY(-4px);
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}
.member-card h3 {
margin: 12px 0 4px;
font-size: 18px;
color: #1f2937;
}
.member-card p {
color: #6b7280;
font-size: 14px;
margin: 0;
}
`]
})
export class TeamDashboardComponent {
teamMembers: TeamMember[] = [
{
name: 'Sarah Chen',
email: 'sarah@company.com',
githubId: 'sarahchen',
role: 'Frontend Lead'
},
{
name: 'Mike Johnson',
profileImage: 'assets/avatars/mike.jpg',
role: 'Backend Engineer'
},
{
name: 'Emma Wilson',
email: 'emma@company.com',
role: 'UX Designer'
},
{
name: 'David Kim',
githubId: 'davidkim',
role: 'DevOps Engineer'
}
];
onAvatarClick(event: any, member: TeamMember) {
console.log(`Clicked on ${member.name}'s avatar`, event);
// Navigate to member profile or show details
}
}
The Magic of Smart Fallbacks

One of ngx-avatar’s killer features is its intelligent fallback system. Here’s how it works:
@Component({
selector: 'app-user-avatar',
standalone: true,
imports: [AvatarComponent],
template: `
<!-- This single component tries multiple sources automatically -->
<ngx-avatar
[githubId]="user.githubUsername"
[gravatarId]="user.email"
[src]="user.uploadedPhoto"
[name]="user.fullName"
size="120">
</ngx-avatar>
`
})
export class UserAvatarComponent {
user = {
githubUsername: 'johndoe',
email: 'john@example.com',
uploadedPhoto: '/api/users/123/photo',
fullName: 'John Doe'
};
}
The component will try sources in this order:
- GitHub avatar (if githubId is provided)
- Gravatar (if email/gravatarId is provided)
- Custom image (if src URL is provided)
- Name initials (if name is provided)
- Default avatar (if everything fails)
Advanced Customisation: Making It Your Own

Custom Color Schemes
Want to match your brand colors?
Configure the avatar module globally:
// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideHttpClient } from '@angular/common/http';
import { AvatarModule } from 'ngx-avatar-2';
// Your brand colors
const brandColors = [
'#8B5CF6', // Violet
'#EC4899', // Pink
'#06B6D4', // Cyan
'#10B981', // Emerald
'#F59E0B' // Amber
];
export const appConfig: ApplicationConfig = {
providers: [
provideHttpClient(),
// Configure avatar module with custom colors
...AvatarModule.forRoot({
colors: brandColors
}).providers!
]
};
Custom Source Priority
Need to prioritize certain sources? Customize the fallback order:
import { AvatarSource } from 'ngx-avatar-2';
const customSourceOrder = [
AvatarSource.CUSTOM, // Try custom image first
AvatarSource.GRAVATAR, // Then Gravatar
AvatarSource.GITHUB, // Then GitHub
AvatarSource.INITIALS // Finally, initials
];
// In your module or app config
AvatarModule.forRoot({
sourcePriorityOrder: customSourceOrder
})
Performance Tips for Angular 20
Angular 20’s new features pair perfectly with ngx-avatar:
1. Use OnPush Change Detection
@Component({
selector: 'app-avatar-list',
standalone: true,
imports: [CommonModule, AvatarComponent],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
@for (user of users; track user.id) {
<ngx-avatar
[name]="user.name"
[gravatarId]="user.email">
</ngx-avatar>
}
`
})
export class AvatarListComponent {
@Input() users: User[] = [];
}
2. Lazy Load Avatar Component
// routes.ts
export const routes: Routes = [
{
path: 'profile',
loadComponent: () => import('./profile/profile.component')
.then(m => m.ProfileComponent)
}
];
3. Use Angular 20’s New Control Flow
@Component({
template: `
@if (user) {
<ngx-avatar [name]="user.name"></ngx-avatar>
} @else {
<div class="loading-skeleton"></div>
}
`
})
Accessibility First
ngx-avatar now includes built-in accessibility features:

<ngx-avatar
name="John Doe"
alt="John Doe's profile picture"
ariaLabel="View John Doe's profile"
[clickable]="true"
role="button">
</ngx-avatar>
Creative Use Cases
1. Status Indicators

@Component({
template: `
<div class="user-status">
<ngx-avatar [name]="user.name" size="50"></ngx-avatar>
<span class="status-dot" [class.online]="user.isOnline"></span>
</div>
`,
styles: [`
.user-status {
position: relative;
display: inline-block;
}
.status-dot {
position: absolute;
bottom: 0;
right: 0;
width: 14px;
height: 14px;
background: #9ca3af;
border: 2px solid white;
border-radius: 50%;
}
.status-dot.online {
background: #10b981;
}
`]
})
2. Progress Avatars

@Component({
template: `
<ngx-avatar
[value]="project.completion + '%'"
[bgColor]="getProgressColor(project.completion)"
size="80">
</ngx-avatar>
`
})
export class ProjectProgressComponent {
getProgressColor(completion: number): string {
if (completion >= 80) return '#10b981'; // Green
if (completion >= 50) return '#f59e0b'; // Yellow
return '#ef4444'; // Red
}
}
3. Group Avatars

@Component({
template: `
<div class="avatar-group">
@for (member of members.slice(0, 3); track member.id; let i = $index) {
<div class="avatar-wrapper" [style.z-index]="3 - i">
<ngx-avatar
[name]="member.name"
size="40"
borderColor="white">
</ngx-avatar>
</div>
}
@if (members.length > 3) {
<div class="avatar-wrapper">
<ngx-avatar
[value]="'+' + (members.length - 3)"
bgColor="#e5e7eb"
fgColor="#4b5563"
size="40">
</ngx-avatar>
</div>
}
</div>
`,
styles: [`
.avatar-group {
display: flex;
align-items: center;
}
.avatar-wrapper {
margin-left: -10px;
position: relative;
}
.avatar-wrapper:first-child {
margin-left: 0;
}
`]
})
Migration from Earlier Angular Versions
If you’re upgrading from an older Angular version, here’s what’s new in ngx-avatar for Angular 20:
// Old way (NgModule-based)
@NgModule({
imports: [AvatarModule]
})
// New way (Standalone)
@Component({
standalone: true,
imports: [AvatarComponent]
})
Troubleshooting Common Issues
Avatar Not Loading from External Sources?
Make sure you’ve provided HttpClient:
// main.ts
bootstrapApplication(AppComponent, {
providers: [
provideHttpClient() // Don't forget this!
]
});
Custom Colors Not Working?
Ensure you’re importing the configured module:
// Use forRoot configuration
AvatarModule.forRoot({
colors: ['#custom1', '#custom2']
})
Performance Issues with Large Lists?
Use track functions and virtual scrolling:
@for (user of users; track user.id) {
<ngx-avatar [name]="user.name"></ngx-avatar>
}
Whether you’re building a small team dashboard or a large-scale social platform, ngx-avatar scales with your needs while maintaining simplicity. The combination of Angular 20’s performance improvements and ngx-avatar’s efficient design creates a delightful user experience.
What started as a community need when the original package was abandoned has evolved into a modern, actively maintained library that serves thousands of Angular developers. I’m committed to keeping ngx-avatar-2 up-to-date with each Angular release and continuously improving it based on community feedback.
Get Started Today
npm install ngx-avatar-2
Visit the GitHub repository for more examples, and don’t forget to star the project if you find it useful!
Acknowledgments
Special thanks to Haithem Mosbahi for creating the original ngx-avatar package that inspired this project, and to all the contributors and users who have helped make ngx-avatar-2 better with each release.
Happy coding! 🚀
Have questions or suggestions? Feel free to open an issue on GitHub or contribute to the project. The ngx-avatar community is always happy to help!
Maintained with ❤️ by Bhushan Kalvani