---
title: "CollectFrontendIconsEvent"
manual: "Academic Base"
version: "main"
permalink: "https://docs.typo3.org/permalink/fgtclb/academic-base:developers-event-collect-frontend-icons-event@main"
source: "Developers/Events/CollectFrontendIconsEvent.rst"
rendered: "2026-10-17T08:47:46+00:00"
---

# CollectFrontendIconsEvent {#developers-event-collect-frontend-icons-event}

`\FGTCLB\AcademicBase\Event\CollectFrontendIconsEvent` lets code
contribute icons to the [frontend icon registry](https://docs.typo3.org/permalink/fgtclb/academic-base:configuration-frontend-icons@main) of this extension. It is meant for icons whose
identifiers are only known at runtime, read from a configuration file of an
extension for example. An icon a package ships with a fixed identifier belongs
in its `Configuration/FrontendIcons.php` instead.

**category_types** uses the event for the icons of the category types
and category groups an installation registers.

-   [When it is dispatched](https://docs.typo3.org/permalink/fgtclb/academic-base:when-it-is-dispatched@main)
-   [What a listener reads and changes](https://docs.typo3.org/permalink/fgtclb/academic-base:what-a-listener-reads-and-changes@main)
-   [Example: icons from code](https://docs.typo3.org/permalink/fgtclb/academic-base:example-icons-from-code@main)
-   [Rules and pitfalls](https://docs.typo3.org/permalink/fgtclb/academic-base:rules-and-pitfalls@main)
-   [Introduced in](https://docs.typo3.org/permalink/fgtclb/academic-base:introduced-in@main)

## When it is dispatched {#developers-event-collect-frontend-icons-event-dispatch}

The registry dispatches the event each time it is built, before it reads the
`Configuration/FrontendIcons.php` files of the active packages. The
registry is kept with the system caches, so that happens when the cache entry
is missing, after the system caches were flushed, and when
`vendor/bin/typo3 cache:warmup` builds it. It does not happen per
request: whichever request or command finds the cache entry missing builds it
for the whole installation. What a listener contributes therefore changes only
after the system caches are flushed again.

## What a listener reads and changes {#what-a-listener-reads-and-changes}

| Method | What it does |
| --- | --- |
| `addIcon(string $identifier, string $providerClass, array $options = [])` | Contributes the icon `$identifier`, rendered by the icon provider `$providerClass` with `$options`, the options of an entry of `Configuration/FrontendIcons.php` without `provider`, `source` for example. A second call for the same identifier replaces the first one. |
| `getIcons()` | The icons contributed so far, in the format of `Configuration/FrontendIcons.php`. |

## Example: icons from code {#configuration-frontend-icons-code}

An extension that computes its icons, from a configuration file of its own for
example, contributes them through the event. It is dispatched while the
registry is built, before the files are read, so an entry of a
`Configuration/FrontendIcons.php` with the same identifier replaces a
contributed icon whatever the order of the two packages.

**EXT:my_extension/Classes/EventListener/ContributeFrontendIcons.php**

```php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\EventListener;

use FGTCLB\AcademicBase\Event\CollectFrontendIconsEvent;
use TYPO3\CMS\Core\Attribute\AsEventListener;
use TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider;

#[AsEventListener(identifier: 'my-extension/contribute-frontend-icons')]
final readonly class ContributeFrontendIcons
{
    public function __invoke(CollectFrontendIconsEvent $event): void
    {
        $event->addIcon(
            'my-extension-badge',
            SvgIconProvider::class,
            ['source' => 'EXT:my_extension/Resources/Public/Icons/badge.svg'],
        );
    }
}
```

`addIcon()` rejects a provider that is not an icon provider with an error
that names the icon.

## Rules and pitfalls {#developers-event-collect-frontend-icons-event-rules}

-   **A file always wins.** The contributed icons come first and the files are
    merged over them, so a site package replaces a contributed icon by
    registering the same identifier in its
    `Configuration/FrontendIcons.php`, whatever the loading order of
    the packages.
-   **Flush after a change.** A changed listener, or a change to what it reads,
    reaches the frontend after `vendor/bin/typo3 cache:flush --group
    system`, see [Caching](https://docs.typo3.org/permalink/fgtclb/academic-base:configuration-frontend-icons-cache@main).
-   **One registry for every site.** Do not make what a listener contributes
    depend on the request, the site or the language. The registry is built
    once for the whole installation, by a command as often as by a request.
-   **Only real providers.** `addIcon()` throws an
    `\InvalidArgumentException` with code 1791061902 for a class that does
    not implement `\TYPO3\CMS\Core\Imaging\IconProviderInterface`. An
    icon registered for the frontend only is unknown to the icon registry of
    TYPO3, so an icon the backend shows as well is registered there, too.

## Introduced in {#introduced-in}

-   [Feature: A frontend icon registry and an icon view helper](https://docs.typo3.org/permalink/fgtclb/academic-base:feature-1791061865@main)
-   [Feature: Icons for frontend JavaScript as a JSON map](https://docs.typo3.org/permalink/fgtclb/academic-base:feature-frontend-icon-map@main), which serves the contributed icons to
    JavaScript as well
