Not required for normal use. This page explains the resolution flow, module boundaries, and provider registry design for readers who want to understand how the library works internally.
System overview
The library is organized around a central IconManager that coordinates icon resolution through a provider registry and an attribute renderer.
Consumer Code manager.Get("lucide:home", map{"class": "icon"}) icon.Size(24).Class("text-blue").Fill("currentColor").ToHTML() | v IconManager 1. Resolve alias 2. Parse prefix 3. Find provider 4. Fallback chain 5. Render attrs | | v v Provider IconRenderer Registry prefix->impl Merge attrs | Apply ARIA | +--+--+--+ | | | | v v v v Dir JSON Iconify Chain | v *Icon content (SVG inner) attributes (map) Fluent mutations ToHTML() renderingConsumer code interacts with two entry points: the IconManager (for resolution) and the *Icon (for transformation and output). Everything else is internal plumbing.
Three-module design
The repository contains three independent Go modules, each with its own go.mod. This boundary design prevents dependency leakage to consumers.
Core module
github.com/frostybee/go-swarm-iconsContains the icon manager, all four providers, the renderer, the fluent Icon API, SVG parsing, sanitization, the sprite collector, and the error types. Its only dependency is the Go standard library (net/http for the Iconify provider, encoding/json for JSON parsing, sync for concurrency primitives).
Lucide submodule
github.com/frostybee/go-swarm-icons/lucideEmbeds the Lucide icon set (~800 KB) via go:embed lucide.json. Depends only on the core module. Consumers who do not need Lucide never add this binary weight.
Goldmark submodule
github.com/frostybee/go-swarm-icons/goldmarkAdds inline :icon[prefix:name] syntax to Goldmark-processed Markdown. Depends on the core module and github.com/yuin/goldmark. Consumers who do not use Goldmark never pull in the Goldmark dependency.
Import paths
import swarmicons "github.com/frostybee/go-swarm-icons"import "github.com/frostybee/go-swarm-icons/lucide"import swarmgoldmark "github.com/frostybee/go-swarm-icons/goldmark"Resolution flow
When manager.Get("home", map{"class": "icon"}) is called, the icon passes through six stages.
1. Alias resolution
The manager checks the aliases map. If the name matches an alias, the target name is substituted. This is a single-level lookup (manager-level aliases do not chain). The check happens under a read lock.
2. Name parsing
The name is split on the first : character. The left side is the prefix, the right side is the icon name. If the name has no colon, the default prefix is applied. An empty prefix, empty name, or bare name without a default prefix returns ErrInvalidIconName.
3. Provider lookup
The manager looks up the provider registered for the resolved prefix. If no provider exists, the flow moves to the fallback stage (or returns ErrProviderNotFound if no fallback is configured).
4. Icon retrieval
The provider's Get(iconName) is called. Each provider implementation handles its own loading and caching:
DirectoryProviderreads from disk on first access, caches the result.JsonCollectionProviderparses JSON on first access (viasync.Once), resolves aliases up to depth 10, and caches resolved icons.IconifyProvidermakes an HTTP request on first access and caches the response.ChainProvideriterates its providers in order and returns the first hit.
If the provider returns false (not found), the flow moves to the fallback stage.
5. Fallback chain
Two fallback levels are checked in order:
- Per-prefix fallback: if a fallback is registered for the resolved prefix via
FallbackIconForPrefix, it is tried first. - Global fallback: if a global fallback is registered via
FallbackIcon, it is tried next.
Each fallback is resolved through the same get flow, with a resolvingFallback flag to prevent infinite recursion. If the fallback also fails, ErrIconNotFound is returned (or an empty icon if IgnoreNotFound is enabled).
6. Attribute rendering
The IconRenderer.Render method applies the five-layer attribute merge and ARIA injection, producing a new *Icon with the merged attributes. The original provider-cached icon is not modified.
File inventory
Core module
| File | Purpose |
|---|---|
icon.go |
Icon type, fluent methods, ToHTML, constructors (New, FromFile, FromString) |
icon_transform.go |
Rotate, Flip, Width, Height, CSS transform composition |
iconify_data.go |
Internal Iconify entry parsing and transform application |
manager.go |
IconManager, resolution algorithm, Default() |
renderer.go |
IconRenderer, five-layer attribute merge, ARIA rules |
config.go |
Config builder, deferred registration, Build() |
provider.go |
Provider interface definition |
directory_provider.go |
DirectoryProvider, path traversal guard |
json_provider.go |
JsonCollectionProvider, lazy parse, alias resolution |
chain_provider.go |
ChainProvider, first-found composite |
iconify_provider.go |
IconifyProvider, HTTP with host fallback |
internal/svgparse/svgparse.go |
SVG parsing and the nine-stage sanitization pipeline |
cache.go |
iconCache, shared sync.RWMutex cache |
sprite.go |
SpriteCollector, ID namespacing |
errors.go |
Sentinel error values |
doc.go |
Package documentation |
Lucide submodule
| File | Purpose |
|---|---|
lucide/lucide.go |
go:embed directive, Provider() factory |
lucide/lucide.json |
Embedded Iconify JSON (~800 KB) |
Goldmark submodule
| File | Purpose |
|---|---|
goldmark/extension.go |
Extension struct, Extend() registration |
goldmark/parser.go |
InlineParser for :icon[...] syntax |
goldmark/node.go |
IconNode AST node, KindIconNode |
goldmark/renderer.go |
NodeRenderer, transform vs. pass-through dispatch |
See also
- Core Concepts: a shorter introduction to the same ideas for readers who want the overview without the implementation detail
- Providers: comparison table and overview of all five provider types