Creating a Dynamic Starter Kit for React Native - React Native Infinity
Tags: reactnative, showdev, react
Published: 2019-10-03 16:24:00

![React Native Infinity](https://thepracticaldev.s3.amazonaws.com/i/u3fcabx8ff4x8wasqoip.gif)

Popular libraries (UI, navigation, _etc_.) and frameworks often provide example projects for educating new users on basic configuration. Some even provide full starter projects to ease initial project setup. However, since modern apps generally require a combination of these libraries, developers are forced to manually configure different types of libraries together.

Starter kits are the obvious next evolutionary step, as they come pre-configured with many popular libraries (react-slingshot, _e.g._). However, unless the included libraries match exactly what a new project requires, developers will need to spend time replacing and adding configuration they need. Additionally, actively maintaining starter kits that cover all possible combinations is simply not feasible.

Available starter kits for rendering React Native on different platforms nicely illustrates this problem. Most [out-of-tree](https://facebook.github.io/react-native/docs/out-of-tree-platforms) starter kits only target the web ([create-a-react-native-web-app](https://www.npmjs.com/package/create-react-native-web-app), [react-native-web-monorepo](https://github.com/brunolemos/react-native-web-monorepo)) leaving other platforms out. Other starters target all platforms ([react-everywhere](https://github.com/react-everywhere/re-start)), requiring developers to manually remove what they don't need.

The problem lies with treating configuration as a static, integrated whole rather than as dynamic, isolated, and individual plugins. Making this switch allows developers to dynamically choose pre-configured libraries, in essence, creating their own starter kits. 

In the case of React Native, isolating platform configuration allows developers to dynamically choose what platforms their app supports both during and after project initialization. React Native Infinity is a small, experimental CLI with this goal in mind. Implementing this is surprisingly simple since React Native already isolates platform configuration for Android and iOS. 

### Isolating Configuration

![RN Folders](https://thepracticaldev.s3.amazonaws.com/i/i41f7rb3y3a7v3eqlnm0.png)

Broadly speaking, React Native's structure can be broken into three main parts: `core`, `platform configuration`, and the actual `app code`.

**Core** - Configuration and files that apply across the whole project, for example `package.json`, `index.js`, and `app.json`.

**Platform Configuration** - Configuration for rendering and building the app on a specific platform.

**App Code** - Business logic, UI, and everything else that lives in `src`.

Out of the box React Native provides Platform Configuration for Android and iOS in their respective folders: `android` and `ios`. React Native Infinity simply takes this structure and applies it to new platforms by isolating configuration for out-of-tree renders into new `platform configuration` folders.

For example, `react-native-web` requires configuration (`webpack.config.js`), platform files (`index.html`), and dependencies (`react-dom`) that are specific to rendering React Native on the web but are not required for Android, iOS, MacOS, or Windows. Configuration and platform files can easily go into a separate folder, but `core` configuration (dependencies, _e.g._), should go in shared files (`package.json`) at the project root.

Adding support for more platforms to React Native, then, is a simple process:

1. Identify and isolate the bare essential configuration for each platform.
2. Identify core files and changes required for each platform.
3. Bundle all platform configuration into a separate folders.
4. Merge shared core configuration.

This process can be expanded beyond platforms to other React Native libraries, such as navigation, state management, and UI libraries. A simple example is implemented in React Native Infinity with two UI Libraries: Material Bread and UI Kitten.

The last step, after all configuration has been isolated and merge functions created, is to build a simple CLI that asks users what platforms and libraries they want to add.

## React Native Infinity CLI

React Native Infinity CLI generates React Native projects that target any combination of platforms (Mobile, Web, Electron, Windows, and MacOS). Platforms can also be added later on with the `add-platform` command. Finally, two UI libraries can be added at initialization. Built with Commander.js and Enquirer.js.

[Github](https://github.com/codypearce/react-native-infinity) 

```
npm i -g react-native-infinity
```

Note: This is an experiment in the early stages, if you find a bug, please consider contributing with an issue or PR.

### Init

Command to initializes a new project with a series of questions.

```
npx react-native-infinity init
```
![React Native Infinity init](https://thepracticaldev.s3.amazonaws.com/i/fqd1qks9dt84x57j2xli.gif)

### Add-Platform

Command to add platform configuration to an existing project. Platforms are provided as lowercase, simple strings.

```
npx react-native-infinity add-platform <platform>
```

![Add platform](https://thepracticaldev.s3.amazonaws.com/i/fh85flkxf628g2awmvlt.gif)


![React Native Infinity ](https://thepracticaldev.s3.amazonaws.com/i/ejs3xdib9wrf96qpfyxq.png)

Please visit the [docs](https://github.com/codypearce/react-native-infinity) for more information.