Quill Editor Integration in CMS
Quill — an open-source rich-text editor with simple API and Delta data format. A good choice for tasks with moderate requirements: text formatting, images, tables — without complex custom blocks.
Installation
npm install quill react-quill-new
Using react-quill-new
import dynamic from 'next/dynamic';
import 'quill/dist/quill.snow.css';
// Dynamic import for Next.js (SSR not supported)
const ReactQuill = dynamic(() => import('react-quill-new'), { ssr: false });
const MODULES = {
toolbar: [
[{ header: [2, 3, 4, false] }],
['bold', 'italic', 'underline', 'strike'],
[{ list: 'ordered' }, { list: 'bullet' }],
['blockquote', 'code-block'],
['link', 'image'],
['clean']
],
clipboard: { matchVisual: false }
};
const FORMATS = ['header', 'bold', 'italic', 'underline', 'strike', 'list', 'blockquote', 'code-block', 'link', 'image'];
function QuillEditor({ value, onChange }) {
return (
<ReactQuill
theme="snow"
value={value}
onChange={onChange}
modules={MODULES}
formats={FORMATS}
style={{ height: '400px' }}
/>
);
}
Custom Image Handler
By default, Quill inserts images as base64 — poor for performance. A custom handler is needed:
const imageHandler = () => {
const input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', 'image/*');
input.click();
input.onchange = async () => {
const file = input.files[0];
const formData = new FormData();
formData.append('image', file);
const response = await fetch('/api/media/upload', {
method: 'POST',
body: formData
});
const { url } = await response.json();
const quill = quillRef.current.getEditor();
const range = quill.getSelection(true);
quill.insertEmbed(range.index, 'image', url);
};
};
const MODULES = {
toolbar: {
container: [...],
handlers: { image: imageHandler }
}
};
Delta Data Format
Quill stores content in Delta format — an array of insert/delete/retain operations:
{
"ops": [
{ "insert": "Article Title", "attributes": { "header": 2 } },
{ "insert": "\n" },
{ "insert": "Text with " },
{ "insert": "bold", "attributes": { "bold": true } },
{ "insert": " word.\n" }
]
}
Content can be saved as JSON or converted to HTML via quill.getHTML(). Delta is preferable for further transformations.
Quill Limitations
- No built-in table support (only via third-party
quill-better-tableplugin) - Complex extensibility for non-standard blocks
- Version 2.x still in active development
Integration timeline: 1 business day with custom image handler.







