--- category: framework-tutorials order: 10 menu-title: Creating a simple plugin --- # Creating a simple CKEditor 5 plugin In this tutorial you will learn how to implement a more complex CKEditor 5 plugin. We will build a "Simple box" feature which allows the user to insert a custom box with a title and body fields into the document. We will use the widget utils and work with the model-view conversion in order to properly setup the behavior of this feature. Later on, we will create a UI which allows inserting new simple boxes into the document via the toolbar button and allow controlling simple box properties such as alignment and width. ## Before you start While it is not strictly necessary to read the {@link TODO Quick start} guide before going through this tutorial, it may help you to get more comfortable with CKEditor 5 framework before you will dive into this tutorial. We will also reference various parts of the {@link TODO CKEditor 5 architecture} section as we go. While reading them is not necessary to finish this tutorial, you can read those guides later on to get a better understanding of the mechanisms used in this tutorial. ## Let's start This guide assumes that you are familiar with npm and your project uses npm already. If not, see the [npm documentation](https://docs.npmjs.com/getting-started/what-is-npm) or call `npm init` in an empty directory and keep your fingers crossed. First, install packages needed to build and setup a basic CKEditor 5 instance. ```bash npm install --save \ postcss-loader \ raw-loader \ style-loader \ webpack@4 \ webpack-cli@3 \ @ckeditor/ckeditor5-dev-utils \ @ckeditor/ckeditor5-editor-classic \ @ckeditor/ckeditor5-essentials \ @ckeditor/ckeditor5-paragraph \ @ckeditor/ckeditor5-heading \ @ckeditor/ckeditor5-list \ @ckeditor/ckeditor5-basic-styles \ @ckeditor/ckeditor5-theme-lark ``` Create minimal webpack configuration: ```js // webpack.config.js 'use strict'; const path = require( 'path' ); const { styles } = require( '@ckeditor/ckeditor5-dev-utils' ); module.exports = { entry: './app.js', output: { path: path.resolve( __dirname, 'dist' ), filename: 'bundle.js' }, module: { rules: [ { test: /\.svg$/, use: [ 'raw-loader' ] }, { test: /\.css$/, use: [ { loader: 'style-loader', options: { singleton: true } }, { loader: 'postcss-loader', options: styles.getPostCssConfig( { themeImporter: { themePath: require.resolve( '@ckeditor/ckeditor5-theme-lark' ) }, minify: true } ) }, ] } ] }, // Useful for debugging. devtool: 'source-map', // By default webpack logs warnings if the bundle is bigger than 200kb. performance: { hints: false } }; ``` Create your project's entry point: ```js // app.js import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor'; import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials'; import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph'; import Heading from '@ckeditor/ckeditor5-heading/src/heading'; import List from '@ckeditor/ckeditor5-list/src/list'; import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold'; import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic'; ClassicEditor .create( document.querySelector( '#editor' ), { plugins: [ Essentials, Paragraph, Heading, List, Bold, Italic ], toolbar: [ 'heading', 'bold', 'italic', 'numberedList', 'bulletedList' ] } ) .then( editor => { console.log( 'Editor was initialized', editor ); // Expose for playing in the console. window.editor = editor; } ) .catch( error => { console.error( error.stack ); } ); ``` And an `index.html` page: ```html
Editor content goes here.
This is a simple box:
The description goes here.