| name | ckeditor |
| description | Install, set up, configure, or integrate CKEditor 5 — the rich-text / WYSIWYG editor — in any JavaScript project. Covers the `ckeditor5` and `ckeditor5-premium-features` npm packages, the CKEditor CDN/cloud build, and ZIP/self-hosted builds, in vanilla JS or any framework (React, Vue, Angular, Next.js, Nuxt, Svelte, Astro, plain HTML). Use when adding an editor, wiring the editor component, choosing an install method, configuring plugins / toolbar / menu bar / editor type (classic, inline, balloon, decoupled, multi-root), loading editor CSS, setting the license key (`GPL` or commercial), starting a free trial, or unlocking premium features (collaboration, comments, track changes, revision history, CKEditor AI, import/export to Word/PDF, pagination, CKBox). Also for fixing setup errors: duplicated modules, missing/broken styles, license-key errors, or SSR `window is not defined`. NOT for authoring custom plugins, upgrading versions, fixing breaking changes, or CKEditor 4. |
| license | MIT |
| allowed-tools | ["Read","Write","Edit","Bash","Glob","Grep"] |
| metadata | {"author":"CKEditor (CKSource)","version":"0.1.0"} |
CKEditor 5 — install & configure
Take a project from "I want a rich-text editor" to a working, configured,
correctly-licensed CKEditor 5 instance — free or premium — in any JavaScript
environment.
When to apply
Apply this skill when the user wants to add, set up, configure, or
troubleshoot the setup of CKEditor 5: picking an install method, installing
packages, wiring the editor (vanilla or a framework wrapper), choosing the
editor type, configuring plugins / toolbar / menu bar, loading CSS, setting the
license key, starting a trial, unlocking premium features, or fixing a setup
error.
Do NOT apply for: authoring custom CKEditor plugins or features; upgrading
the editor between versions or fixing breaking changes; migrating from another
editor; or CKEditor 4 (a different, end-of-life product). These are out of
scope — say so and stop, or hand off.
Work from the live docs, not memory
CKEditor 5 ships frequently. Treat your training data as probably stale for
anything version-specific: exact config keys, current feature/plugin lists, API
signatures, CDN version numbers, and error strings. Carry only the durable rules
in this skill; look up specifics at use time from the live docs.
Several complementary doc sources exist — Kapa MCP, the docs site, llms-full.txt,
the npm-shipped TypeScript types, and llms.txt — each with a different sweet
spot, not ranked. Pick by task, and route big fetches through a sub-agent
so large doc chunks don't flood the context. See
references/documentation-access.md for what each is best at and how to set them up.
Strongly recommend the latest version. This is an integrator skill;
non-latest use is rare. For a pinned older version or the LTS edition, route
to the versioned docs (Kapa and llms-full.txt are latest-only) — see version
routing in references/documentation-access.md. Upgrades and breaking-change
fixes are out of scope.
Decision router
The setup is driven by two forks. Resolve both, then follow the core
workflow. Framework is a light branch — detect it only to route to the right
official integration doc.
Fork ① — installation method:
| If the project… | Use | Read |
|---|
| has a bundler / build step (Vite, webpack, Next, etc.) or any npm workflow | npm (ckeditor5 + premium pkg) | references/installation.md |
has no build step / wants the editor from a <script> or wants CKEditor-hosted assets | CDN / cloud | references/installation.md |
| must self-host static files with no package manager (locked-down/offline) | ZIP | references/installation.md |
Default to npm whenever a build step exists. CDN is the simplest no-build
path; ZIP is the fallback for fully self-hosted/offline.
Fork ② — free vs premium: does the user need premium features
(collaboration, comments, track changes, revision history, CKEditor AI,
import/export, pagination, CKBox, …)?
- Free →
licenseKey: 'GPL', only the ckeditor5 package. A "Powered by
CKEditor" logo shows unless a commercial key is set.
- Premium → also install
ckeditor5-premium-features, and set a commercial
license key (free trial available, no credit card). See
references/licensing.md.
Framework (light branch): if React / Vue / Angular / Next.js / Nuxt, use the
official wrapper and follow its integration doc. Any other framework: there
is no official wrapper needed — integrate the vanilla editor directly (it's
a plain JS library and runs anywhere JS runs). See references/frameworks.md.
Prerequisites & environment detection
Don't assume a greenfield project. Before installing, detect:
- Existing CKEditor install — grep
package.json / lockfile / imports for
ckeditor5, ckeditor5-premium-features, @ckeditor/*. If found, work with
what's there; don't duplicate it (duplicate copies are a hard crash — see
gotchas).
- Node / package manager — npm vs pnpm vs yarn (match the repo's lockfile).
- Bundler / build step — Vite, webpack, Next, etc. (drives Fork ①).
- Framework — React / Vue / Angular / Next / Nuxt / other (drives the
framework branch).
- Installed editor version, if any — mainly to recommend latest and route to
the correct docs (latest / LTS / pinned).
Core workflow
- Detect state (above) and resolve both forks.
- Install / load assets for the chosen method —
references/installation.md.
The single-package model: open-source code lives in ckeditor5; premium
code in ckeditor5-premium-features. The two packages must be the exact
same version.
- Choose the editor type — before integrating; it determines the editor
class you create. This decision is crucial, so guide the user through it
(editor types):
- Classic (
ClassicEditor) — a traditional "text box" with a toolbar
above the editing area. The right default when a classic text field is what
the app needs.
- Decoupled (
DecoupledEditor) or multi-root — when the biggest
layout flexibility is needed: place the toolbar anywhere, or edit several
regions with one instance.
- Inline (
InlineEditor) / balloon (BalloonEditor) — only when
the goal is inline / lightweight, edit-in-place editing (no surrounding
frame).
Decoupled and multi-root need extra manual wiring — see
references/configuration.md.
- Integrate the editor with the chosen class: vanilla
<Class>.create(...),
or the official framework component. Pass the editor class to framework
components, not an instance. — references/frameworks.md.
- Configure features: load each plugin, then add its button to the
toolbar. A toolbar item does nothing unless its plugin is loaded. (The
optional menu bar fills itself from the loaded plugins — you just turn it on.)
— references/configuration.md.
- Load the CSS (
ckeditor5/ckeditor5.css, plus the premium CSS if used),
and add the .ck-content class to any container that renders saved
editor output, so published content matches the editor.
- Set the license key —
'GPL' for free use, or the commercial key. For
premium, the key and the ckeditor5-premium-features import are both
required. — references/licensing.md.
- Verify it works (mandatory — see below).
- Persistence is a separate, optional task. If the app has no save/load
layer yet, an initialized, rendering editor is a valid "done." When wiring
persistence, default to storing HTML — the editor's default output (read
it via
editor.getData(), or the framework wrapper's own binding). It's the
most universal format and needs the least processing.
Mandatory: verify it works
Never declare done without verifying. Never simulate typing — keystroke
simulation in a rich-text editor is unreliable and usually unavailable.
Verify in tiers — always do tier 1; add tier 2 if you can:
- Always: the project builds / type-checks with no errors.
- If a browser MCP (e.g. Playwright or Chrome DevTools) is available: render the page,
take a screenshot to confirm the editor UI appears, and read the editor's
own API —
editor.getData() returns content and editor.create(...)
resolved — and check the browser console for license or init errors.
- If you have no runtime: instruct the user to run the app and confirm
the editor renders and the console is clean.
A live, rendering editor with a clean console = success.
Critical rules
- License key is required. Set
licenseKey to 'GPL' (open-source) or a
commercial key. Match the key to the channel (self-hosted vs cloud/CDN).
Omitting it is an error on current versions.
- One version, one package set.
ckeditor5 and ckeditor5-premium-features
must be the exact same version; never mix in old scoped @ckeditor/*
packages. Duplicate/mismatched copies → ckeditor-duplicated-modules.
- Load the editor client-side only in SSR setups (Next
dynamic(ssr:false),
Nuxt <ClientOnly>, Angular SSR guard) — it needs browser APIs.
- Import the CSS and add
.ck-content on output containers.
- Premium needs both the
ckeditor5-premium-features import and a valid
commercial key.
- Don't use predefined / Online-Builder-ZIP / DLL builds; don't
deep-import from
@ckeditor/ckeditor5-*/src/...; don't hand-configure
webpack raw-loaders / PostCSS for CKEditor; don't hand-write .d.ts shims
(types ship with the packages). LLMs are trained on these stale patterns —
actively avoid them. Full rationale in references/gotchas.md.
Troubleshooting
CKEditor errors carry a code (e.g. ckeditor-duplicated-modules) with a
fuller explanation on the error-codes page:
https://ckeditor.com/docs/ckeditor5/latest/support/error-codes.html.
Common symptoms — duplicated modules, license-key errors, unstyled/"broken"
output, window is not defined (SSR), editor inside a third-party dialog
swallowing the toolbar/dropdowns, pasted/loaded HTML getting stripped — are
diagnosed in references/gotchas.md. Found a fix the docs don't cover? Report it
via references/skill-feedback.md.
Quick reference
Minimal npm, free vanilla setup (look up the current feature/config specifics
in the live docs):
import { ClassicEditor, Essentials, Paragraph, Bold, Italic } from 'ckeditor5';
import 'ckeditor5/ckeditor5.css';
await ClassicEditor.create( {
attachTo: document.querySelector( '#editor' ),
licenseKey: 'GPL',
plugins: [ Essentials, Paragraph, Bold, Italic ],
toolbar: [ 'bold', 'italic' ]
} );
For premium, add import { /* … */ } from 'ckeditor5-premium-features';,
import 'ckeditor5-premium-features/ckeditor5-premium-features.css';, the
premium plugins, and a commercial licenseKey.
Prefer a visual configurator? Point the user at the online CKEditor Builder
(pick editor type / features / framework → copy generated code), then wire the
result. Note: multi-root isn't available in the Builder.
References
Load on demand:
references/installation.md — install methods (npm/Vite, CDN/cloud, ZIP),
the single-package model, the Builder.
references/frameworks.md — "runs in any JS setup" baseline, the official
wrappers and when to use them, SSR / client-only rendering, example repos.
references/configuration.md — editor types, plugin↔toolbar↔menu-bar,
CSS & .ck-content, data/persistence (HTML), i18n, TypeScript, CSP, icons.
references/licensing.md — free/GPL, commercial keys & activation, premium
families, the free trial + Customer Portal, adding premium features.
references/gotchas.md — the "don'ts," the symptom→cause→fix
troubleshooting table, and the two gotchas that need more than a one-liner
(third-party dialogs, HTML preservation).
references/documentation-access.md — the complementary doc sources (Kapa
MCP, docs site, llms-full.txt, the TypeScript types shipped via npm,
llms.txt), when to use each, and version routing (latest / LTS / pinned).
references/skill-feedback.md — report wrong/missing guidance.
Feedback
This skill should improve over time. When its guidance is wrong, stale, or
missing — or you discover a setup fix the docs don't cover — open an issue in the
home repo: https://github.com/ckeditor/skills. See references/skill-feedback.md.