Fullstack Express-React App With TypeScript
The definitive guide including CI tests in Travis and deployment to Heroku. TL;DR sneak peek the source! 👀
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.
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.
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
$ 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:
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! 🎉
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:
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:
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 firstname.lastname@example.org:[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.
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.
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.
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”.
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!
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:
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!
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:
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! 👏 👀 ⭐️