AlgoInsight

Q&A

How to deploy a React app to Heroku

By AlgoInsight Team2026-06-07cloud-computingfrontendgitherokunodejsreactjavascript

Overview

A React app created with tools like Create React App or Vite is, in production, just static files (HTML/CSS/JS) produced by a build step. Deploying to Heroku means getting Heroku to (1) run that build and (2) serve the resulting files. Because Heroku runs a process per app, the common approach is to serve the build with a minimal server.

graph LR
    A[git push heroku main] --> B[Heroku detects Node app]
    B --> C[Runs npm install + build script]
    C --> D[Runs start script: serve build/]
    D --> E[App live at *.herokuapp.com]
    style A fill:#1e1b4b,color:#fff

Prerequisites

Approach 1: Serve with the serve package (simplest)

Step 1 - add serve and scripts. In package.json:

{
  "scripts": {
    "start": "serve -s build",
    "build": "react-scripts build",
    "heroku-postbuild": "npm run build"
  },
  "dependencies": {
    "serve": "^14.0.0"
  }
}

Step 2 - create and deploy:

heroku create my-react-app
git add .
git commit -m "Prepare for Heroku"
git push heroku main          # triggers build + start
heroku open                   # open the live URL

Approach 2: Express server (more control / API in same app)

Create a small server that serves the build and can also host API routes:

// server.js
const express = require("express");
const path = require("path");
const app = express();

app.use(express.static(path.join(__dirname, "build")));

// SPA fallback: send index.html for any non-file route
app.get("*", (req, res) => {
  res.sendFile(path.join(__dirname, "build", "index.html"));
});

const port = process.env.PORT || 3000;   // Heroku injects PORT
app.listen(port, () => console.log(`Listening on ${port}`));
"scripts": {
  "start": "node server.js",
  "build": "react-scripts build",
  "heroku-postbuild": "npm run build"
}

Critical: bind to process.env.PORT. Heroku assigns the port dynamically; hard-coding a port causes the app to crash on boot.

Approach 3: Static buildpack

For a pure static SPA you can use a static buildpack (e.g. heroku-buildpack-static or a community buildpack) with a static.json describing routing. This serves files via nginx without a Node process - lighter, but less flexible than an Express server.

Environment Variables

React build-time variables (Create React App: prefixed REACT_APP_) must be set as Heroku config vars so they're present during the build:

heroku config:set REACT_APP_API_URL=https://api.example.com

Verifying and Debugging

heroku logs --tail        # watch live logs
heroku ps                 # see running dynos

Common boot failures show up here - usually a missing start script, not binding to $PORT, or a build error.

Why This Matters in Interviews

This ties together build tooling, the PaaS model (Heroku from this batch's Cloud Computing question), and production serving of an SPA. Key points: a React app builds to static files; Heroku needs a start process; you must bind to process.env.PORT; and SPA routing needs an index.html fallback. Knowing heroku-postbuild and config vars shows real deployment experience.

Common Pitfalls

References

More answers