A Complete Guide to Building and Deploying Your Own Website with React, Flask and Heroku

Ade Balogun
Geek Culture
Published in
7 min readOct 25, 2021

--

Photo by Christopher Gower on Unsplash

There’s something magical about putting your work out for other people to see. There’s a sense of deep pride infused with a sense that you can make anything happen — that it’s not too crazy to believe that you can build the next great service, product, idea, or company.

But it’s also easy to feel like you don’t have the knowledge or tools to make that happen . If someone just made the most basic of that sacred knowledge available, you would be off to the races! I felt that way when I first learned how to build web apps. For my first few weeks in the thorns of online resources and tutorials, I found a lot of great resources, but nothing consolidated. I couldn’t find anything that readily gave me space to take the tutorial product in my own direction. I stumbled through a lot of errors and endlessly consulted old StackOverflow threads.

Not to mention that I wanted to build something a little unusual — a React-Flask App. This super-powered holy grail of web development would have a React JS frontend (client) and Flask Python backend (server). Imagine the most powerful JavaScript tool teaming up with the most powerful Python tool (in my opinion) just for you. The possibilities are endless!

This walkthrough will consolidate the dozens of hours I’ve spent searching for how to build a React-Flask app deployed on Heroku. By the end of the walkthrough, you should have something like this (don’t mind the domain name — it’s just a spare that I had lying around). Hopefully, you can use this tutorial to painlessly launch your next great idea!

Getting Started

Flask is a micro-framework for building web apps. Flask has a wide range of applications but today we’ll focus on using it to build the server side of our website. React is a tool for building dynamic user interfaces. It’ll unlock an enormous field of possibilities for developing our website. If you’re already familiar with HTML, it’s incredibly easy to pick up, and if not, there’s great documentation for specific use cases. We’ll use React to power the client side of our website. Our React client will make requests to our Flask server using Fetch API. So let’s start building!

All of the code for the frontend and backend will be available on Github and linked at the end of this tutorial. We’ll spend the rest of the tutorial explaining how those repositories were built.

Building the Flask Side

We’ll start with the Flask side. I created a folder to contain the code for the backend. I entered this folder and created a virtual environment in the folder with the terminal command virtualenv env. This will store the python packages that will power the backend. You can find a list of the requirements in requirements.txt.

Entering the folder and creating an env folder

Flask is configured with a set of environment variables. This is generally kept in a file called .env. You can also use this file to inject other variables into your application. This is incredibly useful for storing API keys and keeping them secret. You do not want to upload your .env, environment folder, or some other cache files to Github. These files either contain sensitive information or are junk for other people trying to run your app. We can use .gitignore to prevent these files from going public.

Next, we’ll build out the structure of the application in a factory design pattern. You can read more about this design pattern here. We’ll use CORS to restrict who can make requests to our server. Flask-CORS is a great resource for accomplishing this task. CORS is really important for building secure web apps. It prevents malicious actors from making calls to your API. This is important for more reasons than we can cover in this walkthrough.

These CORS settings are essential. CORS_ALLOW_ORIGIN must be set to the domain of your client side while CORS_SUPPORTS_CREDENTIALS must be true to accept cookies from the client. More on the importance of cookies to follow.

We’ll configure the settings for our app and CORS in utils/config.py. Furthermore, for our protected route, we’ll request a special session token, provided when the client requests to /get/unprotected. The protected route will be wrapped by a decorator called auth_required. This decorator looks for a session token in the incoming request header. It was inspired by a similar decorator provided by the Flask API documentation which is definitely worth checking out!

Auth_required is a decorator which looks for the ‘sessionToken’ in the request header sent by the client. This is how most apps handle user authentication after login and between requests.

Otherwise, we can see the code for our simple app in routes/main.py.

We will have three routes that are powered by our server: unprotected, protected, and post.

We’re almost done with our Flask server! In the root folder, we’ll create a file called application.py which will produce our app from the factory created in __init__.py. We will also create a Procfile. Heroku will need these in order to host our server. Now for the client side.

