A letter editor illustrates the distinction. A white page with margins can look finished while its Save button sends the original text. Check toolbar placement and saved data as separate parts of the integration.
Start from the current decoupled setup
Use the official setup for your installed CKEditor version, including its imports, required plugins, styles, and license configuration. Do not mix initialization snippets from different major versions. The current documentation shows the document editor's root element in its configuration; the DecoupledEditor API explains how its UI elements are managed.
Keep an explicit toolbar container and an editable area in your layout:
<div id="letter-toolbar"></div>
<div id="letter-editor"><p>Equipment collection letter</p></div>
Use #letter-editor as root.element in the current initialization configuration. Once that initialization resolves with an editor instance, attach its toolbar to the separate container:
// Inside the initialization .then(editor => { ... }) callback:
document.querySelector('#letter-toolbar')
.appendChild(editor.ui.view.toolbar.element);
The editor uses the existing root element as its editable area; your application places the toolbar. This fragment assumes successful initialization with the required plugins, styles and license configuration. It is not a complete installation. If controls are missing, inspect that toolbar attachment. If a control is present but disabled, inspect whether the corresponding feature is installed and available for the current selection.
A page-shaped editing area is a visual choice. It does not establish pagination, DOCX export, PDF export, or a print layout. Confirm those requirements separately before promising them to authors.
Load one document and preserve the instance
For an illustrative equipment letter, use this short starting content:
<h2>Equipment collection</h2>
<p>Please collect the projector on Thursday.</p>
Enable the heading feature if authors need that heading to remain editable as a heading. After initialization, keep the editor instance available to the rest of the application. CKEditor documents these two operations:
editor.setData('<p>Please collect the projector on Friday.</p>');
const currentHtml = editor.getData();
The first replaces the document; the second reads its current data. They do not send anything to a database. Avoid repeatedly calling setData() while someone is typing, because a record refresh can replace their work. Getting and setting CKEditor data
Make Save read the edited document
Connect the application's Save action to the current editor instance. Read its data at the time of saving, submit that value through the application's existing save endpoint, and show success only after the save succeeds. Keep failed saves visibly unsaved.
Do not assume the decoupled editor has the automatic form integration described for Classic editor replacing a textarea. CKEditor's data guide limits that integration to that configuration. A hidden field or source element can still hold an older value.
For the equipment letter, change “Thursday” to “Friday” in the editor. Save, leave the document, and reopen the same record. The reopened text must say “Friday.” Merely inspecting a request or seeing a Save toast does not establish that reopening works.
Separate editing styles from the reader's page
Check the saved content in the actual publication renderer. If the editor's margins or fonts disappear there, inspect the content styles used by that renderer. Copying the editor's outer container is not a substitute for defining how stored content should appear.
HTML embed widgets solve another task: placing a raw snippet inside the document. They do not create this document layout or persistence flow. For a letter editor, finish by checking readable controls on a narrow screen, the saved wording after reopening, and the reader's rendered letter before adding more features.