Fullstack Express-React App With TypeScript

The definitive guide including CI tests in Travis and deployment to Heroku. TL;DR sneak peek the source! 👀

Join this journey into deep space to explore marvelous possibilities, far and beyond.

In this story we’ll build a Fullstack application with Express and Mongo in the backend and React in the frontend, both sides developed in TypeScript. We’ll have 100% test coverage with Jest including CI tests in Travis and deployment to Heroku. Pretty bold, huh?

The motivation for creating this starter kit and writing this story was the lack of a definitive guide to put everything together and help me get a hang of this whole end-to-end process, so I’ve decided to join the bits and pieces.

The setup

Important note to adventurers: make sure you’re using node 8 (or greater). Throughout this series we’ll be using yarn, but you can try to stick to regular npm if you wish. Last but not least, make sure you have MongoDB (community edition will do) installed and set up.

1. Clone the repo

Clone the repo from here to your favorite folder and we’ll walk through the set up step by step.

$ git clone https://github.com/Fabianopb/express-react-ts-ci.git

2. Run Mongo locally

First of all run your local instance of Mongo! This is important so the script to populate the database with sample data can connect to Mongo. In my case I have created a data directory in /data/test/ (running $ mkdir /data/test/ for example) so the command to start it can be simply:

$ sudo mongod --dbpath /data/test/ --port 27017

I suggest you to use the same directory (/data/test/, that is) because I’ve included a script to run that command above in the root package.json so I don’t have to remember it all the time. If you have the directory /data/test/ you could simply run $ yarn start:db. Notice that this is a sudo command, so it will ask for your admin password.

3. Install dependencies

Now you can open a new terminal tab and install all the dependencies for the project. By doing so in the root, the script will also install the frontend and backend dependencies and it will create a fresh new build for both as they run yarn build on postinstall for you.

$ yarn install

4. Create the env variables

In the backend folder there’s a file called .env.example. The purpose of that file is to serve as an example for the environment variables that we’ll need for the application. You could keep your environment variables in your bash_profile for example, but keeping them in the application is often easier as they are promptly visible to you (and only you as .env is git-ignored). This works because we’re using the package dotenv.

For now you’ll only need a variable for user authentication, so create a .env file in that same folder and fill it with, for example:

AUTH_SHARED_SECRET=my-auth-shared-secret-hash-here

5. Start it up

Now you can simply start the application:

$ yarn start

Now the backend and frontend will be fired off concurrently. And we’re up and running! 🎉

If you did everything right you should be seeing this in your browser. Also, your terminal should be clean of errors. Bonus: the database is already populated with sample data in the first install!

There’s a node script configured to populate the database with sample data in case it’s empty (in case you want to check it out take a look at backend/scripts/populateDatabase.js). Now simply log in with the sample credentials and hit the button “Get test data” to see this:

Log into the application and hit “Get test data” to see this example.

I recommend you use something like Robo 3T as an interface to visualize your Mongo databases locally.

With everything up and running, it’s time for…

Continuous integration and deployment

Oh the so-called (and many times feared) CI/CD. Let’s engage and get full speed into deep space… 🚀

6. Travis CI

What is Travis? It’s a CI tool with easy set up, highly configurable, and integrable with many languages — and it’s free for open source projects.

So wait no more, go to https://travis-ci.com/ and sign up using your GitHub account (then check in settings if you’re allowing Travis to access your repos). Now take a look at the file .travis.yml in the root of the project which is the secret spicy that makes Travis work:

Seriously, that’s it! This is saying “Hey Travis, this is a project in JavaScript (with Node.js) and I want you to use Node 8. Oh, and when you’re building and testing, please use these environment variables”.

Now create a new repo in GitHub, remove the current remote origin (because that points to my repo), add yours, push, and the magic happens. ✨

// remove the current remote origin (that was linked to my repo)
$ git remote rm origin
// add your new remote (use your path here)
$ git remote add origin git@github.com:[you]/[your-repo].git
// push to your repo!
$ git push -u origin master

Now hurry back to Travis!!! You should see the application building and running all the tests, and of course, they should pass. If nothing has been triggered in Travis, you most likely have to go to your account’s settings and check if you have granted access to your repos. In that case you can change the configuration and push anything else for it to work.

