Skip to main content

Outline

At a glance:
  • Where TinyMCE shows up: Automatically for XhtmlString properties in the CMS UI
  • Primary developer lever: Centralized configuration via DI using IConfigureOptions<TinyMceConfiguration>
  • Scope model: Default() (global) → content-type specific → property-specific overrides
  • Why it matters: Editor capabilities shape stored HTML, which shapes frontend rendering consistency

Introduction

In Optimizely CMS 12 (PaaS), TinyMCE is the default rich text editor for properties of type XhtmlString. For developers building structured content models and editorial experiences, understanding how TinyMCE is integrated, configured, and extended is critical. Although editors experience it as a toolbar and a content area, developers interact with it through configuration pipelines, initialization modules, and content model attributes.

This article explores the technical foundation of TinyMCE in CMS 12, how it is registered and configured, what its default behavior looks like, and how developers can influence its behavior at the application level.

1. How TinyMCE is Integrated in CMS 12

TinyMCE is not manually embedded into views. It is automatically wired into the editorial UI when the CMS detects a property of type XhtmlString:

C#
[Display( Name = "Main body", Description = "Primary rich text area", GroupName = SystemTabNames.Content, Order = 100)] public virtual XhtmlString MainBody { get; set; }

When this property is rendered in Edit mode, the CMS attaches TinyMCE as the editing surface. Under the hood, the CMS UI loads the TinyMCE integration package, configuration is resolved from dependency injection, default settings are applied unless overridden, and content is stored as HTML in the database. TinyMCE configuration is therefore service-driven, not view-driven.

2. Default TinyMCE Behavior in CMS 12

Out of the box, CMS 12 provides a default TinyMCE configuration. Developers do not need to manually register plugins or toolbars unless customization is required.

Default capabilities:
  • Basic formatting (bold, italic, underline)
  • Headings (H1–H6 depending on configuration)
  • Ordered and unordered lists
  • Links (internal and external, CMS-aware)
  • Image insertion and blockquotes
  • Tables (if enabled)
  • Paste handling and cleanup

The default configuration is designed to support valid HTML structure, CMS-aware link management, media references stored as content links, and safe rendering within the CMS UI. These defaults are defined by Optimizely and can be extended.

3. Configuration Pipeline in CMS 12

TinyMCE configuration is performed during application startup using dependency injection. Implement IConfigureOptions<TinyMceConfiguration> and register it in Program.cs:

C#
using EPiServer.Cms.TinyMce.Core; using Microsoft.Extensions.Options; public class ConfigureTinyMceOptions : IConfigureOptions<TinyMceConfiguration> { public void Configure(TinyMceConfiguration config) { config .Default() .AddPlugin("lists") .AddPlugin("link") .Toolbar("bold italic | bullist numlist | link"); } }
C#
builder.Services.ConfigureOptions<ConfigureTinyMceOptions>();

This approach uses .NET Core DI, keeps configuration centralized and version-controlled, avoids per-view customization, and makes behavior consistent across environments.

4. The Default() Configuration Scope

config.Default() applies settings globally to all XhtmlString properties unless a more specific configuration is defined. You can also target a specific property on a specific content type:

C#
config.For<StandardPage>(p => p.MainBody) .Toolbar("bold italic underline");

The configuration hierarchy resolves in order - more specific scopes override broader ones:

  • Global default (Default())
  • Content-type specific (For<T>())
  • Property-specific override (For<T>(p => p.Property))

This layered model prevents duplication while allowing fine-grained tuning at exactly the level of specificity needed.

5. Plugins and Toolbar Customization

TinyMCE operates through plugins. CMS 12 allows enabling or disabling them via the fluent configuration API:

C#
config.Default() .AddPlugin("code") .AddPlugin("table") .AddPlugin("image") .Toolbar("bold italic | table | code");
Important:
  • Enabling a toolbar button without enabling its plugin will not work - the plugin must be registered first.
  • Some plugins require additional configuration parameters passed via AddSetting().
  • Overexposing plugins leads to inconsistent editorial markup that is hard to style reliably on the frontend.

6. Content Output and Storage

TinyMCE outputs HTML that is stored in the CMS database as an XhtmlString. This is not sanitized by default at render time - configuration is expected to enforce allowed markup at the editor level. When rendering in Razor:

HTML
@Html.PropertyFor(x => x.MainBody)

The CMS rendering pipeline resolves internal links, maps content references, and translates permanent links - keeping the HTML structured and content-aware. This means developers must avoid overly permissive configuration, align TinyMCE capabilities with frontend rendering expectations, and ensure frontend CSS covers all allowed elements.

7. Default Settings and Allowed Elements

CMS 12 provides default settings governing allowed block elements, valid inline elements, paste behavior, and formatting rules. These defaults prevent editors from inserting arbitrary HTML. If stricter control is required, developers can restrict allowed markup via valid_elements:

C#
config.Default() .AddSetting("valid_elements", "p,strong/b,em/i,ul,ol,li,a[href|target]");

Such restrictions are essential in structured design systems where markup consistency across all CMS-authored content matters.

8. Relationship Between the CMS UI and TinyMCE

TinyMCE operates inside the CMS editing interface, not the frontend application. It runs in an isolated editing iframe, loads CMS-specific plugins, integrates with the asset pane, and supports drag-and-drop content references.

Because of this deep integration, link dialogs are CMS-aware, media selection uses the content repository, and references are stored as internal identifiers rather than plain URLs. TinyMCE in CMS 12 is not a standalone editor instance - it is part of the CMS UI framework.

9. Extensibility Considerations

TinyMCE in CMS 12 can be extended by adding custom plugins, injecting custom configuration settings, registering custom styles, and modifying the content CSS. Custom style registration enables structured content patterns controlled by frontend styling:

C#
config.Default() .AddSetting("style_formats", new[] { new { title = "Callout Box", block = "div", classes = "callout" } });

Developers should align TinyMCE configuration with component-based frontend architectures, accessibility standards, security best practices, and brand guidelines.

10. Operational Best Practices in PaaS

In a DXP environment, TinyMCE configuration is part of the deployed codebase - no direct production UI configuration should be relied upon, and all changes require a CI/CD deployment.

  • Version-control TinyMCE configuration alongside the rest of the application code so changes are auditable and reversible.
  • Keep configuration minimal and intentional. Every added plugin or toolbar button expands what editors can produce - and therefore what the frontend must handle.
  • Avoid environment-specific overrides. The same configuration should produce the same editorial capabilities across Integration, Preproduction, and Production.
  • Test HTML output before promoting to higher environments. Because content persists across deployments, configuration changes must consider backward compatibility of already-stored markup.

Note: Removing a TinyMCE plugin that was previously enabled does not sanitize already-stored content. If editors have used a plugin to produce markup that the plugin no longer renders - for example, removing the table plugin after tables have been authored - those elements will remain in the database and must be handled on the frontend.

Conclusion

TinyMCE in Optimizely CMS 12 is more than a rich text editor - it is a structured content input system tightly integrated with the CMS editing framework. Understanding how it is registered, configured, and scoped through dependency injection is essential for developers building production-grade editorial experiences.

Default configurations provide a safe and functional baseline, but production-grade solutions require deliberate control over plugins, toolbars, and valid markup. In PaaS deployments, these configurations become part of the application architecture and must be managed through code and CI/CD pipelines. Mastering TinyMCE configuration lays the foundation for implementing rich editorial experiences while maintaining structural integrity and frontend consistency.