# Router

In any frontend or backend application, the router is a place which is one of the most important ones to make plugin-friendly, when using Mosaic. Any amount of routes can be added to it, if it is designed correctly.&#x20;

This article will demonstrate a router design from [@scandipwa/shopify](https://github.com/scandipwa/shopify) project, which is written completely in Mosaic.

## Source implementation

Let's see the router itself! It is also available on [this link](https://github.com/scandipwa/shopify/blob/master/packages/router/src/component/Router/Router.component.js). This is exactly the form of the router at the moment of writing this article.&#x20;

It is clearly visible that the router does not actually render any routes! It just provides several convenient points for modification with Mosaic [runtime plugins](https://docs.mosaic.js.org/develop-an-extension/plugins): `_beforeSwitchRenderList`, `_switchRenderList` and `_afterSwitchRenderList`

```javascript
import { createSortedRenderMap } from '@scandipwa/framework/src/util/SortedMap';
import { createBrowserHistory } from 'history';
import { PureComponent } from 'react';
import { Router as ReactRouter } from 'react-router';
import { Switch } from 'react-router-dom';

export const history = createBrowserHistory({ basename: '/' });

/** @namespace Router/Component/Router/Component/RouterComponent */
export class RouterComponent extends PureComponent {
    static propTypes = {};

    _beforeSwitchRenderList = createSortedRenderMap({});

    _switchRenderList = createSortedRenderMap({});

    _afterSwitchRenderList = createSortedRenderMap({});

    contentRenderList = createSortedRenderMap({
        routerBeforeSwitch: this._beforeSwitchRenderList.render,
        routerRenderSwitch: this.renderSwitch.bind(this),
        routerAfterSwitch: this._afterSwitchRenderList.render
    });

    renderSwitch() {
        return (
            <Switch>
                { this._switchRenderList.render() }
            </Switch>
        );
    }

    renderRouterContent() {
        return this.contentRenderList.render();
    }

    render() {
        return (
            <ReactRouter history={ history }>
                { this.renderRouterContent() }
            </ReactRouter>
        );
    }
}

export default RouterComponent;
```

## Filling such a router by using plugins

A router is pointless without routes, right? So let's add a route to the one defined above! We will use the [Mosaic runtime plugins](https://docs.mosaic.js.org/develop-an-extension/plugins) for this purpose.

As you see, the plugin declaration file presented below modifies the [namespace](https://docs.mosaic.js.org/develop-an-extension/plugins#target-namespace) of the class above, a member called `_switchRenderList` of [target kind](https://docs.mosaic.js.org/develop-an-extension/plugins#target-kind) `member-property` &#x20;

It implements a [plugin (proxy) function](https://docs.mosaic.js.org/develop-an-extension/plugins#implement-proxy-function) `addCartPage`, which accepts the initial member - sorted render map `_switchRenderList` declared above, adds an additional item to that map and returns the modified value to the application.

```javascript
/* eslint-disable @scandipwa/scandipwa-guidelines/jsx-no-props-destruction */
import { createElement, lazy, Suspense } from 'react';
import { Route } from 'react-router';

import CartFallbackPage from '../component/CartFallbackPage';

const CartPage = lazy(() => import('../component/CartPage'));

const addCartPage = (member) => {
    const CART_PAGE_POSITION = 1000;

    member.addItem(
        () => createElement(Route, {
            path: '/cart',
            exact: true,
            render: (props) => (
                <Suspense fallback={ <CartFallbackPage /> }>
                    <CartPage { ...props } />
                </Suspense>
            )
        }),
        'routerCartPage',
        CART_PAGE_POSITION
    );

    return member;
};

export default {
    'Router/Component/Router/Component/RouterComponent': {
        'member-property': {
            _switchRenderList: addCartPage
        }
    }
};

```
