- v0.0.97-integrationLatest
- v0.0.98-productionalize
- v0.0.97-productionalize
- v0.0.96
- v0.0.96-integration
- v0.0.95
- v0.0.95-integration
- v0.0.94
- v0.0.94-integration
- v0.0.93
- v0.0.93-integration
- v0.0.92-integration
- v0.0.92
- v0.0.91
- v0.0.91-integration
- v0.0.90-integration
- v0.0.90
- v0.0.89
- v0.0.89-integration
- v0.0.88
- v0.0.88-integration
- v0.0.86
- v0.0.86-integration
- v0.0.85-integration
- v0.0.85
- v0.0.84
- v0.0.84-integration
- v0.0.83
- v0.0.83-integration
- v0.0.82
- v0.0.81
- v0.0.81-integration
- v0.0.80
- v0.0.80-integration
- v0.0.79
- v0.0.79-integration
- v0.0.78
- v0.0.78-integration
- v0.0.77
- v0.0.77-integration
- v0.0.76
- v0.0.76-integration
- v0.0.75
- v0.0.75-integration
- v0.0.74
- v0.0.74-integration
- v0.0.73
- v0.0.73-integration
- v0.0.72-integration
- v0.0.68
- v0.0.68-integration
- v0.0.67
- v0.0.67-integration
- v0.0.66
- v0.0.66-integration
- v0.0.65
- v0.0.65-integration
- v0.0.64
- v0.0.64-integration
- v0.0.63
- v0.0.63-integration
- v0.0.62
- v0.0.62-integration
- v0.0.61-integration
- v0.0.59
- v0.0.59-integration
- v0.0.58
- v0.0.58-integration
- v0.0.57
- v0.0.57-integration
- v0.0.48-integration
- v0.0.55
- v0.0.47-integration
- v0.0.53
- v0.0.46-integration
- v0.0.51
- v0.0.45-integration
- v0.0.49
- v0.0.44-integration
- v0.0.44
- v0.0.41-integration
- v0.0.42
- v0.0.40-integration
- v0.0.39
- v0.0.39-integration
- v0.0.38
- v0.0.38-integration
- v0.0.37
- v0.0.37-integration
- v0.0.36-integration
- v0.0.35
- v0.0.35-integration
- v0.0.34
- v0.0.34-integration
- v0.0.33
- v0.0.33-integration
- v0.0.32
- v0.0.32-integration
- v0.0.31
- v0.0.31-integration
- v0.0.30
- v0.0.30-integration
- v0.0.28
- v0.0.28-integration
- v0.0.27
- v0.0.27-integration
- v0.0.26
- v0.0.26-integration
- v0.0.25
- v0.0.25-integration
- v0.0.24
- v0.0.24-integration
- v0.0.23-integration
- v0.0.21-integration
- v0.0.19
- v0.0.19-integration
- v0.0.18
- v0.0.18-integration
- v0.0.17
- v0.0.17-integration
- v0.0.16
- v0.0.16-integration
- v0.0.15
- v0.0.15-integration
- v0.0.14
- v0.0.14-integration
- v0.0.13-integration
- v0.0.13
- v0.0.10-integration
- v0.0.11
- v0.0.9-integration
- v0.0.9
- v0.0.8
- v0.0.8-integration
- v0.0.7-integration
- v0.0.6-integration
- v0.0.5-integration
- v0.0.4-integration26
- v0.0.4
- v0.0.3-integration40
- v0.0.3-integration39
- v0.0.3-integration38
- v0.0.3-integration37
- v0.0.3-integration35
- v0.0.3-integration34
- v0.0.3-integration33
- v0.0.3-integration32
- v0.0.3-integration31
- v0.0.3-integration30
- v0.0.3-integration29
- v0.0.3-integration28
- v0.0.3-integration27
- v0.0.3-integration26
- v0.0.3-integration25
- v0.0.3-integration24
- v0.0.3-integration23
- v0.0.3-integration22
- v0.0.3-integration21
- v0.0.3-integration20
- v0.0.3-integration19
- v0.0.3-integration18
- v0.0.3-integration17
- v0.0.3-integration16
- v0.0.3-integration15
- v0.0.3
- v0.0.3-integration14
- v0.0.3-integration13
- v0.0.3-integration12
- v0.0.3-integration11
- v0.0.3-integration10
- v0.0.3-integration9
- v0.0.3-integration8
- v0.0.3-integration1
- v0.0.3-integration0
- v0.0.2-integration0
- v0.0.1
- v0.0.2
- v0.0.1-integration64
- v0.0.1-integration63
- v0.0.1-integration62
- v0.0.1-integration60
- v0.0.1-integration59
- v0.0.1-integration58
- v0.0.1-integration57
- v0.0.1-integration56
- v0.0.1-integration55
- v0.0.1-integration51
- v0.0.1-integration50
- v0.0.1-integration49
- v0.0.1-integration48
- v0.0.1-integration47
- v0.0.1-integration46
- v0.0.1-integration45
- v0.0.1-integration44
- v0.0.1-integration43
- v0.0.1-integration42
- v0.0.1-integration41
- v0.0.1-integration39
- v0.0.1-integration38
- v0.0.1-integration37
- v0.0.1-integration36
- v0.0.1-integration35
- v0.0.1-integration34
- v0.0.1-integration33
- v0.0.1-integration32
- v0.0.1-integration31
- v0.0.1-integration30
- v0.0.1-integration29
- v0.0.1-integration28
- v0.0.1-integration27
- v0.0.1-integration26
- v0.0.1-integration25
- v0.0.1-integration24
- v0.0.1-integration23
- v0.0.1-integration22
- v0.0.1-integration21
- v0.0.1-integration20
- v0.0.1-integration19
- v0.0.1-integration18
- v0.0.1-integration17
- v0.0.1-integration16
- v0.0.1-integration15
- v0.0.1-integration14
- v0.0.1-integration13
- v0.0.1-integration12
- v0.0.1-integration11
- v0.0.1-integration10
- v0.0.1-integration9
- v0.0.1-integration8
- v0.0.1-integration7
- v0.0.1-integration6
- v0.0.1-integration4
Fathym Atomic Icons
Build, optimize, and consume SVG icon sprite sheets with ergonomic, typed icon components for Deno projects. Works standalone or alongside Fathym’s Everything‑as‑Code (EaC) runtime.
Install
Add imports to your deno.json
or deno.jsonc
using JSR. Pin a version for stability.
{
"imports": {
"@fathym/atomic-icons": "jsr:@fathym/atomic-icons@^0.0.0",
"@fathym/atomic-icons/browser": "jsr:@fathym/atomic-icons/browser@^0.0.0"
}
}
Note: You can also use the deno.land URL if preferred, but JSR is recommended for resolution and versioning.
Naming Icons
Prefer semantic names decoupled from the upstream set. For example, map material-symbols:check-circle
to check-circle
. This keeps usage consistent across the app and makes future set swaps painless.
Quick Start
- Create a config describing your icon set and generation options.
// ./fathym-atomic-icons.config.ts
import { IconSetConfig, IconSetGenerateConfig } from "@fathym/atomic-icons";
export const curIconSetConfig: IconSetConfig = {
IconMap: {
"x-circle": "https://api.iconify.design/bi:x-circle.svg",
"check-circle": "https://api.iconify.design/material-symbols:check-circle.svg",
"exclaim": "https://api.iconify.design/bi:exclamation-circle.svg",
},
Optimize: true, // run SVGO on the generated sheet
};
export const curIconSetGenerateConfig: IconSetGenerateConfig = {
// When true, write typed <XxxIcon /> wrappers and add an import alias.
Exports: true,
// Optional: where generated files go (defaults to ./build/iconset)
// OutputDirectory: "./build/iconset",
IconSet: curIconSetConfig,
// URL path where the sheet is available (static or served).
SpriteSheet: "/iconset/icons",
};
- Generate assets via a script and Deno task.
// ./scripts/icons.atomic.ts
import { useFileIconSet, useIconSetComponents } from "@fathym/atomic-icons";
import { curIconSetConfig, curIconSetGenerateConfig } from "../fathym-atomic-icons.config.ts";
// Generate a physical sheet. Adjust the path for your static files setup.
await useFileIconSet("./static/icons.sprite.svg", curIconSetConfig);
// Generate typed components + add a Deno import alias for easy consumption.
await useIconSetComponents(curIconSetGenerateConfig, "");
// deno.jsonc
{
"tasks": {
"icons": "deno run -A ./scripts/icons.atomic.ts"
}
}
Run: deno task icons
Add build/
to your .gitignore
.
- Use your icons.
// Option A: Use the low-level <Icon /> with your sheet
import { Icon } from "@fathym/atomic-icons/browser";
export default function Page() {
return (
<>
<Icon src="/iconset/icons" icon="x-circle" />
<Icon src="/iconset/icons" icon="check-circle" class="text-blue-500 w-[50px] h-[50px]" />
</>
);
}
// Option B: Use generated components (added under the alias below)
import { CheckCircleIcon, ExclaimIcon, XCircleIcon } from "$fathym/atomic-icons";
export default function Page() {
return (
<>
<XCircleIcon />
<CheckCircleIcon class="text-purple-500 w-[50px] h-[50px]" />
<ExclaimIcon class="text-purple-500 w-[24px] h-[24px]" />
</>
);
}
When Exports
is true, useIconSetComponents
writes an import alias to your deno.json(c)
:
{
"imports": {
"$fathym/atomic-icons": "./build/iconset/icons/.exports.ts"
}
}
Serving the Sprite Sheet
- Static: Commit or copy the generated
./static/icons.sprite.svg
and reference it via<Icon src="/icons.sprite.svg" ... />
. - EaC runtime: This package also provides an EaC processor/handler that can serve the sheet dynamically at the
SpriteSheet
path. If you are using Fathym’s runtime, wire upEaCAtomicIconsProcessor
with yourIconSet
config and route pattern. (See thesrc/plugin
folder for details.)
Icon Sources
Any SVG can go into the sprite sheet. Good sources:
- Icônes: https://icones.js.org/
- Simple Icons: https://simpleicons.org/
- Flowbite Icons: https://flowbite.com/icons
API Reference (quick)
IconSetConfig
:{ IconMap: Record<string, string | URL>; Optimize?: boolean }
useFileIconSet(outputPath, config)
: Renders and writes an SVG sheet, runs SVGO whenOptimize
is true.IconSetGenerateConfig
:{ IconSet, SpriteSheet, Exports?, Imports?, OutputDirectory?, Generate? }
useIconSetComponents(config, root)
: Generates typed icon components and (optionally) adds an import alias to your Deno config.root
should be the path prefix used when resolvingSpriteSheet
(often""
for absolute paths).- Browser exports:
@fathym/atomic-icons/browser
exposes{ Icon, type IconProps, type JSX }
.
Tips
- Keep names semantic and stable (
check-circle
,x-circle
, etc.). - Pin package versions in
deno.json(c)
for reproducible builds. - If you change
SpriteSheet
, re-run theicons
task so generated components point to the correct path.
Acknowledgements
Thanks to the authors whose posts informed parts of this implementation: