# Understand the generated build output

Running `npm run build` creates two flavors of output in `dist/`: one for npm-based installations and one for direct browser loading. You can use the same generated package together with the standard CKEditor 5 npm, ZIP, or CDN distributions.

> **Important**
>
> The generated package is an add-on, not a full editor build. It does not bundle `ckeditor5`, it does not create a ZIP archive, and it does not publish anything to CKEditor Cloud CDN. You always combine it with a regular CKEditor 5 installation.

This guide uses `<packageName>` as the npm package placeholder. `Callout` and `CKCallout` are example plugin and UMD global names for `ckeditor5-callout`. Your actual package, plugin, and global names depend on the values you used during generation.

<a id="generated-project-structure">

## Generated project structure

The generated package has a small, predictable structure:

| Path                                                | Purpose                                                |
| --------------------------------------------------- | ------------------------------------------------------ |
| `src/`                                              | Plugin source files and the package entry point.       |
| `sample/`                                           | The local sample app loaded by `npm run start`.        |
| `tests/`                                            | Unit tests run by Vitest.                              |
| `theme/`                                            | Icons and CSS used by your plugin.                     |
| `lang/contexts.json`                                | Translation context descriptions for synchronization.  |
| `scripts/`                                          | Helper scripts, including translation synchronization. |
| `dist/`                                             | Files created by `npm run build`.                      |
| `ckeditor5-metadata.json`                           | Plugin metadata used by CKEditor 5 tools.              |
| `vite.config.[js\|ts]`                              | Build and test configuration.                          |
| `src/augmentation.ts`, `typings/`, `tsconfig*.json` | TypeScript-only typing support.                        |

<a id="typescript-augmentation">

## TypeScript augmentation

When you choose the TypeScript template, the generator creates the `src/augmentation.ts` file. This is the place where the generated package augments CKEditor 5 types such as `PluginsMap`. Update this file when you add new plugins or commands.

Depending on your plugin, you will usually augment one or more of these interfaces:

* [`EditorConfig`](../../../api/module_core_editor_editorconfig-EditorConfig.md) when your plugin adds configuration.
* [`PluginsMap`](../../../api/module_core_plugincollection-PluginsMap.md) when you want `editor.plugins.get()` to return your plugin type.
* [`CommandsMap`](../../../api/module_core_commandcollection-CommandsMap.md) when you add commands and want `editor.commands.get()` to return typed results.

The generated template already imports `./augmentation.js` from `src/index.ts`.

```ts
import type { Callout } from './index.js';

declare module '@ckeditor/ckeditor5-core' {
	interface PluginsMap {
		[ Callout.pluginName ]: Callout;
	}
}
```

<a id="what-goes-into-dist">

## What goes into `dist/`

After `npm run build`, the output looks similar to this:

```
dist/
├─ index.js
├─ index.css
├─ index.d.ts                # TypeScript only
├─ callout.d.ts              # TypeScript only
├─ augmentation.d.ts         # TypeScript only, if present
├─ translations/
│  ├─ <language>.d.ts
│  ├─ <language>.js
│  └─ <language>.umd.js
└─ browser/
    ├─ index.es.js
    ├─ index.umd.js
    └─ index.css
```

Each file has a different job:

| File                        | Use it for                                                                                                                                          |
| --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `dist/index.js`             | The npm package entry. It is ESM and keeps `ckeditor5` as an external dependency.                                                                   |
| `dist/index.css`            | The CSS file for npm consumers. Import it separately in the consuming app.                                                                          |
| `dist/*.d.ts`               | TypeScript declarations generated from `src/`. They are published together with the npm build.                                                      |
| `dist/translations/*.js`    | ESM and UMD translation assets generated from `lang/translations/*.ts`.                                                                             |
| `dist/browser/index.es.js`  | The browser ESM build for `type="module"` and import-map setups. It still expects `ckeditor5` to be provided separately.                            |
| `dist/browser/index.umd.js` | The browser UMD build for plain `<script>` setups. It expects `CKEDITOR` to exist and exposes your package on the global name chosen for the build. |
| `dist/browser/index.css`    | The CSS file for ZIP and CDN-style browser integrations.                                                                                            |

