Own the output
The generated Go package, sprite, manifest, provenance, and licenses live with your application. The bundled Goshtoso icons remain unchanged.
Consumer-owned extension
Extend the icon set without changing Goshtoso's bundled components. The iconpack tool turns verified SVG sources into a typed Go package, a sprite, and the provenance files your application ships.
The generated Go package, sprite, manifest, provenance, and licenses live with your application. The bundled Goshtoso icons remain unchanged.
Select exact names from an Arai Hu Assets release, or combine a GitHub tree, a remote SVG, and other packs through .iconpack.yaml.
Generated helpers use the same accessibility, sizing, color, and same-origin sprite rules as Goshtoso's core Icon component.
Extension proof
This site ships a small Bootstrap Icons package generated outside the bundled Heroicons set. It keeps the same label, decorative, sprite, and parent-color behavior used by Goshtoso icons.
Use the archive digest and the release metadata digests published with that Assets release. Select assets by their literal catalog canonicalName; do not infer names from filenames.
go run github.com/araihu/goshtoso/cmd/iconpack@latest \
-release-archive ./araihu-assets-v0.2.0.tar.gz \
-archive-sha256 "$ASSETS_ARCHIVE_SHA256" \
-release v0.2.0 \
-catalog-sha256 "$CATALOG_SHA256" \
-release-json-sha256 "$RELEASE_JSON_SHA256" \
-checksums-sha256 "$CHECKSUMS_SHA256" \
-name brand-developer-icons-tRPC \
-name ui-hi-16-solid-check \
-out ./internal/appicons \
-package appicons \
-const-prefix Icon \
-sprite-url /assets/icons/appicons/sprite.svgFor a verified extracted release root, use -release-root instead of -release-archive. Keep the output parent present and let the generator publish the owned output directory atomically.
This file belongs to Goshtoso. It does not discover or modify an existing muamba.yaml. Muamba runs as a Go library; the first trust records source bytes, and later runs verify them.
schemaVersion: 1
sources:
- id: heroicons
url: https://github.com/tailwindlabs/heroicons/tree/master/src
packName: heroicons
paths:
- 16/solid/academic-cap.svg
license: MIT
licensePath: LICENSE
licenseUrl: https://raw.githubusercontent.com/tailwindlabs/heroicons/master/LICENSE
- id: bootstrap
kind: file
url: https://raw.githubusercontent.com/twbs/icons/v1.11.3/icons/alarm.svg
path: alarm.svg
license: MIT
licensePath: LICENSE
licenseUrl: https://raw.githubusercontent.com/twbs/icons/v1.11.3/LICENSE.mdgo run github.com/araihu/goshtoso/cmd/iconpack@latest \
-config ./.iconpack.yaml -trust \
-out ./internal/appicons -package appicons \
-const-prefix Icon -sprite-url /assets/icons/appicons/sprite.svgThe generated .iconpack.lock.yaml is the TOFU boundary. Remove -trust after the first run. The Muamba adapter declaration is built in memory, so no .iconpack.engine.yaml file is left in the consumer project. If paths is omitted, every SVG in the tree is locked and available; names use packName-path, such as heroicons-16-solid-academic-cap. Git trees without packName use the repository name; other sources use id-full-normalized-path. The same file supports multiple sources.
Existing JSON and YAML manifests remain supported for migration and for the checked-in Bootstrap fixture. New integrations should use .iconpack.yaml so source acquisition and lock verification stay in one place.
go run github.com/araihu/goshtoso/cmd/iconpack@latest \
-source-root ./vendor/bootstrap-icons \
-source-manifest ./bootstrap-icons.goshtoso.json \
-name bootstrap-icons-alarm \
-out ./internal/bootstrapicons -package bootstrapicons \
-const-prefix Icon -sprite-url /assets/icons/bootstrapicons/sprite.svgThis compatibility path still verifies explicit per-file SHA-256 values. It does not read or modify any Muamba manifest.
Serve the generated sprite at the same-origin URL passed to the generator. The generated Icon helper accepts a small config and delegates rendering to Goshtoso's core icon component.
import (
"github.com/araihu/goshtoso/components/icon"
"example.com/myapp/internal/appicons"
)
// Route /assets/icons/appicons/sprite.svg to ./internal/appicons/sprite.svg.
templ ProviderIcon() {
@appicons.Icon(appicons.Config{
Symbol: appicons.IconBrandDeveloperIconsTRPC,
Size: icon.SizeLG,
Label: "tRPC",
RootClass: "text-primary",
})
}appicons.NameBrandDeveloperIconsTRPC represents brand-developer-icons-tRPC. Go identifiers are normalized only for language syntax.
appicons.IconBrandDeveloperIconsTRPC binds devicon-trpc exactly as published by the catalog; do not reconstruct the symbol from the Go name.
When configuration stores canonical names, resolve them through the generated Name type and Lookup. A missing name is a configuration error; do not silently substitute another glyph.
func IconForName(name appicons.Name) icon.Instance {
glyph, ok := appicons.Lookup(name)
if !ok {
panic("icon is not in this generated pack")
}
return appicons.Icon(appicons.Config{
Symbol: glyph.Symbol,
Label: string(glyph.CanonicalName),
})
}Keep these files with the application. Together they record the selected release, source bytes, symbols, output hashes, provenance, and licenses without reopening the source tree.
sprite.svgOnly the selected SVG symbols, with the catalog sprite symbols preserved literally.
icons_gen.goTyped Name, Glyph, icon.Symbol constants, Lookup, Config, SpriteURL, and Icon.
manifest.jsonRelease, source kind, archive identity, selected assets, generated identifiers, and output hashes.
provenance.json + PROVENANCE/Per-family source and license references copied from the verified release.
licenses/ + NOTICEThe notices required to redistribute the selected assets.
<use> behavior.Label. Set Decorative: true on purely visual icons; the generated helper passes both decisions to core.currentColor through your normal Goshtoso classes.The generated-consumer proof above uses the same core rendering path as Goshtoso's bundled icons; it does not modify the bundled sprite.
Goshtoso can store preferences and demo state in your browser. Some examples use cookies and IndexedDB to persist local demo state. There is no analytics, advertising, or third-party tracking. You can use the site without storage, but preferences and some examples will reset or stop persisting. Details in our Privacy Policy.