Die Einbindung des RTE (aktuell CKEditor) in eine Frontend-Extension an sich ist ja nicht sonderlich schwierig... Sobald das RTE Feld jedoch sowohl im Backend (TCA Formulare) als auch im Frontend verwendet werden soll (also über beide Wege Daten gepflegt bzw. editiert werden), muss eine einheitliche Transformation der Inhalte auf dem Weg in die Datenbank sowie aus der Datenbank heraus sichergestellt werden.

Konkret werden beispielsweise Absätze im RTE als "Empty Paragraphs" ausgegeben, bei einer gewöhnlichen Konfiguration werden diese jedoch über die Transformation lediglich als Newlines in der Datenbank gespeichert.

Das folgende Snippet zeigt, wie diese Transformation nach der TYPO3 Core API umgesetzt werden kann. Hierbei ist keine zusätzliche Konfiguration für die Frontend-Transformation erforderlich, da die bereits vorhandene globale RTE Konfiguration sowie eine ggf. zusätzlich vorhandene TCA Konfiguration für den RTE auf Feldebene berücksichtig werden.

Es lohnt sich ein Blick in die Klassen TYPO3\CMS\Core\Html\RteHtmlParser und TYPO3\CMS\Core\Configuration\Richtext sowie die Stellen im Core, wie diese verwendet werden.

use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Configuration\Richtext;
use TYPO3\CMS\Core\Html\RteHtmlParser;

/**
 * RTE Utility
 */
class RteUtility {
    
    /**
     * Transforms RTE content
     * 
     * @param string $content
     * @param string $direction Can be 'db' (towards db) or 'rte' (towards rte)
     * @param string $table
     * @param string $field
     * @param int $pid
     * 
     * @return string
     */
    public static function transformRte($content, $direction, $table, $field, $pid) {
        
        $recordType = '';
        $tcaFieldConf = $GLOBALS['TCA'][$table]['columns'][$field]['config'];
        
        /* @var $richtextConfigurationProvider \TYPO3\CMS\Core\Configuration\Richtext */
        $richtextConfigurationProvider = GeneralUtility::makeInstance(Richtext::class);
        $richtextConfiguration = $richtextConfigurationProvider->getConfiguration($table, $field, $pid, $recordType, $tcaFieldConf);
        
        /* @var $rteHtmlParser \TYPO3\CMS\Core\Html\RteHtmlParser */
        $rteHtmlParser = GeneralUtility::makeInstance(RteHtmlParser::class);
        $rteHtmlParser->init($table . ':' . $field, $pid);
        $transformedContent = $rteHtmlParser->RTE_transform($content, [], $direction, $richtextConfiguration);
        
        return $transformedContent;
        
    }  

}

Inhalt für die Datenbank transformieren:

RteUtility::transformRte($document->getTemplate(), 'rte', 'tx_myext_domain_model_document', 'template', $this->configurationManager->getContentObject()->data['pid']

Inhalt für den RTE im Frontend transformieren:

RteUtility::transformRte($document->getTemplate(), 'db', 'tx_myext_domain_model_document', 'template', $this->configurationManager->getContentObject()->data['pid']