# Beta releasing new features on your react application

I'm going to share how you can easily enable beta testing or conditional access to new features to a closed user group on your react application, if it is based on create-react-app.

We're going to create a demo application with create-react-app, and use a mock API to simulate different users. Then we'll see that how we can have a default experience for a category of users, and an upgraded experience for a new category of users.

Of course there are several ways of doing this, one of them being making your routes conditional, but this way, its incredibly simple, and does not involve making lots of `if-else` Condition in your code. 

In this method, we're going to _change the path where the assets are deployed_ and have a common index.html which will have the conditions to fetch the assets from respective directory.

So, yeah lets get started. 

### Step 1: 
#### Create a react app with CRA boilerplate

```javascript
npx create-react-app beta-testing-demo
cd beta-testing-demo
npm start

```
At this stage you'll be able to see the default create-react-app starting up in your browser and you'll see the homepage with a spinning react icon. 

Now this is going to be our baseline app, so **lets assume that all your users see this version of the application, but you want to make some changes to this application, and deploy it, such that only a few chosen users gets to see the updated application**

### Step 2: 
#### Set the build and deploy configurations
Lets create an `.env` file and put the following in it. 
> If you need to know more about .env configurations in CRA, see [here](https://create-react-app.dev/docs/advanced-configuration)

```
#It is assumed that the project files will be served from [domain]/default location
PUBLIC_URL=/default

#after build the project files will be located at [project-root]/build/default/ directory
BUILD_PATH=./build/default
```
### Step 3: 
#### Run and verify

Run the build and see if it can be run properly
```bash
$ npm run build
$ cd build/
$ npx serve .

   ┌────────────────────────────────────────────────────┐
   │                                                    │
   │   Serving!                                         │
   │                                                    │
   │   - Local:            http://localhost:3000        │
   │   - On Your Network:  http://x.x.x.x:3000          │
   │                                                    │
   │   Copied local address to clipboard!               │
   │                                                    │
   └────────────────────────────────────────────────────┘

```
Open `localhost:3000` on your browser and navigate to localhost:3000/default, and you'll see the default create react app boilerplate running. 

> At this point of time, we have the default application ready and assuming all your customers are using this. We'll now make some code changes to create a version2.

### Step 4:
#### Create the beta version

Let's open the code in vscode and make some CSS change. We'll keep the changes to a minimum, just visually identifiable. 

Open `App.css` and change the following
```css
.App-header {
  background-color: #282c34; //Change this to #fff
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: calc(10px + 2vmin);
  color: white; // Change this to #222
}

.App-link {
  color: #61dafb; // Change this to #555
}
```

Run `npm start` to see the changes appear in the browser.

Now before you deploy this, you need to make changes to your `env` file

Change `default` to `beta`
```
#It is assumed that the project files will be served from [domain]/default location
PUBLIC_URL=/beta

#after build the project files will be located at [project-root]/build/default/ directory
BUILD_PATH=./build/beta
```
Save this.

Now run the following on your console to build your app and see the compiled code on your browser

```bash
$ npm run build
$ cd build/
$ npx serve .

   ┌────────────────────────────────────────────────────┐
   │                                                    │
   │   Serving!                                         │
   │                                                    │
   │   - Local:            http://localhost:3000        │
   │   - On Your Network:  http://x.x.x.x:3000          │
   │                                                    │
   │   Copied local address to clipboard!               │
   │                                                    │
   └────────────────────────────────────────────────────┘

```

Open browser and navigate to `localhost:3000/beta` and you'll see the application running with changes visible.

### Step 5:
#### Playing with different paths and see if they work fine

Let's _assume_ that your `./build` directory is the one that gets deployed. 
Now you have the old version of the application in `/default` and new version of the application in `/beta`

Now copy the index.html from `./build/default` and place in its parent, `./build`.
and then run `serve` again
```bash
$ cp ./default/index.html ./
$ serve .
```
Open `localhost:3000` on your browser and you'll see the old version running.

now, if you replace this html from the html of the `./build/beta` you'll see the beta version running on your browser. 

We, therefore, **need a strategy to change the HTML content based on the users**. For normal it will serve from `/default`, but for few privileged people it will serve from `/beta`

---

### Step 6:
#### Changing the HTML dynamically

Changing this HTML can be done in many ways.
1. If your html is server side rendered, like using a CMS or using express templates etc, it can be dynamically manipulated before rendering. 
2. You can do redirection from the previous page, eg. in your login page after successful authentication if the user is eligible for beta, redirect to /beta or else redirect to /default
3. You can make an API request from your HTML to find out the user category and based on that load script and css dynamically from the respective paths. This, makes it slow though. 

I'll let you figure out the best strategy for your project. 

### PS:
If you're using push state based routing like BrowserRouter from react-router, you need to be really cautious about the paths from where you're serving it.  

Thanks.
