Skip to main content
go-swarm-icons
On this page

Chain Provider

Combine multiple providers with priority-based fallback for local overrides plus remote sources.

Sometimes icons come from more than one source. The chain provider wraps multiple providers in priority order and returns the first match, so local overrides take precedence over remote fallbacks.

What it does

ChainProvider wraps an ordered list of providers and returns the first match. It lets multiple icon sources act as a single provider with fallback behavior.

When to use it

Reach for a chain when the project needs local overrides on top of a remote source, or when combining multiple icon sets under a single prefix. The most common pattern is a directory of custom SVGs backed by the Iconify API for everything else.

For single-source providers, see Directory Provider, JSON Collection Provider, or Iconify Provider.

Setup

Direct construction

Go
import swarmicons "github.com/frostybee/go-swarm-icons"
dirP, err := swarmicons.NewDirectoryProvider("./heroicons")
if err != nil {
log.Fatal(err)
}
iconifyP := swarmicons.NewIconifyProvider("heroicons")
chain := swarmicons.NewChainProvider(dirP, iconifyP)
manager := swarmicons.Default("heroicons", chain)

The directory provider is checked first. If it has the icon, the Iconify provider is never called.

Config builder with AddHybridSet

The AddHybridSet shortcut creates a ChainProvider combining a DirectoryProvider and an IconifyProvider under a single prefix:

Go
import swarmicons "github.com/frostybee/go-swarm-icons"
manager, err := swarmicons.NewConfig().
AddHybridSet("heroicons", "./heroicons").
DefaultPrefix("heroicons").
Build()

This is equivalent to the manual chain above, but constructed internally during Build().

Options & behavior

Resolution order

Get() iterates the provider list in order and returns the first icon found. If no provider has the icon, it returns (nil, false).

Chain[DirectoryProvider, IconifyProvider]
Get("home"):
1. DirectoryProvider.Get("home") → found? return it
2. IconifyProvider.Get("home") → found? return it
3. not found → (nil, false)

Has() short-circuits

Has() returns true as soon as any provider in the chain reports the icon exists. It does not query remaining providers.

All() deduplicates

All() returns the union of all providers' icon names, deduplicated. Names appear in the order they are first encountered (first provider's names first, then new names from subsequent providers).

No internal caching

The chain provider does not cache results itself. Each wrapped provider manages its own cache. Repeated Get() calls on the chain still benefit from each provider's internal caching.

Constructor

NewChainProvider copies the provider slice. Modifying the original slice after construction has no effect on the chain.

Examples

Local overrides with remote fallback

Go
import (
"fmt"
"log"
swarmicons "github.com/frostybee/go-swarm-icons"
)
func main() {
// Local directory with a few custom overrides
dirP, err := swarmicons.NewDirectoryProvider("./overrides/heroicons")
if err != nil {
log.Fatal(err)
}
// Iconify API as the fallback for icons not in the directory
iconifyP := swarmicons.NewIconifyProvider("heroicons")
chain := swarmicons.NewChainProvider(dirP, iconifyP)
manager := swarmicons.Default("heroicons", chain)
// "home" resolves from disk if ./overrides/heroicons/home.svg exists,
// otherwise from the Iconify API.
icon, err := manager.Get("home")
if err != nil {
log.Fatal(err)
}
fmt.Println(icon.ToHTML())
}

Config builder shortcut

Go
import (
"fmt"
"log"
swarmicons "github.com/frostybee/go-swarm-icons"
"github.com/frostybee/go-swarm-icons/lucide"
)
func main() {
manager, err := swarmicons.NewConfig().
AddProvider("lucide", lucide.Provider()).
AddHybridSet("heroicons", "./heroicons").
DefaultPrefix("lucide").
Build()
if err != nil {
log.Fatal(err)
}
// Lucide icon via default prefix
home, _ := manager.Get("home")
fmt.Println(home.ToHTML())
// Heroicons via explicit prefix (directory checked first, then Iconify)
check, _ := manager.Get("heroicons:check-circle")
fmt.Println(check.ToHTML())
}

Choosing a provider

Provider Source Network Disk Caching Best for
Directory .svg files No Yes Per-icon on first access Custom/brand icons
JSON Collection Iconify JSON No Yes (or go:embed) Full parse on first call Production icon sets
Iconify API HTTP API Yes No Per-icon on first fetch Prototyping, unknown sets
Chain Multiple providers Depends Depends Per-provider Local-first + fallback
Embedded Lucide go:embed in binary No No Full parse on first call Quick start, Lucide-only

See also

Edit this page

Last updated: