CKEditor Integration into CMS
CKEditor 5 is a modern modular WYSIWYG editor. Distinguished from TinyMCE by clean plugin architecture, good TypeScript support, and active development. Available as cloud SaaS solution and open-source.
Installing CKEditor 5 (modular build)
npm install @ckeditor/ckeditor5-react @ckeditor/ckeditor5-build-classic
import { CKEditor } from '@ckeditor/ckeditor5-react';
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
function RichTextEditor({ value, onChange }) {
return (
<CKEditor
editor={ClassicEditor}
data={value}
config={{
language: 'en',
toolbar: {
items: [
'heading', '|',
'bold', 'italic', 'link', '|',
'bulletedList', 'numberedList', '|',
'blockQuote', 'insertTable', '|',
'uploadImage', 'mediaEmbed', '|',
'undo', 'redo', 'sourceEditing'
]
},
image: {
upload: { types: ['jpeg', 'png', 'gif', 'bmp', 'webp', 'tiff'] }
}
}}
onChange={(event, editor) => onChange(editor.getData())}
/>
);
}
Custom Image Upload Adapter
class UploadAdapter {
constructor(private loader: FileLoader) {}
async upload() {
const file = await this.loader.file;
const formData = new FormData();
formData.append('image', file);
const response = await fetch('/api/media/upload', {
method: 'POST',
headers: { 'X-CSRF-TOKEN': getCsrfToken() },
body: formData
});
const data = await response.json();
return { default: data.url };
}
abort() {}
}
// Register adapter
function UploadAdapterPlugin(editor) {
editor.plugins.get('FileRepository').createUploadAdapter = (loader) =>
new UploadAdapter(loader);
}
// In config
extraPlugins: [UploadAdapterPlugin]
CKEditor 5 with Custom Plugins
CKEditor 5 lets you create plugins for content blocks—e.g., product insertion with search:
import { Plugin, ButtonView, Command } from 'ckeditor5';
class InsertProductCommand extends Command {
execute({ productId, productName, productPrice }) {
const editor = this.editor;
editor.model.change(writer => {
const productBlock = writer.createElement('productBlock', {
productId, productName, productPrice
});
editor.model.insertContent(productBlock);
});
}
}
Headless CKEditor (no UI)
For Next.js sites needing only serialization/deserialization without WYSIWYG interface:
import { ClassicEditor } from '@ckeditor/ckeditor5-editor-classic';
// Parse HTML → model → back to HTML (for content conversion)
const editor = await ClassicEditor.create(document.createElement('div'), { /* config */ });
editor.setData(htmlContent);
const processed = editor.getData();
editor.destroy();
Integration timeline: 1–2 working days with custom upload adapter and toolbar configuration.







