How to add a new frontend plugin

Follow the steps to add a new frontend plug-in

1. Register the plugin

Add the following PHP code to Configuration/TCA/Overrides/tt_content.php file

// Register back button plugin
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
    'Webtemplate',
    'Button',
    'LLL:EXT:webtemplate/Resources/Private/Language/locallang_tca.xlf:tx_webtemplate_button.title',
    'EXT:webtemplate/Resources/Public/Icons/webtemplate-button.svg'
);

Add corresponding entry in locallang_tca.xlf file with id tx_webtemplate_button.title and add the icon file named webtemplate-button.svg to Resources/Public/Icons/ folder.

2. Configure the plugin

Add the following PHP code to ext_localconf.php file.

\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
    'Webtemplate',
    'Button',
    [
        \Hso\Webtemplate\Controller\ButtonController::class => 'show',
    ],
    // non-cacheable actions
    [
        \Hso\Webtemplate\Controller\ButtonController::class => 'show',
    ]
);

Change Button to your plug-in name and ButtonController to the controller class you wish to invoke.

3. Add new wizard for the plugin

The configuration wizard for new content elements/plug-ins are located at Configuration/TSConfig/Page/Mod/Wizards/NewContentElement/ folder. Create a file called Button.tsconfig in the folder with the following content.

mod.wizards.newContentElement.wizardItems.plugins {
    elements {
        webtemplate_button {
            iconIdentifier = webtemplate-button
            title = LLL:EXT:webtemplate/Resources/Private/Language/locallang_tca.xlf:tx_webtemplate_button.title
            description = LLL:EXT:webtemplate/Resources/Private/Language/locallang_tca.xlf:tx_webtemplate_button.description
            tt_content_defValues {
                CType = list
                list_type = webtemplate_button
            }
        }
    }
    show = *
}

Add corresponding language entries in locallang_tca.xlf file.

4. Add flexform for the plugin

To create form fields for configuring the plug-in, add the following in the same tt_content.php file.

// Button Flexform
$GLOBALS['TCA']['tt_content']['types']['list']['subtypes_addlist']['webtemplate_button'] = 'pi_flexform';
$GLOBALS['TCA']['tt_content']['types']['list']['subtypes_excludelist']['webtemplate_button'] = 'layout,select_key,pages,recursive';

\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue(
    'webtemplate_button',
    'FILE:EXT:webtemplate/Configuration/FlexForms/Button.xml'
);

Create Button.xml inEXT:webtemplate/Configuration/FlexForms/ folder and add the configuration options there.

5. Register a new icon for the plug-in

Add the following configuration in ext_localconf.php and add SVG icon in Resources/Public/Icons/ folder. You can also use the included icons from TYPO3. See TYPO3 icons github page. Check whether icon registry is instantiated in ext_localconf.php . If not, create a new instance of IconRegistry class as shown below.

// Icon Registry
$iconRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
    \TYPO3\CMS\Core\Imaging\IconRegistry::class
);

// Button plug-in
$iconRegistry->registerIcon(
    'webtemplate-button',
    \TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class,
    ['source' => 'EXT:webtemplate/Resources/Public/Icons/webtemplate-button.svg']
);

6. Add Plugin typoscript

Add the following typoscript in Configuration/TypoScript/Plugins.typoscript

# Page section
plugin.tx_webtemplate_button {
    view {
        templateRootPaths.0 = EXT:webtemplate/Resources/Private/Templates/Plugins/
        partialRootPaths.0 = EXT:webtemplate/Resources/Private/Partials/Plugins/
        layoutRootPaths.0 = EXT:webtemplate/Resources/Private/Layouts/Plugins/
    }
    persistence {
        storagePid =
        # recursive = 1
    }
    features {
        # skipDefaultArguments = 1
        # if set to 1, the enable fields are ignored in BE context
        ignoreAllEnableFieldsInBe = 0
        # Should be on by default, but can be disabled if all action in the plugin are uncached
        requireCHashArgumentForActionArguments = 1
    }
    mvc {
        # callDefaultActionIfActionCantBeResolved = 1
    }
}

See the tutorial at the following https://docs.typo3.org/m/typo3/book-extbasefluid/master/en-us/4-FirstExtension/Index.html