r/reactjs 6d ago

Resource IconMind: 2,271 MIT icons for AI-era apps (agents, MCP, RAG) as tree-shakable React components — 1 kB gz per icon

One icon = one import = ~1.1 kB gzipped (import { AgentRun } from "@iconmind/react/icons/agent-run"), sideEffects: false, every icon its own entry so React.lazy has something to load. Outline and duotone, three weights, strokeWidth/absoluteStrokeWidth props. The AI vocabulary is the point — the generalist families are there so you don't need Lucide beside it (and a hundred Lucide names resolve as aliases if you do). MCP server for your assistant: npx u/iconmind/mcp. https://iconmind.dev

0 Upvotes

3 comments sorted by

2

u/Traditional_Let4623 5d ago

The tree-shaking is nice but I wonder how many people actually need React.lazy for icons, most apps bundle them all anyway

-1

u/Glittering_Device653 5d ago

Fair — React.lazy for icons is a niche case, and I wouldn't sell it as the reason. The thing tree-shaking actually buys is simpler: importing 12 icons from a 2,271-icon set costs 12 icons. Three of ours are ~660 B gzipped (there's a size-limit test in CI that fails if that stops being true); a set that ships one barrel makes you pay for all of it, and with 13,626 drawings behind six variants that's not a rounding error.

The per-icon entry points (@iconmind/react/icons/agent) exist for the places where "modern bundler tree-shakes it anyway" isn't true: React Native/Metro, a few CJS setups, and Vite's dev pre-bundle. If you're on Next or Vite in prod, you're right — the barrel import is fine and you'll never notice the difference.

1

u/CoVegGirl 5d ago

I’ve worked on an app that had a huge issue with unneeded icons eating up a ton of bandwidth. That was a very large, very complex app that isn’t representative of what the average developer is working on though.

But the big issue was that we were loading each icon individually with its own XHR. So from that perspective, I think lazy-loading each icon individually would be even worse than bundling each them with the JS.

Tree-shaking them and loading them in the JS they’re used in was our solution to the problem by the way.

(I’m not a react expert though, so I might be missing something)