Building the React Side

Building the frontend is made simple with the create-react-app package produced by the React team and Facebook. We can use this to quickly spin up a client side, then trim and add where necessary. I did this with npx create-react-app demo-client where demo-client is the name of the folder.

After deleting some unnecessary files from the package, we’ll have a barebones React app. We’ll use some simple styling, contained in index.css, and we’ll install bootstrap with yarn add bootstrapto make this a faster build. We’ll also need react-router-dom to handle our multiple pages and js-cookie to handle cookie settings.

Each of our pages will be represented as components, meeting in App.js. You’ll notice one component for our unprotected page, one for our protected page, one for posting data from the client, and a landing page. These components are built in the functional pattern, and for more information on what is happening in each component, refer to the React JS documentation.

For now, we are just interested in observing how data is sent between our client and server. This is especially important for the protected page, which requires credentials to be sent in the request header.

The session token is received from the server and set using js-cookie. When you build you app, you’ll need to use HTTPS and set a ‘secure: true’. This seems to be a feature of cookies where ‘secure’ cannot be false while ‘samesite’ is ‘none’. Samesite must be ‘none’ for this application structure to work. You can add HTTPS to your Heroku apps by upgrading from the free tier to the hobby tier. I have not done this for the example in this article.
The cookie previously set is pulled from the browser and sent with the request to the server. This only works because the server and client have the same domain: ‘.bomb.fyi’ and both have HTTPS, or SSL certificates.

We’re almost done with our React side! Let’s create an .env file for our React app, so we can inject the address of the server when the app loads. React requires that environmental variables referenced in the app start with ‘REACT_APP_*’. To access this variable in the app we use ‘process.env.REACT_APP_*’ as seen above. Now let’s deploy!

Moving to Heroku

There are plenty of existing resources which cover how to deploy on Heroku. I’ll assume that you already have an account with Heroku, are configured, and know how to push to Heroku.

The key things to know for our project is that we’ll be deploying two Heroku applications: one for our React side and one for our Flask side. Once you’ve deployed these repositories, we’ll go into each of their settings and update their environment variables under the Config Vars tab. You will also need to give each of the Heroku apps their own custom domains for the cookies to work.

Environment variables for the React side, hosted at http://client.bomb.fyi. This is just for demo. Your app will use HTTPS which will allow credential cookies to be sent between the client and server.
Environment variables for the Flask side, hosted at http://server.bomb.fyi. Again, this is just for demo. Your app will use HTTPS while will allow credential cookies to be sent between the client and server.

We’re almost done. For our React app, we’ll also need to use a special buildback called ‘https://buildpack-registry.s3.amazonaws.com/buildpacks/mars/create-react-app.tgz’. You can search for this under the Buildpacks tab in the settings for the React app in Heroku. This buildpack makes it easy to deploy instances of create-react-app on Heroku.

Wrapping Up

If you’ve done everything correctly, you should arrive at a web app like this! Because I don’t have SSL certificates for my client and server, the credential cookies won’t set and the protected page will reject you. I did this to save costs on this demo app :), but your project should have SSL set up for HTTPS!

If your client doesn’t seem to be communicating with your server, you most likely have a cookie problem. You can check to see if the cookie is being set in your browser by looking in the developer tools under ‘Application’, if you’re using Chrome. This React-Flask application structure requires both the client and server to be hosted on the same custom domain with different subdomains and SSL certificates. In your React app, the cookie should be set with samesite=none and secure=true. If you open your developer tools and you don’t see ‘sessionToken’ as one of your cookies, then you can be certain that your browser is rejecting the cookie that React is trying to set. Cookie permissions are difficult, but they are meant to prevent malicious actors from attacking your app.

Hopefully, you found this tutorial helpful and good luck with your next great project!

--

--

Ade Balogun
Geek Culture

Environmental Engineering, Columbia 2020. MSc. Candidate @ Imperial College London.