# Quick Start

Want to get started quickly with React. We got you.

### Requirements

**Reactium** requires a minimum of [Node 18](https://nodejs.org/en) LTS (Recommended), and supports up to Node 20.

### Create a starter React app

Before we get into the multitude of pieces and uses of the whole platform, let's get into the easiest and fastest way to get started. If you just want to feel the instant power of the first major and important piece of the platform you can get up and going very quickly with the Reactium App Foundation.

* [ ] Install [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) and [Node.js](https://nodejs.org/en)
* [ ] Create a new application in the directory of your choice

```bash
mkdir my-app # whatever you want
cd my-app
npx reactium init
```

{% hint style="info" %}
To just use **`reactium`** instead of **`npx reactium`**, install it globally with:\
**`npm install -g reactium`**
{% endhint %}

<figure><img src="/files/EvOZIvcFq2qlOVlfqt4C" alt=""><figcaption><p><code>reactium init</code> can create Web or API projects</p></figcaption></figure>

{% hint style="success" %}
Great! Now you've got Reactium installed!
{% endhint %}

### Running Locally

Much like other popular React application creators, Reactium already has a lot of the local development environment taken care of. With a single npm script, you'll be compiling modern React javascript and Sassy CSS into a routable Node/Express application.

```bash
npm run local
```

If you did everything correctly, you will see the reactium.io website appear in an iframe.

### Remove Welcome Component

Before we go further, let's remove the **Welcome** React component.

```bash
rm -rf src/app/components/Welcome # or remove from the GUI
```

Now the root of route should just be a blank page.

### The Development Server

By default, the node/express server will listen on port **3030** and **3000** (Express and BrowserSync respectively). Your default browser should automatically open to <http://localhost:3000> for you.

### Your First Routed Hello World Component

You can manually create React components in your project, but Reactium can also help you with some common boilerplate. Let's create a simple hello world component for our homepage:

```
npx reactium component
```

![Easily set a route for a new component.](/files/-Merc8LWSciCoF_rVGXB)

### Prerequisites

This page assumes you are have some familiarity with:

* Node.js and React
* npm (node package manager)


# Discuss

Come join our community on Discord!

Come talk with the authors of Reactium and our community on our [Reactium Discord Server!](https://discord.gg/NwtHd4FZvf)


# Architecture

The Reactium Ecosystem is meant to provide a developer the means to develop any sort of application rapidly and at scale.&#x20;

![https://cdn.reactium.io/reactium/reactium\_stack.png](/files/-M5KnOpcn7AnenHpy5v8)

### The Approach

We set out to create a modular and headless JavaScript architecture where parts can be swapped out or omitted per need.&#x20;

That being said, there's a fair bit of configuration and convention that must be adhered to in order to achieve certain outcomes.&#x20;

### Tech Stack&#x20;

Our primary tech stack includes the following:&#x20;

| Tech                                                                       | Usage                                                                           |
| -------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| [**Node**](https://nodejs.org/en/)<mark style="color:blue;">**.js**</mark> | Core Javascript technology used by all foundational technologies                |
| [**Express**](https://expressjs.com/)                                      | Used as the server and API foundation for Actinium and Reactium                 |
| [**MongoDB**](https://docs.mongodb.com/drivers/node/)                      | Used by Actinium as the database server                                         |
| [**Parse Server**](https://github.com/parse-community/parse-server)        | Used by Actinium to rapidly build persistent objects and cloud APIs for MongoDB |
| [**Parse SDK**](https://docs.parseplatform.org/js/guide)                   | Used by **Reactium SDK** as the connector to Actinium                           |
| [**Gulp**](https://gulpjs.com/)                                            | Used as a toolkit to automate build process and pipelines                       |
| [**Babel**](https://babeljs.io/)                                           | Used by Reactium to compile JavaScript                                          |
| [**Webpack**](https://webpack.js.org/)                                     | Used by Reactium to pre-process and bundle JavaScript                           |
| [**React**](https://reactjs.org/)                                          | Used by Reactium as the JavaScript library for building User Interfaces         |
| [**Sass**](https://sass-lang.com/)                                         | Used by Reactium for styling                                                    |


# DDD Introduction

As a Developer or Software Engineer, you're probably working with teams of varying skill, size, and expertise. Usually in an environment where people can be slotted in and out on a weekly basis. Or maybe you're a consultant or freelancer who has multiple projects in different stages of development.&#x20;

Keeping track of every project is a daunting task. You don't need the application organization and structure to add to that mental load.&#x20;

Reactium aims to lighten the load by implementing Domain Driven Design ***(DDD)***

### Domain Driven Design

A common strategy for developing applications is Model Driven Engineering ***(MDE)***, where the code is organized by functional domains. A popular MDE is Model/View/Controller ***(MVC)***.&#x20;

> *Techs love acronyms*&#x20;

In most applications that follow MDE you'll find that creating the initial feature is pretty straight forward.&#x20;

*Need a view?* \
Just add it to the **/views** directory and give it a name-spaced file name.

&#x20;*Need a controller?* \
Just add it to the **/controllers** directory and give it a name-spaced file name.&#x20;

Before you know it you have a completed app where there are 50 **views** and 50 **controllers**. Doesn't sound too bad. But what happens when your application model spans more than just views and controllers? Given the feature of a **Page**, your model could expand to include **styles**, **services**, **assets**, and **lang**.&#x20;

Fast-forward 2 months. The marketing department has asked for a new hero image on the Home page with a Spanish and Chinese translation with right to left design implemented for the Chinese translation.

Looking at MDE there will be a fair amount of traversing and getting your bearings on where to make the necessary edits *(even with the fixed set we're working with in the following example)*.&#x20;

{% code title="MDE" %}

```jsx
/assets
    about-hero.jpg
    home-hero.jpg
 
/controllers
    about-actions.js
    home-actions.js

/services
    about-services.js
    home-services.js
 
/styles
    about-styles.css
    about-styles-rtl.css
    home-styles.css
    home-styles-rtl.css
 
/lang
    /cn
        about.cn.pot
        home.cn.pot
    /en
        about.en.pot
        home.en.pot
    /es
        about.es.pot
        home.es.pot

/views
    about.html
    home.html        
```

{% endcode %}

Imagine what MDE would look like if you're looking at a full site with multiple page templates and multiple language support.&#x20;

Looking at DDD it's a lot easier to figure out where to start and what to touch.&#x20;

{% code title="DDD" %}

```jsx
/about-page
    /assets
        hero.jpg
        
    /lang
        cn.pot
        en.pot
        es.pot
        
    controller.js
    services.js
    styles.css
    view.html
    
/home-page
    /assets
        hero.jpg
        
    /lang
        cn.pot
        en.pot
        es.pot
        
    controller.js
    services.js
    styles.css
    styles-rtl.css
    view.html
```

{% endcode %}

You'll notice that since we're working with an exact set of files in each domain, we can reduce the number of sub-directories required for grouping files, opting to only use a sub-directory when the number of files will be unknown or varies per domain. You'll also notice that the domain model for each page it the exact same, creating an implied knowledge of the codebase and establishing predictability.&#x20;

Imagine the same request came in for the About page.&#x20;

After completing the Home page edits, it will be easier and faster to make the About page edits. Your brain has the domain in recent memory and since the domain model is the same, you spend no time traversing the code for the necessary files to edit.&#x20;

### DDD Pros&#x20;

* If you were new to the codebase, you wouldn't have the entire application to discern while trying to figure out what to edit. **After successfully making the first edit, you will feel empowered to make the next and any other similar changes while increasing your domain knowledge**.&#x20;
* **Domain experts can write clear and concise documentation** that can be consumed in smaller chunks with progressive knowledge acquisition making the on-boarding process smoother and require less hand holding.&#x20;
* **Creating variance is as easy as replicating a domain** and making the necessary changes.&#x20;
* **Installing, removing or refactoring a feature is simple** and less risky.&#x20;
* **Identifying problems is a tighter loop** as most issues will be domain specific and not systematic.&#x20;
* **Identifying systematic issues is easier**, you'll be able to trace where the issues are based on which domains are effected and what they share in common.&#x20;

It wouldn't be fair to suggest DDD without listing its cons.&#x20;

### DDD Cons&#x20;

* Repetitive. With having a domain model comes the need for boilerplate code. This can be mitigated with [generators](/approach/intro#generators) and [aggregators](/approach/intro#aggregators).&#x20;
* Maintaining the domain model integrity will some times cause for micro-files with 3 or 4 lines of code. It's worth noting this is dependent on how you structure your domain model. The more specific your domain files are the more this will happen. With practice you can find your sweet spot pretty quickly.&#x20;
* Refactoring boilerplate files can become tedious. With a good IDE this isn't as big of a problem. You can easily enough do a regular expression search in a text editor like [Atom](https://atom.io/) and aggregate the files into a list much like they would be shown in MDE.&#x20;
* Sharing functionality across domains can be risky if not done with care.&#x20;

{% hint style="info" %}
**Neutral:** With larger or remote teams, planned collaboration is needed to ensure domain experts can share knowledge and reduce duplicating effort when features have overlapping requirements. This can be both a pro and con depending on your team and how you prefer to work.&#x20;
{% endhint %}


# Domain Model

The Domain Models are structured so that the build process can easily scoop up files and aggregate them to be used when bootstrapping or referencing at run-time.&#x20;

Our goal is to eliminate the need to manually add import/require statements for DDD artifacts all over the code. We believe import & require should be *application* focused and not *framework* focused.&#x20;

{% hint style="danger" %}
Our Domain Models are ever evolving and should be treated as so. \
We will do as much as we can to maintain backward compatibility where possible.
{% endhint %}

{% content-ref url="/pages/-M5FaINXMv\_Q4nCkQSrQ" %}
[Reactium Domain Model](/reactium/domain)
{% endcontent-ref %}

{% content-ref url="/pages/-M5Oa72Tk6kmzKIJrrNg" %}
[Actinium Domain Model](/actinium/actinium)
{% endcontent-ref %}


# Reactium Guides

A series of guides to help you understand how to work with the Reactium platform.

## How do I build plugins, and what types are there?

In short, there are [build-time plugin](/reactium/reactium-guides/plugin-development-guide#create-a-build-time-plugin) for extending your API (Actinium) and your web app (Reactium) and [run-time plugins](/reactium/reactium-guides/plugin-development-guide#run-time-plugins) for extending your web app at runtime.

{% content-ref url="/pages/-MCDHeBV06HbqwQqgr3d" %}
[Plugin Module Guide](/reactium/reactium-guides/plugin-development-guide)
{% endcontent-ref %}

## How do use my Actinium cloud function in my Reactium app?

You will use the Reactium SDK with built-in features for accessing your API. [This is easy to setup.](/reactium/reactium-guides/reactium-+-actinium)

{% content-ref url="/pages/-M5NYwx2jKAZmpOTc8uc" %}
[Reactium + Actinium (APIs)](/reactium/reactium-guides/reactium-+-actinium)
{% endcontent-ref %}

## Can I add my own REST API to my Reactium app?

Absolutely, you can extend the Reactium SDK by registering your own API very easily, using `Reactium.API.register()`

{% content-ref url="/pages/-M5NZ-P7DjA8WyX7kTHv" %}
[Reactium + REST](/reactium/reactium-guides/reactium-+-rest)
{% endcontent-ref %}

## I just want to make a simple routed React app. Can I do that?

If all you want is a simple routed React app, you can just use the Reactium foundational framework alone. Creating new components and setting them up to be routed is really easy with Reactium.

{% content-ref url="/pages/-M4q2hQcrIv5au8JMdMo" %}
[Creating a Simple Single Page Web App (SPA)](/reactium/reactium-guides/creating-a-website)
{% endcontent-ref %}

## Is it possible to animate a transition from one route to another?

The Reactium SDK has a feature for each route, activated when a route is registered with `transitions: true`, and will let you cycle through pre-defined transitions from one route to another using `Reactium.Routing.nextState()`. You can use this feature to animate with a library like TweenMax or with CSS transitions or key frames.

{% content-ref url="/pages/-MNoSKNgz5oW4EKOneFm" %}
[Animating React Routes](/reactium/reactium-guides/animating-react-routes)
{% endcontent-ref %}

## How do I Deploy Reactium to Production?

Reactium deploys as a container or to Heroku with very little effort, in traditional Node.js server environments, here are the things you need to know.

{% content-ref url="/pages/1BnaE6JCTRVG4RjK6xQ7" %}
[Reactium in Production](/reactium/reactium-guides/reactium-in-production)
{% endcontent-ref %}


# Creating a Simple Single Page Web App (SPA)

The Reactium foundational framework can be used to build a stand-alone simple Web App. Need a quick React app with routed components, here's how you do it!

### TL;DR - from the command line, run:

```bash
mkdir myapp
cd myapp

npx reactium init

[ARCLI] > Initialize what type of project?:  (Use arrow keys)
❯ Reactium (Web Application) 
  Actinium (Web API) 

# Delete the default component
rm -rf src/app/components/Welcome

# Create Your Home Page!
npx reactium component

[ARCLI] > Select directory:  src/app/components
❯ src/app/components
  src/app/components/common-ui
  
[ARCLI] > Component Name:  Home

[ARCLI] > Route:  /

[ARCLI] > Reactium Hooks?:  Yes

[ARCLI] > Domain file?:  Yes

[ARCLI] > Stylesheet?:  Yes

[ARCLI] > Select stylesheet type:  
  base 
  atoms 
  molecules 
❯ organisms 
  overrides 
  default 
  mixins
  
[ARCLI] > Preflight checklist:
{
  "destination": "src/app/components/Home",
  "name": "Home",
  "route": "['/']",
  "hooks": true,
  "domain": true,
  "style": true,
  "styleType": "_reactium-style-organisms.scss",
  "className": "home",
  "index": true
}

[ARCLI] > Proceed?:  (y/N) y

npm run local  
```

That's it. You should be looking at a running simple app, with your **`Home`** component running on <http://localhost:3000>

### Creating A Page

Let's break down what's happening with the previous `reactium` command. After proceeding, your `scr/app` directory should look something like this:

```
src/app
├── components
│   ├── Home
│   │   ├── Home.jsx
│   │   ├── reactium-domain-home.js <- defines the unique namespace of our component
│   │   ├── reactium-hooks-home.js <- Reactium plugin hooks go here
│   │   ├── reactium-route-home.js <- Defines the Route where this component renders in the front-end
│   │   └── _reactium-style-organisms-Home.scss <- Styles go here
└── main.js <- The main entry point of the app (usually no modifications needed)
```

### Create a Second Page

```bash
npx reactium component

[ARCLI] > Select directory:  src/app/components
❯ src/app/components
  src/app/components/common-ui
  
[ARCLI] > Component Name:  About

[ARCLI] > Route:  /about

[ARCLI] > Reactium Hooks?:  Yes

[ARCLI] > Domain file?:  Yes

[ARCLI] > Stylesheet?:  Yes

[ARCLI] > Select stylesheet type:  
  base 
  atoms 
  molecules 
❯ organisms 
  overrides 
  default 
  mixins
  
[ARCLI] > Preflight checklist:
{
  "destination": "src/app/components/About",
  "name": "About",
  "route": "['/about']",
  "hooks": true,
  "domain": true,
  "style": true,
  "styleType": "_reactium-style-organisms.scss",
  "className": "about",
  "index": true
}

[ARCLI] > Proceed?:  (y/N) y
```

### Single Page Application Navigation

You already have a React single-page application started.&#x20;

Let's create a navigation component and render it on both pages!

```bash
npx reactium component

[ARCLI] > Select directory:  common-ui
❯ src/app/components/common-ui

[ARCLI] > Component Name:  Nav

[ARCLI] > Route:
[ARCLI] > Reactium Hooks?:  (Y/n)  Yes
[ARCLI] > Domain file?:  (Y/n)  Yes

[ARCLI] > Stylesheet?:  (Y/n) Yes
  variables 
  base 
  atoms 
❯ molecules 
  organisms 
  overrides 
  default 
(Move up and down to reveal more choices)

[ARCLI] > Preflight checklist:

{
  "destination": "src/app/components/common-ui/Nav",
  "name": "Nav",
  "route": "[]",
  "hooks": true,
  "domain": true,
  "style": true,
  "styleType": "_reactium-style-molecules",
  "className": "nav",
  "index": true
}

[ARCLI] > Proceed?:  (Y/n) Yes
```

Ok, let's modify our Nav component:

{% code title="common-ui/Nav/Nav.jsx" %}

```jsx
import React from 'react';
import { NavLink } from 'react-router-dom';

/**
 * -----------------------------------------------------------------------------
 * Component: Nav
 * -----------------------------------------------------------------------------
 */
export const Nav = ({ className }) => {
    return (
        <nav className={className}>
            <NavLink to='/' exact={true} activeClassName='active'>
                Home
            </NavLink>
            <NavLink to='/about' activeClassName='active'>
                About
            </NavLink>
        </nav>
    );
};

Nav.defaultProps = {
    className: 'nav',
};

export default Nav;
```

{% endcode %}

Let's also add some sassy styles for Nav:

{% code title="common-ui/Nav/\_reactium-style-molecules-Nav.scss" %}

```scss
.nav {
    display: flex;
    flex-direction: column;
    padding: 20px;

    a {
      &, &:visited {
        color: gray;
      }
      &:hover, &.active {
        color: black;
      }
    }
}
```

{% endcode %}

Great, now let's include the Nav in both the Home page and the About page:

{% tabs %}
{% tab title="Home.jsx" %}

```jsx
import {
    useSyncState,
    useHookComponent,
} from '@atomic-reactor/reactium-core/sdk';
import React from 'react';

/**
 * -----------------------------------------------------------------------------
 * Component: Home
 * -----------------------------------------------------------------------------
 */
export const Home = ({ className }) => {
    const Nav = useHookComponent('Nav');
    const state = useSyncState({ content: 'Home' });

    return (
        <div className={className}>
            <Nav />
            <h1>{state.get('content')}</h1>
            <p>This is the Home page.</p>
        </div>
    );
};

Home.defaultProps = {
    className: 'home',
};

export default Home;
```

<figure><img src="/files/CGmyOoUg6zgX7POF3g8W" alt=""><figcaption><p>/</p></figcaption></figure>
{% endtab %}

{% tab title="About.jsx" %}

```jsx
import {
    useSyncState,
    useHookComponent,
} from '@atomic-reactor/reactium-core/sdk';
import React from 'react';

/**
 * -----------------------------------------------------------------------------
 * Component: About
 * -----------------------------------------------------------------------------
 */
export const About = ({ className }) => {
    const Nav = useHookComponent('Nav');
    const state = useSyncState({ content: 'About' });

    return (
        <div className={className}>
            <Nav />
            <h1>{state.get('content')}</h1>
            <p>This is the About page.</p>
        </div>
    );
};

About.defaultProps = {
    className: 'about',
};

export default About;
```

<figure><img src="/files/yx2uXSvV5UbKIJWvrP47" alt=""><figcaption><p>/about</p></figcaption></figure>
{% endtab %}
{% endtabs %}

### Great, Now we are SPA Routing!

But wait, does that mean I have to have common elements like the **`Nav`** on every routed page?

Let's create an **`AppParent`** component to be the "window dressing" for our app!

```bash
npx reactium component

[ARCLI] > Select directory:  common-ui
❯ src/app/components/common-ui

[ARCLI] > Component Name:  AppParent

[ARCLI] > Route:
[ARCLI] > Reactium Hooks?:  (Y/n)  Yes
[ARCLI] > Domain file?:  (Y/n)  Yes

[ARCLI] > Stylesheet?:  (Y/n) Yes
  variables 
  base 
  atoms 
  molecules 
❯ organisms 
  overrides 
  default 
(Move up and down to reveal more choices)

[ARCLI] > Preflight checklist:

{
  "destination": "src/app/components/common-ui/AppParent",
  "name": "AppParent",
  "route": "[]",
  "hooks": true,
  "domain": true,
  "style": true,
  "styleType": "_reactium-style-organisms",
  "className": "appparent",
  "index": true
}

[ARCLI] > Proceed?:  (Y/n) Yes
```

Let's move the **`Nav`** to the **`AppParent`** component, and add some common page structure to the app.

{% tabs %}
{% tab title="AppParent.jsx" %}

```jsx
import { useHookComponent } from '@atomic-reactor/reactium-core/sdk';
import React from 'react';

/**
 * -----------------------------------------------------------------------------
 * Component: AppParent
 * -----------------------------------------------------------------------------
 */
export const AppParent = ({ className, children }) => {
    const Nav = useHookComponent('Nav');
    const Footer = useHookComponent('Footer');
    return (
        <main className={className}>
            <aside className='main-nav'>
                <Nav />
            </aside>
            <section className='main-content'>{children}</section>
            <footer className='main-footer'>
                <Footer />
            </footer>
        </main>
    );
};

AppParent.defaultProps = {
    className: 'appparent main',
};

export default AppParent;

```

{% hint style="success" %}
Note that the **`Footer`** component need not actually already exist. If someone creates one with that name, it will just show up!
{% endhint %}

{% hint style="success" %}
By creating an **`AppParent`** component that returns **`props.children`**, it will automatically take the place of the component in reactium-core. Registered components are overridden! A good thing!
{% endhint %}
{% endtab %}

{% tab title="\_reactium-style-organisms-AppParent.scss" %}

```scss
.main {
    padding: 50px;
    &-nav, &-content {
      border-bottom: 1px solid black;
    }

    &-content {
      padding: 20px 0;
    }
}

```

{% endtab %}

{% tab title="Home.jsx" %}

```jsx
import { useSyncState } from '@atomic-reactor/reactium-core/sdk';
import React from 'react';

/**
 * -----------------------------------------------------------------------------
 * Component: Home
 * -----------------------------------------------------------------------------
 */
export const Home = ({ className }) => {
    const state = useSyncState({ content: 'Home' });

    return (
        <div className={className}>
            <h1>{state.get('content')}</h1>
            <p>This is the Home page.</p>
        </div>
    );
};

Home.defaultProps = {
    className: 'home',
};

export default Home;

```

{% endtab %}

{% tab title="About.jsx" %}

```jsx
import { useSyncState } from '@atomic-reactor/reactium-core/sdk';
import React from 'react';

/**
 * -----------------------------------------------------------------------------
 * Component: About
 * -----------------------------------------------------------------------------
 */
export const About = ({ className }) => {
    const state = useSyncState({ content: 'About' });

    return (
        <div className={className}>
            <h1>{state.get('content')}</h1>
            <p>This is the About page.</p>
        </div>
    );
};

About.defaultProps = {
    className: 'about',
};

export default About;
```

{% endtab %}

{% tab title="\_reactium-style-molecules-Nav.scss" %}

```scss
.nav {
    display: flex;

    a {
        padding: 10px 20px;
        &,
        &:visited,
        &:hover,
        &:active {
            text-decoration: none;
        }

        &,
        &:visited {
            color: gray;
        }
        &:hover,
        &.active {
            color: white;
            background: gray;
        }
    }
}

```

{% endtab %}
{% endtabs %}

### Final Simple SPA

<figure><img src="/files/FgkTEuyloKOemAY5MfZS" alt=""><figcaption><p>Front-end Routed Single Page Application</p></figcaption></figure>


# Creating a Sassy Style Sheet

Reactium makes SASS components easy.

## Domain Atomic Partials

Reactium will track your component domain partials for you, and helps you keep your style hierarchy organized by [Atomic Design concepts](https://atomicdesign.bradfrost.com/table-of-contents/).

Ordinarily in SASS, you would be fully responsible for setting up your base .scss stylesheet, and manage a set of `@import` statements for each partial in your system. With Reactium, any specially named partials found throughout your `src` code-base will be automatically imported into a special partial, found at `src/assets/style/_scss/_reactium-modules.scss`. This partial is managed by Reactium, so just import it in your top-level stylesheet to get started.

{% code title="src/assets/style/style.scss" %}

```scss
@import '_scss/reactium-modules';
```

{% endcode %}

{% hint style="info" %}
In general you won't need to edit this file. This is the default.
{% endhint %}

When starting the Reactium build locally, a style.css will automatically be generated and placed in the `/public/assets/style` directory, which will be served by Node/Express at `http://localhost:3030/assets/style/style.css`.

### Dynamic Partials

See [\_reactium-style partials reference](https://docs.reactium.io/reactium/domain/basic-domain-model#_reactium-style.scss) for more information.

Rather than managing all of your styles in one place (such as the `/src/assets/style directory`), this will let you place your styles anywhere in the `src` directory, and will automatically import them in a sensible order.

The order which these partials is loaded in your sassy style-sheet is:

1. **mixins**: for sass mixins and functions
2. **variables**: for sass variables
3. **base**: for global base html element styles (like reset)
4. **atoms**: for specific small-grain atomic styles
5. **molecules**: for molecule (or multiple composed atoms)
6. **organisms**: for larger markup structure styles
7. **overrides**: for overriding existing styles using natural cascade order

### Example: Bootstrap SCSS

In this example, let's add bootstrap styles from the NPM module into the Reactium stylesheet hierarchy.

First, let's install bootstrap into the project.

```bash
npm install --save bootstrap@5.1.3
```

Ok, now let's create the following files anywhere in our `src` directory:

```
├── bootstrap
│   ├── _reactium-style-atoms.scss
│   ├── _reactium-style-base.scss
│   ├── _reactium-style-mixins.scss
│   ├── _reactium-style-molecules.scss
│   └── _reactium-style-organisms.scss
```

In our `_reactium-style-mixins.scss` partial, let's import the highest priority items from the bootstrap framework (functions, mixins, default variables):

{% code title="\_reactium-style-mixins.scss" %}

````scss
/*!
 * Bootstrap v5.1.3 (https://getbootstrap.com/)
 * Copyright 2011-2021 The Bootstrap Authors
 * Copyright 2011-2021 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
 */

// scss-docs-start import-stack
// Configuration
@import "~bootstrap/scss/functions";
@import "~bootstrap/scss/variables";

// Toggles
//
// Used in conjunction with global variables to enable certain theme features.

// Vendor
@import "~bootstrap/scss/vendor/rfs";

// Deprecate
@import "~bootstrap/scss/mixins/deprecate";

// Helpers
@import "~bootstrap/scss/mixins/breakpoints";
@import "~bootstrap/scss/mixins/color-scheme";
@import "~bootstrap/scss/mixins/image";
@import "~bootstrap/scss/mixins/resize";
@import "~bootstrap/scss/mixins/visually-hidden";
@import "~bootstrap/scss/mixins/reset-text";
@import "~bootstrap/scss/mixins/text-truncate";

// Utilities
@import "~bootstrap/scss/mixins/utilities";

// Components
@import "~bootstrap/scss/mixins/alert";
@import "~bootstrap/scss/mixins/backdrop";
@import "~bootstrap/scss/mixins/buttons";
@import "~bootstrap/scss/mixins/caret";
@import "~bootstrap/scss/mixins/pagination";
@import "~bootstrap/scss/mixins/lists";
@import "~bootstrap/scss/mixins/list-group";
@import "~bootstrap/scss/mixins/forms";
@import "~bootstrap/scss/mixins/table-variants";

// Skins
@import "~bootstrap/scss/mixins/border-radius";
@import "~bootstrap/scss/mixins/box-shadow";
@import "~bootstrap/scss/mixins/gradients";
@import "~bootstrap/scss/mixins/transition";

// Layout
@import "~bootstrap/scss/mixins/clearfix";
@import "~bootstrap/scss/mixins/container";
@import "~bootstrap/scss/mixins/grid";

@import "~bootstrap/scss/_utilities.scss";
```
````

{% endcode %}

Next, let's add our base styles controlling layout from the bootstrap framework into `_reactium-style-base.scss`:

{% code title="\_reactium-style-base.scss" %}

```scss
// Layout & components
@import "~bootstrap/scss/root";
@import "~bootstrap/scss/reboot";
@import "~bootstrap/scss/type";
@import "~bootstrap/scss/images";
@import "~bootstrap/scss/containers";
@import "~bootstrap/scss/grid";
```

{% endcode %}

Next, let's select a handful of atom (small-grain) styles we wish to use from the framework, and add them into `_reactium-style-atoms.scss`:

{% code title="\_reactium-style-atoms.scss" %}

```scss
@import "~bootstrap/scss/tables";
@import "~bootstrap/scss/forms/labels";
@import "~bootstrap/scss/forms/form-text";
@import "~bootstrap/scss/forms/form-control";
@import "~bootstrap/scss/forms/form-select";
@import "~bootstrap/scss/forms/form-check";
@import "~bootstrap/scss/forms/form-range";
@import "~bootstrap/scss/forms/floating-labels";
@import "~bootstrap/scss/forms/input-group";
@import "~bootstrap/scss/forms/validation";
@import "~bootstrap/scss/buttons";
@import "~bootstrap/scss/transitions";
@import "~bootstrap/scss/dropdown";
```

{% endcode %}

Next, let's select some molecule styles:

{% code title="\_reactium-style-molecules.scss" %}

```scss
@import "~bootstrap/scss/button-group";
@import "~bootstrap/scss/nav";
@import "~bootstrap/scss/navbar";
@import "~bootstrap/scss/card";
@import "~bootstrap/scss/accordion";
@import "~bootstrap/scss/breadcrumb";
@import "~bootstrap/scss/pagination";
@import "~bootstrap/scss/badge";
@import "~bootstrap/scss/alert";
@import "~bootstrap/scss/progress";
@import "~bootstrap/scss/list-group";
@import "~bootstrap/scss/close";
@import "~bootstrap/scss/toasts";

```

{% endcode %}

Next, our large organisms and any late precedence styles from the framework:

{% code title="\_reactium-style-organisms.scss" %}

```scss
@import "~bootstrap/scss/modal";
@import "~bootstrap/scss/tooltip";
@import "~bootstrap/scss/popover";
@import "~bootstrap/scss/carousel";
@import "~bootstrap/scss/spinners";
@import "~bootstrap/scss/offcanvas";
@import "~bootstrap/scss/placeholders";

// Helpers
@import "~bootstrap/scss/helpers/clearfix";
@import "~bootstrap/scss/helpers/colored-links";
@import "~bootstrap/scss/helpers/ratio";
@import "~bootstrap/scss/helpers/position";
@import "~bootstrap/scss/helpers/stacks";
@import "~bootstrap/scss/helpers/visually-hidden";
@import "~bootstrap/scss/helpers/stretched-link";
@import "~bootstrap/scss/helpers/text-truncation";
@import "~bootstrap/scss/helpers/vr";

// Utilities
@import "~bootstrap/scss/utilities/api";

```

{% endcode %}

Ok, now let's look at what Reactium will put in our modules partial for us automatically:

{% code title="src/assets/style/\_scss/\_reactium-modules.scss" %}

```scss
// WARNING: Do not directly edit this file !!!!
// File generated by gulp styles:partials task

@import 'bootstrap/_reactium-style-mixins';
@import 'bootstrap/_reactium-style-base';
@import 'bootstrap/_reactium-style-atoms';
@import 'bootstrap/_reactium-style-molecules';
@import 'bootstrap/_reactium-style-organisms';
```

{% endcode %}

{% hint style="warning" %}
Note the WARNING message. Don't modify this file, as Reactium will recreate it frequently during local development and production build.
{% endhint %}

#### Variables

Ok, now that we've importing those components of bootstrap that we want, let's setup a SCSS variables file so we can override any of the variable defaults in bootstrap for Themeing:

{% code title="src/assets/style/\_reactium-style-variables.scss" %}

```scss
$white: #fff;
$gray-100: #f8f9fa;
$gray-200: #e9ecef;
$gray-300: #dee2e6;
$gray-400: #ced4da;
$gray-500: #adb5bd;
$gray-600: #6c757d;
$gray-700: #495057;
$gray-800: #343a40;
$black: #212529;
$black: #000;

```

{% endcode %}

### Domain Styling

Up to this point, we've been building out style-sheet from the top-level `/src/assets/style` directory in our project. This is sometimes desirable, such as in this case (importing styles from a library). Often though we have styles that apply to a component in our application, and it would nice to create that style in the same directory as our component.

Fortunately, Reactium will find these partials anywhere in your src directory, and automatically import them.

Let's say I have a custom Button component, and I want to style it in place:

{% code title="src/app/components/common-ui/CustomButton/index.js" lineNumbers="true" %}

```jsx
import React from 'react';

const CustomButton ({children, ...props}) => 
    (<button {...props} className='custom-button'>{children}</button>);

export default CustomButton;
```

{% endcode %}

Now to style this button, I can create an atom style partial in the same directory, and Reactium will automatically import it:

{% code title="src/app/components/common-ui/CustomButton/\_reactium-style-atoms.scss" %}

```scss
.custom-button {
    background: $gray-800;
    color: $white;
}
```

{% endcode %}

{% hint style="info" %}
This component directory can now be moved safely anywhere in the src directory without changing needing to change the import statement in your stylesheet!
{% endhint %}


# Reactium Core

Reactium is a Node/Express + React.js framework for creating front-end apps.

Reactium is built on a core framework. The local development and build configuration that comes out of the box is meant to be upgradeable, so long as your application was built off a semver that is minor-version compatible with the current.

Even for larger version steps, we are going to attempt to describe (or automate) much of the migration from one version of Reactium core to another.

Updating core is performed with the **`reactium`** command:

```bash
npx reactium update
```

> See: [Updating](/reactium/updating) for details

With a number of other front-end frameworks, even those based on React, the philosophy is to entirely hide the local development/build configuration from the developer, sometimes with an eject feature to get raw configuration / build files.

Our philosophy is to create a strong opinion for building a React application, from application structure, to out of the box capabilities such as routing, plugins, and state management, while giving the code maintainer, lead-dev, and ops roles on your team the power to replace, augment, or override behaviors of the build.

## Hacking Core

{% hint style="danger" %}
Should you hack reactium\_modules? Short answer: **no**
{% endhint %}

If you hack on the files in the **`reactium_modules`** directory of your project, those changes will be overwritten when executing routing `reactium install` operations, similar to `npm install` for **`node_modules`**. Instead of modifying these files directly, fork [**Reactium-Core-Plugins** on Github](https://github.com/Atomic-Reactor/Reactium-Core-Plugins) and send us a pull-request. We'll either add your update if appropriate.

That being said, there are a number of build and development overrides built-in to core for your use.

| Reason                                                                                                                      | Purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | Where                                                                                                                                                                                                                                                                                                   |
| --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [**reactium-gulp.js**](https://docs.reactium.io/reactium/reactium-guides/pages/hRde7H32F95HIdkL0Xds#reactium-gulp.js)       | DDD (domain-driven design) artifact to register/unregister gulp tasks with the ReactiumGulp registry, used to generate gulp tasks at build-time. You can use this in a Reactium plugin to alter gulp tasks within your own domain. Final tasks can be overriden by **gulp.tasks.override.js**.                                                                                                                                                                                                                                                                | <p></p><p>Create this file in any of the following:</p><ul><li>In any domain directory under <strong>src/</strong></li><li>In any node module's <strong>reactium-plugin/</strong> directory.</li><li>In any directory within a module under <strong>reactium\_modules/</strong></li></ul>               |
| [**reactium-webpack.js**](https://docs.reactium.io/reactium/reactium-guides/pages/hRde7H32F95HIdkL0Xds#reactium-webpack.js) | DDD (domain-driven design) artifact to interact with the ReactiumWebpack registry, used to generate the webpack configuration at build-time. Final configuration can be overridden by **webpack.override.js**                                                                                                                                                                                                                                                                                                                                                 | <p></p><p>Create this file in any of the following:</p><ul><li>In any domain directory under <strong>src/</strong></li><li>In any node module's <strong>reactium-plugin/</strong> directory.</li><li>In any directory within a module under <strong>reactium\_modules/</strong></li></ul>               |
| **gulp.config.override.js**                                                                                                 | <p><strong>Override:</strong> <strong>.core/gulp.config.js</strong></p><ul><li>Change build <strong>src/dest</strong> and <strong>port</strong></li></ul>                                                                                                                                                                                                                                                                                                                                                                                                     | <p>Create this file in any of the following:</p><ul><li>Project root</li><li>In any node module's <strong>reactium-plugin/</strong> directory.</li><li>In any directory under <strong>src/</strong></li><li>In any directory within a module under <strong>reactium\_modules/</strong></li></ul>        |
| **gulp.tasks.override.js**                                                                                                  | <p><strong>Override:</strong> <strong>.core/gulp.tasks.js</strong></p><ul><li>Add pre or post build tasks. <br>Replace built-in tasks.</li><li>See <a href="/pages/-M5FaINXMv_Q4nCkQSrQ#reactium-gulp-js"><strong>reactium-gulp.js</strong> DDD artifact </a>for more portable / modular way to approach changing gulp tasks.</li></ul>                                                                                                                                                                                                                       | Create this file in the project root.                                                                                                                                                                                                                                                                   |
| **manifest.config.override.js**                                                                                             | <p><strong>Override:</strong> <strong>.core/reactium-config.js</strong></p><ul><li>Add component search context.</li><li>Add application dependencies to dependency module. </li></ul>                                                                                                                                                                                                                                                                                                                                                                        | <p></p><p>Create this file in any of the following:</p><ul><li>Project root</li><li>In any node module's <strong>reactium-plugin/</strong> directory.</li><li>In any directory under <strong>src/</strong></li><li>In any directory within a module under <strong>reactium\_modules/</strong></li></ul> |
| **webpack.override.js**                                                                                                     | <p><strong>Override:</strong> <strong>.core/webpack.config.js</strong></p><ul><li>Make changes to the Webpack bundling process</li><li>Use this when you want access directly to change the webpack configuration data structure.</li><li>See <strong>reactium-webpack.js</strong> DDD artifact for more portable / modular way to approach manipulating webpack configuration.</li></ul>                                                                                                                                                                     | <p></p><p>Create this file in any of the following:</p><ul><li>Project root</li><li>In any node module's <strong>reactium-plugin/</strong> directory.</li><li>In any directory under <strong>src/</strong></li><li>In any directory within a module under <strong>reactium\_modules/</strong></li></ul> |
| **webpack.umd.override.js**                                                                                                 | <p><strong>Override:</strong> <strong>.core/webpack.config.umd.js</strong></p><ul><li>Make changes to the Webpack bundling process for UMD (Universal Module Definition) modules, created automatically by <a href="/pages/-M5FaINXMv_Q4nCkQSrQ#umd-js"><strong>umd.js</strong> DDD artifacts.</a></li><li>Use this when you want access directly to change the webpack configuration data structure.</li><li>See <strong>reactium-webpack.js</strong> DDD artifact for more portable / modular way to approach manipulating webpack configuration.</li></ul> | <p></p><p>Create this file in any of the following:</p><ul><li>Project root</li><li>In any node module's <strong>reactium-plugin/</strong> directory.</li><li>In any directory under <strong>src/</strong></li><li>In any directory within a module under <strong>reactium\_modules/</strong></li></ul> |
| **babel.config.js**                                                                                                         | <p><strong>Override: .core/babel.config.js</strong></p><ul><li>Add Babel presets / plugins. </li><li>Add module alias for both server / compiled front-end.</li></ul>                                                                                                                                                                                                                                                                                                                                                                                         | Must exist in the project root.                                                                                                                                                                                                                                                                         |

### gulp.config.override.js

Exports a function that takes core gulp configuration object as a parameter, and returns configuration object used by gulp tasks.

{% hint style="info" %}
In some case Webpack uses the gulp config.
{% endhint %}

{% code title="/gulp.config.override.js" %}

```javascript
module.exports = config => {

    // Electron configuration
    config.dest.electron = 'build-electron';
    config.dest.static = 'build-electron/app/public';
    config.electron = {
        config: {
            width: 1280,
            height: 1024,
            show: false,
            title: 'App Title',
            backgroundColor: '#000000',
        },
        devtools: true,
    };

    // Disable auto launch of default browser
    config.open = false;

    return config;
};
```

{% endcode %}

### gulp.tasks.override.js

Exports a function that takes an object defining core gulp tasks as a parameter, and returns and object whose properties define the tasks run by gulp.

```
Code example
```

### manifest.config.override.js

Exports a function that takes configuration the manifest-tools use to build src/manifest.js as a parameter, and returns new manifest configuration.

{% code title="/manifest.config.override.js" %}

```javascript
module.exports = config => {
    // Disable code splitting for Electron projects
    config.contexts.components.mode = 'sync';
    config.contexts.common.mode = 'sync';
    config.contexts.toolkit.mode = 'sync';
    config.contexts.core.mode = 'sync';

    return config;
};

```

{% endcode %}

### webpack.override.js

Exports a function that takes the core webpack configuration as a parameter, and returns an object that will be used for webpack to build the js bundle.

{% code title="/webpack.override.js" %}

```javascript
const webpack = require('webpack');
const path = require('path');

/**
 * Passed the current webpack configuration from core
 * @param  {Object} webpackConfig the .core webpack configuration
 * @return {Object} your webpack configuration override
 */
module.exports = webpackConfig => {
    const newWebpackConfig = Object.assign({}, webpackConfig);

    newWebpackConfig.entries['entry'] = path.resolve('/path/to/my/entry');
  

    newWebpackConfig.plugins.push(new webpack.ContextReplacementPlugin(/^my-context/, context => {
      context.request = path.resolve('./src/app/my-context');
    }));

    return newWebpackConfig;
};
```

{% endcode %}

### webpack.umd.override.js

Serves the same purpose at the **webpack.override.js** except overrides the configuration used for each UMD (Universal Module Definition) module that is created by making a [**umd.js** DDD artifact](/reactium/domain#umd-js) in your project. The callback function you export will receive at separate webpack configuration for each umd.js module to be created.

{% code title="/webpack.umd.override.js" %}

```
/**
 * Passed the current webpack configuration from core
 * @param  {Object} umd module manifest configuration, generated when
 * umd files are located.
 * @param  {Object} webpackConfig the .core webpack configuration
 * @return {Object} your webpack configuration override
 */
module.exports = (umd, webpackConfig) => {
    if (umd.libraryName === 'media-uploader') {
        delete webpackConfig.module.rules;
    }
    return webpackConfig;
};

```

{% endcode %}

{% hint style="info" %}
To see what is generated for each umd in the manifest, look in **.tmp/umd-manifest.json** after running the build (**`npm run build`**). This will contain all the objects generated when looking for umd.js DDD artifacts. See the [umd-config.json DDD artifact](/reactium/domain#umd-config-json) for more information on controlling this behavior.
{% endhint %}

### babel.config.js

{% hint style="warning" %}
**Required** and provided by default.
{% endhint %}

Imports babel configuration and exports the configuration used by Webpack and babel-node.

{% code title="/babel.config.js" %}

```javascript
const config = require('./.core/babel.config');

// To add a module resolver for node and webpack
const path = require('path');

const moduleResolver = config.plugins.find(plugin => plugin[0] === 'module-resolver');
moduleResolver[1].alias['redux-addons'] = './src/app/redux-addons';

module.exports = config;
```

{% endcode %}

## Node/Express&#x20;

Important to dev-leads, ops and backend devs, there are a number of ways you can change the behavior of the core express server without hacking **.core**.

### Express Middleware

To add or change the stack of Node / Express middleware for the running server, create a **src/app/server/middleware.js** file, which should export a function taking an array of express middlewares as an argument, and returns the modified list of middlewares.

In this way, you can add/change routing, security configuration, etc to your hearts content.

#### Express Middleware Example #1:

{% code title="/src/app/server/middleware.js" %}

```javascript
module.exports = expressMiddlewares => {

    // Simple Logger
    const mySimpleRequestLogger = (req, res, next) => {
        console.log('SIMPLE LOGGER: REQUEST '+req.path);
        next();
    };

    return [
        {
            name: 'mySimpleRequestLogger',
            use: mySimpleRequestLogger,
        },
        ...expressMiddlewares,
    ];
};
```

{% endcode %}

**Express Middleware Example #2:**

{% code title="/src/app/server/middleware.js" %}

```javascript
// Health check route handler

const express = require('express');
const router = express.Router();

const healthy = router.get('/healthcheck', (req, res) => {
    res.status(200).send('ok');
});

module.exports = expressMiddlewares => {
    return [
        {
            name: 'myRouteHandler',
            use: router,
        },
        ...expressMiddlewares,
    ];
};
```

{% endcode %}

**Express Middleware Example #3:**

{% code title="/src/app/server/middleware.js" %}

```javascript
// More secure Cross Origin Request Sharing for production:

const cors = require('cors');

module.exports = expressMiddlewares => {
    return expressMiddlewares.map(mw => {
        // no change
        if (nw.name !== 'cors' || !('CORS_ORIGIN' in process.env)) {
            return mw;
        }

        // enforce origin
        return {
            name: 'cors',
            use: cors({
                origin: process.env.CORS_ORIGIN,
            }),
        };
    });
};
```

{% endcode %}

### Application Defines

Node/Express **global.defines** variables can be set by creating a **src/app/server/defines.js** file that exports a JavaScript object.

The file will also be used in constructing a Webpack defines plugin values.

Theoretically, your *server-side* and FE *(front-end)* code could make reference to values specified here.

Contrived **src/app/server/defines.js**:

{% code title="/src/app/server/defines.js" %}

```
module.exports = {
    foo: 'bar',
};
```

{% endcode %}

Isomorphic Define JS somewhere in front-end React code:

{% code title="/src/app/server/defines.js" %}

```javascript
let fooValue;
if (typeof window !== 'undefined') {
    fooValue = foo; // webpack define plugin
} else {
    fooValue = defines.foo; // node express global
}
```

{% endcode %}

### Environment Variables

Reactium uses the following environment variables:&#x20;

| Variable                    | Description                                                                                                                      |
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| **PORT**                    | For environments where running application is specified by **`PORT`** var                                                        |
| **APP\_PORT**               | For environments where running application is specified by **APP\_PORT** var                                                     |
| **PORT\_VAR**               | Tells express where to look in environment variable to get the HTTP port setting                                                 |
| **DEBUG**                   | Enable or Disable logging                                                                                                        |
| **WEBPACK\_RESOURCE\_BASE** | Used to dynamically define the base URL where webpack bundles are served.                                                        |
| **PUBLIC\_DIRECTORY**       | Change the directory that express will serve static assets from                                                                  |
| **ACTINIUM\_APP\_ID**       | Used to identify the application when connecting Reactium to Actinium API. Defaults to **`Actinium`**                            |
| **REST\_API\_URL**          | Used when connecting Reactium to a REST API or Actinium                                                                          |
| **PROXY\_ACTINIUM\_API**    | When set to **`off`**, disables api proxy, and API calls will got direct to the API server.                                      |
| **PROXY\_API\_PATH**        | Defaults to **`/api`**. The path used to proxy to the API server. Use in tandem with **`REST_API_URL`** to control API behavior. |
| **ACTINIUM\_API\_ENABLED**  | When set to **`off`**, Actinium/Parse API will not be loaded.                                                                    |

#### WEBPACK\_RESOURCE\_BASE

Use this environment variable when you plan to upload your webpack assets to a CDN. It defaults to serving webpack assets from the document root at `/assets/js/.` If you wanted to upload the js folder to cdn.example.com for example, you might start the server like so:

```sh
WEBPACK_RESOURCE_BASE=https://cdn.example.com/js/ npm start
```

> **Default: /assets/js/**

**PORT**

Any TCP port appropriate for HTTP protocol (**port.proxy** in **./core/gulp.config.js**) where running application port is specified by **PORT** var.

> **Default:** **3030**

{% hint style="danger" %}
Some environments like [Heroku](https://devcenter.heroku.com/articles/deploying-nodejs) automatically set this value
{% endhint %}

#### APP\_PORT

Any TCP port appropriate for HTTP protocol (**port.proxy** in **./core/gulp.config.js**) where running application port is specified by **APP\_PORT** var.

> **Default:** **3030**

{% hint style="danger" %}
Some environments automatically set this value
{% endhint %}

#### DEBUG

Logging can be helpful for troubleshooting server-side rendering issues.&#x20;

{% hint style="info" %}
Server-side logging can drive front-end devs batty
{% endhint %}

* **off** to suppress logging to STDOUT
* **on** to enable logging

> **Default:** **off**

#### PUBLIC\_DIRECTORY

Full-path to public assets directory used the static middleware module.&#x20;

{% hint style="info" %}
If you have changed the build process to output static assets (js/css/images, etc) you will want to specify this value.&#x20;
{% endhint %}

> **Default: ./public**

#### **ACTINIUM\_APP\_ID**

Used by `@atomic-reactor/reactium-api` Reactium module, specify the Actinium Application ID used by [Actinium API](/actinium/actinium-core).

> **Default: Actinium**

#### **REST\_API\_URL**

Used by `@atomic-reactor/reactium-api` Reactium module, specify the fully qualified URL to the [Actinium API](/actinium/actinium-core) server.

{% hint style="info" %}
By default, this URL is proxied from any request on the Reactium host with path prefix /api. e.g. <https://myreactiumhost/api> proxies requests to <https://myactinumhost/api>
{% endhint %}

> **Default**: <http://localhost:9000/api>

{% hint style="warning" %}
While this default value eases local development, it is an unlikely value for production.
{% endhint %}

#### **PROXY\_ACTINIUM\_API**

Used by `@atomic-reactor/reactium-api` Reactium module, can be used to disable the proxy middleware to the Actinium API.

* **on**: Actinium API proxy is enabled. API calls direct through Reactium back-end and are proxied to Actinium API.
* **off**: Actinium API proxy is disabled. API calls go direct to Actinium API from the Reactium front-end.

> **Default**: on

{% hint style="info" %}
By proxying through the Reactium back-end, you won't have to worry about CORS.
{% endhint %}

#### **PROXY\_API\_PATH**

Used by `@atomic-reactor/reactium-api` Reactium module, can be used to set the front-end path that proxies to the Actinium API.

> **Default**: /api

#### **ACTINIUM\_API\_ENABLED**

Used by `@atomic-reactor/reactium-api` Reactium module, can be used to disable just the Actinium API.

* **on**: Actinium API is enabled
* **off**: Actinium API is disabled

> **Default**: on

{% hint style="info" %}
You can also uninstall the module, using arcli.
{% endhint %}

## Single Page App Template

The default templates are good for simple SPAs, but inevitably you will need to provide a different template for rendering your application's **index.html**.

To do so, generate server templates using ARCLI:&#x20;

```bash
reactium server template
```

Modify the newly created templates found in: **/src/app/server/template** directory

Reactium core will use your custom templates to serve your SPA so long as your template **version** string satisfies the **semver** property found for your **@atomic-reactor/reactium-core,** in your `reactiumDependencies` section of `package.json`.

You may need to update these templates after major and minor version updates of core.

To find out the **version** and **semver**:&#x20;

```bash
reactium version
```

{% hint style="danger" %}
**Important:** replace the **version** property string found in the SPA templates with the version number found in **reactium\_modules/@atomic-reactor/reactium-core/reactium-config.js**
{% endhint %}

## Static Build Template

There is a **/src/index-static.html** file provided, which can be used to compile a static **index.html** file when running static build:&#x20;

```
$ npm run static
```

This is for Reactium applications that will be served by another web-server like Apache, Nginx, Tomcat, etc.&#x20;

{% hint style="info" %}
Supports only front-end rendered React
{% endhint %}


# Reactium + Actinium (APIs)

Reactium foundational web app framework comes with built-in support for the complementary API framework, Actinium, giving you rapid access to built-in cloud functions, and your own API extensions.

The default API experience with Reactium is facilitated by a [separate API server](/actinium/actinium-core), Actinium, coupled with a front-end module that makes integration with the API server easy.

{% hint style="info" %}
The Actinium API module is installed by default. To install it manually, use Reactium CLI:

```
npx reactium install @atomic-reactor/reactium-api
```

{% endhint %}

Out of the box Reactium is ready to work with Actinium with a little configuration. Simply set the **REST\_API\_URL** and the **ACTINIUM\_APP\_ID** environment variables.&#x20;

```javascript
$ export REST_API_URL=https://my.actinium.url/api
$ export ACTINIUM_APP_ID=Actinium
$ npm start
```

In your Reactium code use the default helper module provided to immediately begin using the Actinium SDK.

{% code title="/SomeDomain/services.js" %}

```jsx
import Reactium from 'reactium-core/sdk'; 

export default {
    myCloudFunction: params => Reactium.Cloud.run('myCloudFunction', params)
    .then(data => { /* do something */ })
};
```

{% endcode %}

{% hint style="success" %}
Start Actinium then start Reactium and you're good to go!
{% endhint %}

While the extensible Reactium SDK is our opinion for the best way to quickly add backend API functionality to your webapp, supporting other client-side APIs is a snap. See [Reactium + REST](/reactium/reactium-guides/reactium-+-rest).

### Running the Full-Stack Locally

Start by installing both [Reactium](/installing-foundations/install) and [Actinium](/installing-foundations/install-actinium) locally.

Once you have Reactium and Actinium installed, you can run the UI server and the API server on the same machine.

For local development, Actinium runs on localhost on port 9000 and Reactium will run on localhost on port 3000 for browser-sync (and 3030 for the base Node/Express server).

See the [Architechure Diagram](/approach/architecture) to get a visual sense of the relationship between these two servers. In summary, Reactium is a micro-service for serving the front-end of your web-app, and Actinium is a micro-service for building an API (and database) for your application.

### Using Actinium in Express Middleware

There may be a time when you will want access to Actinium when creating Express middleware inside of a [***reactium-boot.js***](https://docs.reactium.io/reactium/reactium-guides/pages/HYFEMg0Q0BDsx6NRDRh2#reactium-boot.js) file. If you have the reactium-api module installed, Actinium is available out of the box as a global.&#x20;

{% code title="reactium-boot.js" lineNumbers="true" %}

```javascript
const bodyParser = require('body-parser');
const express = require('express');
const router = express.Router();

router.use(bodyParser.json());
router.use(bodyParser.urlencoded({ extended: false }));

router.post('/auth', async (req, res) => {
    const { username, password } = req.body;
    const result = await Actinium.Cloud.run('my-auth-function', { username, password });
    res.json(result);
});

ReactiumBoot.Server.Middleware.register('auth', {
    name: 'auth',
    use: router,
    order: ReactiumBoot.Enums.priority.highest,
});
```

{% endcode %}


# Reactium + REST

The foundational web app framework Reactium can be used with our Actinium API or with and client-side API of your choosing.

### Creating a simple API

Use axios, native fetch, or a library of your choosing, in some API domain folder of your choice, generate a new `reactium-hooks.js` file.

{% code title="reactium-hooks.js (version 1)" %}

```javascript
import Reactium from 'reactium-core/sdk';
import axios from 'axios';

const helloAPI = {
  hello() {
    return axios.get('http://demo7132150.mockable.io/hello');
  }
};

// TODO: register API here
```

{% endcode %}

### Register your API

The above is incomplete. In order to make this API available to the rest of your app, let's register it.

{% code title="reactium-hooks.js (version 2)" %}

```javascript
import Reactium from 'reactium-core/sdk';
import axios from 'axios';

const helloAPI = {
  contructor(baseURL) {
    this.axios = axios.create({
      baseURL,
    });
  }
  hello() {
    return this.axios.get('/hello');
  }
};

Reactium.API.register({
  name: 'helloAPI',
  api: new helloAPI('http://demo7132150.mockable.io'),
});
```

{% endcode %}

Now that we've registered our REST API with the Reactium SDK, we can use it throughout out app as `Reactium.helloAPI`. Congrats! You just extended the Reactium SDK with your own API!

### Use your API

Let's say we want to surface our `/hello` API endpoint in a React component. We can now access our `helloAPI` on the Reactium SDK directly.

{% code title="src/app/components/Hello/MyHelloComponent.js" %}

```javascript
import React, { useState } from 'react';
import Reactium, { useAsyncEffect } from 'reactium-core/sdk';

const MyHelloComponent = ({ startingMsg = ''}) => {
  const [ message, setMessage ] = useState(startingMsg);
  
  useAsyncEffect(async mounted => {
    let newMessage;
    try {
      const { data } = await Reactium.helloAPI.hello();
      newMessage = data.msg;
    } catch (error) {
      newMessage = 'Oh no!';
    }
    
    if (mounted()) {
      setMessage(newMessage);
    }
  });
  
  return (<div>{message}</div>);
};

MyHelloComponent.defaultProps = {
  startingMsg: 'Waiting...',
};

export default MyHelloComponent;
```

{% endcode %}


# Plugin Module Guide

Guide to building Actinium & Reactium plugin modules.

## Overview

One of the compelling reasons for using the Reactium Framework is our robust and powerful plugin architecture. There are a two approaches to creating plugins:

* [Build-time Plugins](/reactium/reactium-guides/plugin-development-guide#build-time-plugins) - extending functionality at build-time
* [Run-time Plugins](/reactium/reactium-guides/plugin-development-guide#run-time-plugins) - extending functionality at run-time

## Build-time Plugins

Build-time Plugins extend the functionality of Reactium or Reactium API (Actinium) projects. When downloaded from the Reactium Plugin Registry, the code from a Build-time Plugin is downloaded into your project **reactium\_modules** (or **actinium\_modules** respectively) directory and bundled with your application at build-time.&#x20;

Build-time plugins only require a **package.json** in your plugin directory for publishing it to the Reactium Plugin Registry.

```
# installs Demo site plugin into reactium_modules
npx reactium install @atomic-reactor/reactium-demo
```

### Create A Build-time Plugin

{% tabs %}
{% tab title="Reactium" %}
{% code title="From Reactium root:" %}

```
npx reactium component
```

{% endcode %}
{% endtab %}

{% tab title="Actinium" %}
{% code title="From Actinium root:" %}

```bash
npx reactium plugin
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% hint style="info" %}
&#x20;**See:** [*Creating A Component*](broken://pages/-M4yjrVMQdHaPqJ5YjF7) *for more information on Component Development*
{% endhint %}

### Publish A Build-time Plugin

Once you're done building your plugin, publish it to the Reactium Plugin Registry so that it can be installed in other projects.

{% code title="From plugin directory:" %}

```
npx reactium publish
```

{% endcode %}

You will be prompted to create a **package.json** if it does not exist in the plugin directory.&#x20;

The plugin files will then be compressed and uploaded to the Reactium Plugin Registry.&#x20;

Plugins are version controlled and exercise an Access-control List **(ACL)** to restrict who has permission to install the plugin. By default, plugins are public. Making your plugin private will restrict access to the ACL.

```
npx reactium publish
[ARCLI] > Version: (0.0.138)
[ARCLI] > Private (Y/N): Y
```

{% hint style="info" %}
*You can update your plugin ACL from your Reactium Plugin Registry account.*&#x20;
{% endhint %}

### Install A Build-time Plugin

Once your plugin has been published, it can be installed in any Actinium or Reactium project.&#x20;

{% tabs %}
{% tab title="Actinium" %}
{% code title="From Actinium root:" %}

```
npx reactium install @myscope/MyPlugin
```

{% endcode %}
{% endtab %}

{% tab title="Reactium" %}
{% code title="From Reactium root:" %}

```
npx reactium install @myscope/MyPlugin
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% hint style="info" %}
**Note:** *If you don't have access to the specified plugin an error message will be displayed.*
{% endhint %}

### NPM Build-time Plugin

The last type of build-time plugin for Reactium / Actinium are NPM modules. Much like how at build-time Reactium will look for Domain Driven artifacts in your source directory, it will also look for them in your `node_modules` directory, albeit with some constraints. NPM build-time modules are constructed much like  `actinium_modules` and `reactium_modules`, however you will likely need to transpile these modules as ES5 common-js modules, using a tool like babel before publishing. This is an advanced topic, and requires understanding of these tools.

#### Actinium NPM Build-time Plugin Module

An NPM module containing a `plugin.js` for Actinium, will be discovered if there is found an NPM module contains an `actinium` directory with a file named `*plugin.js`. This file will automatically be loaded as an Actinium plugin module. If found directly in an `actinium` directory, the following files will be loaded:

* **actinium/\*cloud.js** - Parse Cloud functions can be defined here
* **actinium/\*plugin.js** - Actinium plugin file. Register your plugin and hooks here.
* **actinium/\*middleware.js** - Register express middleware here to be automatically included.

#### Reactium NPM Build-time Plugin Module

An NPM module containing a directory named `reactium-plugin` will be searched for any DDD artifact that would ordinary by globbed by the Node/Express server (such as **reactium-boot.js**), or any resources that would be loaded automatically by the constructed **src/manifest.js** manifest file:

* **domain.js** - define a domain namespace
* **actions.js** - exports redux actions for domain
* **actionTypes.js** - exports redux action types for domain
* **reducers.js**  - exports redux reducers for a domain
* **state.js** - export default redux initial state for a domain
* **route.js** - export React component route(s)
* **services.js** - export API services for a domain
* **middleware.js** - export redux middleware to be included
* **enhancer.js** - export redux enhancer to be included
* **zone.js** - export rendering zone component registration(s) for a domain
* **reactium-hooks.js** - plugin hooks can be registered here
* **reactium-boot.js** - Node/Express bootstrap hooks can be registered here

## Run-time Plugins

Run-time Plugins are served to a Reactium Application from an Actinium instance as pre-compiled static assets via the API, or by adding the CSS/js import to your HTML templates (via modified templates or the Server SDK). This allows you to dynamically add components, register hooks, cause component to render in `Zone` components throughout your application, even if those component are not present in the app at build time. This is particularly useful for code-splitting with separate codebases, or facilitating 3rd party extensions to your application at runtime.

Run-time Plugins are similar to Build-time Plugins except their code is not downloaded into your project and bundled with your application. A separate script tag includes the plugin. This allows you to add functionality to your Reactium application with hooks at runtime.

Another difference is that Run-time Plugins can be turned on/off from the Reactium Admin without the application being rebuilt, if they are served from an Actinium plugin.&#x20;

Creating a Run-time Plugin involves creating both an Actinium Build-time Plugin and a Reactium Plugin

### Create A Run-time Plugin

After you've created your [Actinium Build-time](/reactium/reactium-guides/plugin-development-guide#create-a-build-time-plugin) plugin create your Reactium Run-time Plugin:

{% code title="From Reactium root:" %}

```bash
npx reactium plugin module
```

{% endcode %}

Follow the prompt to name your module (the word "plugin" must not appear in the name), and it will generate boiler plate directory under `src/app/component/plugin-src`

```
<module-name>
├── assets
│   └── style
│       └── <module-name>-plugin.scss // styles to be compiled to <module-name>-plugin.css
├── index.js // Main entry for developing your new runtime-features
├── reactium-boot.js // Used for local development only, not used in compiled module
├── reactium-hooks.js // Used for local development only, not used in compiled module
├── reactium-hooks.json // used by arcli plugin local to toggle local dev /testing
├── umd-config.json // Used by webpack to build your runtime module <module-name>.js
└── umd.js // Build-time entry point
```

In your `src/app/component/plugin-src/<module-name>/index.js` file, you will have access to certain Reactium framework libraries that will be available as global externals, automatically as es module imports. For example, the following import statements do not bundle anything with your runtime module, but sources them externally:

```javascript
// These default (alias) and named exports are automatically external
// dependencies when used in runtime plugins
import Reactium, { __, useHookComponent } from 'reactium-core/sdk'; // valid
// import SDK from 'reactium-core/sdk'; // invalid, must use alias "Reactium"
import op from 'object-path';
import _ from 'underscore';
```

The following modules can be imported without adding any additional weight to your runtime plugins.

* `axios`
* `classnames`
* `copy-to-clipboard`
* `gsap/umd/TweenMax`
* `moment`
* `object-path`
* `prop-types`
* `react`***\**** (`React` is alias for `default`export)
* `react-router-dom`
* `redux`
* `redux-super-thunk`
* `react-dom` ***\****`(ReactDOM` is alias for `default`export)
* `reactium-core/sdk` ***\**** (`Reactium` is alias for `default` export)
* `semver`
* `shallow-equals`
* `underscore`
* `uuid`
* `xss`

{% hint style="warning" %}
Important: ***`*`***&#x44;ue to the mechanism used by [webpack to proved external dependencies](https://webpack.js.org/configuration/externals/#root), when external ecmascript-modules above contain **BOTH**`default` export **AND** one or more "named exports", there will be a mandatory alias for the default export.&#x20;

For example, you must use `Reactium` as the default export of `reactium-core/sdk`, `React` as the default export of `react`, etc. You may not import such default exports to a different object name. All named exports can be imported in any way you would ordinarily use them.
{% endhint %}

### Registering Components

One of the most useful features of your runtime plugin is the ability to provide your component or consume external React components from a completely different code bundle (even from a different codebase) at runtime.

In the target application, often the developer will have provided a rendering **`Zone`** in the application, that will render unknown (TBD) components, may have declared a theoretical component of a specific name and property set that is not implemented (i.e. left for you to implement in your plugin), or may have registered a component from the codebase that you may use in your foreign code. These are all powerful mechanisms for providing ways to extend your application without needing to know the exact details of how this will be done.

#### Sidebar Example

In this example, we'll imagine a `Zone` component in the parent application that designates a rendering zone for any component you might choose to render in your third-party runtime plugin:<br>

{% code title="Sidebar.js" %}

```javascript
// Parent App somewhere
import React from 'react';
import { Zone, useHookComponent } from 'reactium-core/sdk';

const SideBar = props => {
  const SideBarHeader = useHookComponent('ZoneHeader');
  return (
    <section className='sidebar-zone'>
      <SideBarHeader {...props} />
      <Zone zone='sidebar' {...props} />
    </section>
  );
};

export default SideBar;
```

{% endcode %}

Above we have a hypothetical SideBar component in your parent application. There are two aspects of this component that can be extended dynamically by a plugin:

1. A dynamic `Zone`, which can render one or more unknown components provided by your any plugin. Each component rendered by the `Zone` will receive any properties passed to the `Zone` component.
2. A hook component, which may or may not exist (will be a null component by default), which may be implemented by some plugin.

In your runtime plugin directory, create a `MenuItem.js` file (doesn't matter what you call this). Implement a React component, and register it to the `sidebar` zone in your plugin:

{% code title="src/app/components/plugin-src/my-runtime-feature/index.js (version 1)" %}

```javascript
import Reactium from 'reactium-core/sdk';
import MenuItem from './MenuItem';

// defer any code until plugins are mounted
Reactium.Plugin.register('my-plugin').then(() => {
  Reactium.Zone.addComponent({
    zone: ['sidebar'],
    component: MenuItem,
    order: Reactium.Enums.priority.lowest,
  });
});
```

{% endcode %}

Now in your parent application, when the `SideBar` component renders, your MenuItem component will dynamically render, even if your plugin is a 3rd party plugin, loaded into the browser.

In addition, you may wish to implement the hook component named `SideBarHeader`, create a component in your plugin in a file named `SideBarHeader.js` (again this name does not matter). Using the SDK, register this component:

{% code title="src/app/components/plugin-src/my-runtime-feature/index.js (version 2)" %}

```javascript
import Reactium from 'reactium-core/sdk';
import MenuItem from './MenuItem';
import SideBarHeader from './SideBarHeader';

// defer any code until plugins are mounted
Reactium.Plugin.register('my-plugin').then(() => {
  Reactium.Zone.addComponent({
    zone: ['sidebar'],
    component: MenuItem,
    order: Reactium.Enums.priority.lowest,
  });
  Reactium.Component.register('SideBarHeader', SideBarHeader);
});
```

{% endcode %}

Whenever a component uses `useHookComponent` to get the `SidebarHeader` component, now your component will render (instead of the null component).

{% hint style="info" %}
Components registered with `Reactium.Component.register()` are replaceable. The last plugin chronologically (and by priority) to register a component will replace whatever implementation was previously being used.
{% endhint %}

In addition to providing components for the parent application to use, you may use components provided elsewhere in your own plugin if the parent application or another plugin registered any components. This provides a way to share components across codebase without necessarily needed to have them in your codebase at build-time.\
\
When you're done developing your plugin eject it to the Actinium Build-time plugin you created above:

{% code title="From Reactium root:" %}

```
$ npx reactium plugin eject
```

{% endcode %}

{% hint style="info" %}
You will be prompted to select the plugin and destination directory, and can save this location with a label for subsequent builds.
{% endhint %}

In your target Actinium plugin location, the css and js assets of your runtime plugin will be copied. For example: If your plugin is called `my-runtime-features`, your assets will found in a `plugin-assets` directory, containing `my-runtime-features.js` and `my-runtime-features-plugin.css.`

```
.
└── plugin-assets
    ├── my-runtime-features-plugin.css
    └── my-runtime-features.js
```

Up until now, you've been developing your runtime plugin, but practically you've been doing this at build-time. To see your plugin actually served at runtime, you need register these assets with the Actinium plugin. Register each asset using the Actinium Plugin SDK:

{% tabs %}
{% tab title="Actinium Source" %}
{% code title="plugin.js" %}

```javascript
const path = require('path');
const PLUGIN = {
  ID: 'MyPlugin',
  name: 'My Plugin',
  description: 'My Actinium Plugin. Facilitates runtime plugin when activated.',
  version: {
    plugin: '1.0.0',
  },
};

Actinium.Plugin.register(PLUGIN);

Actinium.Plugin.addScript(path.resolve(
  PLUGIN.ID,
  __dirname, 'plugin-assets/my-runtime-features.js'
  ),
  'my-app' // app name, defaults to 'admin'
);

Actinium.Plugin.addStylesheet(path.resolve(
  PLUGIN.ID,
  __dirname, 'plugin-assets/my-runtime-features-plugin.css'
  ),
  'my-app' // app name, defauts to 'admin'
);
```

{% endcode %}
{% endtab %}
{% endtabs %}

Now, when this plugin is installed and activated, these assets will be stored and served on the API. The API path URI to these assets will be added to the plugin metadata. <br>

{% hint style="info" %}
For Reactium Admin, active Actinium plugins that have registered assets of type 'admin' will automatically be served to your Admin at runtime. Additional work may be required in your target app, otherwise. See Serving Runtime Assets below.
{% endhint %}

### Serving Runtime Assets

Now that you have configured your Actinium plugin to serve your runtime plugin assets, you will want your Reactium application to serve those assets. To do so, in some build-time plugin directory in your application (anywhere in your application src or any reactium\_module), create a `reactium-boot.js` file, and load active plugins from the API, like so:

{% code title="reactium-boot.js" %}

```javascript
// node/express code (es-modules allowed)
import _ from 'underscore';
const { Hook, Enums } = ReactiumBoot; // A global on the server 

// Get all the API plugins as a list from the server and assign to
// nodejs global.plugins
Hook.register('Server.AppGlobals', async (req, AppGlobals) => {
    try {
        const { plugins } = await Reactium.Cloud.run('plugins');

        // makes plugins configuration available on global for node.js and
        // window for your front-end code
        AppGlobals.register('plugins', {
            value: plugins,
            order: Enums.priority.highest,
        });
    } catch (error) {
        console.error('Unable to load plugins list', error);
    }
});

// for each active plugin with script targeting this app, register
// to be served to the browser
Hook.registerSync(
    'Server.AppScripts',
    (req, AppScripts) => {
        _.sortBy(op.get(global, 'plugins', []), 'order').forEach(plugin => {
            const script = op.get(plugin, 'meta.assets.my-app.script');
            AppScripts.unregister(plugin.ID);
            if (script && plugin.active) {
                const url = !/^http/.test(script) ? '/api' + script : script;
                AppScripts.register(plugin.ID, {
                    path: url,
                    order: Enums.priority.high,
                });
            }
        });
    },
    Enums.priority.highest,
);

// for each active plugin with stylesheet targeting this app, register
// to be served to the browser
Hook.registerSync(
    'Server.AppStyleSheets',
    (req, AppStyleSheets) => {
        _.sortBy(op.get(global, 'plugins', []), 'order').forEach(plugin => {
            const style = op.get(plugin, 'meta.assets.my-app.style');
            AppStyleSheets.unregister(plugin.ID);
            if (style && plugin.active) {
                const url = !/^http/.test(style) ? '/api' + style : style;
                AppStyleSheets.register(plugin.ID, {
                    path: url,
                    order: Enums.priority.high,
                });
            }
        });
    },
    Enums.priority.highest,
);

```

{% endcode %}

To test your static assets delivered from the browser through the API, toggle off your local development:

```bash
# from your Reactium application root
npx reactium plugin local
```

Select your runtime plugin to toggle off local development, and restart your node server.

{% hint style="info" %}
Toggling local development on/off changes the `development: true` to `false` in your runtime plugins' `reactium-hooks.json` file. This can also be performed manually, or with the CLI.
{% endhint %}

After restarting the server, you should now see your runtime plugin .js and .css served on the page, and it should function, even if you comment out the index.js file in your plugin locally.

### Styles and Assets

Runtime plugins present some unique challenges when it comes to assets you will need for your styles. By default (if you haven't extended your webpack configuration), style loaders and asset loaders are not included in your runtime plugin UMD (Universal Module Definition) build. Reactium's opinion, out-of-the-box, is to utilize SCSS (Sassy CSS) to pre-process styles for your application, and create CSS assets for your app. Even if you were to use webpack to load styles, for production they would often have to be extracted again anyway to avoid FOUC (Flash of unstyled content). This also slows down your Javascript build dramatically over time, and we prefer to process CSS separately.

For build-time plugins, this is not much of a problem, as your styles are usually incorporated into the larger stylesheet at build-time with an import statement.

For runtime plugins, this can mean coming up with some way to use styling for local development, and you will need to understand how that differs from using the runtime plugin css in the wild.

#### Assets

Reactium uses gulp tasks to copy and optimize assets it finds under any `assets` directory, and they often are served at build-time in a flattened `/assets/` URI off the document root. This means that for build-time plugin, you can have CSS background images, and predict where they will be served both for local development and in production (e.g. /assets/images/my-background.jpg could be in your CSS as `background: url('/assets/images/my-background.jpg')`

For runtime plugins, running in production, these assets won't exist (or would exist on a completely different URL, so hard-coding this URL into CSS isn't gonna work), so it would be nice to use them in the stylesheet in a way that will work for both local development and production.

Reactium offers a supplementary DDD asset `style-assets.json`, which can allow the runtime-plugin developer to designate certain assets to be embedded in their stylesheet.

{% code title="style-assets.json" %}

```json
{
  "background1": "images/background1.jpg"
}
```

{% endcode %}

{% hint style="info" %}
Note: **style-assets.json** can be placed in any directory under `src/app`, and will gulp will produce a **\_reactium-style-variables.scss** partial in that same directory. File paths found in the plugin-assets.json must be relative to this json file.
{% endhint %}

Now that I've created this file, given the existence of the relative files themselves, when I start the local development environment (or run the production build), these assets will be encoded into a SCSS partial in the same directory that can now be used in my runtime plugin's stylesheet. This partial will define an `$assets` variable which will be a SCSS map using the property names you specified in your plugin-assets.json, and a data url for the value.

```css
.bg1 {
     // add the data-url for background1.jpg to my
     // compiled css
     background: url(map-get($assets, 'background1'));
}
```

In this way, it is possible to bundle your runtime plugin CSS assets for production.

#### Where are my styles coming from?

In local development, it can be important to understand how the CSS is being loading into the browser. When your local development is toggled **on,** (reactium-hooks.json development is set to **true**), starting the local build will load the locally built css for the runtime plugin into the browser automatically. Changes will be streamed to the browser in real-time using browser sync.

When your local development is toggled **off,** (reactium-hooks.json development is set to false), styles must be loaded from the production CSS using some other mechanism in your app.

{% hint style="info" %}
For the @atomic-reactor/admin plugin, any admin plugins registered in Actinium with CSS assets are already setup to be loaded via the API. You can setup a similar mechanism in your own application, see [Serving Runtime Assets](/reactium/reactium-guides/plugin-development-guide#serving-runtime-assets).
{% endhint %}

### Separate Development / Production Codebase

It is important to know that you should not maintain your runtime plugin src in the same codebase as your deployed application, because its presence in the `src/app/component/plugin-src` in your deployable application would essentially negate the whole point of runtime plugins (i.e. code that is introduced to your app only at runtime.) Instead, you'll want to develop your runtime plugin in a separate copy of your base application, so that the compiled runtime assets can be served elsewhere (such as from a CDN or your API plugin). This is because when developing your runtime plugin, during this activity it is essentially a specially structured build-time plugin, but during normal deployed use, these assets are precompiled and loaded in the browser instead.

* **development codebase** - consists of your base application plus one or more runtime plugin source directories under `src/app/components/plugin-src` These constitute the local development environment (uses same facilities as build-time plugins). A special **umd.js** DDD artifact provides the build entry point for creating the compiled runtime js asset.
* **application codebase** - code here loads only the static assets compiled in development codebase, but the source of the runtime plugin cannot be found.

{% hint style="info" %}
Note that both the reactium-hooks.js file and the umd.js file import from index.js in the boilerplate code. This is so you can make your changes in one place for both local dev and the production asset build, **index.js**.
{% endhint %}

Because in the target application codebase, you will only have browser-loaded js and CSS, some artifacts you would ordinary expect to work for a runtime plugin are not available in the runtime context.

{% hint style="danger" %}
A common mistake in creating runtime plugins is forgetting that you can't import components and code from the surrounding application using direct relative or webpack contextual imports (e.g. `import Something from 'component/Something';` will work great in local development, but will break in the application codebase.)\
\
Only framework provided externals can be imported into your **index.js** entry point. [See Create a Run-time plugin for list of externals that can be imported.](/reactium/reactium-guides/plugin-development-guide#create-a-build-time-plugin) You **MAY** import from NPM dev dependency libraries that are not listed, but note that these dependencies will be bundled with your runtime library, sometimes considerably adding to the duplicate weight of the plugin. Consider "hosting" these components using the parent application (e.g. `Reactium.Component.register()`to make these available to all the runtime plugins vis `useHookComponent()`)

Treat your plugin src directory as something that should be encapsulated or interacting only with the SDK, not as part of the larger application codebase, or you risk it not building correctly for runtime usage.\
\
Build-time DDD artifacts like route.js, reactium-hooks.js, reactium-boot.js, state.js, actions.js, reducers.js, etc. will work in the local development environment, but will not be included in your UMD, and will not apply in the application codebase.\
\
Hooks registrations, SDK extensions, component registrations, should be added to the **index.js** entry point, and **reactium-hooks.js** should not be modified in your local development codebase, as it will create confusing differences between dev and production.
{% endhint %}

### Publish A Run-time Plugin

Once your Reactium Run-time Plugin has been ejected into your Actinium Build-time Plugin you can publish the Actinium Build-time Plugin to the Reactium Plugin Registry:

{% code title="From Actinium build-time plugin directory:" %}

```
npm reactium publish
```

{% endcode %}

### Install A Run-time Plugin

Once the Actinium Build-time Plugin serving the Reactium Run-time Plugin has been published, you can install it to any Actinium project which will make it available in your Reactium project:

{% code title="From Actinium root:" %}

```
npx reactium install @myscope/MyPlugin
```

{% endcode %}


# Animating React Routes

Want to animate changes from one route to another? Reactium.Routing transition states give you control over the process.

Reactium uses the React Router under the hood by default, but we've made a few opinionated decisions to give you some powerful capabilities in the client application.

In [Domain Model](/reactium/domain#route-js), we discuss the two methods for adding a routed component to your Reactium app. One is creating a **route.js** file which exports an object with properties supported by the React Router `<Route>` component. Likewise, your plugins can register routes dynamically of the same type using the Reactium SDK`Reactium.Routing.register()`.

These route objects have been extended in Reactium to give you control over a set of transitionary states between routes.

By default, registered routes are set to `transitions: false` This is intentional, because turning on transitions means you will need to write code to progress the routing state forward. This interrupts the quick / automatic loading of your routed component until such a time that your application is ready. e.g. you wish to animate the old component off the screen, and animate the new component onto the screen.

To turn on transitionary states for your routed component, set **transitions** to **true** when you define your route.

{% tabs %}
{% tab title="route.js" %}

```javascript
import Article from './Article';
import Product from './Product';

// This is the same as the default
const transitionStates = [
    {
        state: 'EXITING',
        active: 'previous',
    },
    {
        state: 'LOADING',
        active: 'current',
    },
    {
        state: 'ENTERING',
        active: 'current',
    },
    {
        state: 'READY',
        active: 'current',
    },
];

// route.js can export an array of routes as well
export default [
 {
   path: '/article/:id',
   component: Article,
   transitions: true,
   transitionStates,
   type: 'articles',
 },
 {
   path: '/product/:id',
   component: Product,
   transitions: true,
   transitionStates, 
   type: 'products',
 },
];
```

{% endtab %}

{% tab title="Article.js" %}
{% code title="Article.js (version 1)" %}

```jsx
import React, { useEffect } from 'react';
import Reactium from 'reactium-core/sdk';
import { Link } from 'react-router-dom';

const Article = (props) => {
    const {
        active,
        currentRoute,
        previousRoute,
        transitionState,
        transitionStates,
        changes,
    } = props;

    useEffect(() => {
        // Change Transition State on this component if not READY
        // every 1 second
        const to = setTimeout(() => {
            if (transitionState !== 'READY') {
                Reactium.Routing.nextState();
            }
        }, 1000);
        return () => clearTimeout(to);
    }, [transitionState]);

    console.log('Article', { transitionState });
    
    if (transitionState === 'LOADING')
        return <div>Loading...</div>;

    return (
        <div>
          <div>(Article) Route Status: {transitionState}</div>
          <Link to={'/product/1'}>Product 1</Link>         
        </div>
    );
};

export default Article;
```

{% endcode %}
{% endtab %}

{% tab title="Product.js" %}
{% code title="Product.js (version 1)" %}

```jsx
import React, { useEffect } from 'react';
import Reactium from 'reactium-core/sdk';
import { Link } from 'react-router-dom';

const Product = (props) => {
    const {
        active,
        currentRoute,
        previousRoute,
        transitionState,
        transitionStates,
        changes,
    } = props;
    
    useEffect(() => {
        // Change Transition State on this component if not READY
        // every 1 second
        const to = setTimeout(() => {
            if (transitionState !== 'READY') {
                Reactium.Routing.nextState();
            }
        }, 1000);
        return () => clearTimeout(to);
    }, [transitionState]);

    console.log('Product', {transitionState});

    if (transitionState === 'LOADING')
        return <div>Loading...</div>;

    return (
        <div>
          <div>(Product) Route Status: {transitionState}</div>
          <Link to={'/article/1'}>Article 1</Link>
        </div>
    );
};

export default Product;
```

{% endcode %}
{% endtab %}
{% endtabs %}

The default transition states are:

* **EXITING** - exiting the previous routed component
* **LOADING** - loading any data for the current routed component
* **ENTERING** - the current component is entering
* **READY** - the current component is fully loaded

The routed component will be passed a number of properties based on the current routing state:

| Property             | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **active**           | **"previous"** or **"current"** indicating whether the currently rendered component is the previous exiting component, or if the current component is for the current route.                                                                                                                                                                                                                                                                                                                                                                  |
| **currentRoute**     | Object containing the routing configuration for the **current** matched route, including the **location** - router history.location object, **match** - the matched route object, **params** - route params, and **search** - URL search                                                                                                                                                                                                                                                                                                      |
| **previousRoute**    | If applicable, the object containing the routing configuration for the **previous** route, including the **location** - router history.location object, **match** - the matched route object, **params** - route params, and **search** - URL search                                                                                                                                                                                                                                                                                          |
| **transitionState**  | The state of the routing transition, by default one of **EXITING**, **LOADING**, **ENTERING**, or **READY**, but customizable per route.                                                                                                                                                                                                                                                                                                                                                                                                      |
| **transitionStates** | An array of the remaining states left to walk through, each with **state** and **active** properties.                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| **changes**          | <p>Object describing what caused the last routing state change (Boolean flags):</p><p><strong>routeChanged</strong> - true when active route object changes</p><p><strong>pathChanged</strong> - true when URL path has just changed</p><p><strong>searchChanged</strong> - true when search params have just changed</p><p><strong>notFound</strong> - true when no matching route was found for current route</p><p><strong>transitionStateChanged</strong> - true when Reactium.Routing.nextState() was called from last routing state</p> |

Reactium.Routing will wait to progress to each transition state (including rendering your routed component), until your application calls`Reactium.Routing.nextState()`. You can also subscribe to the routing state by registering a route listener, which will get calls whenever the routing state changes.

{% code title="reactium-hooks.js" %}

```javascript
import op from 'object-path';

const routingStateHandler = async updates => {
    if (['LOADING', 'READY'].includes(op.get(updates, 'transitionState'))) {
        // unless LOADING or READY, waiting 1 second and then go to next state

        await new Promise(resolve => setTimeout(resolve, 1000));
        Reactium.Routing.nextState();
    }
};

Reactium.Routing.routeListeners.register('my-routing-observer', {
    handler: routingStateHandler,
    order: Reactium.Enums.priority.low,
});
```

{% endcode %}

Ok, now when clicking the links in one of our components, you'll see them EXITING, and then stop at LOADING. Let's add a hypothetical loading function to each component, and then progress the transition after loading is complete.

{% tabs %}
{% tab title="Article.js" %}
{% code title="Article.js (version 2)" %}

```jsx
import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import Reactium, { useAsyncEffect } from 'reactium-core/sdk';
import op from 'object-path';

const Article = ({
    active,
    currentRoute,
    previousRoute,
    transitionState,
    transitionStates,
    changes,
}) => {
    const [ article, setArticle ] = useState();
    
    useAsyncEffect(async mounted => {
      // this component is current and we need to load the content
      if (active === 'current' && transitionState === 'LOADING') {
        // load the article content
        const article = await Reactium.Cloud.run('content-retrieve', {
          type: { machineName: 'article' },
          objectId: currentRoute.params.id,
        });
        
        // set the component state and then progress the routing transition
        if (mounted()) {
          setArticle(article);
          Reactium.Routing.nextState();
        }
      }
    }, [active, transitionState]);

    if (transitionState === 'LOADING')
        return <div>Loading...</div>;

    return (
        <div className={transitionState.toLowerCase()}>
          <div>(A) Route Status: {transitionState}</div>
          <div>Article: {op.get(article, 'title', 'Unknown')}</div>
          <Link to={'/product/1'}>Product 1</Link>         
        </div>
    );
};

export default Article;
```

{% endcode %}
{% endtab %}

{% tab title="Product.js" %}
{% code title="Product.js (version 2)" %}

```jsx
import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import Reactium, { useAsyncEffect } from 'reactium-core/sdk';
import op from 'object-path';

const Product = ({
    active,
    currentRoute,
    previousRoute,
    transitionState,
    transitionStates,
    changes,
}) => {
    const [ product, setProduct ] = useState();
    
    useAsyncEffect(async mounted => {
      // this component is current and we need to load the content
      if (active === 'current' && transitionState === 'LOADING') {
        // load the product content
        const product = await Reactium.Cloud.run('content-retrieve', {
          type: { machineName: 'product' },
          objectId: currentRoute.params.id,
        });
        
        // set the component state and then progress the routing transition
        if (mounted()) {
          setProduct(product);
          Reactium.Routing.nextState();
        }
      }
    }, [active, transitionState]);

    if (transitionState === 'LOADING')
        return <div>Loading...</div>;

    return (
        <div className={transitionState.toLowerCase()}>
          <div>(Product) Route Status: {status}</div>
          <div>Product: {op.get(product, 'sku', 'Unknown')}</div>
          <Link to={'/article/1'}>Article 1</Link>
        </div>
    );
};

export default Product;
```

{% endcode %}
{% endtab %}
{% endtabs %}

Now our component is responding to the LOADING transition state for the route, causing a data load to happen, and progressing the routing state forward. You could even use a tool such as Tween Max to animate your page content onto the screen, and then progress the routing forward after tweening, or you could create css transitions from the transition state class on the element.


# Reactium in Production

Reactium is designed to be easy to deploy to production.

Reactium is meant to be easy to build React apps, just like React Create App, appropriate to deploy to production in a wide set of circumstances, without the need to "eject" the app. That being said, the base case is well suited to deploying as a full Reactium project, using Heroku (basically effortless), using containers (see the Reactium [**`Dockerfile`**](https://raw.githubusercontent.com/Atomic-Reactor/Reactium/master/Dockerfile)), or a traditional CI/CD pipeline to a Node.js environment.

### Production Build

To build the production assets, with the front-end images, styles, and Javascript bundles minified and gzip compressed, use the npm build script.

```bash
npx reactium install # installs build dependencies
npm run build # builds all front-end assets
npm prune --production # after build is complete, remove all development dependencies
```

After this, the minimum assets needed in the running Node.js 18+ environment will be:

1. **package.json** file
2. **node\_modules** directory
3. **reactium\_modules** directory
4. **src** directory

### Running in Production

After deploying the above production build assets into your final environment, your environment should start the project using the npm start script (as normal convention for Node.js projects).

```bash
npm start
```

### Environment Variables

The most common production use-case need is to be able to configure the running port for the server.

Set the PORT environment variable, if you need the server to run on something other than the default. Set this appropriately for your operating system, shell, etc. On Linux, this can also be provided on start.&#x20;

```bash
PORT=8080 npm start
```

{% hint style="info" %}
The default running port is **3030**
{% endhint %}

#### Special Port Environments

In some deployment environments, you will not have direct control over the environment variable that provides the running port. Reactium also supports `APP_PORT` by default, as well as allowing administrators to specify by environment variable where Reactium should expect to find the running port.

```bash
# Specify where the port will be found in your environment
PORT_VAR=<YOUR_ENVIRONMENT_PORT_VAR> npm start 
```

See the [Reactium Core - Environment Variables](/reactium/reactium-guides/reactium-core#environment-variables) for additional environment variables.

### Deploying only Front-End to CDN

If you have deployed your front-end javascript bundles from your `public/assets/js` directory into a CDN (such as cloud-front), you must let Reactium know where to find these files, so the entry minimal loading `main.js` bundle is able to find and load other bundles as needed to run the web application.

#### Running Reactium Server

If you deployed your public Javascript to a CDN, and still want to run the Reactium Node.js server, add your CDN path to the Javascript files, using the **WEBPACK\_RESOURCE\_BASE** environment variable.

```bash
WEBPACK_RESOURCE_BASE=https://cdn.example.com/path/to/js/ npm start
```

#### Running a different server

You can also let the Reactium **`main.js`** bundle know where to find other bundles in your HTML template directly, by adding the following to your HTML template:

```html
<script>
    window.resourceBaseUrl = "https://cdn.example.com/path/to/js/";
</script>
<script src="https://cdn.example.com/path/to/js/main.js" />
```

{% hint style="warning" %}
This will work only if the **`src/app/main.js`** contains the default **`__webpack_public_path__`** line. This file can be modified, but should contain the following for this to work:

<pre class="language-javascript"><code class="lang-javascript"><strong>__webpack_public_path__ = window.resourceBaseUrl || '/assets/js/';
</strong></code></pre>

{% endhint %}

### Running with Actinium API Server

Dev/Ops should be aware that by default, when running Reactium with an Actinium server to provide the application's API, the Reactium server will automatically proxy any requests (server to server) with prefix **`/api`** to the Actinium instance. By default, it expects this server to be running on the same host on port **9000.**

{% hint style="info" %}
**/api** proxies to **<http://127.0.0.1:9000/api>** to be precise.
{% endhint %}

If you wish to proxy API requests to a different Actinium host and port (this is recommended), you will need to provide this as an environment variable to specify this base URI.

```bash
REST_API_URL=https://api.example.com/api npm start
```

{% hint style="warning" %}
You will need to allow server to server connection on the appropriate port to facilitate this proxy. Allow ingress to your API server from your Reactium server on whatever port you chose to run your API server on. This proxy will simplify [Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) for your web app.
{% endhint %}

#### Direct API URL (Not Proxied)

If you do not wish to (or can not) proxy `/api` requests from server to server, you can configure the client to connect directly to the Actinium server.

```bash
PROXY_ACTINIUM_API=off REST_API_URL=https://api.example.com/api npm start
```

{% hint style="warning" %}
You will need to configure Actinium to handle [Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) for your web app. By default, Actinium instructs the client to be permissive of other origins.
{% endhint %}

### Deploying to Heroku

As was mentioned in the introduction, deploying Reactium (and most Node.js applications) to [Heroku](https://www.heroku.com/), is basically effortless. If your project codebase is hosted on Github (or Heroku's git), simply create a new application in the Heroku dashboards, connect your repository to Heroku on the **Deploy** tab, select which branch you wish to deploy from, and your are basically done. Pushing to this branch will automatically deploy the app.

<figure><img src="/files/Bm8tiXYYt8JcQsILwcxY" alt=""><figcaption><p>Configuring Heroku to Deploy Reactium</p></figcaption></figure>

{% hint style="info" %}
Make sure the **heroku-prebuild** npm script exists in your **package.json**: (it will be by default)

```json
"scripts": {
    "heroku-prebuild": "npx reactium install",
    "local": "gulp local",
    "start": "node src/index.mjs",
    "build": "cross-env NODE_ENV=production gulp"
  }
```

{% endhint %}

### Running TLS over HTTP/2

If you plan to serve Reactium directly from your environment, place your [OpenSSL](https://ubuntu.com/server/docs/security-certificates) certificate and key in a secure location on your server, and only allow your server's process to read these files. (lock down the permissions on this directory) Then instruct Reactium to start the server in TLS mode:

```bash
export REACTIUM_TLS_MODE=on
export REACTIUM_TLS_KEY=/path/to/server.key
export REACTIUM_TLS_CERT=/path/to/server.crt
export TLS_PORT=3443 # default TLS port
npm start
```

{% hint style="success" %}
There can be some performance improvements to your application, in terms of delivering assets to the client running in direct **TLS** mode over **HTTP/2.**
{% endhint %}

{% hint style="warning" %}
**HTTP/2** asset delivery benefits may be prevented / reversed if you have a HTTPS reverse-proxy or Application Load-Balancer (ALB) in front of your Reactium server. If this is your desired configuration, run Reactium over HTTP and terminate your TLS at the proxy/ALB instead.
{% endhint %}

### Binding 80 and 443

Reactium will allow you to bind port 80 and 443, if you start Reactium as the **root (or Windows Administrator)** user.

You will need to provide deescalated user and group for the server to change the process to immediately after binding the listening ports.

<pre class="language-bash" data-title="Running as root user"><code class="lang-bash">export REACTIUM_TLS_MODE=on
export REACTIUM_TLS_KEY=/path/to/server.key
export REACTIUM_TLS_CERT=/path/to/server.crt
export PORT=80 # port 80 requires root
export TLS_PORT=443 # port 443 requires root
<strong>export REACTIUM_RUN_AS=webapp # or your desired user
</strong><strong>export REACTIUM_RUN_AS_GROUP=webapp # or your desired group
</strong><strong>npm start
</strong></code></pre>

{% hint style="success" %}
This will start the server in plain text HTTP over port 80 and encrypted HTTP/2 over TLS on port 443, using the root user, and then will **immediately** steps the process down from root to the selected user/group, making it safer to run in production.
{% endhint %}

{% hint style="danger" %}
**root** or **Administrator** is required to bind ports 0 to 1000 on all operating systems.

This is supported on Windows, Linux, and Mac OS, however permission deescalation is only supported currently on **Linux** or **Mac OS (BSD)**.

You will probably want to forgo running on port 80 or 443 in Windows, as the running server will be able to do anything to your **entire system**. Use a reverse proxy to Windows to achieve PORT 80 / 443 instead.
{% endhint %}


# Reactium Domain Model

Instead of creating large directories by file type, organize your project into domains, and put type specific files in that domain directory.

## Basic Artifacts

Reactium comes with some powerful capabilities with these basic artifacts. The power to route, style, and integrate with other parts of your application. See [Basic Domain Model](/reactium/domain/basic-domain-model) for more details.

Much of the boilerplate of the some of these important artifacts can be create with arcli:

```bash
arcli component
```

| File                                                                                                           | Description                                                                                                |
| -------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| [**route.js**](https://docs.reactium.io/reactium/pages/HYFEMg0Q0BDsx6NRDRh2#route.js)                          | Route configuration file, creating one or more React Router routes.                                        |
| [**index.js**](https://docs.reactium.io/reactium/pages/HYFEMg0Q0BDsx6NRDRh2#index.js)                          | Main component file                                                                                        |
| [**\_reactium-style.scss**](https://docs.reactium.io/reactium/pages/HYFEMg0Q0BDsx6NRDRh2#_reactium-style.scss) | Sass styles                                                                                                |
| [**reactium-hooks.js**](https://docs.reactium.io/reactium/pages/HYFEMg0Q0BDsx6NRDRh2#reactium-hooks.js)        | Reactium isomorphic plugin bind point that run at the file scope on app bootstrap.                         |
| [**domain.js**](https://docs.reactium.io/reactium/pages/HYFEMg0Q0BDsx6NRDRh2#domain.js)                        | Domain configuration file. Used to help group functions to your domain.                                    |
| [**services.js**](https://docs.reactium.io/reactium/pages/HYFEMg0Q0BDsx6NRDRh2#services.js)                    | Utility functions and AJAX requests                                                                        |
| [**reactium-boot.js**](https://docs.reactium.io/reactium/pages/HYFEMg0Q0BDsx6NRDRh2#reactium-boot.js)          | Reactium node/express (back-end only) plugin bind point that run at server startup                         |
| [**test.js**](https://docs.reactium.io/reactium/pages/HYFEMg0Q0BDsx6NRDRh2#test.js)                            | [**Jest**](https://www.npmjs.com/package/jest)**/**[**Enzyme**](https://www.npmjs.com/package/enzyme) test |

## Redux Artifacts

The **@atomic-reactor/reactium-redux** plugin automatically adds the following discoverable Redux-specific DDD artifacts to your application manifest. See [Redux Domain Model](broken://pages/PT91sk5QgfqyEy97VccA) for more details.

| Redux Artifacts                                                                                   | Description          |
| ------------------------------------------------------------------------------------------------- | -------------------- |
| [**actions.js**](https://docs.reactium.io/reactium/pages/PT91sk5QgfqyEy97VccA#actions.js)         | Redux actions        |
| [**actionTypes.js**](https://docs.reactium.io/reactium/pages/PT91sk5QgfqyEy97VccA#actiontypes.js) | Redux actionTypes    |
| [**reducers.js**](https://docs.reactium.io/reactium/pages/PT91sk5QgfqyEy97VccA#reducers.js)       | Redux reducers       |
| [**state.js**](https://docs.reactium.io/reactium/pages/PT91sk5QgfqyEy97VccA#state.js)             | Redux default state  |
| [**middleware.js**](https://docs.reactium.io/reactium/pages/PT91sk5QgfqyEy97VccA#middleware.js)   | Redux middleware     |
| [**enhancer.js**](https://docs.reactium.io/reactium/pages/PT91sk5QgfqyEy97VccA#enhancer.js)       | Redux store enhancer |

## Runtime Artifacts

Reactium comes with built-in capability to generate run-time modules that can be loaded in your applications. The Reactium opinion makes it easy for your applications to be naturally extended. See [Runtime Domain Model](/reactium/domain/runtime-domain-model) for more details.

| File                                                                                                | Description                                                                                                                                                              |
| --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [**umd.js**](https://docs.reactium.io/reactium/pages/cKgvYUNA5ZyqXTnuNyWp#umd.js)                   | Automatically creates entry point for a new UMD (Universal Module Definition) bundle, useful for service workers and runtime plugins.                                    |
| [**umd-config.json**](https://docs.reactium.io/reactium/pages/cKgvYUNA5ZyqXTnuNyWp#umd-config.json) | When found in a directory containing a **umd.js** UMD (Universal Module Definition) entry point, will be used to generate the manifest configuration for the UMD module. |

## Build Artifacts

If you wish to use the Reactium SDK and hooks system to change the behavior of Gulp tasks or Webpack compilation for your plugin, you can use build-time DDD artifacts to register your behaviors. See [Buildtime Domain Model](/reactium/domain/buildtime-domain-model) for more details.

| Build Config Artifacts                                                                                      | Description                                                      |
| ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| [**reactium-gulp.js**](https://docs.reactium.io/reactium/pages/hRde7H32F95HIdkL0Xds#reactium-gulp.js)       | Used to register/unregister gulp tasks for the build.            |
| [**reactium-webpack.js**](https://docs.reactium.io/reactium/pages/hRde7H32F95HIdkL0Xds#reactium-webpack.js) | Used to register/unregister webpack configuration for the build. |


# Basic Domain Model

Without any plugins, the Reactium framework comes with these fundamental building-block artifacts. Use them to quickly start building DDD functionality.

### TLDR;

```bash
npx reactium component # and follow the prompts
```

## Basic Artifacts

### route.js

Reactium aggregates all **route.js** or **reactium-route\*.js** files into a list of routes used to render similar to [React Router Route](https://reacttraining.com/react-router/web/api/Route) components. Reactium also extends this concept to allow controlled transitionary states between routed components using `Reactium.Routing`

{% hint style="info" %}
A route can have most properties that are supported by [\<Route />](https://reacttraining.com/react-router/web/api/Route) component of React Router (e.g. path, exact, component)\
\
Additional Special Properties: transitions, transitionStates (See [Animating Reactium Routes](/reactium/reactium-guides/animating-react-routes))
{% endhint %}

{% code title="/MyComponent/reactium-route-mycomponent.js.js" %}

```javascript
import { MyComponent } from './MyComponent';

export default {
    id: 'MyComponent-route-string-unique',
    path: ['/test'],
    exact: true,
    component: MyComponent,
    order: 0,

    // optional route transition controls
    transitions: false, // defaults to false
    transitionStates: [
        {
            active: 'previous',
            state: 'EXITING',
        },
        {
            active: 'current',
            state: 'LOADING',
        },
        {
            active: 'current',
            state: 'ENTERING',
        },
        {
            active: 'current',
            state: 'READY',
        },
    ];
};
```

{% endcode %}

{% hint style="warning" %}
If you set transition to **`true`** in your `route.js`, you will need to manage the current routing state in your code programmatically, advancing to the next state using `Reactium.Routing.nextState()`. See [Animating React Routes](/reactium/reactium-guides/animating-react-routes) for more information.
{% endhint %}

{% hint style="info" %}
Unlike `<Route>` from React Router, which is defined declaratively in your static application, the order of these routes is determined by sorting on the **order** property.
{% endhint %}

{% hint style="success" %}
All the properties in this object that you specific that are not pertaining to matching the route will be passed on as properties to your component. This is useful when multiple routes render the same component with a different context (in addition to route params and search query).
{% endhint %}

### \<Component>.jsx

When generated by **`reactium`** cli, the boilerplate for this file will vary based on the type of component you specified when generating.&#x20;

> See: [Creating A Component](broken://pages/-M4yjrVMQdHaPqJ5YjF7) for additional information

{% hint style="warning" %}
**YourComponent.jsx** is conceptually part of your domain, but it is not added to the built-time manifest `src/manifest.js`. Your component must be registered to be used in the application:

* **reactium-route-\<yourcomponent>.js** - import component here to assign it to a route
* **reactium-hooks.js** - import here to register component globally for shared use (using `Reactium.Component.register()`), or to a rendering zone (using `Reactium.Zone.addComponent()` )
  {% endhint %}

{% hint style="info" %}
Use **`npx reactium component`** to create these files.
{% endhint %}

### \_reactium-style.scss

One opinion of Reactium is to **NOT** use css-in-js by loading and processing styles using Webpack. Instead we use gulp and dart SASS to compile one or more CSS stylesheets. This would ordinarily make placing your styles with your component challenging, as you would have a lot of extra work to manage the imports into your main stylesheet.

This is no sweat with Reactium. By placing a **scss** partial with a filename *beginning with* **`_reactium-style`** in your domain folder, Reactium will automatically manage the imports into a common generated partial, **`src/assets/style/_scss/_reactium-modules.scss`**

This generated partial is included in the compilation of the style.css for your application by default with a new Reactium install.

There are some common directories or filename suffixes that will result in your partial being sorted differently in the generated **\_reactium-modules.scss** partial:

| Directory                           |                Suffix               | Priority |
| ----------------------------------- | :---------------------------------: | :------: |
| **mixins**/\_reactium-style.scss    |   \_reactium-style-**mixins**.scss  |   -1000  |
| **variables**/\_reactium-style.scss | \_reactium-style-**variables**.scss |   -900   |
| **base**/\_reactium-style.scss      |    \_reactium-style-**base**.scss   |   -800   |
| **atoms**/\_reactium-style.scss     |   \_reactium-style-**atoms**.scss   |     0    |
| **molecules**/\_reactium-style.scss | \_reactium-style-**molecules**.scss |    800   |
| **organisms**/\_reactium-style.scss | \_reactium-style-**organisms**.scss |    900   |
| **overrides**/\_reactium-style.scss | \_reactium-style-**overrides**.scss |   1000   |

{% hint style="info" %}
The default priority of **\_reactium-style.scss** is the same as organism (800), and is the default generated filename when you create a module using **`arcli component`**

You can also use the optional generated **reactium-gulp.js** file that comes with your style to define a different priority of your style partial by regex pattern.
{% endhint %}

{% hint style="success" %}
We highly recommend the book [*Atomic Design*](https://atomicdesign.bradfrost.com/) by [Brad Frost](http://bradfrost.com/) to understand the significance of these distinctions!
{% endhint %}

### reactium-hooks.js

If you're looking to get some things done before the first render or in the file scope, this is the place. Many of the Reactium SDK functions are available and those that are not, can be accessed after a plugin has been successfully registered.&#x20;

{% tabs %}
{% tab title="reactium-hooks.js" %}
{% code title="MyComponent/reactium-hooks.js" %}

```jsx
import Component from './index';
import Reactium from 'reactium-core/sdk';

Reactium.Plugin.register('MyComponent-plugin').then(() => {
    // register 'MyComponent' to be used in other components
    // using the useHookComponent React hook
    Reactium.Component.register('MyComponent', Component);
});

Reactium.Hook.register('some-custom-hook', async (param1, param2, context) => {
  // do something in this hook
  // often mutate a shared context object (always the last parameter)
});

Reactium.Hook.register('routes-init', async () => {
    // alternative to statically defined route.js
    // some hypothetical custom cloud function 'my-route'
    const { routes = [] } = await Reactium.Cloud.run('my-routes', { where: 'MyComponent'});

    // register all the routes where this component should render dynamically
    for (const route of routes) {
      Reactium.Routing.register({
       ...route,
       component: Component,
      });
    }
});
```

{% endcode %}
{% endtab %}

{% tab title="SomeComponent.js" %}

```javascript
import React from 'react';
import { useHookComponent } from 'reactium-core/sdk';

const SomeComponent = props => {
  // share a component from another place
  const MyComponent = useHookComponent('MyComponent');
  return <MyComponent />
};
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
**reactium-hooks.js** provides a generic file scope for your domain to create a build-time plugin for your application. Registering Hook callbacks, registry objects, registered components, declaring components to render in generic application rendering zones, and more. The example above is one of infinite ways you can extend your application with this artifact.
{% endhint %}

### domain.js

There are times when you will need to describe the domain for certain situations. The `domain.js` file is where that should happen. An important feature of `domain.js` is it will allow you to prevent namespace conflicts between your domains when Reactium builds your build-time manifest.

{% hint style="info" %}
For instance: when creating a component library that will be imported as an NPM module into another Reactium project.&#x20;
{% endhint %}

{% code title="/MyComponent/domain.js" %}

```jsx
module.exports = {
    name: 'MyComponent',
};
```

{% endcode %}

{% hint style="info" %}
**domain.js** is used by build-time manifest tools to determine what domain name will be used to group dynamically loaded domain artifacts.
{% endhint %}

### services.js

Reactium aggregates all **services.js** or **reactium-service\*.js** files into the **services** property of the dependencies module default export.&#x20;

A typical **services.js** file may look like this:

{% tabs %}
{% tab title="Services" %}
{% code title="/MyComponent/services.js" %}

```jsx
import axios from 'axios';
import { restHeaders } from 'dependencies';

const restAPI = 'http://demo3914762.mockable.io';

const fetchHello = () => {
    const hdr = restHeaders();
    return axios.get(restAPI + '/hello', { headers: hdr }).then(({ data }) => data);
};

const fetchGoodBye = () => {
    const hdr = restHeaders();
    return axios.get(restAPI + '/goodbye', { headers: hdr }).then(({ data }) => data);
};

export default {
    fetchHello,
    fetchGoodBye,
};
```

{% endcode %}
{% endtab %}

{% tab title="Usage" %}
{% code title="/MyComponent/actions.js" %}

```jsx
import deps from 'dependencies';

export default {
    mount: params => dispatch => {
        deps().services.MyComponent.fetchHello().then(data => {
            dispatch({ type: deps().actionTypes.TEST_MOUNT, payload: data });
        });
    },
};
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% hint style="danger" %}
Services are an area where it may seem like a good idea to share between domains. This is generally not encouraged as domains should be as self sufficient as possible. If you find the need to share a service, consider making it a domain above or adjacent to the consumer domains. *You may also want to consider* [*extending the Reactium SDK*](broken://pages/-M5OCvZvs5gUZ7T8_XzJ)
{% endhint %}

### reactium-boot.js

You can think of **reactium-boot.js** to be for the Reactium Node/Express server, what **reactium-hook.js** is for the client application. Generally, this file is used for hooks that are meant to be used server-side, such as registering Express middleware, server globals, loading scripts and stylesheets, and manipulating the server template.

See the [Server Hooks in the Reactium API Reference](https://atomic-reactor.github.io/Reactium/#api-Hooks).

{% code title="reactium-boot.js" %}

```javascript
import Reactium from 'reactium-core/sdk';
Reactium.Hook.register('Server.AppScripts', async (req, AppScripts) => {
    AppScripts.register('my-onsite-script', {
        path: '/assets/js/some-additional.js'
        footer: true, // load in footer (optional)
        header: false, // don't load in header (optional)
        order: 1, // scripts will be ordered by this
    });
});
```

{% endcode %}

### test.js

Reactium adds a test for your domain when it the test command is run.&#x20;

A typical **test.js** file may look like this:

{% code title="/MyComponent/test.js" %}

```jsx
import React from 'react';
import MyComponent from './index';
import { shallow } from 'reactium-core/enzyme';

test('<MyComponent />', () => {
    const component = shallow(<MyComponent />);

    expect(component.html().length).toBeGreaterThan(0);
});
```

{% endcode %}

{% hint style="danger" %}
If Redux is being used in the above component **MyComponent** would be imported from **./MyComponent** instead of **./index**
{% endhint %}


# Runtime Domain Model

Reactium comes with built-in capability to generate run-time modules that can be loaded in your applications. The Reactium opinion makes it easy for your applications to be naturally extended.

### umd.js and reactium-umd\*.js

Sometimes you need to create a service worker or other separate javascript bundle (separate from the ordinary webpack runtime), that can be loaded into the browser. This can be accomplished easily by creating a **reactium-umd.js** file in any domain. These files will automatically be collected as separate entries for webpack, and will be compiled into their own UMD (Universal Module Definition) at build-time.

{% hint style="info" %}
This occurs once during the build in the **umdLibraries** libraries gulp task. Before this runs, a manifest is generated by the **umdManifest** gulp task, and the UMD manifest is stored in **.tmp/umd-manifest.json**
{% endhint %}

The default UMD javascript module compilation (performed under **./core/umd.webpack.config.js** configuration), is meant to be flexible enough for the needs of two primary use cases:

* A service-worker or worker module.
* A runtime plugin to extend Reactium

### umd-config.json

Optionally found in the same directory as **umd.js**, when you wish to configure the webpack UMD library generation behavior for the module.

For example, below is the default umd-config.js than can be found in **src/sw/umd-config.json** in stock Reactium:

{% code title="umd-config.json" %}

```jsx
{
    "libraryName": "service-worker",
    "globalObject": "this",
    "babelPresetEnv": false,
    "babelReact": false,
    "babelLoader": false,
    "externals": {},
    "addDefines": true
}

```

{% endcode %}

#### UMD Configuration

| Option             | Default                               | Description                                                                                                                                                                                                                  |
| ------------------ | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **libraryName**    | Basename of current domain directory. | Used as the output filename of the UMD file generated by the webpack UMD library compiled from **umd.js**                                                                                                                    |
| **globalObject**   | window                                | When external dependencies are provided for your UMD module, this is where they can be found within the module. (Webpack will expect that some other code will have provided the module, for instance by loading from a CDN) |
| **externals**      | See below                             | When using **umd.js** to create a Reactium runtime plugin, this configuration is provided to webpack to designate modules that will be found on the window object.                                                           |
| **babelPresetEnv** | true                                  | Boolean whether to include the babel env preset in the UMD webpack compilation. (Recommend false for service workers)                                                                                                        |
| **babelReact**     | true                                  | Boolean whether to include the React preset in the UMD webpack compilation.  (Recommend false for service workers)                                                                                                           |
| **babelLoader**    | true                                  | Boolean whether to include the babel loader in the UMD webpack compiliation.  (Recommend false for service workers)                                                                                                          |

{% hint style="warning" %}
Make sure to set globalObject to **this** when creating a service worker, as window does not exist in the running service worker. The default value of **window** is expected for Reactium runtime plugins.

You will probably also need to prevent loading all babel presets to prevent errors in your service worker from transpilation and webpack runtime issues. Set **babelPresetEnv**, **babelReact**, and **babelLoader** to **false** for workers.

Set **externals** to an empty object, to prevent webpack from attempting to create external module dependencies that are inaccessible to the service worker.
{% endhint %}

#### Default UMD Externals

Reactium core automatically exports a number of modules on window to make them available for your umd (Universal Module Definition) bundle, when you are making a runtime loadable plugin for Reactium:

{% code title="default value of "externals" property" %}

```jsx
{
      "axios": "axios",
      "classnames": "classnames",
      "copy-to-clipboard": "copy-to-clipboard",
      "moment": "dayjs",
      "dayjs": "dayjs",
      "object-path": "object-path",
      "prop-types": "prop-types",
      "react": "react",
      "react-router-dom": "react-router-dom",
      "redux": "redux",
      "redux-super-thunk": "redux-super-thunk",
      "react-dom": "react-dom",
      "/reactium-core/sdk$/": "/reactium-core/sdk$/",
      "semver": "semver",
      "shallow-equals": "shallow-equals",
      "underscore": "underscore",
      "uuid": "uuid",
      "xss": "xss"
}
```

{% endcode %}

{% hint style="info" %}
**Externals explained:**

Ordinarily, when webpack encounters a require/import statement, it will "bundle" the imported module into your javascript.

When webpack encounters an "external", instead it instructs the javascript where it can find the module externally, usually on the **window** object. Reactium core provides the above module on **window**, so you don't have to bundle them into your runtime plugin.

This provides some benefits:\
1\. you will not incur additional size to your module, when loading it in the browser\
2\. you will be using the same version of the dependency as core Reactium\
3\. this exposed the Reactium SDK and named exports to your runtime plugin\
4\. this allows you to write code for your runtime module in much the same way you would if it were bundled with your application. This helps the local development workflow for runtime plugins immensely.
{% endhint %}


# Buildtime Domain Model

## Build Artifacts

If you wish to use the Reactium SDK and hooks system to change the behavior of Gulp tasks or Webpack compilation for your plugin, you can use build-time DDD artifacts to register your behaviors.

### reactium-gulp.js

Reactium's build process is started and primarily controlled by Gulp tasks:

{% code title="Gulp tasks" %}

```bash
npx gulp --tasks

Tasks for ~/Reactium/gulpfile.js
├── apidocs
├── local
├── assets
├── preBuild
├─┬ build
│ └─┬ <series>
│   ├── preBuild
│   ├── ensureReactiumModules
│   ├── clean
│   ├── manifest
│   ├─┬ <parallel>
│   │ ├── markup
│   │ └── json
│   ├─┬ <parallel>
│   │ ├── assets
│   │ └── styles
│   ├── scripts
│   ├── umdLibraries
│   ├── serviceWorker
│   ├── compress
│   └── postBuild
├── compress
├── postBuild
├── postServe
├── clean
├── ensureReactiumModules
├── default
├── json
├─┬ manifest
│ └─┬ <series>
│   └─┬ <parallel>
│     ├─┬ <series>
│     │ ├── domainsManifest
│     │ └── mainManifest
│     ├── externalsManifest
│     └── umdManifest
├── domainsManifest
├── mainManifest
├── externalsManifest
├─┬ umd
│ └─┬ <series>
│   ├── umdManifest
│   └── umdLibraries
├── umdManifest
├── umdLibraries
├── markup
├── scripts
├── serve
├── serve-restart
├── serviceWorker
├─┬ sw
│ └─┬ <series>
│   ├── umd
│   └── serviceWorker
├── static
├── static:copy
├── styles:partials
├── styles:pluginAssets
├── styles:colors
├── styles:compile
├─┬ styles
│ └─┬ <series>
│   ├── styles:colors
│   ├── styles:pluginAssets
│   ├── styles:partials
│   └── styles:compile
├── watch
└── watchFork
```

{% endcode %}

As you can see above, there are many tasks performed with Gulp, and you may wish to create, change, or delete tasks that are run during the build, and this can be done with ease using the **reactium-gulp.js** artifact.

When you start the build (`npm run build` or `npm run local` for product or local development respectively), really you are invoking the `gulp` default task, which in turn will kick off a number of other tasks in series or in parallel.

{% hint style="info" %}
All built-in Gulp task are defined in **.core/gulp.tasks.js**
{% endhint %}

An abbreviated summary of the default gulp task starts a series of tasks as follows:

1. A stub **preBuild** task (does nothing, meant to be optionally implemented by your project)
2. Cleanup tasks to prepare the project directory (ensure **`reactium_modules`** directory exists, remove contents of public, ...)
3. Prepare a set of source manifests based on DDD artifacts found throughout your project.
4. Build static html markup and any generated json files
5. Process assets such as images, and compile CSS (using SASS)
6. Compile your application javascript with Webpack
7. Build any UMD (Universal Module Definition) files with Webpack
8. Create a Google Workbox service worker
9. Compress all compiled assets (for quicker delivery)
10. Generate [API docs](https://apidocjs.com/)
11. A stub **postBuild** task (does nothing, meant to be optionally implemented by your project)

{% code title="excerpt of gulp.tasks.js (default task)" %}

```javascript
    task('preBuild'),
    task('ensureReactiumModules'),
    task('clean'),
    task('manifest'),
    gulp.parallel(task('markup'), task('json')),
    gulp.parallel(task('assets'), task('styles')),
    task('scripts'),
    task('umdLibraries'),
    task('serviceWorker'),
    task('compress'),
    task('apidocs'),
    task('postBuild'),
```

{% endcode %}

{% hint style="info" %}
For those industrious folks, see **reactium\_modules/@atomic-reactor/reactium-core/gulp.tasks.js** for the full details of what gulp tasks are defined in core.

See reactium-gulp section below for how to properly change these in your project.
{% endhint %}

#### ReactiumGulp

Prior to running any Gulp task, all of the tasks are registered to a global singleton **ReactiumGulp**, that is made available to any **reactium-gulp.js** file found in your project under:

* anywhere in the **src** directory (or any subdirectory)
* anywhere in the **reactium\_modules** directory

If a [reactium-gulp.js](https://apidocjs.com/) file is found anywhere in one of these location, it will be loaded during the initialization of Gulp prior to running any gulp task. Inside this file, you may register one or more Reactium Gulp synchronous hooks to change the behavior of the gulp build for the whole project.

| Hook       | Usage                                                                                                   |
| ---------- | ------------------------------------------------------------------------------------------------------- |
| **config** | Synchronous hook that provides the gulp configuration and webpack configuration prior to running tasks. |
| **tasks**  | Synchronous hook that provides the Registry (register, unregister) of each Gulp task prior to use.      |

{% hint style="info" %}
For example, say you do not wish to use the current Dart SASS compilation (defined in the .core/gulp.tasks.js in the **styles:compile** task, but instead which to replace this with node-sass. To do this, first you will want to register a synchronous **tasks** hook callback. This hook will be passed the task registry used to generate the full list of gulp tasks you see above. Use this registry to unregister the existing gulp task, and replace it with your own.
{% endhint %}

{% code title="reactium-gulp.js" %}

```
const gulp = require('gulp');
const sass = require('gulp-sass');
sass.compiler = require('node-sass');
const reactiumImporter = require('@atomic-reactor/node-sass-reactium-importer');
const jsonFunctions = require('node-sass-functions-json').default;
const sourcemaps = require('gulp-sourcemaps');
const gulpif = require('gulp-if');
const cleanCSS = require('gulp-clean-css');
const prefix = require('gulp-autoprefixer');
const rename = require('gulp-rename');
const env = process.env.NODE_ENV || 'development';
const isDev = env === 'development';
const browserSync = require('browser-sync');

ReactiumGulp.Hook.registerSync('tasks', (GulpRegistry, config) => {
    GulpRegistry.unregister('styles:compile');

    const compileStyles = () => {
        return gulp
            .src(config.src.style)
            .pipe(gulpif(isDev, sourcemaps.init()))
            .pipe(
                sass({
                    functions: Object.assign({}, jsonFunctions),
                    importer: reactiumImporter,
                    includePaths: config.src.includes,
                }).on('error', sass.logError),
            )
            .pipe(prefix(config.browsers))
            .pipe(gulpif(!isDev, cleanCSS()))
            .pipe(gulpif(isDev, sourcemaps.write()))
            .pipe(rename({ dirname: '' }))
            .pipe(gulp.dest(config.dest.style))
            .pipe(gulpif(isDev, browserSync.stream()));
    };

    GulpRegistry.register('styles:compile', {
        task: compileStyles,
        order: 100,
    });
});
```

{% endcode %}

{% hint style="info" %}
You might also wish to change the values specified by **.core/gulp.config.js** that are used in your tasks. You can do this with the synchronous **config** hook.
{% endhint %}

{% code title="reactium-gulp.js" %}

```
// change the location where _colors.scss is generated by the
// styles:colors gulp task

ReactiumGulp.Hook.registerSync('config', gulpConfig => {
  gulpConfig.dest.colors = 'src/app/components/Admin/style/_colors.scss';
});
```

{% endcode %}

{% hint style="info" %}
This isn't the last or only way to manipulate the gulp tasks for your project. If you would prefer to get in between the final list of tasks that are used for gulp, you may wish to create a [gulp.tasks.override.js file.](/reactium/reactium-guides/reactium-core#gulp-tasks-override-js) Either method is fine, however **gulp.tasks.override.js** will simply export a function that returns the entire list of gulp tasks (including the **default**), and may invalidate other plugins' efforts from **reactium-gulp.js**. If you wish to play nice, use **reactium-gulp.js**
{% endhint %}

### reactium-webpack.js

When the Gulp **scripts** task is run, Gulp will run the Webpack compilation specified by the overridable configuration in **.core/webpack.config.js**. Likewise, when compiling any UMD (Universal Module Definition) javascript modules during the Gulp **umdLibraries** task, Gulp will run the Webpack compiliation specified by the overridable configuration provided in **.core/umd.webpack.config.js**.

#### ReactiumWebpack

Prior to running any either the main or umd Webpack compilations, the webpack configuration is run through a series of hooks that are registered to a global singleton **ReactiumWebpack**, that is made available to any **reactium-webpack.js** file found in your project under:

* anywhere in the **src** directory (or any subdirectory)
* in any node module directory located in a **reactium-plugin** directory
* anywhere in the **reactium\_modules** directory

If a [reactium-webpack.js](https://apidocjs.com/) file is found anywhere in one of these location, it will be loaded during the initialization of Webpack configuration prior to running any compilation. Inside this file, you may register one or more Reactium Webpack synchronous hooks to change the behavior of the webpack compilation for the whole project.

| Hook              | Usage                                                                                          |
| ----------------- | ---------------------------------------------------------------------------------------------- |
| **before-config** | Provides the **WebpackSDK** as an argument                                                     |
| **externals**     | Provide the **WebpackSDK**.externals registry, **WebpackSDK**.name, and **WebpackSDK**.context |
| **ignores**       | Provide the **WebpackSDK**.ignores registry, **WebpackSDK**.name, and **WebpackSDK**.context   |
| **rules**         | Provide the **WebpackSDK**.rules registry, **WebpackSDK**.name, and **WebpackSDK**.context     |
| **plugins**       | Provide the **WebpackSDK**.plugins registry, **WebpackSDK**.name, and **WebpackSDK**.context   |

{% hint style="info" %}
Note: most of the **WebpackSDK** registries (ignores, externals, rules, plugins) have an **sdk** property that refers back to the WebpackSDK object.
{% endhint %}

Both of the main webpack configuration and the umd configurations are built using a helper object, **WebpackSDK:**

#### WebpackSDK

This class provided the following public properties and methods, to aid in managing your Webpack configuration:

#### WebpackSDK setters

Most of the webpack configuration that is not terribly complex is handled with simple setters.

{% tabs %}
{% tab title="WebpackSDK.mode" %}
Setter for the webpack [**mode**](https://webpack.js.org/configuration/mode/) configuration property
{% endtab %}

{% tab title="Example" %}

```javascript
WebpackSDK.mode = 'development'; // or production
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="WebpackSDK.entry" %}
Setter for the webpack [**entry**](https://webpack.js.org/configuration/entry-context/) configuration property
{% endtab %}

{% tab title="Example" %}

```javascript
WebpackSDK.entry = {
  main: './src/app/main.js'
};
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="WebpackSDK.target" %}
Setter for webpack [**target**](https://webpack.js.org/configuration/target/) configuration property
{% endtab %}

{% tab title="Example" %}

```javascript
WebpackSDK.target = 'web';
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="WebpackSDK.output" %}
Setter for webpack [**output**](https://webpack.js.org/configuration/output/) configuration property
{% endtab %}

{% tab title="Example" %}

```javascript
WebpackSDK.output = {
  publicPath: '/assets/js/',
  path: path.resolve(__dirname, dest),
  filename: '[name].js',
};
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="WebpackSDK.devtool" %}
Setter for webpack [**devtool**](https://webpack.js.org/configuration/devtool/) configuration property
{% endtab %}

{% tab title="Example" %}

```javascript
WebpackSDK.devtool = process.env.NODE_ENV === 'development' ? 'source-map' : '';
```

{% endtab %}
{% endtabs %}

#### WebpackSDK Methods

{% tabs %}
{% tab title="WebpackSDK.setCodeSplittingOptimize(env)" %}
Automatically configures the webpack [**optimization**](https://webpack.js.org/configuration/optimization/) configuration property, attempting to code-split Reactium javascript bundles into chunks that can be lazy loaded automatically by webpack, optimized to Reactium's logical components.

| Argument     | Type   | Description                   |
| ------------ | ------ | ----------------------------- |
| env          | String | 'development' or 'production' |
| {% endtab %} |        |                               |

{% tab title="Example" %}

```javascript
WebpackSDK.setCodeSplittingOptimize(process.env.NODE_ENV);
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="WebpackSDK.setWebpackDefaultOptimize(env)" %}
Automatically configures the webpack [**optimization**](https://webpack.js.org/configuration/optimization/) configuration property, attempting to code-split Reactium javascript bundles into chunks that can be lazy loaded automatically by webpack, in a way that is fairly default Webpack code-splitting behavior.

| Argument     | Type   | Description                   |
| ------------ | ------ | ----------------------------- |
| env          | String | 'development' or 'production' |
| {% endtab %} |        |                               |

{% tab title="Example" %}

```javascript
WebpackSDK.setWebpackDefaultOptimize(process.env.NODE_ENV);
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="WebpackSDK.setNoCodeSplitting(env)" %}
Automatically configures the webpack [**optimization**](https://webpack.js.org/configuration/optimization/) configuration property, setting up Reactium to bundle everything together in one monolithic bundle.

{% hint style="info" %}
To get this behavior for the top-level application entries, you can also start the build with the Environment Variable **DISABLE\_CODE\_SPLITTING** set to **'true'.**
{% endhint %}

| Argument     | Type   | Description                   |
| ------------ | ------ | ----------------------------- |
| env          | String | 'development' or 'production' |
| {% endtab %} |        |                               |

{% tab title="Example" %}

```javascript
WebpackSDK.setNoCodeSplitting(process.env.NODE_ENV)
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="WebpackSDK.addPlugin(pluginId, plugin)" %}
Used to register Webpack [**plugins**](https://v4.webpack.js.org/configuration/plugins/), and give them an id, so they can be overridden or removed.

| Argument | Type           | Description                                                              |
| -------- | -------------- | ------------------------------------------------------------------------ |
| pluginId | String         | Unique id of the webpack plugin instance, so that it can be manipulated. |
| plugin   | Webpack Plugin | Instance of a Webpack plugin                                             |

{% hint style="info" %}
Alternately, you can call register() on **WebpackSDK.plugins** (a standard Reactium registry). See **Using Registry** tab.
{% endhint %}
{% endtab %}

{% tab title="Example" %}

```
WebpackSDK.addPlugin('defines', new webpack.DefinePlugin({ foo: 'bar'}));
```

{% endtab %}

{% tab title="Using Registry" %}

```
WebpackSDK.plugins.register('defines', { 
  plugin: new webpack.DefinePlugin({ foo: 'bar'}),
});

// or unregister
WebpackSDK.plugins.unregister('defines');
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="WebpackSDK.addRule(ruleId, rule)" %}
Used to register Webpack [**module rules**](https://v4.webpack.js.org/configuration/module/#modulerules), but give them an id, so they can be easily overridden or removed.

| Argument | Type                                                                     | Description                          |
| -------- | ------------------------------------------------------------------------ | ------------------------------------ |
| ruleId   | String                                                                   | Your identifier for the module rule. |
| rule     | [**Webpack Rule**](https://v4.webpack.js.org/configuration/module/#rule) | A webpack rule object                |

{% hint style="info" %}
Alternately, you can call register() on **WebpackSDK.rules** (a standard Reactium registry). See **Using Registry** tab.
{% endhint %}
{% endtab %}

{% tab title="Example" %}

```javascript
WebpackSDK.addRule('babel-loader', {
        test: [/\.jsx|js($|\?)/],
        exclude: [/node_modules/, /umd.js$/],
        resolve: {
            extensions: ['.js', '.jsx', '.json'],
        },
        use: [
            {
                loader: 'babel-loader',
            },
        ],
    });
```

{% endtab %}

{% tab title="Using Registry" %}

```javascript
WebpackSDK.rules.register('babel-loader', {
  rule: {
        test: [/\.jsx|js($|\?)/],
        exclude: [/node_modules/, /umd.js$/],
        resolve: {
            extensions: ['.js', '.jsx', '.json'],
        },
        use: [
            {
                loader: 'babel-loader',
            },
        ],
    },
});

// or to unregister
WebpackSDK.rules.unregister('babel-loader');
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="WebpackSDK.addIgnore(ignoreId, regExp)" %}
A special registry that manages the [**webpack.IgnorePlugin**](https://v4.webpack.js.org/plugins/ignore-plugin/), allowing you to easily specify regular expression that will instruct Webpack what sort of modules to ignore.

| Argument | Type   | Description                            |
| -------- | ------ | -------------------------------------- |
| ignoreId | String | Your identifier for the ignore pattern |
| regExp   | RegExp | Regular express pattern to ignore.     |

{% hint style="info" %}
Alternately, you can call register() on **WebpackSDK.ignores** (a standard Reactium registry). See **Using Registry** tab.
{% endhint %}
{% endtab %}

{% tab title="Example" %}

```javascript
WebpackSDK.addIgnore('sass', /\.sass$/);
```

{% endtab %}

{% tab title="Using Registry" %}

```javascript
WebpackSDK.ignores.register('sass', {
  test: /\.sass$/,
});

// or remove the ignore
WebpackSDK.ignores.unregister('sass');
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="WebpackSDK.addContext(contextId, contextMap)" %}
A special registry that manages the **webpack.ContextReplacementPlugin**, allowing you to easily specify regular expression that will instruct Webpack what sort of modules to ignore.

| Argument   | Type   | Description                                                                             |
| ---------- | ------ | --------------------------------------------------------------------------------------- |
| contextId  | String | Your identifier for the webpack context                                                 |
| contextMap | Object | Object with **from** regex pattern to match and **to** path to map the webpack context. |

{% hint style="info" %}
Alternately, you can call register() on **WebpackSDK.plugins** (a standard Reactium registry), and register a new instance of the **webpack.ContextReplacementPlugin**. See **Using Registry** tab.
{% endhint %}
{% endtab %}
{% endtabs %}


# Reactium SDK

The Reactium SDK is imported from the ES Module, and provides useful means of extending and using the Reactium foundational framework.

## Reactium SDK

When we speak of the "Reactium SDK", we are generally referring to:

* the Reactium Singleton object, imported like so: **`import Reactium from 'reactium-core/sdk';`**
* or, a number of named exports, such as custom React hooks, string translation utilities, etc, e.g. **`import { useHookComponent } from 'reactium-core/sdk';`**
* A list of documented Reactium **"hooks"**. A Reactium hook (not to be confused with [React Hooks](https://reactjs.org/docs/hooks-intro.html)), is a named tag for which you can register callbacks. You can both register hooks in your code to run when important things happen in Reactium, and create your own invocations where others can register callbacks.

{% hint style="info" %}
**`'reactium-core'`** used in an import statement in Reactium is a babel-alias for the path to th&#x65;**`'.core/'`** directory, which can be used anywhere in your code so you don't need to know the relative path.
{% endhint %}

{% content-ref url="/pages/-M5Oz\_0A6tKNNithCSLr" %}
[Broken mention](broken://pages/-M5Oz_0A6tKNNithCSLr)
{% endcontent-ref %}


# Updating Reactium

One of the greatest features of Reactium is the ability to update to the latest version with minimal worrying about your current project being disrupted.&#x20;

```bash
npx reactium update
```

{% hint style="info" %}
Run this command if you wish to have any project-level update scripts run (migrations designed for major and minor version jumps.
{% endhint %}

{% hint style="warning" %}
*Updating is usually relatively non-invasive, but It's always a good idea to commit your current project to version control before updating. Also, review the changes made to the top-level project directory to make sure your modifications haven't been disrupted.*
{% endhint %}

### Patch Releases

Most ordinary **patch** releases (reference [\<major>.\<minor>.\<patch> semver versioning](https://www.baeldung.com/cs/semantic-versioning)) of Reactium do not require any migration scripts to be run. In these cases, the least disruptive Reactium core update is just to install the latest core module.

```bash
# will update just the core module to latest version
npx reactium install @atomic-reactor/reactium-core
```

Other core modules you may wish to update (if they are in your project):

```bash
npx reactium install @atomic-reactor/reactium-api
npx reactium install @atomic-reactor/reactium-capability
npx reactium install @atomic-reactor/reactium-role
npx reactium install @atomic-reactor/reactium-setting
npx reactium install @atomic-reactor/reactium-svg
npx reactium install @atomic-reactor/reactium-user
npx reactium install @atomic-reactor/reactium-service-worker
```


# Before You Install

The Reactium platform can be install all at once, or you can install foundational frameworks Reactium and Actinium individually.

Before installing **Reactium** or **Actinium**, you need to check that your hosting provider fulfills the necessary software requirements and that you have access to server.&#x20;

### Server Requirements

* [**Node**](https://nodejs.org/en/) 18 or greater
* [**NPM**](https://www.npmjs.com/) 9.5.1 or greater

### Local Development Requirements

In addition to the server requirements above, you will need the following local requirements:

* [Text Editor](https://en.wikipedia.org/wiki/List_of_text_editors)&#x20;
* [Terminal](https://support.apple.com/guide/terminal/welcome/mac) or [Command Line](https://www.digitaltrends.com/computing/how-to-use-command-prompt/) access
* [Git](https://git-scm.com/) *(Windows users will need to install* [*Git for Windows*](https://git-scm.com/download/win)*)*

{% hint style="info" %}
*For Mac users the Local Development Requirements are usually already installed.*
{% endhint %}


# Install Reactium

## TL;DR

```bash
cd /your/reactium/project
npx reactium init # Select Reactium when prompted
npm run local
```

Under most circumstances, Reactium is pretty easy to install and takes less than 5 minutes. Most hosting providers require no install at all.&#x20;

## Install Locally

> If you haven't done so already, be sure to read the [Before You Install](https://docs.reactium.io/get-started/before-you-install) article

### Step 1: Set Current Working Directory

Reactium CLI relies on your project directory to give it contex&#x74;**:**

```bash
cd /your/reactium/project
```

### Step 2: Install Reactium CLI (Optional)

Fire up terminal or command-line and install the [**Atomic Reactor CLI**](https://www.npmjs.com/package/@atomic-reactor/cli):

```bash
npm install -g reactium # alternative to using npx all the time
```

### Step 3: Install Reactium

```bash
reactium init
[ARCLI] > Initialize what type of project?:  (Use arrow keys)
❯ Reactium (Web Application) 
  Actinium (Web API)
Preparing to initialize Reactium...

[ARCLI] > Initialize Reactium here?:  (y/N) y
```

```
$ npm install 
```

### Step 4: Run Locally

```
$ npm run local
```

{% hint style="success" %}
**Done!**

After the [Webpack](https://webpack.js.org/) build completes, your default browser will launch with the Welcome component loaded on the / route.
{% endhint %}


# Install Actinium

### Step 1: Reactium CLI

If you don't have it already, globally install the [Reactium CLI](https://www.npmjs.com/package/reactium)

```javascript
npm install -g reactium
```

### Step 2: Install Database

Actinium relies on MongoDB as its database service. You will need to set up a local instance for development purposes.

You can install MongoDB however you wish, but [Homebrew](https://brew.sh/) is an easy way.

#### Install Homebrew

```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
```

#### Install MongoDB&#x20;

{% hint style="info" %}
If you're not sure if you have MongoDB installed already or are running an older version that may not be supported, you can run:&#x20;

```
brew services stop mongodb
brew uninstall mongodb
```

{% endhint %}

```
brew tap mongodb/brew
brew install mongodb-community
```

#### Run MongoDB Service

```
brew services start mongodb-community
```

### Step 3: Create DB Users

If this is your first time running MongoDB locally, you'll need to create the root admin user account.

#### Create DB Admin User

```jsx
mongo
use admin
db.createUser({user:"dbadmin", pwd:"PASSWORD", roles:[{role:"root", db:"admin"}]})
```

{% hint style="warning" %}
**Note:** be sure to replace **PASSWORD** with the actual password you wish to use
{% endhint %}

#### Create DB Actinium User

```jsx
use actinium
db.createUser({user:"actinium", pwd:"PASSWORD", roles:["readWrite"]})
exit
```

{% hint style="warning" %}
**Note:** be sure to replace **PASSWORD** with the actual password you wish to use
{% endhint %}

### Step 4: Install Actinium

```
cd /YOUR/PROJECT
reactium init
[ARCLI] > Initialize what type of project?:  
  Reactium (Web Application) 
❯ Actinium (Web API) 
[ARCLI] > Initialize Actinium here?:  (y/N) y
```

### Step 5: Configure Actinium

Configure Actinium to run using the default db and user:

```javascript
cd /WHERE/YOU/SAVED/ACTINIUM
reactium db -u "mongodb://actinium:PASSWORD@localhost:27017/actinium"
```

### Step 6: Run Locally

```
npm run local
```

{% hint style="success" %}
**Done!**&#x20;

To view the Database Dashboard provided by Parse Server:

* **Navigate to:** [localhost:9000/parse](http://localhost:9000/parse)
* **Username:** admin
* **Password:** admin
  {% endhint %}


# Actinium Core

A Node/Express framework with built-in Parse Cloud API.

{% hint style="info" %}
Actinium == The Node Express API framework for the Reactium platform. Use me whenever I need a Mongo backed API.
{% endhint %}

Actinium is built on a core framework, designed to quickly and easily create your Node/Express API with Parse. The local development and build configuration that comes out of the box is meant to be upgradeable, so long as your application was built off a [semver](https://docs.npmjs.com/cli/v6/using-npm/semver) (Semantic Version) that is minor-version compatible with the current.

Even for larger version steps, we are going to attempt to describe (or automate) much of the migration from one version of Actinium core to another.

Updating core is performed with the **reactium** command:

```bash
reactium update
```

## Hacking Core

Core functionality of the Node.js / Express server running Parse Server can be found in the actinium\_modules directory. These modules are installed from the Reactium registry much in the way node\_modules are installed via npm. Just like you would not modify the contents of modules in node\_modules, you should not modify actinium\_modules.

The core modules are maintained in the Actinium Modules project on Github. Please feel free to fork and make a Pull-Request if you have any good general purpose ideas.

Actinium's processes and cloud functions are heavily hooked and can easily be altered with [**plugins**](/actinium/actinium#plugin-js) and [**middleware**](/actinium/actinium#middleware-js).

{% hint style="warning" %}
Any updates you make to actinium\_modules will be ovewritten any time you run **`reactium install`**, much as **`npm install`** will overwrite node\_modules.
{% endhint %}

## Environment Variables

Actinium primarily relies on environment variables for configuration. To ease the pain of setting EVs on every local launch, you can set them in the **/src/env.json** and/or **/src/env.remote.json**&#x20;

| Variable                                  | Type    | Usage                                                       |
| ----------------------------------------- | ------- | ----------------------------------------------------------- |
| **ACTINIUM\_ENV\_ID**                     | String  | Specifies the env file id to load                           |
| **ACTINIUM\_ENV\_FILE**                   | String  | Specifies the env file path to load                         |
| **APP\_ID**                               | String  | The app identifier                                          |
| **APP\_NAME**                             | String  | The app name                                                |
| **APP\_PORT**                             | Number  | Application port                                            |
| **CONTENT\_NAMESPACE**                    | String  | Namespace for uuid key creation of content slugs            |
| **DATABASE\_URI**                         | String  | Mongo connection string                                     |
| **LIVE\_QUERY\_SERVER**                   | Boolean | Enable/Disable Live Queries                                 |
| **LIVE\_QUERY\_SETTINGS**                 | Object  | Configuration Object for Live Queries                       |
| **LOG**                                   | Boolean | Enable/Disable event log                                    |
| **LOG\_LEVEL**                            | String  | Set the event log level                                     |
| **MASTER\_KEY**                           | String  | String used as the master key for elevated cloud operations |
| **NO\_DOCS**                              | Boolean | Enable/Disable the **/docs** route                          |
| **PARSE\_ALLOW\_CLIENT\_CLASS\_CREATION** | Boolean | Enable/Disable class creation from client SDKs              |
| **PARSE\_DASHBOARD**                      | Boolean | Enable/Disable the Parse Dashboard                          |
| **PARSE\_DASHBOARD\_USERS**               | Array   | Parse Dashboard access list                                 |
| **SERVER\_URI**                           | String  | Public accessible URI to the server                         |
|                                           |         |                                                             |

### ACTINIUM\_ENV\_ID

To select the **/src/env.remote.json** file simply pass **remote** as the value. You can create any number of env files with the same file naming pattern.&#x20;

### ACTINIUM\_ENV\_FILE

There maybe instances where your env file is not stored in the Actinium **src** directory. You can tell Actinium where to load it from by supplying the full path to the file.&#x20;

> **Default:** **/src/env.json**&#x20;

### APP\_ID

Unique ID for the Parse App. Used when connecting via client SDKs.

> **Default:** Actinium

### APP\_NAME

Display name used in the Parse Dashboard.&#x20;

> **Default:** Actinium

### APP\_PORT

The application port where Actinium will run from.

{% hint style="danger" %}
**Note:** Some hosts like [Heroku](https://heroku.com) will automatically set this value.
{% endhint %}

### **CONTENT\_NAMESPACE**

Used as a **uuidv5** namespace for the purpose of generating uuids identifying content types.&#x20;

Given the namespace uuid + a content type slug, will always yield the same exact uuid for that slug and namespace, therefore you can always derive the same uuid given the content type slug.

### **DATABASE\_URI**

The MongoDB connection string. Supports standalone, replicant set, and shared clusters.

{% hint style="info" %}
**See:** MongoDB [Connection String URI Format](https://docs.mongodb.com/manual/reference/connection-string/) for details
{% endhint %}

### **LIVE\_QUERY\_SERVER**

> **Default:** true

### LIVE\_QUERY\_SETTINGS

Object containing key value pairs specifying configuration for Live Queries

```css
"LIVE_QUERY_SETTINGS": {
    "classNames": ["Changelog"]
},
```

### LOG

By setting this value to false your server will no longer emit event logs.&#x20;

> **Default:** true

### LOG\_LEVEL

The level of detail and frequency at which system logs are emitted.&#x20;

| Value              | LEVEL | Parse Log Level    |
| ------------------ | ----- | ------------------ |
| **DEBUG**          | 1000  | verbose or greater |
| **INFO**           | 500   | info or greater    |
| **BOOT (default)** | 0     | error or greater   |
| **WARN**           | -500  | error or greater   |
| **ERROR**          | -1000 | error or greater   |

### MASTER\_KEY

A key that overrides all permissions. Used for operations that require untethered access to the database.&#x20;

{% hint style="danger" %}
**Important:** Keep this secret and use it only on the server.&#x20;
{% endhint %}

### NO\_DOCS

When you deploy Actinium to a production server it's a good idea to disable the /docs route. Unless of course your app is expressly an API and you want to expose the docs for documentation purposes.

> **Default:** false

### **PARSE\_ALLOW\_CLIENT\_CLASS\_CREATION**

Set this to true if you want grant client SDKs to the ability to create new collections. This is generally not a common practice as clients may not take into consideration permissions and capabilities.&#x20;

> **Default:** false

### PARSE\_DASHBOARD

When you deploy Actinium to a production server it's a good idea to disable the Parse Dashboard.&#x20;

> **Default:** true

### PARSE\_DASHBOARD\_USERS

Object Array container **user**, **pass** key value pairs.&#x20;

```css
"PARSE_DASHBOARD_USERS": [
    {
        "user": "admin",
        "pass": "admin"
    }
],
```


# Setting up your User

Using the Parse Dashboard, we need to create your admin user.

By default, when your API service is running locally, it will be accessible on **<http://localhost:9000/api>**. You will also have a Parse dashboard site running at **<http://localhost:9000/parse>**.

The Parse dashboard can be a useful development tool.

### Parse Dashboard Users

In your `API/src/env.json` file, use the `PARSE_DASHBOARD_USERS`env.json variable to configure your parse dashboard.

### PARSE\_DASHBOARD\_USERS var

Object Array container **user**, **pass** key value pairs.&#x20;

```css
...
"PARSE_DASHBOARD_USERS": [
    {
        "user": "admin",
        "pass": "admin"
    }
],
...
```

{% hint style="danger" %}
Don't commit dashboard users to git if you intend to use this file in **production**. Instead, do one of the following:\
\- Supply an environment variable **`PARSE_DASHBOARD_USERS`** containing a JSON string.\
\- Supply an **env.json** file in your production environment by file extension using the environment variable  **ACTINIUM\_ENV\_FILE**
{% endhint %}

### Log In To Parse Dashboard

Visit <http://localhost:9000/parse> to view the Parse Dashboard login:

![Login with username and password specified in PARSE\_DASHBOARD\_USERS](/files/-MdbZrwnZvFl8jng0rER)

{% hint style="danger" %}
The Parse Dashboard provides a very low level "super-user" look at your Parse mongo database! This should only be used by an administrator (or for local development).
{% endhint %}

### Create a Parse User

Once logged into Parse, you should be able to manually create an application user for your API. You can use this to assign a **role** and its associated **capabilities**


# Actinium SDK

The Actinium SDK provides important facilities you will need to interact with the API server, and extends the Parse SDK with a few notable changes.

### Parse Extension

| Class                                                    | Changes                                                                                                                                                                                                                                                                              |
| -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| <p><strong>User</strong></p><p></p><p></p><p></p><p></p> | <ul><li>Added <strong>Meta</strong> and <strong>Pref</strong> extensions</li><li>Added a <strong>list</strong> function to easily get a user list</li><li>Added a <strong>trash</strong> function that deletes a user but saves the object in the Trash for a limited time</li></ul> |
| **File**                                                 | Replaced **create** function                                                                                                                                                                                                                                                         |
| <p><strong>Cloud</strong></p><p></p>                     | Replace the **define** function where you have to specify the plugin associated with the cloud function                                                                                                                                                                              |

{% hint style="info" %}
**See:** [Actinium SDK API Docs](https://reactiumcore.github.io/Actinium) for available functions and definitions
{% endhint %}

{% content-ref url="/pages/-M5ZF5ZJLk6D3X6MBBa2" %}
[Broken mention](broken://pages/-M5ZF5ZJLk6D3X6MBBa2)
{% endcontent-ref %}


# Actinium Domain Model

## Artifacts

| File              | Description                                                                                                                                                           |
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **middleware.js** | Express middleware file for [registering middleware.](https://atomic-reactor.github.io/Actinium/#api-Actinium-Middleware)                                             |
| **plugin.js**     | Actinium plugin file for [registering a plugin.](https://atomic-reactor.github.io/Actinium/#api-Actinium-Plugin.register)                                             |
| **sdk.js**        | File in a plugin directory that defines an extension to the Actinium SDK. (optional)                                                                                  |
| **route.js**      | File in a plugin directory that defines data driven routes for dynamic routes in the admin or another UI application. (optional)                                      |
| **blueprints.js** | File in a plugin directory that defines UI layouts for the Admin. (optional)                                                                                          |
| **schema.js**     | File in a plugin directory that defines DB schema information for [registering Parse Collections](https://atomic-reactor.github.io/Actinium/#api-Actinium-Collection) |

### plugin.js

Actinium will attempt to add any file within the **/src/app** directory with a file name that ends with **plugin.js** and execute in the file scope.

A typical **plugin.js** file may look like:&#x20;

{% code title="/src/app/MyPlugin/plugin.js" %}

```javascript
const PLUGIN = {
    ID: 'MyPlugin',
    description: 'My plugin is here!',
    name: 'My Plugin',
};

const COLLECTION = 'MyPluginCollection'; 

// Register plugin
Actinium.Plugin.register(PLUGIN);

// Define a cloud function
Actinium.Cloud.define(PLUGIN.ID, 'my-plugin-log', req => {
    console.log(req.params); 
    return { message: 'OK', status: 200, ...req.params };
});

// Define an after save function that will run an after-save hook 
Actinium.Cloud.afterSave(COLLECTION, async req => {
    // run this code if MyPlugin is active
    if (!Actinium.Plugin.isActive(PLUGIN.ID)) return;
    await Actinium.Hook.run(`${COLLECTION}-after-save`, req); 
    console.log(`Saved a ${COLLECTION} object!`); 
});

// Register a start hook 
Actinium.Hook.register('start', () => {
    // run this code if MyPlugin is active
    if (!Actinium.Plugin.isActive(PLUGIN.ID)) return;
    console.log(PLUGIN.ID, 'Yo!');
});
```

{% endcode %}

### middleware.js

Actinium will attempt to add any file within the **/src/app** directory with a file name that ends with **middleware.js** and execute it in the file scope.&#x20;

A typical **middleware.js** file may look like:&#x20;

{% code title="/src/app/MyPlugin/middleware.js" %}

```javascript
const express = require('express');
const request = require('request');
const op = require('object-path');
const _ = require('underscore');

// Add an Express route hanlder for /media/* 
// and serve an Actinium.File object if a matching route is found
Actinium.Middleware.register(
    'media',
    app => {
        const router = express.Router();

        router.use('/media/*', (req, res) => {
            const p = [80, 443].includes(PORT) ? '' : `:${PORT}`;
            const files = Object.values(Actinium.Cache.get('Media.files', {}));
            const rec = _.findWhere(files, { url: req.baseUrl });
            const fileURL = String(op.get(rec, 'file.url', ''))
                .replace('undefined/', `${ENV.ACTINIUM_MOUNT}/`)
                .substr(1);

            const url = `${req.protocol}://${req.hostname}${p}/${fileURL}`;

            request(url).pipe(res);
        });

        app.use(router);

        return Promise.resolve();
    },
    0,
);
```

{% endcode %}

{% hint style="info" %}
Actinium will traverse **node\_modules/\*\*/actinium** directories for **plugin.js** and **middleware.js** artifacts.&#x20;
{% endhint %}


# Extending

Actinium is easy to extend and much of its bootstrapping is hook-able.

{% hint style="info" %}
**For more information on the available hooks see:** \
[Actinium Hooks](https://atomic-reactor.github.io/Actinium/#api-Hooks)
{% endhint %}

### Actinium SDK&#x20;

Suppose you're creating a plugin and you want to share the functionality with other plugins. You can opt to extend the Actinium SDK by creating a namespace on the Actinium global.&#x20;

{% tabs %}
{% tab title="Plugin" %}
{% code title="/src/app/MyPlugin/plugin.js" %}

```javascript


// Extend Actinium SDK 
Actinium.MyPlugin = require('./sdk');
```

{% endcode %}
{% endtab %}

{% tab title="MyPlugin SDK" %}
{% code title="/src/app/MyPlugin/sdk.js" %}

```javascript
const COLLECTION = 'SomeCollection';

const MyPluginSDK = {}; 

MyPluginSDK.create = async (req, options) => {
    
    // Get params from request object 
    let { params } = req; 
    
    // Run a hook so other plugins can do some thangs to the params
    await Actinium.Hook.run('some-collection-before-create', params, req, options);
    
    // Create the new object
    const obj = new Actinium.Object(COLLECTION);
    
    // Save the object
    let savedObj = await obj.save(params, options);
    
    if (!savedObj) { 
        return new Error('Unable to save SomeCollection object'); 
    }
    
    // Convert the Actinium.Object into a JavaScript Object. 
    savedObj = saveObj.toJSON(); 
    
    // Run a hook so other plugins can do some thangs 
    await Actinium.Hook.run('some-collection-created', savedObj, req, options);
    
    return savedObj;
};

module.exports = MyPluginSDK;
```

{% endcode %}
{% endtab %}
{% endtabs %}

In the above example your Actinium extension will be available regardless of your plugin's active status. If you want your extension to only be available if your plugin is active you'll want to register a **plugin-load** hook and define it after validating that your plugin is active using [**Actinium.Plugin.isActive**](https://atomic-reactor.github.io/Actinium/#api-Actinium-Plugin_isActive)**.**

{% code title="/src/app/MyPlugin/plugin.js" %}

```javascript
const SDK = require('./sdk'); 

const PLUGIN = {
    ID: 'MyPlugin',
    name: 'My Awesome Plugin',
    description: 'The name says it all bro',
    version: {
        actinium: '>=3.0.5',
        plugin: '0.0.1',
    },
};

Actinium.Plugin.register(PLUGIN);

Actinium.Hook.register('plugin-load', async ({ ID }) => {
    if (ID !== PLUGIN.ID) return;
    if (!Actinium.Plugin.isActive(ID)) return;
    
    Actinium.MyPlugin = SDK;
});
```

{% endcode %}

{% hint style="warning" %}
**Note:** In the above example your extension will not be available in the file scope.
{% endhint %}

### Cloud Functions

Cloud functions are another way to extend Actinium functionality. Cloud functions are accessible to other plugins and the Actinium client SDK via **Actinium.Cloud.run**. You can define a cloud function in a **plugin.js** file. A typical cloud function may look like:

{% code title="/src/app/MyPlugin/plugin.js" %}

```javascript
const SDK = require('./sdk'); 
const { CloudRunOptions } = require(`${ACTINIUM_DIR}/lib/utils`);

const PLUGIN = {
    ID: 'MyPlugin',
    name: 'My Awesome Plugin',
    description: 'The name says it all bro',
    version: {
        actinium: '>=3.0.5',
        plugin: '0.0.1',
    },
};

Actinium.Plugin.register(PLUGIN);

Actinium.Cloud.define('my-plugin-create', req => {
    const options = CloudRunOptions(req); 
    return SDK.create(req, options); 
});
```

{% endcode %}

{% hint style="info" %}
If your cloud function requires capabilities or roles be sure to create the **options** object via the **CloudRunOptions** helper.&#x20;
{% endhint %}

{% tabs %}
{% tab title="Client Side Usage" %}
{% code title="Usage: Reactium \~ services.js" %}

```javascript
import Actinium from 'appdir/api'; 

const create = params => Actinium.Cloud.run('my-plugin-create', params);

export default {
    create,
};
```

{% endcode %}
{% endtab %}

{% tab title="Other Plugin Usage" %}
{% code title="Usage: Actinium \~ plugin.js" %}

```javascript
const { CloudRunOptions } = require(`${ACTINIUM_DIR}/lib/utils`);

Actinium.Cloud.define('some-other-plugin', async req => {
    const options = CloudRunOptions(req);
    const params = { someparam: 'somevalue' };
    const newObj = await Actinium.Cloud.run('my-plugin-create', params, options); 
    
    // do something else like transform the newObj with a hook 
    await Actinium.Hook.run('some-other-plugin-hook', newObj, req, options); 
    
    return newObj;  
};
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Express Middleware

You can extend the underlying Express app by registering middleware that will be loaded on start-up. Register middleware using the **Actinium.Middleware.register** function.

```javascript
const express = require('express');
const { myPluginMiddleware } = require('./sdk'); 

Actinium.Middleware.register('my-plugin-mw', app => {
    // custom middleware 
    app.use(myPluginMiddleware()); 
    
    // custom route handler
    const router = express.Router();
    
    router.use('/some/route/*', (req, res, next) => {
        console.log('Log something'); 
        res.send('Send something to browser'); 
    });
    
    // mount the router on app
    app.use(router);
});
```

{% hint style="info" %}
**For more information on middleware see:** \
[Express Middleware](https://expressjs.com/en/guide/using-middleware.html)
{% endhint %}


# Updating

One of the greatest features of Actinium is the ability to update to the latest version with minimal worrying about your current project being disrupted.&#x20;

{% hint style="warning" %}
*Updating is usually non-invasive, but It's always a good idea to commit your current project before updating.*
{% endhint %}

```
$ arcli actinium update
```

After updating, ensure that you have the updated dependencies by running:

```
$ arcli install -s
```

Under the hood, the latest version of Actinium Core is pulled down, extracted, and an update script makes necessary edits to your config files.


# Live Query

Live Query allows you to subscribe to a **Parse.Query** you are interested in. Once subscribed, the server will notify clients whenever a **Parse.Object** that matches the **Parse.Query** is created or updated, in real-time.

Suppose you're building a To Do app and multiple users can make edits to the list. **Parse.Query** would require you to constantly poll the server for status. That's not an ideal situation.&#x20;

A Live Query solves this and makes it to where the client can subscribe to a **Parse.Query** and when updates are made, the subscriber will be notified.&#x20;

## Setup

Live Query requires you to configure which collections can be subscribed to. There are two ways to configure collections, [**env.json**](/actinium/live-query#env-json) and [**live-query-classnames**](/actinium/live-query#live-query-classnames-hook) hook.&#x20;

### env.json

Open the **/src/env.json** file and update the **LIVE\_QUERY\_SETTINGS.classNames** array with the collection name you wish to include.&#x20;

{% code title="/src/env.json" %}

```css
{
    ...
    "LIVE_QUERY_SERVER": true,
    "LIVE_QUERY_SETTINGS": {
        "classNames": ["Changelog", "YourCollection"]
    },
    ...
}
```

{% endcode %}

{% hint style="info" %}
If you have multiple **env.json** files be sure to update them accordingly&#x20;
{% endhint %}

### live-query-classnames hook

{% code title="/src/app/MyPlugin/plugin.js" %}

```javascript
Actinium.Hook.register('live-query-classnames', classNames => {
    classNames.push('MyPluginCollection'); 
});
```

{% endcode %}

{% hint style="warning" %}
Using the **live-query-classnames** hook will execute regardless of your plugin's active status due to the fact that this hook is run before the server starts.&#x20;
{% endhint %}


# Overview

Before getting started with the Toolkit, it's a good idea to understand what you can create with it

## Reactium Toolkit Plugin

You can use the Reactium Toolkit Plugin to create [**Style Guides**](/reactium-toolkit/overview#style-guides), [**UI Component Libraries**](/reactium-toolkit/overview#ui-component-libraries), and [**Prototypes**](/reactium-toolkit/overview#prototypes).

![](/files/-MTM9PADDC-372TvQxdh)

## Style Guides

![](/files/-MTM8LYfEBr6dHOopl3A)

A style guide is a document that provides guidelines for the way your brand should be presented from both a graphic and language perspective. The purpose of a style guide is to make sure that multiple contributors create in a clear and cohesive way that reflects the brand style and ensures consistency with everything from design to writing. A style guide should provide all of the necessary details for consistent branding with context as to when and where to use components.

Style guides help create a shared vocabulary and reinforce design consistency. By keeping a tight rein on brand consistency, brands can drive user perception and expectations.

## UI Component Libraries

![](/files/-MTM8LYaAN2EgW8klNPf)

A UI component library is a wide range of building blocks available to developers and consists of all the styles and components used in an app, website, or software.&#x20;

Design systems use components as the building blocks for creating a user interface. Building a UI component library is an optimized way to reduce the overhead that comes with maintaining multiple repositories for multiple components.

## Prototypes

![](/files/-MTM8LYgpjfq4CgTuWoz)

Combine UI Components and realize design concepts and features quickly and with extreme agility.&#x20;

Good candidates for prototyping include complex interactions, new functionality and changes in workflow, technology or design.&#x20;


# Installation

From the Reactium root directory:

```bash
npx reactium @atomic-reactor/toolkit
```

{% hint style="success" %}
After the plugin has been downloaded you will be prompted to add the Toolkit styles to your project.
{% endhint %}

```bash
[ARCLI] > Inject Toolkit styles?: (Y/n)
```


# Configuration

You can modify the default behavior of the Toolkit by overriding the configuration object:

{% tabs %}
{% tab title="Properties" %}

| Property              | Type      | Description                                            |
| --------------------- | --------- | ------------------------------------------------------ |
| **brand**             | `Node`    | String or component used to display the brand name     |
| **info**              | `Node`    | String or component used to display version info       |
| **titlebar**          | `String`  | Text used in the Titlebar of the browser               |
| **sidebar**           | `Object`  | Sidebar configuration object                           |
| **sidebar.collapsed** | `Boolean` | Collapsed state of the Sidebar. **Default:** `true`    |
| **sidebar.position**  | `String`  | Position of the Sidebar. **Default:** `left`           |
| **sidebar.width**     | `Number`  | Width of the Sidebar when expanded. **Default:** `320` |
| {% endtab %}          |           |                                                        |

{% tab title="Default" %}

```javascript
{
    brand: 'Reactium',
    info: 'Toolkit version %ver',
    titlebar: 'Reactium | Toolkit',
    sidebar: {
        collapsed: true,
        position: Reactium.Toolkit.Sidebar.position.left,
        width: 320,
    },
};
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
**Note:** The initial Sidebar configuration is overridden by user preferences.&#x20;
{% endhint %}

{% code title="/MyPlugin/reactium-hooks.js" %}

```jsx
import Reactium from 'reactium-core/sdk'; 

Reactium.Plugin.register('MyPlugin').then(() => {
    // Ensure the toolkit plugin is available
    if (!Reactium.Toolkit) return;
    
    // Override sidebar width
    Reactium.Toolkit.setConfig('sidebar.width', 480);
});
```

{% endcode %}

The [Toolkit SDK](/reactium-toolkit/sdk) exposes a read-only property for the configuration object:

```javascript
Reactium.Toolkit.config
```

```jsx
import React from 'react'; 
import Reactium from 'reactium-core/sdk';

const MyComponent = () => {
    const config = Reactium.Toolkit.config; 
    
    console.log(config); 
    
    return <div>My Plugin</div>;
};
```


# Customization

The Reactium Toolkit can be customized to fit your design aesthetic and extended to add new functionality.&#x20;

## Logo

You can replace the logo by registering a component with an ID of **RTKLOGO**

{% code title="/CustomLogo/reactium-hooks.js" %}

```javascript
import CustomLogo from '.';
import Reactium from 'reactium-core/sdk'; 

Reactium.Plugin.register('CustomLogo').then(() => {

    // Ensure the toolkit plugin is available
    if (!Reactium.Toolkit) return;
    
    // Replace Logo on plugin-ready
    Reactium.Hook.register('plugin-ready', () => {
        Reactium.Component.register('RTKLOGO', CustomLogo);
    });
});
```

{% endcode %}

## Brand Name

You can replace the default brand name by registering a configuration hook and setting the `brand` property to your custom component or string.&#x20;

{% code title="/MyPlugin/reactium-hooks.js" %}

```javascript
import Reactium from 'reactium-core/sdk'; 

Reactium.Plugin.register('MyPlugin').then(() => {

    // Ensure the toolkit plugin is available
    if (!Reactium.Toolkit) return;
    
    Reactium.Hook.register('plugin-ready', () => {
    
        // Register Toolkit config override
        Reactium.Hook.registerSync('rtk-config', config => {
            config.brand = <div>My Awesome Brand</div>;
        });
    });
});
```

{% endcode %}

## Version Info

You can replace the default version info by registering a configuration hook and setting the `info` property to your custom component or string.

{% code title="/MyPlugin/reactium-hooks.js" %}

```javascript
import Reactium from 'reactium-core/sdk'; 

Reactium.Plugin.register('MyPlugin').then(() => {
    
    // Ensure the toolkit plugin is available
    if (!Reactium.Toolkit) return;

    Reactium.Hook.register('plugin-ready', () => {
    
        // Register Toolkit config override
        Reactium.Hook.registerSync('rtk-config', config => {
            config.info = <div>Style Guide</div>;
        });
    });
});
```

{% endcode %}


# Creating Elements

Elements are components added to specific zones in the Toolkit Plugin. You can create new elements by registering components with the [Toolkit SDK](/reactium-toolkit/sdk).

{% tabs %}
{% tab title="TL;DR" %}
There's a lot to know about creating elements. Let the ARCLI do it for you:

```
$ arcli toolkit element
```

{% endtab %}

{% tab title="Prompts" %}

```bash
[ARCLI] > Type: Top-Level
[ARCLI] > ID: test
[ARCLI] > Label: Test
[ARCLI] > URL?: Yes
[ARCLI] > Order: 100
[ARCLI] > Directory: /My Reactium Project/src/app/components/Toolkit/Sidebar

[ARCLI] > A new toolkit sidebar item will be created using the following configuration:

{
  "type": "group",
  "id": "test",
  "label": "Test",
  "url": "/toolkit",
  "order": 100,
  "directory": "/My Reactium Project/src/app/components/Toolkit/Sidebar/Test"
}

[ARCLI] > Proceed?: (y/N)
```

{% endtab %}
{% endtabs %}

{% code title="/ButtonColors/reactium-hooks.js" %}

```jsx
import ButtonColors from '.';
import Reactium from 'reactium-core/sdk';


// Register a new Reactium Plugin
Reactium.Plugin.register('ToolkitButtonColors').then(() => {

    // Ensure the toolkit plugin is available
    if (!Reactium.Toolkit) return;

    // Wait for plugins to be initialized
    Reactium.Hook.register('plugin-ready', () => {
    
        // Get the MenuLink component
        const MenuLink = Reactium.Component.get('RTKMENULINK');

        // Register the Sideber link
        Reactium.Toolkit.Sidebar.register('button-colors', {
            order: 10,
            component: MenuLink,
            children: 'Button Colors',
            url: '/toolkit/button/colors',
        });

        // Register the Element
        Reactium.Toolkit.Elements.register('button-colors', {
            order: 0,
            zone: 'button-colors',
            component: ButtonColors,
        });
    });
});
```

{% endcode %}

{% hint style="info" %}
The Element **zone** value is derived from the Sidebar **url** value. Given the url: `/toolkit/button/colors`\
\
The corresponding zone would be:  \
`button-colors`
{% endhint %}

The above registration creates the following view in the Toolkit:

![/toolkit/button/colors](/files/-MTMIibIsoiG1lQNO4Um)


# Sidebar Elements

Sidebar Elements are components added to the Toolkit Sidebar component. You can create new Sidebar Elements by registering components with the [Toolkit SDK](/reactium-toolkit/sdk).

![](/files/-MTMPYEWdNeCQRhoKIIf)

{% tabs %}
{% tab title="TL;DR" %}
We understand that adding elements to the Sidebar leaves a lot to consider. To lighten the load you can use the Reactium CLI (also known as ARCLI) to generate Sidebar navigation elements.

```bash
npx reactium toolkit sidebar
```

{% endtab %}

{% tab title="Prompts" %}

```bash
[ARCLI] > Type: Child Link
[ARCLI] > Parent ID: button
[ARCLI] > Link ID: button-colors
[ARCLI] > Label: Button Colors
[ARCLI] > URL?: Yes
[ARCLI] > Order: 100
[ARCLI] > Directory: /My Reactium Project/src/app/components/Toolkit/Sidebar

[ARCLI] > A new toolkit sidebar item will be created using the following configuration:

{
  "type": "link",
  "group": "button",
  "id": "button-colors",
  "label": "Button Colors",
  "url": "/toolkit/button/button-colors",
  "order": 100,
  "directory": "/My Reactium Project/src/app/components/Toolkit/Sidebar/Button/ButtonColors"
}

[ARCLI] > Proceed?: (y/N)
```

{% endtab %}
{% endtabs %}

## Sidebar Navigation

The Sidebar has a stylized navigation link called the [MenuLink](/reactium-toolkit/components/menu-link) which can be used in your project to render a Sidebar element. By default you can add either a [**Top-Level**](/reactium-toolkit/creating-elements/sidebar#top-level-link) Link or [**Child Link**](/reactium-toolkit/creating-elements/sidebar#child-link) via the [MenuLink](/reactium-toolkit/components/menu-link) component.

![](/files/-MTMQpZFu9gynltDPe4V)

### Top-Level Link

Top-Level Links are also known as **groups**

{% code title="/MyPlugin/reactium-hooks.js" %}

```javascript
import Reactium from 'reactium-core/sdk';

Reactium.Plugin.register('MyPlugin').then(() => {
    
    // Ensure the toolkit plugin is available
    if (!Reactium.Toolkit) return;
    
    Reactium.Hook.register('plugin-ready', () => {
        const MenuLink = Reactium.Component.get('RTKMENULINK');

        Reactium.Toolkit.Sidebar.register('form', {
            url: '/toolkit/form',
            component: MenuLink,
            children: 'Form',
            'aria-label': 'Form',
            order: Reactium.Enums.priority.lowest,
        });
    });
});
```

{% endcode %}

{% hint style="warning" %}
When using **Reactium.Component.get()** to retrieve a registered component, be sure to wrap your work in the **plugin-ready** hook:&#x20;
{% endhint %}

```jsx
Reactium.Hook.register('plugin-ready', () => {
    
    // Ensure the toolkit plugin is available
    if (!Reactium.Toolkit) return;
    
    const MenuLink = Reactium.Component.get('RTKMENULINK');
    
    // Your registration...
});
```

### Child Link

Adding a Child Link works the same as [Top-Level](/reactium-toolkit/creating-elements/sidebar#top-level-link) Links but the registry object is slightly different:

{% code title="/MyPlugin/reactium-hooks.js" %}

```javascript
Reactium.Plugin.register('MyPlugin').then(() => {

    // Ensure the toolkit plugin is available
    if (!Reactium.Toolkit) return;
    
    Reactium.Hook.register('plugin-ready', () => {
        const MenuLink = Reactium.Component.get('RTKMENULINK');

        // Top-Level Link - Form Elements
        Reactium.Toolkit.Sidebar.register('form', {
            url: '/toolkit/form',
            children: 'Form Elements',
            component: MenuLink,
            order: Reactium.Enums.priority.lowest,
        });

        // Child Link of Form Elements
        Reactium.Toolkit.Sidebar.register('form-inputs', {
            url: '/toolkit/form/inputs',
            children: 'Inputs',
            component: MenuLink,
            order: Reactium.Enums.priority.neutral,
            group: 'form',
        });
    });
});
```

{% endcode %}

Specifying the **group** property will target the ID of a [Top-Level](/reactium-toolkit/creating-elements/sidebar#top-level-link) Link. \
In the example above; **form** is the ID of the [Top-Level](/reactium-toolkit/creating-elements/sidebar#top-level-link) Link while the [Child Link](/reactium-toolkit/creating-elements/sidebar#child-link) specifies **form** as the **group** property value.

### Registry Object

{% tabs %}
{% tab title="Properties" %}

| Property      | Type      | Description                                          |
| ------------- | --------- | ---------------------------------------------------- |
| **children**  | `Node`    | Content passed to the component                      |
| **component** | `Element` | Component used to render the Link                    |
| **group**     | `String`  | ID of a Top-Level Link. Used when adding Child Links |
| **order**     | `Number`  | Index used when rendering elements                   |
| **url**       | `String`  | Wraps the children in an anchor tag                  |
| {% endtab %}  |           |                                                      |

{% tab title="Top-Level Object" %}

```javascript
{
  url: '/toolkit/your-group',
  children: 'Label Text',
  component: MenuLink,
  order: 100,
}
```

{% endtab %}

{% tab title="Child Object" %}

```javascript
{
  url: '/toolkit/your-group/your-slug',
  children: 'Label Text',
  group: 'your-group',
  order: 100,
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Any additional properties added to the registry object will be passed to the **component** as props.
{% endhint %}


# Toolbar Elements

If you have created an element using the ARCLI you will notice that the generated component uses the [Element](/reactium-toolkit/components/element) wrapper component:

{% code title="/Reactium Project/src/app/component/Toolkit/Test/index.js" %}

```jsx
import React from 'react';
import { useHookComponent } from 'reactium-core/sdk';

export default () => {
    const { Element } = useHookComponent('RTK');

    return <Element title='Test'>Test Element</Element>;
};
```

{% endcode %}

The Element wrapper component adds the Toolbar component which has a zone included that allows you to add elements to the Toolbar.&#x20;

<div align="center"><img src="/files/-MTMeaMjKaHTCm2m68b9" alt="Toolbar Zone"></div>

## Adding Toolbar Elements

You can add Toolbar elements by registering a component with the [Toolkit SDK](/reactium-toolkit/sdk).&#x20;

{% code title="/MyPlugin/reactium-hooks.js" %}

```javascript
import Reactium from 'reactium-core/sdk'; 

Reactium.Plugin.register('MyPlugin').then(() => {

    // Ensure the toolkit plugin is available
    if (!Reactium.Toolkit) return;
    
    Reactium.Toolkit.Toolbar.register('CustomButton', {
        align: Reactium.Toolkit.Toolbar.align.left,
        component: <button>CustomButton</button>,
        order: Reactium.Enums.priority.neutral,
    });
});
```

{% endcode %}

{% hint style="warning" %}
When using the Toolkit SDK to add a Toolbar component, the component you register will persist across all Toolbars. You can control it's persistence by rendering **null** on urls you don't want it to appear on.&#x20;
{% endhint %}

You can temporarily register Toolbar elements within a useEffect:&#x20;

{% code title="/Reactium Project/src/app/component/Toolkit/Test/index.js" %}

```jsx
import React, { useEffect } from 'react';
import Reactium, { useHookComponent } from 'reactium-core/sdk';


const TestToolbarButton = () => <button>Test</button>;


export default () => {
    useEffect(() => {
    
        // Ensure the Toolbar is visible
        Reactium.Toolkit.setFullscreen(false);

        // Register the TestToolbarButton
        Reactium.Toolkit.Toolbar.register('TestToolbarButton', {
            align: Reactium.Toolkit.Toolbar.align.right,
            component: TestToolbarButton,
        });

        // Unregister TestToolbarButton on unmount
        return () => {
            Reactium.Toolkit.Toolbar.unregister('TestToolbarButton');
        };
    }, []);

    return <div>Test Element</div>;
};
```

{% endcode %}

Using the [Element](/reactium-toolkit/components/element#properties) wrapper component, you can add temporary Toolbar elements by specifying the **toolbar** property:&#x20;

![](/files/-MTMit0xHGsX9o54K8Dz)

{% code title="/Reactium Project/src/app/component/Toolkit/Test/index.js" %}

```jsx
import React from 'react';
import { useHookComponent } from 'reactium-core/sdk';


const TestToolbarButton = () => <button>Test</button>;


export default () => {
    const { Element } = useHookComponent('RTK');

    return (
        <Element 
            title='Test'
            toolbar={TestToolbarButton}>
            Test Element
        </Element>
    );
};
```

{% endcode %}

## Registry Object

{% tabs %}
{% tab title="Properties" %}

| Property      | Type     | Description                                                      |
| ------------- | -------- | ---------------------------------------------------------------- |
| **align**     | `String` | The horizontal alignment of the component`[left\|right\|center]` |
| **component** | `Node`   | React element to insert                                          |
| **order**     | `Number` | Index used to list the Toolbar components when rendering         |
| {% endtab %}  |          |                                                                  |

{% tab title="Object" %}

```javascript
{
    align: Reactium.Toolkit.Toolbar.align.left,
    component: <button>X</button>,
    order: Reactium.Enums.priority.neutral
}
```

{% endtab %}
{% endtabs %}


# Documentation Elements

The Toolkit plugin adds the [Markdown](/reactium-toolkit/components/markdown) component which takes *markdown* text and converts it into *JSX*.&#x20;

When creating an element via the Reactium CLI (also known as ARCLI), you will be prompted to include documentation.&#x20;

```bash
npx reactium toolkit element

...

[ARCLI] > Documentation?: (Y/n)
```

You can add a documentation component to existing elements as well:&#x20;

```bash
npx reactium toolkit document
```

```bash
[ARCLI] > Document Name: Documentation
[ARCLI] > Document ID: docs
[ARCLI] > Directory: /My Reactium Project/src/app/components/Toolkit/Test/Documentation
[ARCLI] > Sidebar?: Yes
[ARCLI] > Sidebar Group ID (optional): test
[ARCLI] > Sidebar Label: Test Documentation
[ARCLI] > Sidebar URL?: Yes
[ARCLI] > Sidebar Order: 100

[ARCLI] > A new toolkit document will be created using the following configuration:

{
  "name": "Documentation",
  "id": "readme",
  "directory": "/My Reactium Project/src/app/components/Toolkit/Test/Documentation/Documentation",
  "sidebar": true,
  "group": "test",
  "label": "Test Documentation",
  "url": "/toolkit/test/readme",
  "order": 100
}

[ARCLI] > Proceed?: (y/N)
```

You can then open the generated **readme.md** file and use markdown text to document an element.&#x20;


# Components

Useful components used to build toolkit elements.

{% content-ref url="/pages/-MS3Hee-Ty\_pYWcKo5L7" %}
[Sidebar](/reactium-toolkit/components/sidebar)
{% endcontent-ref %}

{% content-ref url="/pages/-MS5nJviqQRB5\_CwhMHs" %}
[MenuLink](/reactium-toolkit/components/menu-link)
{% endcontent-ref %}

{% content-ref url="/pages/-MT2yK1BrZSL7HkaR\_hN" %}
[Element](/reactium-toolkit/components/element)
{% endcontent-ref %}

{% content-ref url="/pages/-MSo-xTVc1ItkVgx8MDt" %}
[Code](/reactium-toolkit/components/code)
{% endcontent-ref %}

{% content-ref url="/pages/-MSo03aftMxDgCxLn1Ka" %}
[Markdown](/reactium-toolkit/components/markdown)
{% endcontent-ref %}

{% content-ref url="/pages/-MT36fg8VNM\_O5S5gxMV" %}
[Icon](/reactium-toolkit/components/icon)
{% endcontent-ref %}


# Sidebar

The Sidebar component is accessible as a [**Reactium.Handle**](https://atomic-reactor.github.io/Reactium/#api-Reactium.Handle-Reactium.Handle) object. You can gain access to the Sidebar by doing the following:

```jsx
import React from 'react'; 
import Reactium, { useHandle } from 'reactium-core/sdk';

const SidebarToggleButton = () => {

    const Sidebar = useHandle('RTKSidebar');
    
    return (
        <button onClick={() => Sidebar.toggle()}>
            Toggle Sidebar
        </button>
    );
};
```

## Properties

| Property      | Type      | Description                        |
| ------------- | --------- | ---------------------------------- |
| **collapsed** | `Boolean` | The collapsed state of the Sidebar |
| **expanded**  | `Boolean` | The expanded state of the Sidebar  |

## Methods

### collapse()

Collapse the Sidebar if it is expanded. The `collapse` and `collapsed` events are triggered. \
Returns a Promise that resolves when the collapse animation is complete.

```jsx
import React, { useEffect } from 'react'; 
import Reactium, { useHandle } from 'reactium-core/sdk';

const SidebarCollapseButton = () => {

    const Sidebar = useHandle('RTKSidebar');
    
    useEffect(() => {
        Sidebar.addEventListener('collapse', console.log);
        Sidebar.addEventListener('collapsed', console.log);

        return () => {
            Sidebar.removeEventListener('collapse', console.log);
            Sidebar.removeEventListener('collapsed', console.log);
        };
    }, [Sidebar]);
    
    return (
        <button onClick={() => Sidebar.collapse()}>
            Collapse Sidebar
        </button>
    );
};
```

### expand()

Expand the Sidebar if it is collapsed. The `expand` and `expanded` events are triggered. \
Returns a Promise that resolves when the expand animation is complete.&#x20;

```jsx
import React, { useEffect } from 'react'; 
import Reactium, { useHandle } from 'reactium-core/sdk';

const SidebarExpandButton = () => {

    const Sidebar = useHandle('RTKSidebar');
    
    useEffect(() => {
        Sidebar.addEventListener('expand', console.log);
        Sidebar.addEventListener('expanded', console.log);

        return () => {
            Sidebar.removeEventListener('expand', console.log);
            Sidebar.removeEventListener('expanded', console.log);
        };
    }, [Sidebar]);
    
    return (
        <button onClick={() => Sidebar.expand()}>
            Expand Sidebar
        </button>
    );
};
```

## Events

### collapse

Triggered when the collapse animation starts as a side effect of `collapse()` or `toggle()`

### collapsed

Triggered when the collapse animation is completed as a side effect of `collapse()` or `toggle()`&#x20;

### expand

Triggered when the expand animation starts as a side effect `expand()` or `toggle()`

### expanded

Triggered when the expand animation is completed as a  side effect of `collapse()` or `toggle()`

### resize

Triggered during the expand/collapse animation. The current width of the sidebar is provided as  a property on the event.


# MenuLink

Sidebar Navigation Render Component

![](/files/-MS6115ZtlO3hqsuO7YV)

## Properties

| Property     | Type      | Description                                                                                                     |
| ------------ | --------- | --------------------------------------------------------------------------------------------------------------- |
| **children** | `Node`    | <p>Element to render inside the component</p><p><strong><code>Required: true</code></strong></p>                |
| **exact**    | `Boolean` | <p>When determining the active state, use an exact match</p><p><strong><code>Default: false</code></strong></p> |
| **expanded** | `Boolean` | <p>Determines the default expanded state</p><p><strong><code>Default: false</code></strong></p>                 |
| **group**    | `String`  | When rendering as a Child Link, the Top-Level ID to target                                                      |
| **id**       | `String`  | <p>Unique ID of the component</p><p><strong><code>Required: true</code></strong></p>                            |
| **url**      | `String`  | Wraps the children in an anchor tag                                                                             |

{% hint style="info" %}
Any additional properties are passed to the MenuLink container element.
{% endhint %}

## Usage

{% code title="reactium-hooks.js" %}

```jsx
import Reactium from 'reactium-core/sdk';

Reactium.Plugin.register('ToolkitOverview').then(() => {
    if (!Reactium.Toolkit) return;

    Reactium.Hook.register(
        'plugin-ready',
        () => {
            const MenuLink = Reactium.Component.get('RTKMENULINK');

            Reactium.Toolkit.Sidebar.register('overview', {
                exact: true,
                url: '/toolkit',
                component: MenuLink,
                children: 'Overview',
                'aria-label': 'Overview',
                order: Reactium.Enums.priority.highest,
            });
        }
    );
});
```

{% endcode %}


# Element

Render component for Toolkit sections

When creating Toolkit sections you can wrap your component in the Element component to apply general styling and sizing attributes as well as a heading for the page and toolbar components specific to the element.&#x20;

## Usage

{% code title="/MyToolkitElement.js" %}

```jsx
import React from 'react'; 
import { useHookComponent } from 'reactium-core/sdk'; 

const MyToolkitElement = () => {

    const { Element } = useHookComponent('RTK');

    return (
        <Element title='Buttons'>
            My Buttons
        </Element>
    );
};
```

{% endcode %}

Using the example above, let's add a select input to the Toolbar:&#x20;

{% tabs %}
{% tab title="Element" %}
{% code title="/MyToolkitElement.js" %}

```jsx
import React from 'react'; 
import { Select } from './Select;
import { useHookComponent } from 'reactium-core/sdk'; 

const MyToolkitElement = () => {

    const { Element } = useHookComponent('RTK');

    return (
        <Element title='Buttons' toolbar={Select}>
            My Buttons
        </Element>
    );
};
```

{% endcode %}
{% endtab %}

{% tab title="Select" %}

```javascript
export const Select = props => (
    <select {...props}>
        <option>1</option>
        <option>2</option>
        <option>3</option>
    </select>
);
```

{% endtab %}
{% endtabs %}

## Properties

| Property       | Type          | Description                                                                                         |
| -------------- | ------------- | --------------------------------------------------------------------------------------------------- |
| **children**   | `Node`        | The content of the Element                                                                          |
| **className**  | `String`      | Class name to apply to the wrapper div                                                              |
| **fullscreen** | `Boolean`     | Toggle the fullscreen mode of the toolkit                                                           |
| **title**      | `Node`        | Title component or string to render in the toolbar                                                  |
| **toolbar**    | `Node`        | Temporary Toolbar component                                                                         |
| **xs**         | `Number 1-12` | <p>Grid size when the viewport is <em>xs</em></p><p><strong><code>Default: 12</code></strong></p>   |
| **sm**         | `Number 1-12` | <p>Grid size when the viewport is <em>sm</em></p><p><strong><code>Default: null</code></strong></p> |
| **md**         | `Number 1-12` | <p>Grid size when the viewport is <em>md</em></p><p><strong><code>Default: null</code></strong></p> |
| **lg**         | `Number 1-12` | <p>Grid size when the viewport is <em>lg</em></p><p><strong><code>Default: null</code></strong></p> |

{% hint style="info" %}
Any additional props are passed to the container div
{% endhint %}

### fullscreen

This property causes the Element component to call `Reactium.Toolkt.setFullscreen()` as a side-effect. When rendering multiple Element components in a single view, the last Element component rendered will be the most recent value of the `Reactium.Toolkit.fullscreen` property.&#x20;

### title

If you're rendering multiple Element components in a single view and set the title property on each, you will see multiple titles in the Toolbar.&#x20;


# Code

Component used to present a block of code in a Toolkit element

![](/files/-MSo4a4tQc6MZ3apWbmT)

{% hint style="success" %}
The code block is parsed with [Prettier](https://prettier.io/) before it is rendered.
{% endhint %}

## Usage

{% code title="/MyCodeElement.js" %}

```jsx
import React, { useEffect, useRef } from 'react'; 
import Reactium, { useHookComponent } from 'reactium-core/sdk';


const SomeCode = `
    // Here's some code:
    console.log('Hello Whomans'); 
`;

const MyCodeElement = () => {
    // Reference placeholder
    const codeRef = useRef(); 
    
    // Get the Code component from Reactium.Component registry
    const { Code } = useHookComponent('RTK');
    
    // Change handler 
    const changed = e => {
        console.log(e);
    };
    
    /*
    // Listen to change event as a side-effect
    useEffect(() => {
        if (!codeRef.current) return; 
        
        codeRef.current.addEventListener('change', changed); 
        
        return () => {
            codeRef.current.removeEventListener('change', changed);
        };
        
    }, [codeRef.current]);
    */
    
    // Render
    return <Code value={SomeCode} ref={codeRef} onChange={changed} />;
};
```

{% endcode %}

## Properties

| Property         | Type         | Description                                                                                           |
| ---------------- | ------------ | ----------------------------------------------------------------------------------------------------- |
| **className**    | `String`     | <p>The Class name to apply to the component</p><p><strong><code>Default: rtk-code</code></strong></p> |
| **editor**       | `Codemirror` | Reference to the [Codemirror](https://codemirror.net/) object.                                        |
| **foldGutter**   | `Boolean`    | <p>Enable folding</p><p><strong><code>Default: true</code></strong></p>                               |
| **lineNumbers**  | `Boolean`    | <p>Hide/show the line numbers. </p><p><strong><code>Default: true</code></strong></p>                 |
| **lineWrapping** | `Boolean`    | <p>Wrap long lines of code. </p><p><strong><code>Default: false</code></strong></p>                   |
| **id**           | `String`     | <p>ID value used for action Zone.</p><p><strong><code>Default: code</code></strong></p>               |
| **indentUnit**   | `Number`     | <p>Number of spaces used when indenting. </p><p><strong><code>Default: 4</code></strong></p>          |
| **readOnly**     | `Boolean`    | <p>Disable live editing. </p><p><strong><code>Default: false</code></strong></p>                      |
| **value**        | `String`     | The block of code to output                                                                           |
| **onChange**     | `Function`   | Called when the change event is triggered.                                                            |

{% hint style="info" %}
The Code component is an implementation of [Codemirror](https://codemirror.net/) and most of the properties are passed through to the [Codemirror](https://codemirror.net/) instance. If you want more control over the Code output you can directly apply configuration to the Codemirror instance via the `editor` property.
{% endhint %}

## Events

### change

Triggered when the code value is changed.&#x20;

## Theme

You can theme the Code block by supplying the following scss variables before the Toolkit styles are imported:

```
$rtk-code-border-color
$rtk-code-gutter-bg-color
$rtk-code-linenumber-color
$rtk-code-text-color
$rtk-code-cursor
$rtk-code-quote
$rtk-code-negative
$rtk-code-keyword
$rtk-code-atom
$rtk-code-number
$rtk-code-def
$rtk-code-var-1
$rtk-code-var-2
$rtk-code-var-3
$rtk-code-comment
$rtk-code-string-1
$rtk-code-string-2
$rtk-code-operator
$rtk-code-builtin
$rtk-code-meta
$rtk-code-bracket
$rtk-code-tag
$rtk-code-attribute
$rtk-code-hr
$rtk-code-link
$rtk-code-error
$rtk-code-active
$rtk-code-fold-marker
```


# Markdown

Component used to present documentation in a Toolkit element

## Usage

The Markdown component takes *markdown* text and converts it into *JSX*. Simply import a **.md** file into your element and pass it to the Markdown component as the **value** property:

{% tabs %}
{% tab title="Component" %}
{% code title="MyElement.js" %}

```jsx
import React from 'react';
import readme from './readme.md';
import { useHookComponent } from 'reactium-core/sdk';

const MyElement = () => {

    const { Markdown } = useHookComponent('RTK');
    
    return <Markdown value={readme} />
};
```

{% endcode %}
{% endtab %}

{% tab title="Markdown" %}
{% code title="readme.md" %}

````markup
# Title
---

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.

Some **bold**, *italic*, ~~strike~~, and `code` text

```
<div>markup</div>
```

> Block quote
````

{% endcode %}
{% endtab %}

{% tab title="Output" %}
![](/files/-MT1lQ-qOLyC2hMz-ge1)
{% endtab %}
{% endtabs %}

{% hint style="info" %}
The Toolkit plugin extends the Reactium Webpack configuration to allow **.md** file imports.&#x20;
{% endhint %}

## Properties

| Property  | Type     | Description       |
| --------- | -------- | ----------------- |
| **Value** | `String` | The markdown text |


# Icon

Render single color SVG icons

The Toolkit plugin has a small set of icons available for usage

![Feather Icons](/files/-MT36c21ieBLso39NFnx)

## Usage

{% code title="/MyElement.js" %}

```jsx
import React from 'react';
import { useHookComponent } from 'reactium-core/sdk';

 const MyElement = () => {
   const { Icon, Element } = useHookComponent('RTK'); 
   
   return (
     <Element title='My Element'>
       <Icon name='Feather.AlertCircle' />
     </Element>
   );
 }; 
```

{% endcode %}

## Properties

| Property | Type     | Description                                                                   |
| -------- | -------- | ----------------------------------------------------------------------------- |
| **name** | `String` | The icon name                                                                 |
| **size** | `Number` | <p>The size of the icon. </p><p><strong><code>Default: 24</code></strong></p> |

{% hint style="info" %}
Any additional props are passed to the SVG element.&#x20;
{% endhint %}

## Icons

```javascript
[
  "Feather.AlertCircle",
  "Feather.AlertOctagon",
  "Feather.AlertTriangle",
  "Feather.ArrowDown",
  "Feather.ArrowDownCircle",
  "Feather.ArrowDownLeft",
  "Feather.ArrowDownRight",
  "Feather.ArrowLeft",
  "Feather.ArrowLeftCircle",
  "Feather.ArrowRight",
  "Feather.ArrowRightCircle",
  "Feather.ArrowUp",
  "Feather.ArrowUpCircle",
  "Feather.ArrowUpLeft",
  "Feather.ArrowUpRight",
  "Feather.Box",
  "Feather.Check",
  "Feather.ChevronDown",
  "Feather.ChevronLeft",
  "Feather.ChevronRight",
  "Feather.ChevronUp",
  "Feather.Clipboard",
  "Feather.Code",
  "Feather.Copy",
  "Feather.Cpu",
  "Feather.ExternalLink",
  "Feather.Feather",
  "Feather.File",
  "Feather.Filter",
  "Feather.Folder",
  "Feather.Heart",
  "Feather.HelpCircle",
  "Feather.Info",
  "Feather.Layout",
  "Feather.List",
  "Feather.Maximize",
  "Feather.Menu",
  "Feather.Minimize",
  "Feather.Minus",
  "Feather.MinusCircle",
  "Feather.MinusSquare",
  "Feather.Monitor",
  "Feather.MoreHorizontal",
  "Feather.MoreVertical",
  "Feather.Package",
  "Feather.Plus",
  "Feather.PlusCircle",
  "Feather.PlusSquare",
  "Feather.RefreshCw",
  "Feather.Settings",
  "Feather.Sidebar",
  "Feather.Sliders",
  "Feather.Tag",
  "Feather.X",
  "Feather.XCircle",
  "Feather.XOctagon",
  "Feather.XSquare"
]

```


# Toolkit SDK

The Toolkit plugin extends the [**Reactium SDK**](/reactium/reactium-sdk) with the **Toolkit** namespace. There are a number of helpful functions on the Toolkit SDK but the primary usage is for registering items to the Toolkit plugin such as sidebar, toolbar, and content elements.

## Usage

{% code title="reactium-hooks.js" %}

```jsx
import Reactium from 'reactium-core/sdk';

Reactium.Plugin.register('MyPlugin').then(() => {
    console.log(Reactium.Toolkit.version);
});
```

{% endcode %}

## Properties

| Property       | Type      | Description                                                                                        |
| -------------- | --------- | -------------------------------------------------------------------------------------------------- |
| **config**     | `Object`  | <p>Reference to the Toolkit configuration object</p><p><strong><code>Read-only</code></strong></p> |
| **debug**      | `Boolean` | <p>Whether the Toolkit is in debug mode</p><p><strong><code>Default: false</code></strong></p>     |
| **fullscreen** | `Boolean` | Whether the Toolkit is in fullscreen mode or not                                                   |
| **os**         | `String`  | <p>The current operating system</p><p><strong><code>Read-only</code></strong></p>                  |
| **ENUMS**      | `Object`  | <p>Reference to the Toolkit enum object</p><p><strong><code>Read-only</code></strong></p>          |

## Methods

### codeFormat()

Returns a String that has been formatted by [Prettier](https://prettier.io/). This function is used in the Code component render.

**`codeFormat(code:String, options:Object:Optional)`**&#x20;

{% tabs %}
{% tab title="Params" %}

| Parameter    | Type     | Description                                                                 |
| ------------ | -------- | --------------------------------------------------------------------------- |
| **code**     | `String` | The code string value to format                                             |
| **options**  | `Object` | <p>Prettier options object</p><p><strong><code>Optional</code></strong></p> |
| {% endtab %} |          |                                                                             |

{% tab title="Usage" %}
{% code title="MyCodeBlock.js" %}

```jsx
import React from 'react';
import Reactium from 'reactium-core/sdk';

const MyCodeBlock = () => {
    const markup = Reactium.Toolkit.codeFormat(`<div>   Some  ugly markup</div>`);
    return <pre><code>{markup}</code></pre>;
});
```

{% endcode %}
{% endtab %}

{% tab title="Prettier Options" %}

```jsx
{
    tabWidth: 2,
    printWidth: 80,
    parser: 'babel',
    singleQuote: true,
    trailingComma: 'es5',
    jsxSingleQuote: true,
    jsxBracketSameLine: true,
    plugins: [parserbabel, parserHtml],
}
```

{% endtab %}
{% endtabs %}

### copy()

Copy a string to the clipboard.&#x20;

**`copy(text:String)`**

{% tabs %}
{% tab title="Usage" %}

```javascript
import React, { useCallback } from 'react';
import Reactium from 'reactium-core/sdk';

const MyComponent = () => {
    
    const onClick = useCallback(() => {
        Reactium.Toolkit.copy('Something was copied!');
    });
    
    return <button onClick={onClick}>Copy Something!</button>;
});
```

{% endtab %}
{% endtabs %}

### cx()

Reference to the Toolkit className extension **rtk.**

**`cx('some-class')`**

**Returns:** rtk-some-class

### setConfig()

Set Toolkit configuration value.&#x20;

{% tabs %}
{% tab title="Params" %}

| Parameter    | Type    | Description                                                          |
| ------------ | ------- | -------------------------------------------------------------------- |
| **key**      | `Mixed` | `String:` The object path of the configuration value you are setting |
|              |         | `Object:` The value will be merged with the current config object.   |
| **value**    | `Mixed` | The new configuration value.                                         |
| {% endtab %} |         |                                                                      |

{% tab title="Usage" %}

```javascript
import Reactium from 'reactium-core/sdk';

Reactium.Plugin.register('MyPlugin').then(() => {

    // Set config from key/value
    Reactium.Toolkit.setConfig('sidebar.width', 400);
    
    // Set config from object
    const sidebar = { 
        ...Reactium.Toolkit.config.sidebar, 
        width: 400 
    };
    
    Reactium.Toolkit.setConfig({ sidebar }); 
});
```

{% endtab %}
{% endtabs %}

There are two ways to set config

**`setConfig(key:String, value:Mixed)`**

```jsx
// Key/Value Method:
Reactium.Toolkit.setConfig('sidebar.width', 500);
```

**`setConfig(value:Object)`**&#x20;

```jsx
// Merged Object
Reactium.Toolkit.setConfig({ brand: 'My Brand Name' }); 
```

{% hint style="info" %}
**See:** [Configuration](/reactium-toolkit/config) for more details
{% endhint %}

### setDebug()

Set the Toolkit debug mode. Useful when subscribing to events and tracking down where errors occur.&#x20;

**`setDebug(Boolean)`**

{% tabs %}
{% tab title="Usage" %}
{% code title="MyComponent.js" %}

```jsx
import React, { useEffect, useState } from 'react';
import Reactium from 'reactium-core/sdk';

export default () => {
    const [debug, updateDebug] = useState(Reactium.Toolkit.debug);

    const onDebugChange = ({ value }) => updateDebug(value);

    const toggle = () => Reactium.Toolkit.setDebug(!Reactium.Toolkit.debug);

    useEffect(() => Reactium.Toolkit.subscribe('debug', onDebugChange), []);

    return (
        <div>
            <h2>Toolkit Debug Mode {debug ? 'on' : 'off'}</h2>
            <div>
                <button onClick={toggle}>Toggle Debug</button>
            </div>
        </div>
    );
};
```

{% endcode %}
{% endtab %}
{% endtabs %}

### setFullscreen()

Toggle fullscreen mode.

**`setFullscreen(Boolean)`**

{% tabs %}
{% tab title="Usage" %}
{% code title="MyComponent.js" %}

```javascript
import React, { useCallback } from 'react';
import Reactium from 'reactium-core/sdk';

const MyComponent = () => {
    
    const onClick = useCallback(() => {
        Reactium.Toolkit.setFullscreen(true);
    });
    
    return <button onClick={onClick}>Fullscreen</button>;
};
```

{% endcode %}
{% endtab %}
{% endtabs %}

### subscribe()

Subscribe to Toolkit events.&#x20;

**`subscribe(event:String, callback:Function, id:String:Optional)`**

{% tabs %}
{% tab title="Params" %}

| Parameter    | Type       | Description                                                                                |
| ------------ | ---------- | ------------------------------------------------------------------------------------------ |
| **event**    | `String`   | The event name                                                                             |
| **callback** | `Function` | Reference to the function run when the event is triggered                                  |
| **id**       | `String`   | <p>Unique id assigned to the subscription</p><p><strong><code>Optional</code></strong></p> |
| {% endtab %} |            |                                                                                            |

{% tab title="Usage" %}
{% code title="MyComponent.js" %}

```jsx
import React, { useEffect, useState } from 'react';
import Reactium from 'reactium-core/sdk';

export default () => {
    const [debug, updateDebug] = useState(Reactium.Toolkit.debug);

    const onDebugChange = ({ value }) => updateDebug(value);

    const toggle = () => Reactium.Toolkit.setDebug(!Reactium.Toolkit.debug);

    // Subscribe/Unsubscribe on mount/unmount
    useEffect(() => Reactium.Toolkit.subscribe('debug', onDebugChange), []);

    return (
        <div>
            <h2>Toolkit Debug Mode {debug ? 'on' : 'off'}</h2>
            <div>
                <button onClick={toggle}>Toggle Debug</button>
            </div>
        </div>
    );
};
```

{% endcode %}
{% endtab %}
{% endtabs %}

### unsubscribe()

Unsubscribe from Toolkit events.

{% tabs %}
{% tab title="Params" %}

| Parameter    | Type       | Description                                               |
| ------------ | ---------- | --------------------------------------------------------- |
| **id**       | `String`   | Unique id assigned to the subscription                    |
| **event**    | `String`   | The event name                                            |
| **callback** | `Function` | Reference to the function run when the event is triggered |
| {% endtab %} |            |                                                           |

{% tab title="Usage" %}
{% code title="MyComponent.js" %}

```jsx
import React, { useEffect, useState } from 'react';
import Reactium, { useHookComponent } from 'reactium-core/sdk';

export default () => {
    const { Element } = useHookComponent('RTK');

    const [collapsed, update] = useState(Reactium.Toolkit.debug);

    const onCollapse = () => {
        update(true);
        Reactium.Toolkit.unsubscribe('collapse', onCollapse);
    };

    useEffect(() => {
        Reactium.Toolkit.subscribe('collapse', onCollapse);
    }, []);

    return (
        <Element title='Sidebar Watcher'>
            <h2>{collapsed ? 'Collapsed' : 'Expanded'}</h2>
        </Element>
    );
};
```

{% endcode %}
{% endtab %}
{% endtabs %}

There are two ways to unsubscribe from an event.&#x20;

**`unsubscribe(id:String)`**

```jsx
// Subscription ID Method: 

Reactium.Toolkit.subscribe('config', console.log, 'config-change'); 
Reactium.Toolkit.unsubscribe('config-change'); 
```

**`unsubscribe(event:String, callback:Function)`**

```jsx
// Subscription Event/Callback Method: 

Reactium.Toolkit.subscribe('config', console.log);
Reactium.Toolkit.unsubscribe('config', console.log); 
```


