Ship icons from a theme or plugin
Deliver icons with your code: a theme's assets/icons folder, drop-in folders, a manifest.json and easy_svg_register_icon_collection(), checked with WP-CLI.
You can deliver icons as files in your theme or plugin, instead of uploading them in wp-admin. Easy SVG Pro reads the files, sanitizes them and offers them everywhere icons can be picked: the block inserter, the icon fields, easy_svg_icon() and Twig. This tutorial shows the three ways in, how to describe icons with a manifest.json, and how to check that everything arrived.
The three ways in
| Way | Where the files live | Who chooses the slug | Cached |
|---|---|---|---|
| Theme folder | assets/icons in the parent or child theme | the manifest, else theme, else easy_svg_pro_theme_collection_slug | yes, one day, rescanned on change |
| Drop-in folder | wp-content/easy-svg-icons/<folder>, or any folder added with easy_svg_pro_source_dirs | the manifest, else the folder name | yes, one day, rescanned on change |
| Code | any folder, or an array of markup | you, in easy_svg_register_icon_collection() | no, scanned on every request |
Every icon is then addressed as collection/icon, for example acme/phone.
Pick the way that fits your project
A theme that owns the design: the theme folder. Icons that must survive a theme switch: a drop-in or a plugin. A slug that must be fixed in code: the register function.
Put SVG files in the folder
One file per icon. The file name becomes the icon name, so Phone Ringing.svg is the icon phone-ringing.
Optionally add a manifest.json
Readable labels, search keywords, renamed icons and licence information.
Check what registered
wp easy-svg icons list and wp easy-svg icons problems, or the Packs tab.
Way 1: the theme folder
Put your icons in assets/icons of your theme:
my-theme/
assets/
icons/
phone.svg
mail.svg
manifest.json (optional)
Both the parent and the active child theme are read and merged into one collection:
- An icon in the child theme replaces the parent's icon of the same name. The panel notes that the child overrides the parent.
- The child's manifest
slugandlabelwin over the parent's. - Without a manifest slug the collection is called
themeand labelled "Theme icons".
In a template:
<?php
if ( function_exists( 'easy_svg_icon' ) ) {
echo easy_svg_icon( 'theme/phone', array( 'label' => __( 'Call us', 'acme' ) ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- sanitized SVG.
}
To give the collection a brand name, either put "slug": "acme" in assets/icons/manifest.json or use the filter:
function acme_theme_icon_slug( $slug ) {
return 'acme';
}
add_filter( 'easy_svg_pro_theme_collection_slug', 'acme_theme_icon_slug' );
Way 2: drop-in folders
Every folder directly inside wp-content/easy-svg-icons is its own collection:
wp-content/
easy-svg-icons/
house-icons/
front-door.svg
manifest.json
social/
github.svg
This is also where an exported pack can simply be unzipped. The folder name gives the slug unless the manifest names one. A slug decided for a folder name is recorded in the option easy_svg_pro_dropin_collection_slugs, so it stays stable.
When two collections want the same name, the folder moves aside on its own: it takes the manifest slug when that is free, otherwise the folder's own slug, otherwise that slug with a number (house-icons-2). This is decided fresh on every request, so removing the other collection gives the folder its preferred name back.
Folders elsewhere are added with a filter, and behave exactly like a drop-in:
/**
* Ship a cached icon folder from a plugin.
*/
function acme_plugin_icon_dir( $dirs ) {
$dirs[] = plugin_dir_path( __FILE__ ) . 'icons/acme-social';
return $dirs;
}
add_filter( 'easy_svg_pro_source_dirs', 'acme_plugin_icon_dir' );
Folders are keyed by their folder name, so give every folder a distinct name or a manifest slug.
Way 3: register in code
function acme_register_icons() {
if ( ! function_exists( 'easy_svg_register_icon_collection' ) ) {
return;
}
easy_svg_register_icon_collection(
'acme',
__( 'ACME Icons', 'acme' ),
get_stylesheet_directory() . '/resources/svg'
);
}
add_action( 'init', 'acme_register_icons' );
What makes it different:
- The slug is exactly what you pass. A
manifest.jsonin the folder names the icons, never the collection. - Call it on
initat priority 10. The registry is handed to the core Icon API on priority 11, so a later call still works foreasy_svg_icon()but misses the Icon block. - A folder registered this way is not cached: every request reads and sanitizes all files. For large folders prefer a drop-in through
easy_svg_pro_source_dirs. - A second call with the same slug adds icons to the existing collection and replaces its label.
slug => markup instead of a folder. That markup is registered and printed as it stands, without the sanitizer. Use it only for markup you wrote yourself.Describing icons with manifest.json
A folder works without a manifest. Add one when you want labels, keywords or licence information:
{
"version": 1,
"slug": "house-icons",
"label": "House icons",
"icons": {
"front-door": {
"file": "front-door.svg",
"label": "Front door",
"keywords": ["entrance", "door"]
},
"window": {
"label": "Window"
}
},
"license": "CC0-1.0",
"author": "Your agency",
"source": "https://example.com/packs/house-icons"
}
The rules, as the plugin applies them:
versionis the schema version. A version newer than your Easy SVG Pro understands refuses the whole folder rather than reading it half understood. Leave it at1.slugandlabelname the collection. An invalid slug is ignored and the folder's own slug is used. In a code registration they are ignored for the collection name.iconsis required and may not be empty. It can be an object keyed by icon name, as above, or a list of entries. Each entry may givefile,name(aliasslug),labelandkeywords(aliastags).- An entry without
filemeans the file named after the entry:windowabove iswindow.svg. - An icon name must be lowercase letters, digits,
-and_. An invalid name is skipped, never rewritten. filemust be a plain file name in the same folder. Subfolders,..and symlinks that leave the folder are refused.- The manifest describes, it does not restrict. An SVG in the folder without an entry still loads, named after its file. A file the manifest renamed appears once, under the manifest's name.
license,author,sourceare optional free text. They are shown under the collection in Icons → Packs and never acted on:sourceis never fetched and never made a link.- A manifest that is not valid JSON, has no icons, or is a JSON list instead of an object registers nothing from that folder. That is on purpose: a typo must not publish every file in the folder.
license, author and source so it survives.Limits
| Limit | Default | Change it with |
|---|---|---|
| Icons per folder | 1000 | easy_svg_pro_source_max_icons |
| Bytes per file | 2 MB | easy_svg_pro_source_file_max_bytes |
The limits apply to the theme folder, drop-ins and folders passed to the register function. A changed limit takes effect when a folder is scanned again, so touch a file or wait for the cached scan to expire.
How a folder becomes a collection
Every file goes through the site's sanitizer and the hardener before it is stored in the cache or the registry. The cached scan is invalidated when an SVG, the manifest or the free plugin's sanitizer changes.
The other source hooks
Besides the two documented filters, the scanner has three more hooks. They exist and are listed in this reference, but the readme does not promise them, so treat them as not guaranteed to stay:
easy_svg_pro_parse_manifestreceives a valid manifest in its canonical shape plus the folder path, for example to add keywords. Its result is cached with the scan.easy_svg_pro_collection_iconsreceives the finalslug => markuplist of every source collection on every request. Markup you add here is not sanitized again.easy_svg_pro_registered_collectionfires once per source collection that registered at least one icon, with slug, label, count and folder.
Icon sets made in wp-admin do not pass through any of these. The one hook every collection passes on its way to the core Icon block is easy_svg_pro_registered_icon.
Checking what arrived
On the command line (needs WP-CLI switched on under Icons → Features as well):
wp easy-svg icons list
+-------------+--------------+-------+--------------------+----------+
| collection | label | count | origin | problems |
+-------------+--------------+-------+--------------------+----------+
| acme | ACME Icons | 24 | theme my-theme | 0 |
| house-icons | House icons | 11 | dropin house-icons | 2 |
+-------------+--------------+-------+--------------------+----------+
A collection with problems gets a hint line. Then:
wp easy-svg icons problems
lists one row per file with collection, source, file, icon and reason. The same reasons appear under the collection in Icons → Packs. A folder whose manifest is broken still shows up there, with zero icons and its reason.
| Reason | Meaning |
|---|---|
manifest-invalid | The manifest is not valid JSON, not an object, or has no icons. Nothing from the folder loads. |
unsupported-version | The manifest declares a newer schema than this plugin reads. Nothing loads. |
bad-name | The icon name is not lowercase letters, digits, - and _. |
duplicate | Two entries give the same icon name. The first wins. |
outside-folder | The file is missing, sits in a subfolder, is not an .svg, or is a symlink leaving the folder. |
too-large | Over the per-file byte limit. Not read at all. |
unreadable | Empty or could not be read. |
not-svg | The sanitizer did not accept it as SVG. |
no-drawing | Nothing visible was left after sanitizing and hardening. |
too-many | Past the per-folder icon limit. Never read. |
wp easy-svg icons validate <dir> --strict on it.Common mistakes
- Nothing shows up at all. Check Icons → Features: Theme & folder sources must be on, and the licence active. For the core Icon block you also need Multiple collections and WordPress 7.1 or newer.
- Icons show in templates but not in the Icon block. The code registration ran after
initpriority 10, or Multiple collections is off. - Icons look empty in the Icon block. Core keeps only paths and polygons. Strokes and shapes are rewritten by the free plugin; gradients, masks,
useandtextcannot be carried. They still render througheasy_svg_icon(). - A folder got the slug
name-2. Another collection holds the name. Rename one of them or give the folder a freeslugin its manifest. - A subfolder is ignored. Only SVG files directly in the folder are read, and only one level of folders under
wp-content/easy-svg-iconsis scanned.