`package.json` is already configured so that publishing the package ships `dist/` and `ckeditor5-metadata.json`.

Import the ESM translation asset for npm and import-map integrations, or load the matching `.umd.js` file in script-tag integrations. Follow the [Setting the UI language](../../../getting-started/setup/ui-language.md) guide and load the same language from `ckeditor5` so that the editor also receives the language’s plural-form function.

What you do not get from the generator:

* No full editor bundle with CKEditor 5 built in.
* No ZIP archive ready to download.
* No automatic CDN hosting.

<a id="use-the-output-with-npm">

## Use the output with npm

Start from the [npm or ZIP quick start](../../../getting-started/installation/self-hosted/quick-start.md) guide, then add your generated package on top.

The npm build is the right choice when your application already uses a package manager and a bundler. Publish the package to npm, install it from a local path, or use it from a workspace. In every case, the consuming project loads the package root, not `dist/browser/`.

```bash
npm install ckeditor5 <packageName>
```

```js
import { ClassicEditor, Essentials, Paragraph } from 'ckeditor5';
import { Callout } from '<packageName>';

import 'ckeditor5/ckeditor5.css';
import '<packageName>/index.css';

ClassicEditor
	.create( {
		attachTo: document.querySelector( '#editor' ),
		root: {
			initialData: '<p>Hello from CKEditor 5!</p>'
		},
		licenseKey: '<YOUR_LICENSE_KEY>', // Or 'GPL'.
		plugins: [ Essentials, Paragraph, Callout ],
		toolbar: [ 'undo', 'redo', '|', 'callout' ]
	} )
	.then( /* ... */ )
	.catch( /* ... */ );
```

TypeScript consumers automatically pick up the generated declaration files through the package `types` entry.

<a id="use-the-output-with-a-zip-based-setup">

## Use the output with a ZIP-based setup

Start from the [npm or ZIP quick start](../../../getting-started/installation/self-hosted/quick-start.md) guide, then copy `dist/browser/` to the same static assets area where you keep the extracted CKEditor 5 ZIP files.

<a id="recommended-esm-with-import-maps">

### Recommended: ESM with import maps

Use `dist/browser/index.es.js` when your page loads CKEditor 5 from ESM files and import maps:

```html
<div id="editor"></div>

<link rel="stylesheet" href="./vendor/ckeditor5/ckeditor5.css" />
<link rel="stylesheet" href="./vendor/callout/index.css" />

<script type="importmap">
	{
		"imports": {
			"ckeditor5": "./vendor/ckeditor5/ckeditor5.js",
			"ckeditor5/": "./vendor/ckeditor5/",
			"<packageName>": "./vendor/callout/index.es.js"
		}
	}
</script>

<script type="module">
	import { ClassicEditor, Essentials, Paragraph } from 'ckeditor5';
	import { Callout } from '<packageName>';

	ClassicEditor
		.create( {
			attachTo: document.querySelector( '#editor' ),
			root: {
				initialData: '<p>Hello from CKEditor 5!</p>'
			},
			licenseKey: '<YOUR_LICENSE_KEY>', // Or 'GPL'.
			plugins: [ Essentials, Paragraph, Callout ],
			toolbar: [ 'undo', 'redo', '|', 'callout' ]
		} )
		.then( /* ... */ )
		.catch( /* ... */ );
</script>
```

<a id="alternative-umd-with-script-tags">

### Alternative: UMD with script tags

Use `dist/browser/index.umd.js` when your page uses the UMD files from the ZIP package:

```html
<div id="editor"></div>

<link rel="stylesheet" href="./vendor/ckeditor5/ckeditor5.css" />
<link rel="stylesheet" href="./vendor/callout/index.css" />

<script src="./vendor/ckeditor5/ckeditor5.umd.js"></script>
<script src="./vendor/callout/index.umd.js"></script>

<script>
	const { ClassicEditor, Essentials, Paragraph } = CKEDITOR;
	const { Callout } = CKCallout;

	ClassicEditor
		.create( {
			attachTo: document.querySelector( '#editor' ),
			root: {
				initialData: '<p>Hello from CKEditor 5!</p>'
			},
			licenseKey: '<YOUR_LICENSE_KEY>', // Or 'GPL'.
			plugins: [ Essentials, Paragraph, Callout ],
			toolbar: [ 'undo', 'redo', '|', 'callout' ]
		} )
		.then( /* ... */ )
		.catch( /* ... */ );
</script>
```

