Platform Engineering with Pulumi Episode 2: Build and Deploy a React.js Application
Published: 2022-01-04 13:19:59


## Platform Engineering with Pulumi Episode 2: Build and Deploy a React.js Application

### A guide on how to build the application and deploy it manually.

![](https://cdn-images-1.medium.com/max/NaN/1*PqvYUGoCgCAskeybM-o_GA.png)

In [Chapter 1](https://aws.plainenglish.io/platform-engineering-with-pulumi-episode-1-building-the-aws-landing-zone-with-pulumi-67b559523c78) of this blog (please refer [here](https://aws.plainenglish.io/platform-engineering-with-pulumi-episode-1-building-the-aws-landing-zone-with-pulumi-67b559523c78)) we built an AWS landing zone for our React.js/Node.js application. In this episode, we will build the application and deploy it manually. In the next chapter, we will use GitOps based automated deployment of both the Infrastructure and application code.

The app that we will be building is a very simple web application, that creates and fetches contact details to/from DynamoDB.

In [Chapter 1](https://aws.plainenglish.io/platform-engineering-with-pulumi-episode-1-building-the-aws-landing-zone-with-pulumi-67b559523c78), we already created a DynamoDB with Pulumi. Here is the snippet of the code, that creates the DynamoDB:

![](https://cdn-images-1.medium.com/max/2000/1*lrp6Bz0TsCJppAwLmvz87w.png)

The above Pulumi code in Python creates a table called contacts-table with 2 attributes ContactName and ContactNumber, with other important configurations such as hash_key, secondary_index tags etc.

Now let's build and deploy our application, on the landing zone we created with Pulumi.

### Node API

To access and perform the add and fetchAll operations on the Contacts database, let's build a simple express Node.js application. You can find the source code [here](https://github.com/abvijaykumar/contactlist-blog-app).
>  We could have used Next.js to do both API and App, but I wanted to demonstrate deploying multiple tiers (in a typical tiered web architecture). So please play along 🙏

In this Node.js application, we will expose 2 endpoints:

* /fetchAllContacts: This will connect to DynamoDB and fetch all the contacts and returns as a JSON response

* /addContact: This endpoint accepts the ContactName and ContactNumber as parameters and adds the record to DynamoDB
>  The use case and code is very simple, as our focus is more on the IaC and GitOps, I have kept the application very simple, with no security/login and serious exception and log handling, etc.

Let’s walk through the code quickly:

![](https://cdn-images-1.medium.com/max/2000/1*TD8mRcTHA14GPbiPtJIpoQ.png)

**Line 1–5:** We are importing express, to create the endpoints and cors. For the React.js application to call these endpoints, the URL domains will be different, as the ports are going to be different. So we will need to configure Cross-Origin Resource Sharing.

![](https://cdn-images-1.medium.com/max/2000/1*2a003c8cpkBQpwNmPo3cCQ.png)

**Line 7–11:** In the above code, we are initializing the aws sdk, and setting the default region, and creating a DynamoDB Client object.

![](https://cdn-images-1.medium.com/max/2000/1*D2BBzi8y9cFaozctGeCKLg.png)

**Line 17–28:** We are creating an endpoint /fetchAllContacts using express, and fetching all the records from DynamoDB, using Scan. This fetches all the contacts.

![](https://cdn-images-1.medium.com/max/2832/1*9zbCBdFVGN17b1awQCm2cg.png)

**Line 30–49:** We are extracting the contactName and contactNumber from the request object and adding it to the DynamoDB table.

![](https://cdn-images-1.medium.com/max/2424/1*QEeRo7t42PSATeudVJ4biA.png)

**Line 56–61**: We are then running the Node.js application listening on a port.
>  Please note that in [Episode 1](https://aws.plainenglish.io/platform-engineering-with-pulumi-episode-1-building-the-aws-landing-zone-with-pulumi-67b559523c78), we opened port 80 SecurityGroupIngress. In the recent code, this is edited to open 8081 for the Node.js applicaton and 8082 for the React.js one. Please refer to the latest Pulumi code on[ my GitHub](https://github.com/abvijaykumar/contactlist-blog-infra).

To run the application we will have to install the dependencies and update the package.json, here are the commands:

    npm install aws-sdk --save

    npm install cors --save

    npm install express --save

![](https://cdn-images-1.medium.com/max/2000/1*NGuUOVe4_njN5YkMmP4MoQ.png)
>  The application can be tested from the local machine by configuring AWS using aws configure and pointing it to your account, and running the Node.js application. This is not covered in the blog (to keep the blog short).

Once the application is tested, the application code can be copied to the EC2 instance by running the scp command. Here are the commands, that I executed to copy the relevant files:

    scp -i rsa /Users/vijaykumarab/AB-Home/Developer/contactlist-blog/contactlist-blog-app/package.json ec2-user@3.235.60.38:/home/ec2-user/api/package.json

    scp -i rsa /Users/vijaykumarab/AB-Home/Developer/contactlist-blog/contactlist-blog-app/index.js ec2-user@3.235.60.38:/home/ec2-user/api/index.js

To run the application on EC2, log in to the EC2 and run npm install to install dependencies, and run the node app (node index.js) to test if the APIs are working.
>  Ensure that the right ports are opened. I used export PORT=8081, before I run the node index.js and updated my Pulumi code to open that port. Please refer to the latest code on [my GitHub](https://github.com/abvijaykumar/contactlist-blog-infra).

Now that we have the API running. Let's build a simple React.js application to access this API, and display the results.

### ReactJS App

In the ReactJS app, we are building a simple SPA (Single Page Application). You can refer to the complete code on [my GitHub](https://github.com/abvijaykumar/contactlist-blog-infra). Let's quickly walk you through the application code.
>  To keep it simple, I am using Material UI (my personal preference is Tailwind CSS).

![](https://cdn-images-1.medium.com/max/2948/1*INxftrFIHoCG_EH0W6ToYg.png)

**Line 11–17**: In the above code, we are using useEffect() to fetch all the records from DynamoDB, and when the records are fetched, calling the setContacts, to refresh the page to force a render, using useState() hook.

![](https://cdn-images-1.medium.com/max/2244/1*VjHow5rUNT330bLW2y1atA.png)

**Line 59–73**: In the above code, we are defining a JavaScript Method to add a contact. This picks the values provided in the form (the code is below) and calls theaddContact endpoint to add the contact. It then refreshes the page (There are better ways to refresh the page. But to keep the code quick and simple, I am using location.reload(), which is not a good practice. Ideally, we should be using a state)

![](https://cdn-images-1.medium.com/max/2628/1*VyVozR7vEcuS_fILXm04Ew.png)

**Line 78–95**: In the above code, we are rendering the fetches contacts as a table.

![](https://cdn-images-1.medium.com/max/3468/1*QHkaDY2SYQdnBswTj5cACQ.png)

**Line 96–115**: In the above code, we are rendering a form, that accepts Contact Name and Contact Number, and calls the addContact() method.

To deploy the code, let's copy the React.js code using SCP. The following are the commands, I executed:

    scp -i rsa -r /Users/vijaykumarab/AB-Home/Developer/contactlist-blog/contactlist-blog-react-app/src ec2-user@54.85.92.194:/home/ec2-user/contacts-app/src

    scp -i rsa -r /Users/vijaykumarab/AB-Home/Developer/contactlist-blog/contactlist-blog-react-app/public ec2-user@54.85.92.194:/home/ec2-user/contacts-app

    scp -i rsa -r /Users/vijaykumarab/AB-Home/Developer/contactlist-blog/contactlist-blog-react-app/package.json ec2-user@54.85.92.194:/home/ec2-user/contacts-app

Before we build the application, let's install nvm, pm2 and serve.

Login to EC2.

And execute the following command to install nvm (please refer to the latest documentation on nvm):

    curl -o- [https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh](https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh) | bash

    . ~/.nvm/nvm.sh

Execute nvm install nodeto install node. To check if the node is installed, run node --version.

To install pm2 and serve execute the following commands:

    sudo npm install -g pm2

    sudo npm install -g serve

Once all the packages are installed successfully, let's install the application dependencies, and build our React.js app, by executing the following commands:

    cd contacts-app

    npm install

    npm run build
>  I faced a strange problem when I try to run the npm run build. I was getting Error: error:0308010C:digital envelope routines::unsupported
>  I found the workdaround from ([https://stackoverflow.com/questions/69692842/error-message-error0308010cdigital-envelope-routinesunsupported](https://stackoverflow.com/questions/69692842/error-message-error0308010cdigital-envelope-routinesunsupported)). Thanks to Peter Mortensen

![](https://cdn-images-1.medium.com/max/2000/1*eqRbeiOYgwfHCuzKvrz-4w.png)

The above screenshot shows the code compile. Let’s now run the application using pm2, by running the following commands:

    pm2 serve build/ 8082 — name “contactlist-app” — spa

To check if our application is running let's run pm2 list.

![](https://cdn-images-1.medium.com/max/2132/1*HOZv-5CZ_ioQF28K-u0P_g.png)

Let's now go to the browser and check if the application is running. Following is the screenshot I got on my browser:

![](https://cdn-images-1.medium.com/max/2804/1*FQIONcPmZxY-hIC98qaDNw.png)

As you can see, manual deployment is very painful and messy. In the next chapter, we will automate all of this using GitActions and AWS CodeDeploy, so that when we push any changes to the Git (or do pull requests), the code automatically gets deployed.

You can access the complete source code on my GitHub.

You can find the API code (express code) [here ](https://github.com/abvijaykumar/contactlist-blog-app)and ReactJs app code [here](https://github.com/abvijaykumar/contactlist-blog-react-app)

Hope this was helpful, let’s meet in the next blog…until then stay safe, and have fun, take care.