Strapi IconHub started as a custom plugin I built for my own projects — something lightweight but powerful for managing icons in Strapi. Over time, I realized it could be helpful for others too, so I polished it up and made it public. As of now, it’s one of the only Strapi icon solutions that supports both raw SVG and the massive Iconify icon library out of the box.
✨ Features
- 🔍 Search from 200K+ icons via Iconify
- 🎨 Visual icon picker inside the Strapi UI
- 🧩 Stores both icon name and raw SVG code
- 🧱 Use in any collection type or single type
- ⚙️ Ideal for dynamic, styled frontend rendering
- 🚀 Lightweight and performance-friendly
📦 Installation
Install the plugin using your preferred package manager:
# npm
npm i @arshiash80/strapi-plugin-iconhub
# yarn
yarn add @arshiash80/strapi-plugin-iconhub
Then rebuild the admin panel:
# npm
npm run build && npm run develop
# yarn
yarn build && yarn develop
✅ Verify Installation
Once installed, go to Settings > Plugins and confirm that "IconHub" is listed.
🛠️ Usage Guide
- Go to Content-Type Builder.
- Add a new custom field.
- Switch to the Custom tab and select IconHub.
- Click Save to update your schema.
- Now, when creating or editing entries, you'll see an icon picker powered by Iconify:
The stored structure in Strapi looks like:
type IconField = {
iconName: string; // e.g. "mdi:home"
iconData: string; // Raw SVG string
width?: number; // Optional width of icon (from Iconify)
height?: number; // Optional height of icon (from Iconify)
}
🧪 Example Frontend (Next.js)
Here’s a simple example using both @iconify/react
and raw SVG rendering.
import { Icon } from "@iconify/react"; // Import Iconify's React component
// Define the expected shape of each tag item returned from the API
type Tag = {
name: string;
icon: {
iconName: string; // Iconify icon name (e.g., "mdi:home")
iconData: string; // Raw SVG string for custom rendering
width?: number; // Optional width of the SVG
height?: number; // Optional height of the SVG
};
};
export default async function Home() {
// Fetch tag data from the Strapi API
const res = await fetch("http://localhost:1337/api/tags");
const json = await res.json();
const tags: Tag[] = json.data;
return (
<div className="w-full h-screen flex flex-col justify-center items-center gap-5">
<h1 className="text-5xl font-semibold mb-10">Strapi IconHub Plugin Demo</h1>
{/* Section 1: Rendering icons using @iconify/react */}
<section className="text-center">
<h2 className="text-2xl font-semibold mb-4">Using @iconify/react Icon</h2>
<div className="flex flex-wrap gap-2 justify-center">
{tags.map((tag, i) => (
<div
key={i}
className="bg-gray-800 px-3 py-2 rounded flex items-center gap-2"
>
<Icon icon={tag.icon.iconName} /> {/* Renders using Iconify's component */}
<span>{tag.name}</span>
</div>
))}
</div>
</section>
{/* Section 2: Rendering icons using raw SVG data */}
<section className="text-center mt-10">
<h2 className="text-2xl font-semibold mb-4">Using raw SVG</h2>
<div className="flex flex-wrap gap-2 justify-center">
{tags.map((tag, i) => (
<div
key={i}
className="bg-gray-800 px-3 py-2 rounded flex items-center gap-2"
>
{/* Render raw SVG string using dangerouslySetInnerHTML */}
<svg
width={tag.icon.width || 16}
height={tag.icon.height || 16}
viewBox={`0 0 ${tag.icon.width} ${tag.icon.height}`}
dangerouslySetInnerHTML={{ __html: tag.icon.iconData }}
/>
<span>{tag.name}</span>
</div>
))}
</div>
</section>
</div>
);
}
🎨 Styling & Customization
Since raw SVG data is stored, you can freely apply custom styles using classes or inline attributes.
⚠️ Note: Since the plugin uses SVGs from Iconify, rendering them with dangerouslySetInnerHTML
is safe. Still, only do this with trusted content sources.
// Using Iconify
<Icon icon={icon.iconName} className="text-green-500 text-5xl" />
<Icon icon={icon.iconName} className="text-red-500 text-2xl" />
// Using raw SVG
<svgwidth={48}
height={48}
className="text-green-500"
viewBox={`0 0 ${icon.width} ${icon.height}`}
dangerouslySetInnerHTML={{ __html: icon.iconData }}
/>
<svgwidth={24}
height={24}
className="text-red-500"
viewBox={`0 0 ${icon.width} ${icon.height}`}
dangerouslySetInnerHTML={{ __html: icon.iconData }}
/>
🔐 Compatibility
- ✅ Strapi v4 & v5
- ✅ TypeScript support
- ✅ Compatible with all modern frontend frameworks (Next.js, Vue, etc.)