NextJS, Serverless Framework and Terraform monorepo
Tags: nextjs, terraform, serverless, devops
Published: 2022-02-05 13:09:26

How Wrapper.js combines NextJS, Serverless Framework and Terraform together within one code repository

I recently created a code base called [Wrapper.js](https://github.com/JamesMillerBlog/wrapper.js), which combines NextJS, Serverless Framwork and Terraform within a Monorepo.

After writing a post about the [benefits of using javascript to automate NextJS, Serverless Framework and Terraform Devops processes](https://jamesmiller.blog/combine-terraform-and-serverless-framework/), I wrote this post which will show you how I have put together, in a manner that you can use in your own projects!

---

## What is Wrapper.js and why you should care about it

A TLDR from my [previous blog post](https://jamesmiller.blog/combine-terraform-and-serverless-framework/):


**Full Stack Dynamic Integration**
![NextJS, Serverless Framework and Terraform logos
](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fpdsrgt2wto3pwg4is45.png)
Wrapper.js is a monorepo, that seamlessly and dynamically integrates the [NextJS](https://nextjs.org/), [Serverless Framework](https://www.serverless.com/) and [Terraform](https://www.terraform.io/) together.

Wrapper.JS orchestrates these technologies into one neat solution, which would normally be difficult due to the complexities of each specialism (e.g front end vs back end vs cloud infrastructure).


**Localhost and Cloud Orchestration**
![Explanation of how Wrapper.js orchestrates NextJS, Serverless Framework and Terraform
](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a1vjz94xyrc5nt8u91oa.jpeg)

It orchestrates all technologies through npm commands to:

- run a local dev environment for both front and back ends
- deploy and destroy an environment
- generate environment specific variable files based on aws secrets for NextJS, SLS and Terraform


**Simple Management of Multiple Environments**
![Explanation of how Wrapper.js can be used within a CI/CD pipeline to automate environment deployments dynamically
](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vi5vyvdw69jj8sw2xlxl.png)

It reduces complexity of using these technologies to manage multiple environments within a continous deployment and integration pipeline

---

## How Wrapper.js combines these technologies

Here is a view of the codebase, looking only at the index directories.

Looking at the code base in its most basic form, lets start by looking at the index directory files:

``` 
// index directory files
index.js
bitbucket-pipelines.yml
.env
package.json

// tech stack directories
devops/
backend/
frontend/ 
```

- **index.js:** The nodejs wrapper script, that triggers logic based on the npm command that is executed.
- **bitbucket-pipelines.yml:** The bitbucket config file for continous deployment and integration pipeline
- **.env:** AWS credentials that allow the wrapper script to automate processes that interact with your aws account.
- **package.json:** NPM dependencies that allow the wrapper script to work.


## The Devops Infrastructure

The devops folder enables the wrapper script (the root level index.js) and is also the home of the terraform code.

One of the core concepts of Wrapper.js, is the creation and use of environment variables throughout the stack. This, as well as running a local dev environment and cloud deployment commands, is what the scripts folder enables.

Terraform is configured in this codebase to dynamically generate and manage all cloud resources (apart from lambdas) based on these environment files.

```
index.js
bitbucket-pipelines.yml
.env
package.json
devops
|
└─── continuous-deployment
|   └─── Dockerfile
└─── scripts
|   └─── next.js
|   └─── serverless.js
|   └─── terraform.js
|   └─── utils.js
└─── terraform
    └─── main.tf
    └─── backend.tf
    └─── variables.tf
    └─── terraform.tfvars.json
    └─── modules
         └─── acm
         |    └─── ...
         └─── apiGateway
         |    └─── ...
         └─── cloudfront
         |    └─── ...
         └─── s3
         |    └─── ...
         └─── ...
backend/
frontend/
```
When opening the devops folder, you see where a lot of the magic happens:

- **continuous-deployment:** Contains a Dockerfile for the configuration of the ci/cd server that enables the bitbucket pipeline.
- **scripts:** A folder that contains helper functions to automate deployment and development processes.
- **terraform:** A folder that contains all infrastructure as code Terraform configurations necessary to deploy the cloud services.

---

## The Backend Services

The backend folder contains all the backend logic that is deployed to an environment’s API gateway.

Unlike Terraform, which is being used to create all architectural cloud resources, [Serverless Framework is being used to deploy lambda functions only](https://jamesmiller.blog/why-you-should-learn-serverless-framework/).

This means that within Wrapper.js, Terraform is creating a blank ApiGateway and Serverless Framework is modifying that API Gateway with end points that trigger lambda’s — further details on what is deployed in Terraform vs Serverless [can be found here](https://jamesmiller.blog/combine-terraform-and-serverless-framework/).

Back end code is organised into backend services, each service contains lambda functions based on the business logic that needs to be be performed.

```
index.js
bitbucket-pipelines.yml
.env
package.json
devops/
backend
|
└─── index.js
└─── utils.js
└─── serverless.common.yml
└─── serverless.env.json
└─── package.json
└─── services
     └─── serviceOne
     |    └─── serverless.yml
     |    └─── package.json
     |    └─── lambdaOne
     |    |     └─ lambdaOne.yml
     |    |     └─ lambdaOne.js
     |    └─── lambdaTwo
     |          └─ lambdaTwo.yml
     |          └─ lambdaTwo.js
     |
     └─── serviceTwo
          └─── ...
frontend/
```

Opening the backend folder, shows you how the backend is managed:

- **index.js:** A script to orchestrate the local host development, cloud deployment and removal of multiple Serverless Framework services through npm commands.
- **utils.js:** A file containing helper functions that enables the index.js script.
- **serverless.common.yml:** A YAML file containing configurations that are shared across all services, these depend on variables that are retrieved from serverless.env.json.
- **serverless.env.json:** A file that is dynamically created by the wrapper script, which contains environment specific variables that will feed into the back end services.
- **package.json:** A file that contains all the npm dependencies to run the index.js file.
- **services/:** The Services directory contains each backend service as a directory.

---

## The Frontend Application

Last but not least, the front end folder contains the front end application which is written with ReactJS and uses NextJS as a framework for structuring the codebase.

```
index.js
bitbucket-pipelines.yml
.env
package.json
devops/
backend/
frontend
|
└─── .next
└─── .babelrc
└─── components
|    └─── ...
└─── pages
|    └─── ...
└─── public
|    └─── ...
└─── stores
|    └─── ...
└─── next.config.js
└─── package.json
```

The frontend folder is essentially a standard NextJS application, made up of:

- **.next:** Standard NextJS directory that contains dev and build configurations.
- **.babelrc:** Standard Babel file that contains all dev configurations for ES6 transpiling settings.
- **components/:** A folder that contains ReactJS components.
- **pages/:** A folder that contains special ReactJS components, which render as pages if placed within this folder — this is a special NextJS feature.
- **public/:** A folder that contains all assets (e.g images and videos etc) for the front end.
stores/: A folder containing global state stores that are created using Zustand.
- **next.config.js:** A file that is dynamically generated by the wrapper script, which contains all environment specific variables for the front end.
- **package.json:** A file that contains all npm dependencies and commands required to run the frontend.

---

## In conclusion

This post has detailed Wrapper.js’s approach to how it practically structures the technologies in the same codebase.

I hope this has been helpful and that someone out there is able to use this (or parts of this) to help them!!

Hope this was fun to read — enjoy automating :D