An example of the continuous integration process in progress with Travis!

7. Heroku

What is Heroku? It’s “a platform as a service (PaaS) that enables developers to build, run, and operate applications entirely in the cloud” — important to say again, there’s a free tier which is the one we’ll use.

So let’s launch this up in the sky.

Go to https://www.heroku.com/, create your account, and install the CLI tools.

Next step is to create a new app for example using the menu on the top after you log in to your account. Then just give your app a name and choose a region.

Menu for creating a new app in Heroku.

After creating the app you can go to the “Deployment” tab and chose “GitHub” as your Deployment method. Then you can search the repo to which you’ve pushed your app and hit the “connect” button. Now make sure you check the box “Wait for CI to pass before deploy”, which will make sure that the deployment process in GitHub will be triggered only after Travis has tested your application. 😳 (yeah, I know the feeling). Finally hit “Enable Automatic Deploys”.

“Deploy” tab settings for your application in Heroku.

Now let’s set up your database in the cloud. Go to the “Resources” tab and type “mlab” in the add-ons search box. You’ll see “mLab MongoDB”, yes that’s the one we want, don’t worry, the sandbox version is free. Click on it.

A Modal will open where you can choose the options to provision mLab MongoDB, keep it in the Sandbox and accept. This will already configure the database URI as an environment variable for you, pretty smart!

Modal with the options to provision mLab MongoDB in Heroku.

We’re almost there! Now go to the “Settings” tab and click on “Reveal Config Vars”. You’ll probably see that there’s already a var called MONGO_URI which is the access path to your database in the cloud (don’t touch it!). Now I need you to add two more variables: AUTH_SHARED_SECRET with a password (this is for the user authentication, remember? It can be different than the one you had locally), and NPM_CONFIG_PRODUCTION with the value false which will enable devDependencies to be installed and our application to be fully built and served from the optimized build. Your should have something like this:

Config Vars in your app settings in Heroku. MONGO_URI should have been auto generated when you provisioned mLab, so don’t touch it!

Now back to the source code, notice that we have a file called Procfile in the root of our application with the following information:

This is as necessary for Heroku as .travis.yml is necessary for Travis. So it will tell Heroku what to do after the deployment has succeeded. And if you check the root package.json you’ll see that this script simply runs our server from the optimized build.

Now make any simple change in the application, commit and push! What change? I dunno, write your name in App.tsx for example, the sky is the limit!

After you push, you’ll can go to Travis and see it in action again! 🤖 Nice! 100% coverage in our continuous integration!

The final output in Travis showing that all tests succeeded and we have a test coverage of 100%!

Right after Travis finishes, Heroku will enter in action! 🚀 Go to the “Activity” tab and you’ll see the latest log saying that you have a build in progress. Click on “view log output” and wait until the job is done to see the following:

Final output in Heroku showing that the deployment succeeded. In the detail is the url you should access to see your app up and running!
Yeah, in the end I’ve just added my name to the front page.

Just like in the local instance, the script to populate the database will also run in the cloud if the database is empty. Now you can just enjoy your new fullstack application in Express and React, built with TypeScript, and start creating your own endpoints in the backend and components in the frontend (check some examples in the README.md)!

Bonus: it’s a good idea to share types between your frontend and backend, so both can talk the same language, if you know what I mean. One way to do that is to create a separate @types module in the root of your project and yarn link both with your frontend and backend.


A quick recap on what we did:

  • First of all we have cloned the repo and set up an instance of Mongo running locally.
  • Then we have installed the dependencies, created the necessary environment variables, and started up our local development.
  • Next on the continuous integration, we’ve set up a new GitHub repo and a Travis CI account to work with this application.
  • Finally we’ve created an app in Heroku, provisioned the database, configured the deployment process, and set up the config variables.

The final result was a fullstack application using Express in the backend with Mongo as database, React in the frontend, all written in TypeScript, fully tested in Jest, and with a CI/CD process in Travis CI and Heroku. Phew!

Thank you for reaching up here, and I hope you could learn something new today!

If you like this please clap, follow, and star this repo on Github! 👏 👀 ⭐️