https://github.com/lindemannrock/craft-icon-manager
A comprehensive Craft CMS plugin for icon management supporting SVG files, sprites, Font Awesome, and Material Icons with searchable picker and template integration
https://github.com/lindemannrock/craft-icon-manager
cms craft craft-cms craft-cms-plugin craft-plugin craftcms field-type fontawesome icon icon-management icon-manager icon-picker material-icons php svg
Last synced: 8 days ago
JSON representation
A comprehensive Craft CMS plugin for icon management supporting SVG files, sprites, Font Awesome, and Material Icons with searchable picker and template integration
- Host: GitHub
- URL: https://github.com/lindemannrock/craft-icon-manager
- Owner: LindemannRock
- License: other
- Created: 2025-09-01T18:28:39.000Z (10 months ago)
- Default Branch: main
- Last Pushed: 2026-04-05T09:49:23.000Z (2 months ago)
- Last Synced: 2026-04-05T11:23:30.694Z (2 months ago)
- Topics: cms, craft, craft-cms, craft-cms-plugin, craft-plugin, craftcms, field-type, fontawesome, icon, icon-management, icon-manager, icon-picker, material-icons, php, svg
- Language: PHP
- Homepage:
- Size: 813 KB
- Stars: 0
- Watchers: 1
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.md
Awesome Lists containing this project
README
# Icon Manager for Craft CMS
[](https://packagist.org/packages/lindemannrock/craft-icon-manager)
[](https://craftcms.com/)
[](https://php.net/)
[](https://github.com/LindemannRock/craft-logging-library)
[](LICENSE)
A comprehensive icon management field supporting SVG libraries and icon fonts for Craft CMS 5.x.
## License
This is a commercial plugin licensed under the [Craft License](https://craftcms.github.io/license/). It will be available on the [Craft Plugin Store](https://plugins.craftcms.com) soon. See [LICENSE.md](LICENSE.md) for details.
## ⚠️ Pre-Release
This plugin is in active development and not yet available on the Craft Plugin Store. Features and APIs may change before the initial public release.
## Table of Contents
- [Icon Manager for Craft CMS](#icon-manager-for-craft-cms)
- [Table of Contents](#table-of-contents)
- [Quick Start](#quick-start)
- [Features](#features)
- [Development Status](#development-status)
- [Requirements](#requirements)
- [Installation](#installation)
- [Via Composer](#via-composer)
- [Using DDEV](#using-ddev)
- [Via Control Panel](#via-control-panel)
- [Configuration](#configuration)
- [Plugin Settings](#plugin-settings)
- [Config File](#config-file)
- [Available Configuration Options](#available-configuration-options)
- [Scan Control Settings](#scan-control-settings)
- [Creating Icon Sets](#creating-icon-sets)
- [SVG Folder](#svg-folder)
- [SVG Sprite](#svg-sprite)
- [Font Awesome](#font-awesome)
- [Material Icons](#material-icons)
- [Web Font](#web-font)
- [Usage](#usage)
- [Field Type](#field-type)
- [Template Variables](#template-variables)
- [Basic Icon Rendering](#basic-icon-rendering)
- [Working with Icon Objects](#working-with-icon-objects)
- [List Icons from a Set](#list-icons-from-a-set)
- [Search Icons](#search-icons)
- [Working with Icon Sets](#working-with-icon-sets)
- [Rendering Options](#rendering-options)
- [Icon Metadata](#icon-metadata)
- [Basic Structure](#basic-structure)
- [Advanced Structure with Multilingual Support](#advanced-structure-with-multilingual-support)
- [Label Resolution Priority](#label-resolution-priority)
- [Supported Metadata Properties](#supported-metadata-properties)
- [Security](#security)
- [Automatic Sanitization](#automatic-sanitization)
- [How It Works](#how-it-works)
- [What's Not Sanitized](#whats-not-sanitized)
- [Template Safety](#template-safety)
- [Field Settings](#field-settings)
- [Icon Size](#icon-size)
- [Show Labels](#show-labels)
- [Enable Search](#enable-search)
- [Caching](#caching)
- [Configuration](#configuration-1)
- [Cache Management](#cache-management)
- [Logging](#logging)
- [Permissions](#permissions)
- [Environment-Specific Paths](#environment-specific-paths)
- [SVG Optimization](#svg-optimization)
- [Console Help](#console-help)
- [Enabling/Disabling Optimization](#enablingdisabling-optimization)
- [Optimization Features](#optimization-features)
- [Issue Detection](#issue-detection)
- [PHP Optimizer (Default)](#php-optimizer-default)
- [SVGO (Advanced)](#svgo-advanced)
- [Scan Controls vs SVGO Configuration](#scan-controls-vs-svgo-configuration)
- [Missing Icon Handling](#missing-icon-handling)
- [Performance Tips](#performance-tips)
- [For Large Icon Sets (500+ icons)](#for-large-icon-sets-500-icons)
- [For Material Icons](#for-material-icons)
- [Cache Strategy by Environment](#cache-strategy-by-environment)
- [Troubleshooting](#troubleshooting)
- [Icons Not Showing in Picker](#icons-not-showing-in-picker)
- [Icons Not Rendering in Templates](#icons-not-rendering-in-templates)
- [Optimization Not Working](#optimization-not-working)
- [Performance Issues with Large Icon Sets](#performance-issues-with-large-icon-sets)
- [Config File Not Working](#config-file-not-working)
- [Examples](#examples)
- [Support](#support)
- [License](#license)
## Quick Start
Get up and running with Icon Manager in 5 minutes:
**1. Install the plugin**
```bash
composer require lindemannrock/icon-manager
./craft plugin/install icon-manager
```
**2. Create your first icon set**
- Go to **Icon Manager → Icon Sets** in the Control Panel
- Click **"New Icon Set"**
- Choose **"SVG Folder"** as the type
- Select a folder containing SVG files (or use the default `/icons` folder)
- Save the icon set
**3. Add an icon field to your section**
- Go to **Settings → Fields**
- Create a new **"Icon Manager"** field
- Add it to your entry type
- Start selecting icons in your entries!
**That's it!** Icons are now available in your templates via `{{ entry.iconField.render() }}`.
See [Usage](#usage) below for template examples and advanced features.
## Features
- **Multiple Icon Formats**: Support for SVG files, SVG sprites, Font Awesome, Material Icons, and custom web fonts
- **Intuitive Interface**: Searchable icon picker with preview, tabs/dropdown for multiple sets
- **Flexible Configuration**: Configure icon sets and field settings (size, labels, search)
- **Performance Optimized**: File or Redis caching for fast icon loading
- **Security**: SVG sanitization to prevent XSS attacks
- **Twig Integration**: Easy icon rendering in templates with automatic HTML safety
- **GraphQL Support**: Icon fields expose structured icon data in Craft GraphQL schemas
## Development Status
⚠️ **Beta Features** - The following features are currently in testing and finalization:
- **SVG Sprite support** - Basic functionality implemented, advanced features pending
- **Material Icons** - Core integration complete, variable fonts being refined
- **Font Awesome** - Free icons working, Pro/Kit support in development
- **Web Font** - Custom icon font support (TTF, WOFF, OTF) with glyph extraction
SVG folder icons are fully stable and production-ready.
## Requirements
- Craft CMS 5.0 or greater
- PHP 8.3 or greater
- [Logging Library](https://github.com/LindemannRock/craft-logging-library) 5.0 or greater (installed automatically as dependency)
## Installation
### Via Composer
```bash
cd /path/to/project
```
```bash
composer require lindemannrock/craft-icon-manager
```
```bash
./craft plugin/install icon-manager
```
### Using DDEV
```bash
cd /path/to/project
```
```bash
ddev composer require lindemannrock/craft-icon-manager
```
```bash
ddev craft plugin/install icon-manager
```
### Via Control Panel
In the Control Panel, go to Settings → Plugins and click "Install" for Icon Manager.
## Configuration
### Plugin Settings
Settings can be configured in the Control Panel at Settings → Icon Manager, or via a config file.
1. **Icon Sets Path**: Set the path to your icon files (default: `@root/icons`)
2. **Cache Settings**: Configure caching for better performance
3. **Display Settings**: Set default display options
4. **Icon Types**: Enable/disable different icon set types
### Config File
Create a `config/icon-manager.php` file to override default settings:
```bash
cp vendor/lindemannrock/craft-icon-manager/src/config.php config/icon-manager.php
```
```php
[
// Plugin display name
'pluginName' => 'Icon Manager',
// Default icons path
'iconSetsPath' => '@root/src/icons',
// Icon types to enable
'enabledIconTypes' => [
'svg-folder' => true,
'svg-sprite' => true,
'font-awesome' => false,
'material-icons' => false,
'web-font' => false,
],
// SVG Optimization
'enableOptimization' => true,
'enableOptimizationBackup' => true,
// Scan Controls (what scanner detects - PHP optimizer only, SVGO uses svgo.config.js)
'scanClipPaths' => true, // Detect empty/unused clip-paths (used ones preserved)
'scanMasks' => true, // Detect empty/unused masks (used ones preserved)
'scanFilters' => true, // Detect filter effects
'scanComments' => true, // Detect regular comments (legal preserved)
'scanInlineStyles' => true, // Detect convertible styles (CSS-only properties preserved)
'scanLargeFiles' => true, // Detect files >10KB (warning only)
'scanWidthHeight' => true, // Detect width/height without viewBox (critical)
'scanWidthHeightWithViewBox' => false, // Detect width/height with viewBox (optional)
],
// Dev environment settings
'dev' => [
// Use source icons in dev
'iconSetsPath' => '@root/src/icons',
// Cache settings for dev
'cacheStorageMethod' => 'file',
'enableCache' => true,
'cacheDuration' => 3600, // 1 hour
// Detailed logging for development
'logLevel' => 'debug',
// Allow all icon types for testing
'enabledIconTypes' => [
'svg-folder' => true,
'svg-sprite' => true,
'font-awesome' => true,
'material-icons' => true,
'web-font' => true,
],
],
// Staging environment settings
'staging' => [
// Production-ready icons path
'iconSetsPath' => '@webroot/dist/assets/icons',
// Optimize for staging
'enableCache' => true,
'cacheDuration' => 86400, // 1 day
],
// Production environment settings
'production' => [
// Production icons path
'iconSetsPath' => '@webroot/dist/assets/icons',
// Optimize for production
'cacheStorageMethod' => 'redis', // Use Redis in production
'enableCache' => true,
'cacheDuration' => 2592000, // 30 days
// Minimal logging for production
'logLevel' => 'warning',
// Only stable icon types in production
'enabledIconTypes' => [
'svg-folder' => true,
'svg-sprite' => false, // Beta
'font-awesome' => false, // Beta
'material-icons' => false, // Beta
'web-font' => false, // Beta
],
],
];
```
Settings defined in the config file will override CP settings and show a warning message in the settings UI.
See [Configuration Documentation](docs/CONFIGURATION.md) for all available options.
#### Available Configuration Options
- **pluginName** - Customize the plugin display name in navigation and settings
- **iconSetsPath** - Path to icon files (supports `@root`, `@storage`, `@webroot`, absolute paths inside those roots, and environment variables that resolve inside those roots)
- **enableCache** - Whether to cache icon data for better performance
- **cacheDuration** - How long to cache icon data, in seconds
- **itemsPerPage** - Number of icon sets per page in CP index (10-500, default: 100)
- **enabledIconTypes** - Enable/disable specific icon set types
- **enableOptimization** - Enable/disable SVG optimization features (default: true)
- **enableOptimizationBackup** - Automatically create backups before optimization (default: true)
- **Scan Controls** - Granular control over what the scanner detects (see Scan Control Settings below)
- **logLevel** - Logging verbosity: error, warning, info, or debug
#### Scan Control Settings (Detection Only)
These settings control what the scanner **detects and reports** in the UI. They do NOT control what gets optimized.
```php
// config/icon-manager.php
return [
'scanClipPaths' => true, // Detect empty/unused clip-paths
'scanMasks' => true, // Detect empty/unused masks
'scanFilters' => true, // Detect filter effects
'scanComments' => true, // Detect comments (excludes legal )
'scanInlineStyles' => true, // Detect convertible inline styles
'scanLargeFiles' => false, // Detect files >10KB (informational)
'scanWidthHeight' => true, // Detect width/height without viewBox (critical)
'scanWidthHeightWithViewBox' => false, // Detect width/height with viewBox (optional)
];
```
**What each scan detects:**
- **scanClipPaths**: Flags empty or unreferenced clip-paths. Used clip-paths are not flagged.
- **scanMasks**: Flags empty or unreferenced masks. Used masks are not flagged.
- **scanFilters**: Flags `` elements (informational - may slow rendering).
- **scanComments**: Flags regular comments (legal comments `` preserved).
- **scanInlineStyles**: Flags convertible styles (CSS-only properties like `isolation` preserved).
- **scanLargeFiles**: Informational for files >10KB (use as file size monitoring guide - may be normal for complex icons, optimization may reduce size but not always).
- **scanWidthHeight**: Flags width/height without viewBox (responsive SVG issue).
- **scanWidthHeightWithViewBox**: Flags width/height even with viewBox (optional optimization).
#### PHP Optimizer Settings (What Gets Applied)
Control which optimization rules are applied during PHP optimization:
```php
// config/icon-manager.php
return [
// Risky rule gate
'optimizeAllowRiskyRules' => true,
// Conversion rules
'optimizeConvertColorsToHex' => true,
'optimizeConvertCssClasses' => true,
'optimizeConvertEmptyTags' => true,
'optimizeConvertInlineStyles' => true,
'optimizeFixAttributeNames' => true,
// Minification rules
'optimizeMinifyCoordinates' => true,
'optimizeMinifyTransformations' => true,
// Removal rules
'optimizeRemoveAriaAndRole' => false,
'optimizeRemoveComments' => true,
'optimizeRemoveDataAttributes' => false,
'optimizeRemoveDefaultAttributes' => true,
'optimizeRemoveDeprecatedAttributes' => true,
'optimizeRemoveDoctype' => true,
'optimizeRemoveDuplicateElements' => true,
'optimizeRemoveEnableBackground' => true,
'optimizeRemoveEmptyAttributes' => true,
'optimizeRemoveEmptyGroups' => true,
'optimizeRemoveEmptyTextElements' => true,
'optimizeRemoveInkscapeFootprints' => true,
'optimizeRemoveInvisibleCharacters' => true,
'optimizeRemoveMetadata' => true,
'optimizeRemoveNonStandardAttributes' => false,
'optimizeRemoveNonStandardTags' => false,
'optimizeRemoveTitleAndDesc' => false,
'optimizeRemoveUnsafeElements' => true,
'optimizeRemoveWhitespace' => true,
'optimizeRemoveUnusedNamespaces' => true,
'optimizeRemoveUnusedMasks' => true,
'optimizeRemoveWidthHeight' => true,
// Structure rules
'optimizeFlattenGroups' => true,
'optimizeScopeSvgStyles' => false,
'optimizeSortAttributes' => true,
];
```
Most cleanup rules default to `true`. Some v8 rules are intentionally more conservative by default, especially risky or security-sensitive rules.
### Creating Icon Sets
1. Navigate to Icon Manager → Icon Sets in the CP
2. Click "New Icon Set"
3. Choose the type and configure settings:
#### SVG Folder
- Point to a folder containing SVG files
- Optionally include subfolders
- Supports metadata.json for keywords
- Works great with icon libraries like:
- [Lucide](https://lucide.dev/) - 1,600+ open source icons
- [Heroicons](https://heroicons.com/) - Beautiful hand-crafted SVG icons
- [Tabler Icons](https://tabler-icons.io/) - 3,000+ free SVG icons
- Any other SVG icon library
#### SVG Sprite
- Point to an SVG sprite file containing multiple `` elements
- Set optional ID prefix for icon references
- **Performance**: Sprite file is loaded once and injected into the page DOM, allowing all icons to reference the same sprite
- **Best for**: Projects using many icons from the same set (e.g., 10+ icons)
- Supports standard SVG sprite format with `` structure
#### Font Awesome
- Supports Font Awesome v7 (latest)
- Configure styles (solid, regular, brands)
- Icons loaded from predefined lists
- Kit support planned for future release
#### Material Icons
- Material Icons (classic) with all styles
- Material Symbols with variable font support
- Configurable axes (weight, fill, optical size)
- **Performance Note**: Automatically loads Google Fonts font file (~3.7 MB) containing all 3,800+ icons. The font file is cached by the browser after first load, but represents a significant initial download.
- **Alternative**: For better performance, download SVG versions of only the icons you need from [Google Fonts](https://fonts.google.com/icons) and add them to an SVG folder or sprite icon set instead.
#### Web Font
- Custom icon fonts (TTF, WOFF, OTF supported)
- Automatic glyph extraction with unicode mapping
- @font-face CSS generation and serving
- Configurable CSS prefix for icon classes
- **Performance**: Font file is served through Craft and cached by the browser after first load. Font size depends on the number of glyphs in your custom font.
- **Note**: WOFF2 not currently supported - use TTF or WOFF formats
## Usage
### Field Type
Add an Icon field to any element:
1. Create a new field of type "Icon Manager"
2. Configure field settings:
- **Enable Search**: Show search box in picker
- **Show Labels**: Display icon names in picker
- **Icon Size**: Small (32px), Medium (48px), or Large (64px)
- **Icon Sets**: Choose which sets are available
- **Allow Multiple Selection**: Enable selecting multiple icons (returns array)
- **Allow Custom Labels**: Let users add custom labels for icons
- **Icons Per Page**: Number of icons displayed in picker (10-500)
3. Use in templates:
```twig
{# Single icon field #}
{% if entry.iconField %}
{{ entry.iconField.render({ size: 32, class: 'my-icon' }) }}
{% endif %}
{# Multiple icons field #}
{% if entry.multipleIconsField %}
{% for icon in entry.multipleIconsField %}
{{ icon.render({ size: 24, class: 'icon-item' }) }}
{{ icon.displayLabel }}
{% endfor %}
{% endif %}
{# displayLabel provides smart label resolution:
1. Site-specific custom label (if set)
2. General custom label (if set)
3. JSON metadata label
4. Database label
5. Translation
6. Formatted filename (fallback)
#}
```
Note: The `|raw` filter is not needed - icons are automatically rendered safely.
### GraphQL
Icon Manager fields expose GraphQL types for both single-select and multi-select field values.
Available GraphQL fields:
- `name`
- `label`
- `type`
- `value`
- `iconSetHandle`
- `customLabel`
- `svg`
- `content`
Single-select fields resolve to one icon object. Multi-select fields resolve to a list of icon objects.
### Template Variables
#### Basic Icon Rendering
```twig
{# Render an icon directly #}
{{ craft.iconManager.renderIcon('myIconSet', 'arrow-right') }}
{# With options (size, class, etc.) #}
{{ craft.iconManager.renderIcon('myIconSet', 'arrow-right', {
width: 24,
height: 24,
class: 'text-blue-500'
}) }}
```
#### Working with Icon Objects
```twig
{# Get icon object for more control #}
{% set icon = craft.iconManager.getIcon('myIconSet', 'star') %}
{% if icon %}
{# Render with default settings #}
{{ icon.render() }}
{# Render with custom attributes #}
{{ icon.render({
width: 32,
height: 32,
class: 'icon-custom',
'aria-label': 'Star rating'
}) }}
{# Get raw SVG content #}
{{ icon.getContent() }}
{# Access icon properties #}
{{ icon.render() }}
{% endif %}
```
#### List Icons from a Set
```twig
{# Get all icons from a set #}
{% set icons = craft.iconManager.getIcons('myIconSet') %}
{% for icon in icons %}
{{ icon.render({ width: 24, height: 24 }) }}
{{ icon.name }}
{% endfor %}
```
#### Search Icons
```twig
{# Search for icons across all sets #}
{% set searchResults = craft.iconManager.searchIcons('arrow') %}
{# Search within specific sets #}
{% set searchResults = craft.iconManager.searchIcons('arrow', ['myIconSet', 'fontAwesome']) %}
{% for icon in searchResults %}
{{ icon.render({ width: 20, height: 20 }) }}
{{ icon.name }} ({{ icon.iconSet.name }})
{% endfor %}
```
#### Working with Icon Sets
```twig
{# Get all enabled icon sets #}
{% set iconSets = craft.iconManager.getEnabledIconSets() %}
{# Get a specific icon set #}
{% set iconSet = craft.iconManager.getIconSet('myIconSet') %}
{% if iconSet %}
{{ iconSet.name }}
Type: {{ iconSet.type }}
Icon count: {{ iconSet.icons|length }}
{% endif %}
```
### Rendering Options
```twig
{{ icon.render({
# Dimensions
width: 24,
height: 24,
# CSS class
class: 'custom-icon-class',
# Additional attributes
'data-icon': icon.name,
'aria-label': 'Icon description',
'role': 'img',
# Style attribute
style: 'fill: currentColor;'
}) }}
```
## Icon Metadata
Add a `metadata.json` file in your icon folders to provide enhanced metadata:
### Basic Structure
```json
{
"star": {
"keywords": ["favorite", "rating", "bookmark"]
},
"heart": {
"keywords": ["love", "like", "favorite"]
}
}
```
### Advanced Structure with Multilingual Support
```json
{
"freshly-baked": {
"label": "Freshly Baked",
"label_en": "Freshly Baked",
"label_ar": "مخبوز طازج",
"label_fr": "Fraîchement Cuit",
"label_de": "Frisch Gebacken",
"label_es": "Recién Horneado",
"label_it": "Appena Sfornato",
"search": {
"terms": ["fresh", "baked", "bread", "bakery", "طازج", "مخبوز", "خبز", "frais", "cuit", "frisch", "gebacken"]
},
"category": "product-features",
"description": "Icon representing freshly baked products"
}
}
```
**Language Code Format:**
- Use `label_{languageCode}` where `{languageCode}` is the site's language code
- **Use underscore `_` not hyphen `-`**: `label_en`, `label_ar`, `label_fr` (correct) vs `label-en` (wrong)
- Supports any language: `label_en`, `label_ar`, `label_fr`, `label_de`, `label_es`, `label_it`, etc.
- Legacy format (`labelEn`, `labelAr`) still supported for backward compatibility
- Primary language codes only (e.g., `en-US` → uses `label_en`, `ar-AE` → uses `label_ar`)
**Label Resolution in Control Panel:**
- Uses the `?site=` URL parameter to determine which language to show
- Example: When editing `?site=fr`, shows `label_fr` from JSON
- Falls back gracefully: `label_fr` → `labelFr` → `label` → filename
**Custom Labels (Per-Site):**
- Custom labels are stored per-site using `customLabels[siteId]` object
- Each site can have different custom labels for the same icon
- Translation Method "Translate for each site" recommended for independent icon selection per site
- Custom labels take priority over JSON labels when set
### Label Resolution Priority
The plugin resolves icon labels in this order:
1. **Site-specific custom label** (highest priority) - set via field's custom label input for current site
2. **JSON metadata label** - from `label_fr`, `label_ar`, `label_en`, or legacy `labelFr`, `labelAr` based on editing site
3. **Database label** - stored label from icon set
4. **Translation system** - Craft's translation files
5. **Propagated custom label** - custom label from another site (as last resort)
6. **Filename** (fallback) - formatted from the SVG filename
**Important Notes:**
- In Control Panel: Uses `?site=` URL parameter to determine language (not user's CP language)
- On Frontend: Uses the current site being viewed
- Custom labels with "Translate for each site" field setting work correctly per-site
- JSON labels always use the editing site's language, ensuring correct translations in CP
### Supported Metadata Properties
- **`label`** - Default display label (fallback)
- **`label_{languageCode}`** - Language-specific labels (e.g., `label_en`, `label_ar`, `label_fr`, `label_de`)
- Supports any Craft site language dynamically
- Use primary language code only (e.g., `en-US` → `label_en`)
- **`labelEn`, `labelAr`** - Legacy format (still supported for backward compatibility)
- **`search.terms`** - Additional search keywords (supports multilingual)
- **`category`** - Icon category for organization
- **`description`** - Icon description for accessibility
- **`keywords`** - Legacy search terms (still supported)
## Security
Icon Manager provides automatic SVG sanitization to protect against XSS (Cross-Site Scripting) attacks and malicious code injection.
### Automatic Sanitization
All SVG content is automatically sanitized at render time to remove potentially malicious code:
- **Script Tags**: All `` tags are removed
- **Event Handlers**: JavaScript event handlers (onclick, onmouseover, onload, etc.) are stripped
- **JavaScript Protocols**: `javascript:` protocols in hrefs are blocked and replaced with `#`
- **Malicious Data URLs**: Data URLs containing script content are prevented
- **External Scripts**: Remote script references are removed
### How It Works
Sanitization occurs when SVG content is rendered via:
- `{{ icon.render() }}` - Full icon rendering with attributes
- `{{ icon.svg }}` - Raw SVG content
- `{{ icon.content }}` - Alias for SVG content
The original SVG files remain unchanged on disk. Sanitization is applied only at render time, ensuring your source files are preserved while output is safe.
### What's Not Sanitized
Icon Manager focuses on security sanitization. The following are **not** automatically removed as they don't pose security risks:
- Clip-paths and masks (visual elements)
- Filters and effects (visual styling)
- Embedded fonts (typography)
- Metadata and comments (documentation)
These elements are preserved because they're part of the SVG's visual design and don't execute code.
### Template Safety
Because sanitization is automatic, you **do not need** to use Twig's `|raw` filter:
```twig
{# ✓ Correct - automatically safe #}
{{ icon.render() }}
{# ✗ Not needed - redundant #}
{{ icon.render()|raw }}
```
The plugin automatically marks output as safe using Twig's `Template::raw()` after sanitization is complete.
## Field Settings
### Icon Size
Controls the display size of icons in both the field preview and picker:
- **Small**: 32x32 pixels
- **Medium**: 48x48 pixels (default)
- **Large**: 64x64 pixels
Note: Font-based icons (Material Icons, Font Awesome, Web Fonts) are rendered 10px smaller than SVG icons for visual balance, as they typically have less padding in their bounding boxes.
### Show Labels
When enabled, displays icon names below icons in the picker and field preview.
### Enable Search
Shows a search box in the icon picker for filtering icons by name or keywords.
## Caching
Icon Manager includes a comprehensive caching system for better performance:
### Configuration
```php
// config/icon-manager.php
return [
'cacheStorageMethod' => 'file', // 'file' or 'redis'
'enableCache' => true, // Enable/disable caching
'cacheDuration' => 86400, // Cache duration in seconds (24 hours)
];
```
**Storage Methods:**
- **File** - Default, stores cache in `storage/runtime/icon-manager/cache/`
- **Redis** - For load-balanced or cloud hosting (Servd, AWS, Platform.sh)
### Cache Management
- **Clear Icon Cache Utility**: Go to Utilities → Clear Icon Cache
- **Integrated with Craft**: Available in Utilities → Clear Caches
- **Automatic**: Cache clears when refreshing icon sets
- **Redis Support**: All cache clearing methods work with both file and Redis storage
## Environment-Specific Paths
Configure different icon paths per environment:
```php
// config/icon-manager.php
return [
'dev' => [
'iconSetsPath' => '@root/src/icons', // Development
],
'production' => [
'iconSetsPath' => '@webroot/assets/icons', // Production
],
];
```
Icons are stored with relative paths in the database, so changing `iconSetsPath` instantly updates all icon locations without rescanning.
## SVG Optimization
Icon Manager supports two SVG optimization engines with intelligent issue detection.
### Console Help
Icon Manager includes a plugin-level console help command that lists the available CLI commands and explains the options that matter for each workflow:
```bash
ddev craft icon-manager/help
ddev craft icon-manager/help optimize
ddev craft icon-manager/help optimize/verify
```
Craft's native help is still available for exact command signatures:
```bash
ddev craft help icon-manager/optimize
ddev craft help icon-manager/optimize/verify
```
### Enabling/Disabling Optimization
SVG optimization can be controlled globally via settings or config file:
**Via Control Panel:**
1. Go to Icon Manager → Settings → SVG Optimization
2. Toggle "Enable Optimization" and "Enable Automatic Backups"
**Via Config File:**
```php
// config/icon-manager.php
return [
'enableOptimization' => true, // Enable optimization features
'enableOptimizationBackup' => true, // Auto-backup before optimization
];
```
When disabled:
- Optimization tab hidden in Icon Sets
- Optimize column hidden in Icon Sets table
- CLI commands show instructions on how to enable
- Utilities page displays disabled message with settings link
### Optimization Features
### Issue Detection
The plugin scans SVG files and identifies:
**Real Issues (Red):**
- **Unused Clip-Paths**: Empty or unreferenced clip-path definitions that can be removed
- **Unused Masks**: Empty or unreferenced mask definitions that can be removed
- **Comments**: Metadata and comments that increase file size
- **Filters**: Complex effects that may slow rendering
- **Inline Styles**: Styles that are harder to override with CSS
- **Width/Height Attributes**: Should use viewBox for responsive SVGs
**Warnings (Yellow):**
- **Large Files**: Files over 10KB (may be normal for complex icons)
**Not Flagged as Issues:**
- Functional clip-paths and masks that are actually used in the SVG
- ViewBox attributes (these are good for responsiveness)
### PHP Optimizer (Default)
Uses [mathiasreker/php-svg-optimizer v8](https://github.com/mathiasreker/php-svg-optimizer) with 32 user-controlled optimization rules plus explicit risky-rule handling. Available in the Control Panel via Icon Manager → Icon Sets → [Set] → Optimize.
**Features:**
- No additional installation required
- Works in CP interface
- 32 toggleable optimization rules organized in 5 categories:
- **Risky Rules**: Explicit opt-in required by v8 before risky rules are applied
- **Conversion**: Colors to hex, CSS classes/styles to attributes, empty tags to self-closing, attribute-name fixes
- **Minification**: Coordinates, transformations
- **Removal**: Comments, metadata, deprecated attributes, duplicate elements, unsafe elements, whitespace, unused masks/namespaces, width/height, and more
- **Structure**: Flatten groups, scope styles, sort attributes
- Risky rules are grouped in the CP and hidden when `Allow Risky Rules` is disabled
- Current risky rules in `php-svg-optimizer` v8.5.x:
- `removeDataAttributes`
- `removeEnableBackgroundAttribute`
- `removeWidthHeightAttributes`
- `scopeSvgStyles`
- Control which rules to apply via Settings → SVG Optimization → PHP Optimizer
- Supports 77 SVG properties for CSS-to-attribute conversion
- Auto-preserves legal comments (`<!--! -->`)
**Configuration:**
Control optimization behavior in Icon Manager → Settings → SVG Optimization:
- **General tab**: Enable optimization, automatic backups
- **Scan Controls tab**: What issues to detect in scans (8 detection rules)
- **PHP Optimizer tab**: What optimizations to apply (32 optimization rules plus risky-rule switch)
**Important:** Scan Controls and PHP Optimizer Settings are separate:
- **Scan Controls**: What scanner detects and displays in UI
- **PHP Optimizer**: What actually gets applied during optimization
- Optimization may modify files even when scan shows 0 issues (applies all enabled rules)
- `Unused Clip-Paths` is still scan-only in the PHP optimizer path because upstream does not currently expose a clip-path cleanup rule
### SVGO (Advanced)
Uses [SVGO](https://github.com/svg/svgo) for advanced optimization with full configuration control. Requires Node.js installation.
**Installation:**
```bash
# Using npm
npm install --save-dev svgo
# Using yarn
yarn add --dev svgo
# Using pnpm
pnpm add -D svgo
```
**Usage:**
```bash
# Interactive mode - prompts for icon set, engine, and optimization preset
ddev craft icon-manager/optimize
# Check if SVGO is available
ddev craft icon-manager/optimize/check
# Direct command with specific icon set
ddev craft icon-manager/optimize --set=3 --engine=svgo
# Use custom config file
ddev craft icon-manager/optimize --set=3 --engine=svgo --config=my-svgo.config.js
# Skip backup creation
ddev craft icon-manager/optimize --set=3 --engine=svgo --no-backup
# Dry run (see what would be optimized without making changes)
ddev craft icon-manager/optimize --set=3 --engine=svgo --dry-run
```
**Interactive Mode:**
When running `ddev craft icon-manager/optimize` without flags, the command will:
1. List available SVG folder icon sets
2. Let you choose an icon set
3. Show available engines (PHP or SVGO)
4. If SVGO is selected and no config file exists, offer optimization presets:
- **Safe**: Remove metadata, comments (preserves visual elements)
- **Balanced**: Safe + cleanup IDs, remove hidden elements
- **Aggressive**: Balanced + merge paths, convert colors (may affect styling)
- **Default**: Use SVGO defaults
5. Ask if you want to create a backup before optimization
6. Show real-time progress during optimization
**Configuration:**
Create a `svgo.config.js` file in your project root for custom optimization:
```javascript
export default {
plugins: [
{
name: 'preset-default',
params: {
overrides: {
convertColors: false, // Preserve colors
mergePaths: false, // Don't merge paths
removeViewBox: false, // Keep viewBox
},
},
},
'removeDimensions', // Remove width/height
'removeEmptyContainers', // Clean up empty elements
'removeEditorsNSData', // Remove editor metadata
],
};
```
See `docs/svgo.config.example.js` for a complete configuration example.
**Auto-Configuration:**
If no `svgo.config.js` is found:
- **Interactive mode**: Prompts you to choose an optimization preset
- **Direct command mode**: Automatically uses the "Safe" preset to prevent breaking SVGs
**Progress Output:**
SVGO shows real-time progress during optimization:
```
Processing (1/123): icon-name.svg...
✓ Optimized
Processing (2/123): another-icon.svg...
- Skipped (already optimized)
```
**Automatic Backups:**
Before optimization, a backup is automatically created (unless `--no-backup` is used):
- Stored in `storage/runtime/icon-manager/backups/`
- Named with timestamp: `icon-set-name_YYYY-MM-DD_HH-MM-SS`
- Can be restored from Icon Manager → Icon Sets → [Set] → Optimize tab (dev mode only)
**When to Use SVGO:**
- Need to optimize clip-paths, masks, or file size
- Want custom configuration per project
- Running optimization in CI/CD pipelines
- Have complex SVGs that need specific handling
- PHP optimizer finds "nothing to optimize"
**When to Use PHP Optimizer:**
- Want to optimize directly in the CP
- Don't have Node.js in your environment
- Need simple, reliable optimization
- Only need basic cleanup (comments, metadata)
### Optimizer Verification Fixtures
Icon Manager can verify an SVG fixture directory against either optimizer engine. Use this after optimizer dependency upgrades or when validating a custom SVGO configuration against representative project icons.
**Purpose:**
- Exercise intentionally problematic SVGs against the installed `php-svg-optimizer`
- Validate risky-rule handling
- Run the same fixtures through SVGO
- Confirm optimized output remains parseable SVG
Prepare a fixture directory with SVG files that represent the icon shapes and SVG features used by the project.
**Run PHP optimizer verification:**
```bash
ddev craft icon-manager/optimize/verify --engine=php --path=path/to/svg-fixtures --keep-outputs=1
```
**Run SVGO verification:**
```bash
ddev craft icon-manager/optimize/verify --engine=svgo --path=path/to/svg-fixtures --config=path/to/svgo.config.mjs --keep-outputs=1
```
**Notes:**
- Verification outputs are written to `storage/runtime/icon-manager/verify/`
- This verifies structural integrity and rule execution, not pixel-perfect visual equivalence
- After dependency upgrades, run the fixture pack and then spot-check a few real-world icons
### Understanding the Three Settings Areas
Icon Manager has three separate configuration areas for SVG optimization:
#### 1. Scan Controls
**Purpose:** What issues to detect and display in scan reports
**Location:** Settings → SVG Optimization → Scan Controls tab
**Affects:** UI reporting only (what you see in the "Issues Found" section)
#### 2. PHP Optimizer Settings
**Purpose:** Which optimization rules to apply when using PHP optimizer
**Location:** Settings → SVG Optimization → PHP Optimizer tab
**Affects:** Actual file modifications when using "Apply Optimizations" button or `--engine=php`
**Available via config file:**
```php
// config/icon-manager.php
return [
// Scan controls (what to detect)
'scanComments' => true,
'scanInlineStyles' => true,
// ... 8 scan settings
// PHP optimizer rules (what to apply)
'optimizeAllowRiskyRules' => true,
'optimizeRemoveComments' => true,
'optimizeConvertInlineStyles' => true,
// ... 32 optimization rules
];
```
#### 3. SVGO Configuration
**Purpose:** Custom SVGO optimization rules
**Location:** `svgo.config.js` in project root
**Affects:** What SVGO optimizes when using `--engine=svgo`
**Example:**
```javascript
// svgo.config.js
export default {
plugins: [
'removeComments',
'removeMetadata',
// ... SVGO plugins
],
};
```
#### Key Differences
**Scan Controls vs PHP Optimizer:**
- **Scan Controls** = Detection/reporting (shows issues in UI)
- **PHP Optimizer** = Action (what gets fixed)
- These are **independent** - you can scan for things you don't optimize, or optimize things you don't scan for
**PHP Optimizer vs SVGO:**
- **PHP Optimizer**: Uses settings from Icon Manager (32 toggles in CP plus risky-rule gating)
- **SVGO**: Uses `svgo.config.js` file (independent of Icon Manager settings)
**Example Scenario:**
```php
// config/icon-manager.php
'scanComments' => false, // Don't show in scan results
'optimizeRemoveComments' => true, // But still remove during optimization
```
Result:
- Scanner won't flag comments as issues
- PHP optimizer will still remove them (rule is enabled)
- Files with comments won't show in "Issue Breakdown" but will be optimized
For SVGO: Icon Manager settings don't affect it - use `svgo.config.js` instead.
## Missing Icon Handling
When an icon file cannot be found:
- **In templates**: Returns `null` (no errors thrown)
- **In CP field**: Shows warning icon with tooltip
- **In logs**: Records warning with full path details
Check if an icon exists:
```twig
{% if icon.exists() %}
{{ icon.render() }}
{% else %}
{# Handle missing icon #}
{% endif %}
```
## Performance Tips
### For Large Icon Sets (500+ icons)
**1. Enable Caching**
```php
'enableCache' => true,
'cacheDuration' => 86400, // 24 hours
```
**2. Optimize Icon Files**
- Run SVGO on your icon sets to reduce file sizes
- Remove unnecessary metadata and comments
- Use viewBox instead of width/height for responsive scaling
**3. Limit Field Icon Sets**
- Configure fields to show only relevant icon sets
- Reduces picker loading time and improves UX
**4. Use SVG Sprites for Repeated Icons**
- If using 10+ icons from the same set on a page
- Sprite loads once, all icons reference it
- Significant performance improvement over individual SVG files
### For Material Icons
Material Icons loads a ~3.7MB font file containing all 3,800+ icons. For better performance:
- Use only the icons you need as SVG files instead
- Download specific icons from [Google Fonts](https://fonts.google.com/icons)
- Add them to an SVG folder icon set
### Cache Strategy by Environment
```php
'dev' => [
'cacheStorageMethod' => 'file',
'cacheDuration' => 3600, // 1 hour - quick iteration
],
'staging' => [
'cacheStorageMethod' => 'file',
'cacheDuration' => 86400, // 1 day - balance updates/performance
],
'production' => [
'cacheStorageMethod' => 'redis', // Use Redis in production
'cacheDuration' => 2592000, // 30 days - maximum performance
],
```
## Logging
Icon Manager uses the [LindemannRock Logging Library](https://github.com/LindemannRock/craft-logging-library) for centralized logging.
### Log Levels
- **Error**: Critical errors only (default)
- **Warning**: Errors and warnings
- **Info**: General information
- **Debug**: Detailed debugging (includes performance metrics, requires devMode)
### Configuration
```php
// config/icon-manager.php
return [
'logLevel' => 'error', // error, warning, info, or debug
];
```
**Note:** Debug level requires Craft's `devMode` to be enabled. If set to debug with devMode disabled, it automatically falls back to info level.
### Log Files
- **Location**: `storage/logs/icon-manager-YYYY-MM-DD.log`
- **Retention**: 30 days (automatic cleanup via Logging Library)
- **Format**: Structured JSON logs with context data
- **Web Interface**: View and filter logs in CP at Icon Manager → Logs
### Log Management
Access logs through the Control Panel:
1. Navigate to Icon Manager → Logs
2. Filter by date, level, or search terms
3. Download log files for external analysis
4. View file sizes and entry counts
5. Auto-cleanup after 30 days (configurable via Logging Library)
**Requires:** `lindemannrock/craft-logging-library` plugin (installed automatically as dependency)
See [docs/LOGGING.md](docs/LOGGING.md) for detailed logging documentation.
## Permissions
Icon Manager provides granular permissions for controlling access to plugin features. Permissions can be assigned to user groups or individual users in **Settings → Users → User Groups** or **Users → [User] → Permissions**.
### Available Permissions
| Permission | Description |
|------------|-------------|
| **View icon sets** | View the icon sets list in the Control Panel |
| **Create icon sets** | Create new icon sets |
| **Edit icon sets** | Edit existing icon sets, enable/disable sets, refresh icons |
| **Delete icon sets** | Delete icon sets |
| **Manage SVG optimization** | Access the SVG Optimization tab, apply optimizations, manage backups |
| **Clear cache** | Clear icon caches (also controls visibility in Craft's Clear Caches utility) |
| **View logs** | View plugin logs in the Control Panel |
| ↳ **Download logs** | Download log files (nested under View logs) |
| **Manage settings** | Access and modify plugin settings |
### Permission Behavior
**Icon Sets Access:**
- Users with **any** icon set permission (view, create, edit, delete, or manage optimization) can see the Icon Sets navigation item
- The "New Icon Set" button only appears for users with **Create icon sets** permission
- Icon set names are only clickable (linking to edit page) for users with **Edit icon sets** permission
- Delete buttons and bulk delete actions require **Delete icon sets** permission
- The SVG Optimization tab on icon set edit pages requires **Manage SVG optimization** permission
**Cache Management:**
- The "Icon Manager caches" option in Craft's Clear Caches utility only appears for users with **Clear cache** permission
- The Clear Icon Cache utility page respects this permission
**Logs:**
- The Logs navigation item only appears for users with **View logs** permission
- The Download button in the logs viewer requires **Download logs** permission
**Settings:**
- The Settings navigation item only appears for users with **Manage settings** permission
### Example Permission Configurations
**Content Editor** (can use icons but not manage them):
- ✗ No Icon Manager permissions needed
- They can select icons in fields but cannot access the Icon Manager CP section
**Icon Manager** (can manage icon sets):
- ✓ View icon sets
- ✓ Create icon sets
- ✓ Edit icon sets
- ✓ Delete icon sets
- ✗ Manage SVG optimization (optional)
- ✓ Clear cache
**Developer** (full access):
- ✓ All permissions
**Support Staff** (can view logs only):
- ✓ View icon sets
- ✓ View logs
- ✓ Download logs
## Troubleshooting
### Icons Not Showing in Picker
**Check icon set is enabled:**
- Go to Icon Manager → Icon Sets
- Ensure the icon set has the green "enabled" status
- Click the set and verify it's enabled in settings
**Refresh icon cache:**
- Go to Utilities → Clear Icon Cache
- Click "Refresh All Icons"
- Or go to the icon set and click "Refresh Icons"
**Check file paths:**
```php
// In config/icon-manager.php
'iconSetsPath' => '@root/icons', // Make sure this path exists
```
Verify the path exists:
```bash
ls /path/to/your/project/icons
```
### Refresh Icons Doesn't Update the Count or Preview
You changed SVG files on disk (added new files, deleted files, removed a whole subfolder), clicked **Refresh Icons** on the icon set's edit page, but the **Icons** count and the **Preview** tab still show the pre-change state.
**Force-wipe the cache:**
- Go to **Utilities → Clear Icon Cache**. This works regardless of storage method and iterates the tracked Redis keys + per-set file caches.
**Check your Cache Storage Method:**
- Icon Manager → Settings → Cache → **Cache Storage Method**
- If set to **Redis/Database**, verify Redis is reachable: `ddev redis ping` or your platform's equivalent.
**Check the plugin log for cache-component warnings:**
- Look for lines like `icon-manager: cacheStorageMethod=redis configured, but Craft's cache component is …`
- This means Redis is selected as the storage method but Craft's `cache` component is not a Redis-backed Yii cache. Icon Manager logs this warning and skips Redis-specific cache operations until the cache component is fixed. Either configure Redis in `config/app.php`, or switch the plugin's storage method to **File**.
**Quick workaround for a single set:**
- Temporarily switch Cache Storage Method to **File**, save settings, click **Refresh Icons** on the set, then switch back to Redis if you want.
### Settings Save Shows a Validation Error
Numeric settings such as cache duration and items per page must be whole numbers within the allowed range. If a value is invalid, Icon Manager keeps you on the same settings page and shows the field error inline.
When a setting is overridden in `config/icon-manager.php`, the Control Panel field is skipped during save. Change the config file value instead.
### Icons Not Rendering in Templates
**Check the icon exists:**
```twig
{% set icon = craft.iconManager.getIcon('mySet', 'iconName') %}
{% if icon %}
{{ icon.render() }}
{% else %}
Icon not found
{% endif %}
```
**Check icon set handle:**
- Icon set handles are case-sensitive
- Verify the handle in Icon Manager → Icon Sets
**Clear Craft cache:**
```bash
./craft clear-caches/all
```
### Optimization Not Working
**Check optimization is enabled:**
- Icon Manager → Settings → SVG Optimization
- Ensure "Enable Optimization" is toggled on
**For CLI optimization, check environment:**
- Apply Optimizations button only works in dev/local
- CLI commands work in all environments
**SVGO not found:**
```bash
# Install SVGO
npm install --save-dev svgo
# Or verify it's installed
ddev craft icon-manager/optimize/check
```
### Performance Issues with Large Icon Sets
**Enable caching:**
```php
'enableCache' => true,
'cacheDuration' => 86400,
```
**Limit icons per page in field:**
- Edit the Icon Manager field
- Set "Icons Per Page" to 50-100 instead of 500
**Optimize SVG files:**
- Large, unoptimized SVGs slow down the picker
- Run optimization on your icon sets
### Config File Not Working
**Check file location:**
```bash
# Should be at:
config/icon-manager.php
# NOT:
vendor/lindemannrock/icon-manager/src/config.php
```
**Verify environment:**
```php
// Check current environment
echo Craft::$app->env; // Should match your config keys
```
**Check for syntax errors:**
```bash
php -l config/icon-manager.php
```
## Examples
For more real-world template examples, see [docs/EXAMPLES.md](docs/EXAMPLES.md) including:
- Navigation menus with icons
- Feature cards and icon grids
- Social media links
- Button components with loading states
- Dynamic icon selection
- Multi-site and RTL support
- Tailwind CSS integration
- Performance optimization techniques
- Accessibility best practices
## Support
- **Documentation**: [https://github.com/LindemannRock/craft-icon-manager](https://github.com/LindemannRock/craft-icon-manager)
- **Issues**: [https://github.com/LindemannRock/craft-icon-manager/issues](https://github.com/LindemannRock/craft-icon-manager/issues)
- **Email**: [support@lindemannrock.com](mailto:support@lindemannrock.com)
## License
This plugin is licensed under the [Craft License](https://craftcms.github.io/license/). See [LICENSE.md](LICENSE.md) for details.
---
Developed by [LindemannRock](https://lindemannrock.com)