Building a SaaS Product - (1) Setting Up the Project (Angular, Express.js)
Tags: saas, angular, express, node
Published: 2021-03-18 04:42:01

For the past several months, I have been developing a SaaS product. This is my first post in a series to show you how to build your own product and deploy it to AWS. We will be creating an Angular frontend, Express.js backend, and using DynamoDb database. I will show you how to use Docker to containerize each component, and then deploying it on AWS. This post will show you how to set up a modular codebase and scaffold all the necessary components. 

Buckle up!

**TLDR** - Here is a link to my [Github](https://github.com/fourgates/blog-saas-starter.git) with the given code. 
## Twelve-Factor App
We will be following the [Twelve-Factor App](https://12factor.net) methodology. This is a framework to help you build software-as-a-service (SaaS). In setting up this project, we will be demonstrating the first two principles, Codebase and Dependencies. Our codebase will be tracked in source control and each component will be able to be developed, built, and deployed independently. 

## Frontend - Angular 
In my [previous blog post](https://pninan.hashnode.dev/how-to-containerize-an-angular-app), I wrote about how to containerize an Angular application. We will use that tutorial as a starter for this frontend.

```
# clone my git repo
git clone https://github.com/fourgates/blog-docker-angular-container-intro.git
# rename the folder to webapp
mv blog-docker-angular-container-intro webapp
cd webapp
# build the docker image
docker-compose build node
# remove my git repo
rm -fr .git
```

## Backend - Express.js
In another [separate previous blog post](https://pninan.hashnode.dev/how-to-containerize-expressjs), I showed you how to containerize an Express.js application. We will use that tutorial as a starter for the backend. 

```
# clone my git repo
git clone https://github.com/fourgates/blog-express-ts-docker.git
# rename the folder to api
mv blog-express-ts-docker api
cd api
# build the docker image
docker-compose build
# remove my git repo
rm -fr .git
```

## Database - DynamoDb
I third [previous blog post](https://pninan.hashnode.dev/how-to-containerize-dynamodb), I taught you how to containerize a DynamoDb database. We will use that tutorial as a starter for the development database. We will modify the Express API `docker-compose.yml` file.

```
version: '3.7'

services:
  express:
    build:
      context: .
      dockerfile: Dockerfile  
    image: express/builder:0.0.1
    container_name: express-container
    ports:
      - '8080:8080'
    volumes:
      - ./src:/usr/src/app/src 
    command: npm run start
  ddb:
    container_name: dynamodb-container
    image: amazon/dynamodb-local
    ports:
      - "8000:8000"
    volumes:
      - dynamodata:/home/dynamodblocal
    command: "-jar DynamoDBLocal.jar -sharedDb -dbPath ."
volumes:
  dynamodata: {}    
```
A couple of notes on this structure:

- `webapp` - this is where the Angular frontend code is
- `api` - this will be for the Express.js backend

## Start Your App!
Once you have all of your docker images created you should be ready to start each component! You can open three terminals and run `docker-compose up dev` in each components folder (webapp, api). Or you can use the `-d` (disconnect) flag to use a single terminal to run all three commands

> Pro Tip - I love [VS Code](https://code.visualstudio.com/download)! I usually open a VS Code instance / window for the frontend and backend (2 total). You can then use the terminal in VS Code to start your container while you develop! This way your code and terminal are all in one place. I also use the VS Code [peacock plugin](https://marketplace.visualstudio.com/items?itemName=johnpapa.vscode-peacock) to give a different color to each window.


![Screen Shot 2021-02-02 at 10.43.41 PM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1612323954821/wCflChZ5V.png)

## Git Init
Optionally but highly recommended,  navigate to the root directory and initialized a new git repo. Run the following commands in the root directory (the parent folder of `api`, `db`, and `webapp`). You will first need to create a new git repo. [Github](https://github.com) is a great place to get started!
```
echo "# My SaaS Product" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin YOUR_GIT_REPO
git push -u origin main
```

## Twelve-Factor App - Codebase
We have successfully implemented the [first principle](https://12factor.net/codebase) of the Twelve-Factor App, `Codebase`.  This principle states that you should have one codebase tracked in source control. If you have more than one codebase this is typically no longer considered a single app, but a distributed system. There is nothing wrong with a distributed system but when you are first building a SaaS product you want to keep things simple and allow a developer to check out one codebase and get started ASAP. As your product grows you may find a use case for additional codebases. 

## Twelve-Factor App - Dependencies
The [second principle](https://12factor.net/dependencies) of the Twelve-Factor App is `Dependencies`. This principle says that an app should never rely on the implied existence of system-wide packages. If the frontend and backend are deployed in two different environments this may break your system. You should be able to check out the codebase, utilize a dependency manager, and get started! We are using a mix of Node Package Manager (`npm`) and Docker. Both of these tools explicitly document the dependencies for each component of our SaaS product. NPM uses `package.json` to document the dependencies for our node components. Our `Dockerfile` describes how our Docker images should be built. Each component can be developed, built, and deployed independently. 

## Conclusion!
That's it! If you run `docker-compose up` in each folder you will have successfully set up three components in our stack! Congrats!  

## Code
Here is a link to my [Github](https://github.com/fourgates/blog-saas-starter.git) with the given code.