NB logo
All Case Studies
BetterIcons for Umbraco

B E T T E R I C O N S   F O R   U M B R A C O

How I built a custom property editor that brings 200,000+ icons to Umbraco CMS, from problem identification to open-source release.

Discovery

  • Umbraco's built-in icon picker only ships ~400 icons with no search or filtering
  • Content editors had to memorize icon names or scroll through a flat grid
  • No support for popular libraries like FontAwesome, Lucide, or Material Icons
  • Extending Umbraco's icons required manually adding SVGs to a specific folder, rebuilding, and restarting the backoffice, a painful workflow for every new icon

Architecture

  • Chose Preact for the picker UI, lightweight and fast virtual scrolling for 200K+ icons
  • Umbraco 13 and below: mounted the Preact picker inside an AngularJS directive for the backoffice
  • Umbraco 14+: rewrapped the same Preact core as a Lit web component for the new Lit/UUI-based backoffice
  • TypeScript throughout for type safety across the Preact ↔ Angular/Lit boundary
  • Lazy-loaded icon libraries to keep the initial bundle small

Challenges

  • Rendering 200K icons without freezing the browser, solved with virtualized grid + debounced search
  • Bridging Preact state with two different host frameworks (AngularJS and Lit), built thin adapter layers for each
  • Supporting multiple icon formats (SVG paths, font classes, components) under one API
  • Ensuring the picker works offline with bundled icon metadata (~2MB compressed)

Result

  • Open-sourced on GitHub with full documentation
  • Published to NuGet for one-line install in any Umbraco project
  • Adopted by the Umbraco community, featured in community newsletters
  • Zero config required, works out of the box with the backoffice

T E C H   S T A C K

U M B R A C O   C M S

Platform

. N E T / C #

Core development

P R E A C T

Picker UI

T Y P E S C R I P T

Type safety

S T Y L E D - C O M P O N E N T S

Picker styling

A N G U L A R

Backoffice mount (v13−)

L I T

Backoffice mount (v14+)

R S P A C K

Build tooling

N U G E T

Package distribution

W H A T   I   L E A R N E D

Framework interop is hard

Bridging Preact inside two different hosts (AngularJS for v13−, Lit for v14+) requires careful state management. Property binding, event delegation, and lifecycle coordination all need explicit handling per framework.

Performance at scale needs planning

Rendering 200K items taught me that virtualization, debouncing, and lazy loading aren't optimizations, they're requirements.

DX matters for adoption

One-line install via NuGet with zero config was the single biggest factor in community adoption. API simplicity beats feature count.

Open source forces quality

Knowing the code would be public pushed me to write better docs, cleaner APIs, and handle edge cases I'd normally skip.

Be part of the thinking behind the craft.

Why real systems behave the way they do. Technical paths that change outcomes.
The web’s native language, decoded.

Monthly. No pandering, no gimmicks, no shallow summaries.