Search 220,000+ open source icons, logos and emoji from 91 curated sets — instant keyword search plus semantic (natural-language) search, with copy/download as SVG, PNG, React, Vue, Svelte or CSS. Live at https://iconsdb.app.
- Data comes from Iconify's per-set
@iconify-json/*packages.packages/icon-indexnormalises them into- D1 rows (icon bodies + metadata) — seeded with
wrangler d1 execute, - a compact client search index (
search-index.json, ~600 KB gzipped) for instant in-browser keyword search, - int8 embeddings (
embeddings.bin, ~11 MB) of every unique icon name, computed locally withbge-small-en-v1.5.
- D1 rows (icon bodies + metadata) — seeded with
- Animated icons — 2,007 of them, in two flavours. line-md, meteocons, svg-spinners, svg-loaders, Agent Loaders and a few eos-icons carry SMIL in the body, which plays wherever the SVG is inlined. Dither Icons animate on hover through a stylesheet keyed to runtime hooks the body cannot carry, so
packages/icon-index/src/dither-motion.tsrewrites those hooks onto classes and prunes the sheet to the rules one icon needs. Either waypackages/core/src/animation.tsdetects them (animatedcolumn per icon, count per collection, index list for the "Animated only" filter) and resolves a still (staticFrame, the most legible frame rather than the last one) for the places animation cannot go: PNG export, CSS masks, and?staticon the SVG endpoint. - Search is hybrid: the browser runs keyword/prefix search itself;
/api/v1/searchembeds the query with Workers AI (@cf/baai/bge-small-en-v1.5), brute-forces cosine similarity over the embeddings in the isolate, and the two lists are blended bypackages/core/src/rank.ts. - App icons — one set is raster rather than vector.
app-iconsholds the 500 most-rated apps on the US App Store as PNGs at 128/256/512/1024, in two shapes:square(Apple's artwork untouched) androunded(the iOS squircle applied as a superellipse, since iOS artwork is a flat opaque square and the OS masks it at render time). These rows carryraster=1and an emptybody; the blobs live in R2 andpackages/core/src/raster.tsis where the split is defined. Unlike every other set they are not openly licensed — see below. - Site is Next.js (App Router) deployed to Cloudflare Workers via
@opennextjs/cloudflare, with D1 for icon data, KV for the Next incremental cache, and static assets for the index files.
apps/web Next.js app + API routes + wrangler config
packages/core shared types, keyword search, ranking, SVG rendering, code snippets
packages/icon-index data pipeline (build -> embed -> seed)
pnpm install
pnpm index:build # normalise icon sets -> packages/icon-index/dist
pnpm --filter @icons-db/icon-index embed # compute embeddings (≈15 s on a laptop)
pnpm dev # next dev with remote D1 + Workers AI bindingsapps/web/scripts/sync-data.mjs copies the pipeline output into apps/web/public/data before dev/build.
cd apps/web
wrangler d1 migrations apply icons-db --remote
for f in ../../packages/icon-index/dist/seed/*.sql; do wrangler d1 execute icons-db --remote --yes --file="$f"; done
pnpm ship # opennextjs-cloudflare build && deploypnpm --filter @icons-db/icon-index add @iconify-json/<prefix>- Add the prefix (and homepage) to
packages/icon-index/src/collections.ts; add manual style suffixes topackages/core/src/variants.tsif the set's metadata doesn't declare them. - Re-run build → embed → seed → deploy.
Animated sets need no extra step: isAnimated flags each icon during the build. A raster set is
a different shape again — see "Raster (PNG) sets" in .claude/skills/deploy/SKILL.md.
One set is ours rather than normalised from upstream: Agent Loaders
(packages/icon-index/icons/agent-loaders/), 39 hand-authored SMIL icons for the states an
LLM or agent UI reports — thinking, calling a tool, reading a file, embedding, streaming
tokens back. Drop a new 24x24 SVG in that directory and the build picks it up; the
conventions are in packages/icon-index/src/agent-loaders.ts.
Code is MIT licensed (see LICENSE) — this covers the site, API, MCP server and pipeline, not the icons. Icons keep their original licenses (MIT/Apache-2.0/ISC/CC0; see https://iconsdb.app/licenses for every set).
One exception: the app-icons set is not open source. Each icon is the property of its app's
publisher, reproduced to identify that app, and carries no licence grant — see
packages/icon-index/app-icons/NOTICE.md and https://iconsdb.app/licenses#app-icons, which
includes the removal process for publishers.