> ## Documentation Index
> Fetch the complete documentation index at: https://docs.activeviam.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create reusable extensions

> How to create, build, and plug reusable Atoti UI extensions using @activeviam/atoti-ui-cli and ExtensionModule, including structuring the NPM module, running atoti-ui-cli build-extension, and registering extensions via extensions.json.

## Why creating reusable extensions?

Extensions allow you to group and package your customizations. Once an extension is built, you can plug it into Atoti UI without having to write additional JavaScript code or to rebuild JavaScript modules.

For instance, suppose that you create two custom widgets and need to add them to multiple Atoti UI projects.

You could package your two widgets as an NPM module and have your UI projects depend on it. But with this approach, it becomes cumbersome to release evolutions: you have to release the module containing your widgets, upgrade it in all projects, rebuild your projects and redeploy them.

To avoid this, you can package your two widgets as an Atoti UI extension instead. Then releasing an evolution becomes simpler: you just have to build the new version of your extension and deploy it within your running project.

## How to split customizations into extensions?

You should limit the number of extensions plugged to your Atoti UI to a minimum. In particular, you should NOT create an atomic extension for each of your customizations.
It is good practice to group customizations that you know will be used together into a single extension.

<Warning>
  Each extension is loaded into your user's browser and registered individually,
  causing an overhead in page loading time.
</Warning>

## Create an extension

To create an extension, first create a new NPM module:

```bash theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
npm init
```

Then install `@activeviam/atoti-ui-cli` and `@activeviam/atoti-ui-sdk`:

```
npm install @activeviam/atoti-ui-cli @activeviam/atoti-ui-sdk
```

Add the following to your `package.json`:

```json theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
"exports": "./dist/manifest.json",
"files": ["dist"],
"scripts": {
  "start": "atoti-ui-cli start-extension -p 3001",
  "build": "atoti-ui-cli build-extension"
}
```

Create a file named `tsconfig.json` with this content:

```json theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
{
  "include": ["./src"]
}
```

Create a folder named `src` and a file `index.ts` inside it, with this content:

```typescript theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
import { ExtensionModule } from "@activeviam/atoti-ui-sdk";

const extension: ExtensionModule = {
  async activate(configuration) {
    configuration.applicationName = "Hello there!";
  },
};

export default extension;
```

Finally, build your extension:

```
npm run build
```

This will create the build of your extension in a folder named `dist`.

## Plug an extension

Extensions can be plugged into the build folder of an Atoti UI project, whether it is a vanilla `atoti-ui-starter` downloaded from [the ActiveViam Artifactory](https://activeviam.jfrog.io/ui/repos/tree/General/activeui-generic-release) or the `build` folder of a project bootstrapped from the `atoti-ui-starter-source`, downloaded from the same place (see [Setup](../../install-and-start/set-up)).

<Tip>
  The build of your Atoti UI project contains a folder named `extensions` and a
  file named `extensions.json`.
</Tip>

### Plug an extension manually

To plug your extension build into your project build manually, copy your extension's `dist` folder (see [Create an extension](#create-an-extension)) into your project's `build/extensions` folder.

Then rename this `dist` folder into your extension name, which is the `name` property in your extension's `package.json`.

Finally, edit the file `extensions.json` in order to add your new extension to it:

```json theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
{
  "@activeviam/starter": "extensions/@activeviam/starter/extensionEntry.js",
  "my-extension": "extensions/my-extension/extensionEntry.js"
}
```

Your extension is plugged and accessible to your users.

Note that if your extension is a scoped NPM module (its name is in the form `@foo/bar`), then the content of its `dist` folder will look like:

* dist
  * extensionEntry.js

In this case, you must create the following folder structure when copying it into `build/extensions`:

* build
  * extensions
    * @foo
      * bar
        * extensionEntry.js

And your `extensions.json` must look like this:

```json theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
{
  "@activeviam/starter": "extensions/@activeviam/starter/extensionEntry.js",
  "@foo/bar": "extensions/@foo/bar/extensionEntry.js"
}
```

### Plug an extension using commands

If you maintain a project bootstrapped with the `atoti-ui-starter-source`, you might find that copying extensions manually into its `build` folder is cumbersome, because this folder is cleaned up each time you run your `start` or `build` scripts.

In this situation, you can install the extension as a dependency of your project:

```bash theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
npm install my-extension
```

Add `"my-extension"` to the scripts allowing you to start and build your application in its `package.json`:

```json theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
  "start-application": "atoti-ui-cli start-application --port 3000 --extensions http://localhost:3001 my-extension --env-file env.development.js"
```

Similarly, update your `build` script:

```json theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
  "build": "atoti-ui-cli build-application --extensions . my-extension --env-file env.production.js"
```

This way, these scripts will copy your extension into your `build` folder, so that you don't have to do it manually.
