Vaadin CKEditor 5: presets, editor types and the premium license path
A comprehensive ckeditor 5 integration for Vaadin 25+
At a glance
- What is it?
- A Java component library that wraps CKEditor 5 for Vaadin 25, with seven presets that trade bundle size for features, four editor types, Lumo theme syncing and a separate licensed path for premium plugins. The version floor is Java 21 with Jackson 3, and CKEditor 5 is pinned to an exact npm version.
- Who is it for?
- Teams already on Vaadin 25.3 or later with Java 21 get a typed builder that covers most editor needs without hand wiring CKEditor, and teams that only need bold, italic, links and lists should start at the BASIC preset rather than FULL. Anything involving export to PDF or Word, import from Word, slash commands or a document outline needs a purchased CKEditor license, a key pinned to approved hosts, and a version match between ckeditor5 and ckeditor5-premium-features.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 19 days ago.
- What is it written in?
- Mainly Java, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 4, 2026, and from our analysis. They are not legal advice.
Star history
- wontlost-ltd/vaadin-ckeditor21 ★ · +0
| Repository | 2026-08-26 | 2026-10-04 |
|---|---|---|
| wontlost-ltd/vaadin-ckeditor | 21 | 21 |
0 Stars in the last 39 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
The preset you pick decides bundle size before any plugin is named
Seven presets cover the range between a stripped editor and a block editor, and each carries an estimated bundle size. `EMPTY` is minimal, only essentials, around 100KB. `BASIC` adds simple formatting with Bold, Italic, Lists and Links at roughly 300KB. `STANDARD` brings in headings, images and tables at about 600KB. `FULL` covers all formatting features at around 700KB, `DOCUMENT` targets professional document editing at roughly 800KB, `EMAIL` handles email composition with image upload at about 500KB, and `NOTION` provides Notion style block editing at around 900KB.
Two entry points reach the same object. The preset alone is enough when nothing else is needed:
// Using preset
VaadinCKEditor editor = VaadinCKEditor.withPreset(CKEditorPreset.STANDARD);
// With builder
VaadinCKEditor editor = VaadinCKEditor.create()
.withPreset(CKEditorPreset.FULL)
.withValue("<p>Hello World!</p>")
.build();
add(editor);Those figures are estimates rather than measurements, so treat the ladder as an ordering and not as a budget. The ordering is also not linear in usefulness: `EMAIL` sits below `STANDARD` in size while still carrying image upload, because a composition editor and a document editor weight the same plugin set differently. Picking `NOTION` for a one field form is the expensive mistake here, and `EMPTY` under a rich content area is the cheap one that shows up as missing toolbar items.
Nothing about the preset blocks a later switch. The enum is an input to the builder rather than a mode the editor is locked into, so a component can start on `BASIC` and move up once the content model settles.
Four editor types differ only in where the toolbar attaches
The type is set through `withType(CKEditorType...)` and CLASSIC is the default. INLINE keeps the toolbar out of sight until text is selected. BALLOON floats the toolbar beside the selection. DECOUPLED separates the toolbar from the editing area entirely and adds minimap support.
// Classic (default)
VaadinCKEditor classic = VaadinCKEditor.create()
.withType(CKEditorType.CLASSIC)
.build();
// Inline - toolbar appears on selection
VaadinCKEditor inline = VaadinCKEditor.create()
.withType(CKEditorType.INLINE)
.build();
// Balloon - floating toolbar
VaadinCKEditor balloon = VaadinCKEditor.create()
.withType(CKEditorType.BALLOON)
.build();
// Decoupled - separate toolbar, supports minimap
VaadinCKEditor decoupled = VaadinCKEditor.create()
.withType(CKEditorType.DECOUPLED)
.build();Which one suits a page depends on the space around it. INLINE and BALLOON earn their keep in a narrow column or a form row, where a permanently docked toolbar competes with the rest of the layout for vertical room. CLASSIC suits a dedicated page section where the toolbar can stay visible and the user benefits from seeing the whole command set.
DECOUPLED is the odd one out because it is the only type that adds a capability rather than a placement, since the minimap needs the toolbar to sit apart from the text it acts on. That separation also means the toolbar is a separately addressable element on the page, which changes where a theme override has to be applied.
Premium plugins need a licensed npm package and a key bound to hosts
Premium features are not switched on by default. The package `ckeditor5-premium-features` has to reach the frontend, and the shorter route is one call at application startup:
import com.wontlost.ckeditor.VaadinCKEditorPremium;
@SpringBootApplication
public class Application implements AppShellConfigurator {
public static void main(String[] args) {
VaadinCKEditorPremium.enable(); // Enable premium features
SpringApplication.run(Application.class, args);
}
}The manual equivalent runs in the Vaadin frontend directory:
npm install ckeditor5-premium-featuresA CKEditor license must be purchased separately. Because the key travels in frontend code by design, the customer portal offers an approved hosts whitelist accepting exact domains such as `example.com`, wildcard subdomains such as `*.example.com`, and IP ranges such as `192.168.*.*`. Premium entries reach the toolbar by name, so `exportPdf` and `exportWord` sit next to ordinary items once added.
The named premium plugins include ExportPdf, ExportWord and ImportWord as toolbar items, plus FormatPainter, SlashCommand, DocumentOutline and Template, which do not all map to a single toolbar entry. Export and import are the three with an obvious toolbar name; the rest are commands the editor exposes without a dedicated button.
AUTO theme follows Lumo, so a dark mode switch needs no editor configuration
Theme handling is one enum with three outcomes in practice. `CKEditorTheme.AUTO` is the default and synchronizes the editor with Vaadin's Lumo theme in both the light and dark directions, so an application level theme switch carries the editor along with it. `CKEditorTheme.DARK` forces the dark appearance regardless of what the surrounding theme does. There is no matching light constant, which means light mode is reached by leaving AUTO in place.
// Auto (default) - syncs with Vaadin's Lumo theme
VaadinCKEditor editor = VaadinCKEditor.create()
.withTheme(CKEditorTheme.AUTO)
.build();
// Force dark theme
VaadinCKEditor darkEditor = VaadinCKEditor.create()
.withTheme(CKEditorTheme.DARK)
.build();That covers the editor chrome. Toolbar and button appearance is separately customizable in fine detail, so an application which already restyles Lumo components can still find work to do on the toolbar itself. The two are related but not the same surface: the theme enum decides the general palette the editor adopts, while the toolbar styling controls individual item shapes and spacing.
Forcing `DARK` on a light page is the shortcut, not the fix. It produces a dark editor inside a light layout, which is a deliberate choice for a code or image embedding page and a jarring one in a form.
Autosave is a debounced callback, not a save protocol
Autosave takes a consumer of the editor content plus an interval in milliseconds. The interval is a debounce window: typing inside it coalesces, and the callback fires once the content settles.
VaadinCKEditor editor = VaadinCKEditor.create()
.withPreset(CKEditorPreset.STANDARD)
.withAutosave(content -> {
// Save content to database
saveToDatabase(content);
}, 3000) // 3 second debounce
.build();What the API leaves out matters as much as what it offers. There is no documented retry, no conflict detection, no version token and no dirty state flag, so persisting the content and coping with two people editing one record are both left to the consumer. The three second window in the sample is a value passed in, not a default being demonstrated.
Read only state is set on the same builder and can be flipped at runtime through `setReadOnly(false)`, which is what a view only or approval mode would drive. A component that starts read only and opens for editing later does not need to be rebuilt, only unlocked.
Autosave and read only are independent of each other. A read only editor stops accepting input, which in turn stops the debounce timer from being fed, so turning autosave on for a locked editor buys nothing.
Plugin selection is explicit and the toolbar string speaks CKEditor's vocabulary
When a preset is too coarse, plugins are named as constants and the toolbar is given as a string of CKEditor items separated by pipes. The two vocabularies differ, which is why the plugin list uses `IMAGE` and `TABLE` while the toolbar uses `insertImage` and `insertTable`.
VaadinCKEditor editor = VaadinCKEditor.create()
.withPlugins(
CKEditorPlugin.ESSENTIALS,
CKEditorPlugin.PARAGRAPH,
CKEditorPlugin.BOLD,
CKEditorPlugin.ITALIC,
CKEditorPlugin.HEADING,
CKEditorPlugin.LINK,
CKEditorPlugin.IMAGE,
CKEditorPlugin.TABLE
)
.withToolbar("heading", "|", "bold", "italic", "|", "link", "insertImage", "insertTable")
.build();More than 70 plugins from the official `ckeditor5` npm package are reachable this way. The count describes availability rather than what a default editor loads, since nothing beyond the preset is enabled until it is named.
The separator token makes grouping explicit, so a toolbar can be split into blocks that read as visual clusters instead of one long row of icons. Because the toolbar string is CKEditor's own item naming, an item the editor does not know produces a toolbar entry that does nothing, which is a failure that shows up in the browser rather than at build time.
Java 21 and Jackson 3 set the floor, and CKEditor is pinned rather than ranged
The compatibility matrix is explicit rather than open ended. Vaadin Platform is 25.3.0 or later on the 25.x line. CKEditor 5 is the npm package `ckeditor5` at version 48.5.2 as an exact version, not a range. `ckeditor5-premium-features` must sit at the same 48.5.2, a matching requirement rather than an independent choice. Java is 21 or later as the Vaadin 25 baseline. Jackson comes from the consumer side as `tools.jackson.core` at 3.1.3 or later, and the Jakarta Servlet API is 6.1.0 or later. Spring Boot 4.0.4 or later is recommended because it matches Jackson 3.1.
<dependency>
<groupId>com.wontlost</groupId>
<artifactId>ckeditor-vaadin</artifactId>
<version>5.4.0</version>
</dependency>implementation("com.wontlost:ckeditor-vaadin:5.4.0")The coordinates shown are versioned, so copying them pins an older patch than the newest release available. Jackson being consumer supplied means a project already carrying Jackson 2 satisfies neither the group nor the version here, since this line uses the Jackson 3 package coordinates.
The exact pin on the CKEditor npm version is the row that changes most often during an upgrade, and it is the one that cannot be relaxed by a version range without breaking the matching requirement on the premium package.
The v47 to v48 field migration was pushed down into the frontend normalizer
An unreleased changelog entry describes the CKEditor 47 to 48 move. That compatibility layer was pushed down into the frontend normalizer instead of being handled on the server. Older top level `initialData`, `placeholder` and `label` fields, along with the v47 AI configuration, migrate automatically to their v48 equivalents.
The automatic migration is why a v47 configuration does not have to be rewritten by hand on upgrade, and it is also why the change is invisible: nothing in the Java builder moved, so a setting that quietly stops working after an upgrade is a field that did not survive the normalizer. The CHANGELOG is where to check which fields moved.
Around the editor the component carries built in file upload with validation and progress tracking, error events with fallback modes, sanitization policies for HTML, and text descriptions for 10 or more languages. The frontend is fully typed TypeScript, which is what lets the builder catch plugin and toolbar mistakes before a page renders.
The upload path is worth separating from the editor itself, since images reach the server through it and the presets differ on whether image upload is part of the bundle at all. An editor without the image plugin has no upload handling to validate, and an editor with it inherits both the progress tracking and the sanitization rules that apply to whatever the user inserts.
Editorial conclusion
Teams already on Vaadin 25.3 or later with Java 21 get a typed builder that covers most editor needs without hand wiring CKEditor, and teams that only need bold, italic, links and lists should start at the BASIC preset rather than FULL. Anything involving export to PDF or Word, import from Word, slash commands or a document outline needs a purchased CKEditor license, a key pinned to approved hosts, and a version match between ckeditor5 and ckeditor5-premium-features. Read the compatibility matrix before upgrading: the CKEditor npm version is pinned exactly rather than ranged, and autosave hands you a callback with no conflict handling attached.
Frequently asked questions
What does CKEditor get used for inside the Vaadin integration?
It supplies the rich text editing surface inside a Vaadin server side view. The integration adds toolbar, theme, upload, sanitization and autosave wiring around it, and offers classic, inline, balloon and decoupled editor types.
Can I use CKEditor for free with Vaadin CKEditor 5?
Yes for the free tier. All plugins from the official ckeditor5 npm package are available, more than 70 of them, across seven presets ranging from EMPTY at roughly 100KB to NOTION at roughly 900KB. Premium plugins need a purchased license.
How much does CKEditor cost for the premium plugins?
The README does not state a price and points to ckeditor.com/pricing instead. What it does spell out is the mechanism: enable the premium npm package, read the key from an environment variable, and restrict it through approved hosts whitelisting in the CKEditor customer portal.
Which is better, TinyMCE or CKEditor in a Vaadin project?
No comparison against TinyMCE appears in the README, so there is no basis here for picking one over the other. What this integration covers is CKEditor 5 only: seven presets, four editor types, and premium plugins such as ExportPdf, ExportWord and ImportWord behind a license.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/wontlost-ltd-vaadin-ckeditor)Star history chart for your README
[](https://hysenlabs.com/projects/wontlost-ltd-vaadin-ckeditor)