Existing HTML content keeps working. Toolbar strings map mostly 1→1. Every premium-tier feature you’re paying for today — AI Toolkit, Track Changes, Comments, Revision History, Mentions — ships in our base licence. Below: side-by-side config cheat sheets, plugin equivalence tables, and a step-by-step checklist.
<richtextbox> as a first-class Razor citizen, not a JS wrapper.dotnet add package RichTextBox.AspNetCore --version 1.0.0-preview.12Program.cs: builder.Services.AddRichTextBox(); · app.MapRichTextBoxUploads();RichTextBox.lic file next to Program.cs (contact sales for a trial key — the demo resolver runs key-less).<textarea id="..."> + TinyMCE init script with a single <richtextbox asp-for="Body" toolbar="full" /> tag.plugins: and toolbar: config to our toolbar attribute — see the cheat sheet below.builder.Services.AddRichTextBoxOpenAiResolver(opts => opts.ApiKey = ...). No proxy server needed.config.filterhtml / filterbeforepaste callbacks.tinymce.init({
selector: '#editor',
plugins: 'lists link image table code',
toolbar: 'bold italic | bullist numlist | link image',
height: 500
});
<richtextbox
asp-for="Body"
toolbar="custom"
height="500px" />
@* Define "custom" toolbar once at site level *@
<script>
RTE_DefaultConfig.toolbar_custom =
"{bold,italic}|{insertunorderedlist,insertorderedlist}|{insertlink,insertimage}";
</script>
tinymce.init({
plugins: 'ai',
toolbar: 'ai',
ai_request: (request, respondWith) => {
respondWith.stream((streamMessage) =>
fetch('/my-proxy-to-openai', {
method: 'POST',
body: JSON.stringify({ ... })
}).then(/* ... */)
);
}
});
builder.Services.AddRichTextBox();
builder.Services.AddRichTextBoxOpenAiResolver(opts =>
{
opts.ApiKey = builder.Configuration["OpenAI:ApiKey"];
opts.Model = "gpt-4o-mini";
});
@* Page *@
<richtextbox asp-for="Body"
enable-ai-toolkit="true" />
Three separate TinyMCE premium add-ons → three base-license attributes.
tinymce.init({
plugins: 'tinycomments a11ychecker '
+ 'revisionhistory',
tinycomments_mode: 'embedded',
tinycomments_author: 'current user',
// Track Changes requires separate license
});
<richtextbox asp-for="Body"
enable-tracked-changes="true"
enable-comments="true"
enable-revision-history="true"
current-user-id="@User.Id"
current-user-name="@User.Name" />
| TinyMCE plugin | RichTextBox equivalent |
|---|---|
link | built-in (insertlink toolbar item) |
image, imagetools | built-in (insertimage, imageeditor) |
media | built-in (insertvideo, insertyoutube) |
table | built-in (inserttable + table control toolbars) |
lists, advlist | built-in (insertorderedlist, insertunorderedlist, insertchecklist) |
codesample | built-in (insertcode, syntaxhighlighter) |
emoticons | built-in (insertemoji) |
template | built-in (inserttemplate) |
mentions (premium) | enable-mentions="true" (base license) |
tinycomments (premium) | enable-comments="true" (base license) |
tinymcespellchecker (premium) | native browser spellcheck + spellcheck toolbar toggle |
revisionhistory (premium) | enable-revision-history="true" (base license) |
| Track Changes (premium) | enable-tracked-changes="true" (base license) |
ai (premium + credits) | enable-ai-toolkit="true" + provider resolver |
exportword (premium) | built-in DOCX endpoint + editor.aiToolkit.exportDocx() |
exportpdf (premium) | html2pdf toolbar item (client-side) |
wordcount | native via editor.getText().length or host wrapper |
autosave | revision history auto-snapshots + form-level autosave |
config.filterhtml.
change event → our editor.attachEvent("change", fn). init / setup → our new RichTextEditor(selector, config) is synchronous; bind events right after construction.
content_css: "..." → our config.contentCssUrl or inline config.contentCssText.
/ inline picker) — more mature than TinyMCE's autocompleter API.dotnet add package RichTextBox.AspNetCore --version 1.0.0-preview.12Program.cs: builder.Services.AddRichTextBox(); · app.MapRichTextBoxUploads();RichTextBox.lic next to Program.cs.ClassicEditor.create(...) init code with a single <richtextbox> tag.toolbar: [ ... ] items to our toolbar attribute (see cheat sheet).enable-collab="true" and load Yjs from npm or a CDN.import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
ClassicEditor.create(document.querySelector('#editor'), {
toolbar: {
items: ['bold', 'italic', '|',
'bulletedList', 'numberedList', '|',
'link', 'imageUpload']
}
});
<richtextbox
asp-for="Body"
toolbar="custom" />
<script>
RTE_DefaultConfig.toolbar_custom =
"{bold,italic}|{insertunorderedlist,insertorderedlist}|{insertlink,insertimage}";
</script>
ClassicEditor.create(el, {
cloudServices: {
tokenUrl: '/api/ckeditor-token',
webSocketUrl: 'wss://cs.cke-cs.com/...'
},
collaboration: {
channelId: documentId
}
});
<richtextbox asp-for="Body"
enable-collab="true"
current-user-id="@User.Id"
current-user-name="@User.Name" />
<script type="module">
import * as Y from "https://esm.sh/yjs";
import { WebsocketProvider } from "https://esm.sh/y-websocket";
const ydoc = new Y.Doc();
const p = new WebsocketProvider(
"wss://your-server/yjs", docId, ydoc);
editor.collab.attach({
doc: ydoc, provider: p,
textSync: true // concurrent typing
});
</script>
ClassicEditor.create(el, {
ai: {
openAI: {
requestHeaders: {
Authorization: 'Bearer ...'
},
apiUrl: 'https://api.openai.com/v1/...'
}
}
});
builder.Services.AddRichTextBox();
builder.Services.AddRichTextBoxOpenAiResolver(opts =>
{
opts.ApiKey = builder.Configuration["OpenAI:ApiKey"];
opts.Model = "gpt-4o-mini";
});
| CKEditor 5 plugin / feature | RichTextBox equivalent |
|---|---|
Bold, Italic, Underline | built-in (bold, italic, underline) |
Link / LinkImage | built-in (insertlink) |
Image / ImageUpload / ImageResize | built-in (insertimage, imageeditor) |
Table / TableProperties | built-in (inserttable + table control toolbars) |
List / TodoList | built-in (insertorderedlist, insertunorderedlist, insertchecklist) |
CodeBlock | built-in (insertcode) |
Mention (premium) | enable-mentions="true" (base license) |
Comments (premium) | enable-comments="true" (base license) |
TrackChanges (premium) | enable-tracked-changes="true" (base license) |
RevisionHistory (premium) | enable-revision-history="true" (base license) |
RealTimeCollaborativeEditing (premium) | enable-collab="true" + peer-dependency Yjs (self-host) |
AIAssistant (premium + usage) | enable-ai-toolkit="true" + provider resolver |
ExportWord (premium Cloud Services) | built-in DOCX endpoint + editor.aiToolkit.exportDocx() |
ExportPdf (premium) | html2pdf toolbar item (client-side) |
Autosave | revision history auto-snapshots + form-level autosave |
PasteFromOffice | built-in (paste-from-Word with improved list fidelity in preview.12) |
contenteditable. For most apps the difference is invisible — both produce standard HTML. If you have a custom CKEditor 5 schema, our structured-content JSON mode is the closest equivalent.
textSync: true is in preview — it covers the same RFP checkbox, but caret behavior on remote apply is rougher. Per-node binding is on the 2026 roadmap.
ckeditor5-inspector and build tooling behind.
<richtextbox> tag.dotnet add package RichTextBox.AspNetCore --version 1.0.0-preview.13Program.cs: builder.Services.AddRichTextBox(); · app.MapRichTextBoxUploads();RichTextBox.lic next to Program.cs.new FroalaEditor('#editor', { ... }) with the <richtextbox asp-for="Body" toolbar="full" /> Tag Helper.toolbarButtons to our toolbar attribute — see cheat sheet below.IRichTextBoxAiResolver: builder.Services.AddRichTextBoxOpenAiResolver(opts => ...).editor.attachEvent("change", fn) equivalents.new FroalaEditor('#editor', {
toolbarButtons: [
'bold', 'italic', 'underline', '|',
'formatOL', 'formatUL', '|',
'insertLink', 'insertImage'
],
height: 500
});
<richtextbox
asp-for="Body"
toolbar="custom"
height="500px" />
<script>
RTE_DefaultConfig.toolbar_custom =
"{bold,italic,underline}|{insertorderedlist,insertunorderedlist}"
+ "|{insertlink,insertimage}";
</script>
FroalaEditor.DefineIcon('aiAssist',
{ NAME: 'magic', SVG_KEY: 'magicWand' });
FroalaEditor.RegisterCommand('aiAssist', {
callback: function () {
fetch('/my-proxy', { ... })
.then(/* manual integration */);
}
});
builder.Services.AddRichTextBox();
builder.Services.AddRichTextBoxOpenAiResolver(opts =>
{
opts.ApiKey = builder.Configuration["OpenAI:ApiKey"];
opts.Model = "gpt-4o-mini";
});
@* Page *@
<richtextbox asp-for="Body"
enable-ai-toolkit="true" />
new FroalaEditor('#editor', {
imageUploadURL: '/api/upload-image',
imageUploadParam: 'file'
});
// Program.cs maps /richtextbox/upload automatically: app.MapRichTextBoxUploads(); // Want to send images to S3 / Azure / Cloudinary instead? // Implement IRichTextBoxUploadStore — see /UploadProviders.
| Froala plugin / button | RichTextBox equivalent |
|---|---|
bold, italic, underline | built-in (bold, italic, underline) |
fontFamily, fontSize | built-in (fontname, fontsize) |
color | built-in (forecolor, backcolor) |
formatOL, formatUL | built-in (insertorderedlist, insertunorderedlist) |
insertLink, insertImage, insertVideo, insertTable | built-in |
emoticons | built-in (insertemoji) |
specialCharacters | built-in (insertchars) |
codeView | built-in (code) |
fullscreen | built-in (fullscreenenter, fullscreenexit) |
print | built-in (print) |
spellChecker | browser-native + spellcheck toolbar toggle |
save | auto-save="true" + auto-save-key + auto-save-delay |
file | built-in (insertdocument) + MapRichTextBoxUploads() |
wordCount | native via editor.getText().length |
| Track Changes | enable-tracked-changes="true" — Froala doesn’t ship this |
| Comments | enable-comments="true" — Froala doesn’t ship this |
| Revision History | enable-revision-history="true" — Froala has only basic undo |
| AI Assist (5.1+) | enable-ai-toolkit="true" + provider resolver |
| Word export | built-in DOCX endpoint + editor.aiToolkit.exportDocx() |
| PDF export | html2pdf toolbar item (client-side) |
class="fr-fic", etc.) for image alignment / floats. Our output uses standard inline styles. For most apps the swap is invisible to downstream consumers.
events: { 'contentChanged': fn } → editor.attachEvent("change", fn).
config.iframe = false to match Froala’s in-page behaviour.
Download the trial, run it on your project, and see the migration in practice.
Need help with migration? [email protected]