# Extensions

{% hint style="info" %}
This guide is an entry point for working with extensions
{% endhint %}

## What is an extension

**Extension** is a reusable, isolated part of your application. It can contain any kind of source logic modifications, source being either a [theme](https://docs.mosaic.js.org/themes/extensions-and-themes) or an extension.

**Extensions** allow to modify the source logic **without editing the source code**. The idea is to write additional logic - [plugins](https://docs.mosaic.js.org/develop-an-extension/plugins), in order to intercept the initial logic and modify it in runtime.&#x20;

[Build configuration](https://docs.mosaic.js.org/develop-an-extension/build-configuration-plugins) (webpack and babel) can also be modified from extensions.

## Initialize a project

Assuming that you have some project you are willing to use mosaic in, install Mosaic in your project by following any setup guide: [Next.js](https://docs.mosaic.js.org/getting-started/nextjs), [CRA](https://docs.mosaic.js.org/getting-started/create-react-app) or [Webpack](https://docs.mosaic.js.org/getting-started/webpack). If you want to start a project from scratch, just create it with Next, CRA or manually with Webpack and follow the same steps.

## Prepare the source logic

A [namespace](https://docs.mosaic.js.org/develop-an-extension/namespaces#namespace) should be set for the piece of functionality we are **willing to make available for plugins**. Using the "[magic comment](https://docs.mosaic.js.org/develop-an-extension/namespaces#how-namespace-comments-work)" syntax is the most convenient option to do it. Our Babel plugin transforms this syntax into a simple function invocation.

In this guide, you will operate with the code depicted below, located in the corresponding directory.

{% tabs %}
{% tab title="Your code" %}
{% code title="./src/router.js" %}

```javascript
/* @namespace Router/getRoutes */ 
function getRoutes(options) { 
    return [ 
        '/home',
        '/my-account'
    ] 
}

const routes = getRoutes(); // routes + additional routes (from plugins)! 
app.setRoutes(routes)
```

{% endcode %}
{% endtab %}

{% tab title="After transpilation" %}

```javascript
const getRoutes = Mosaic.middleware(
    function getRoutes(options) { 
        return [ 
            // ...routes 
        ] 
    },
    'Router/getRoutes'
);

const routes = getRoutes(); 
// routes + additional routes (from plugins)! 
// see the explanation below
app.setRoutes(routes)
```

{% endtab %}
{% endtabs %}

## Create a package

**Within** your project, create a directory for your Mosaic modules (extensions). Conventionally, it is `<root>/packages`

```bash
.
├── 📁 packages/
│   └── 📁 @vendor/
│       └── 📁 additional-routes/
│           └── 📄 package.json
├── 📁 src/
│   └── 📄 router.js
└── 📄 package.json
```

**In that directory, create** a module with proper package.json [additional fields](https://docs.mosaic.js.org/develop-an-extension/anatomy-of-an-extension#package-json), seen below. It is very **important** for this module to be recognised as Mosaic module by the plugin system.

{% code title="./packages/@vendor/additional-routes/package.json" %}

```javascript
{
    "mosaic": {
        "type": "extension"
    }
}
```

{% endcode %}

## Install and enable the module

[Install](https://docs.mosaic.js.org/install-an-extension/use-a-local-extension) it into the package it interacts with. Remember to launch one of the scripts below in order to apply your installation!

{% code title="./package.json" %}

```javascript
{
    "scripts": {
        ...
        // TODO provide a linker package
        "postupdate": "...-scripts link",
        "postinstall": "...-scripts link"
    },
    "dependencies": {
        "@vendor/additional-route": "file:relative/path/to/the/module"
    }
}
```

{% endcode %}

Remember to [enable](https://docs.mosaic.js.org/install-an-extension/enable-or-disable-an-extension) it afterwards!

{% code title="package.json" %}

```javascript
{
    "mosaic": {
        "extensions": {
            "@vendor/additional-route": true
        }
    }
}
```

{% endcode %}

## **Write a plugin**

Create a [plugin declaration file](https://docs.mosaic.js.org/develop-an-extension/plugins#plugin-declaration-files) in the [proper directory](https://docs.mosaic.js.org/develop-an-extension/anatomy-of-an-extension#file-structure) - `src/plugin/`&#x20;

Remember that there is a naming convention for these files - their names should end with `.plugin.js`

[Manipulate](https://docs.mosaic.js.org/develop-an-extension/plugins#implement-proxy-function) the initial logic as you wish! You may have several plugins on a single namespace, if they are compatible with each other all of them will work!

{% code title="packages/@vendor/additional-route/src/plugin/math.plugin.js" %}

```javascript
const plugin = (args, callback) => {
    console.log(args);     // [options]
    console.log(callback); // function getRoutes(options) {...}

    const originalRoutes = callback(...args); // ['/home', '/my-account']
    const additionaloutes = ['/cart', '/contact-us'];
    
    return [
        ...originalRoutes, 
        ...additionalRoutes
    ];
};

export default {
    'Router/getRoutes': {
        function: plugin
    }
}
```

{% endcode %}

## See it in work!

Let's launch the project and see what the initial code will give us. If you followed the guide correctly, you will see that the behavior of `getRoutes` function has changed and now it acts as follows!

It will also log some stuff into the console (explained above).

```javascript
const routes = getRoutes(); // ['/home', '/my-account', '/cart', '/contact-us']
```

## Acknowledge other extensions' features

The plugin system, although is one of the main features of Mosaic, is not the only one. To find out more about it, check out the [in-depth guide](https://docs.mosaic.js.org/develop-an-extension/plugins) dedicated to it.

Extensions can contain not only runtime logic, but also build configuration modifications.

{% content-ref url="../develop-an-extension/build-configuration-plugins" %}
[build-configuration-plugins](https://docs.mosaic.js.org/develop-an-extension/build-configuration-plugins)
{% endcontent-ref %}