`CKCallout` is the example UMD global. If your package is `ckeditor5-callout`, this is the suggested default name. Otherwise, replace it with the global name you confirmed during generation.

<a id="use-the-output-with-cdn-or-cloud-setups">

## Use the output with CDN or cloud setups

Start from the [CDN quick start](../../../getting-started/installation/cloud/quick-start.md) guide, then host your generated browser files yourself. CKEditor 5 can come from the CDN, while your plugin still comes from your server.

<a id="recommended-import-maps">

### Recommended: import maps

```html
<div id="editor"></div>

<link rel="stylesheet" href="https://cdn.ckeditor.com/ckeditor5/49.0.0/ckeditor5.css" />
<link rel="stylesheet" href="/plugins/callout/index.css" />

<script type="importmap">
	{
		"imports": {
			"ckeditor5": "https://cdn.ckeditor.com/ckeditor5/49.0.0/ckeditor5.js",
			"ckeditor5/": "https://cdn.ckeditor.com/ckeditor5/49.0.0/",
			"<packageName>": "/plugins/callout/index.es.js"
		}
	}
</script>

<script type="module">
	import { ClassicEditor, Essentials, Paragraph } from 'ckeditor5';
	import { Callout } from '<packageName>';

	ClassicEditor
		.create( {
			attachTo: document.querySelector( '#editor' ),
			root: {
				initialData: '<p>Hello from CKEditor 5!</p>'
			},
			licenseKey: '<YOUR_LICENSE_KEY>', // Or 'GPL'.
			plugins: [ Essentials, Paragraph, Callout ],
			toolbar: [ 'undo', 'redo', '|', 'callout' ]
		} )
		.then( /* ... */ )
		.catch( /* ... */ );
</script>
```

> **Tip**
>
> If your application also uses Vite, extend the externalization setup from the [CDN quick start](../../../getting-started/installation/cloud/quick-start.md) guide so Vite also leaves your custom package import unresolved.

<a id="alternative-umd-globals">

### Alternative: UMD globals

```html
<div id="editor"></div>

<link rel="stylesheet" href="https://cdn.ckeditor.com/ckeditor5/49.0.0/ckeditor5.css" />
<link rel="stylesheet" href="/plugins/callout/index.css" />

<script src="https://cdn.ckeditor.com/ckeditor5/49.0.0/ckeditor5.umd.js"></script>
<script src="/plugins/callout/index.umd.js"></script>

<script>
	const { ClassicEditor, Essentials, Paragraph } = CKEDITOR;
	const { Callout } = CKCallout;

	ClassicEditor
		.create( {
			attachTo: document.querySelector( '#editor' ),
			root: {
				initialData: '<p>Hello from CKEditor 5!</p>'
			},
			licenseKey: '<YOUR_LICENSE_KEY>', // Or 'GPL'.
			plugins: [ Essentials, Paragraph, Callout ],
			toolbar: [ 'undo', 'redo', '|', 'callout' ]
		} )
		.then( /* ... */ )
		.catch( /* ... */ );
</script>
```

<a id="choose-the-right-output-quickly">

## Choose the right output quickly

| If your project uses…                       | Use these generated files                                                                |
| ------------------------------------------- | ---------------------------------------------------------------------------------------- |
| npm and a bundler                           | `dist/index.js` and `dist/index.css`                                                     |
| ZIP files and import maps                   | `dist/browser/index.es.js` and `dist/browser/index.css`                                  |
| ZIP files and plain `<script>` tags         | `dist/browser/index.umd.js` and `dist/browser/index.css`                                 |
| CKEditor Cloud CDN plus your static hosting | `dist/browser/index.es.js` or `dist/browser/index.umd.js`, plus `dist/browser/index.css` |

---

Full index of the CKEditor 5 documentation: [llms.txt](../../../../llms.txt)
