Deploy React with Express server on seenode
Deploy your React single-page app with a Node static server (Express) and SPA fallback on Seenode.
This guide explains how to deploy an existing React single-page application (SPA) served by a minimal Node server (using Express for static + SPA fallback) to seenode.
Prerequisites
Before you begin, ensure you have:
- A seenode account at seenode.com
- Git configured on your machine
- An existing React SPA ready to build (Vite or CRA)
Project Configuration
To deploy your React SPA on seenode, you need a simple Express server to serve your built static files. This server handles SPA routing by returning index.html for all routes.
Install Express
First, install Express in your project root:
npm install expressyarn add expresspnpm add expressbun add expressCreate server.js
Create a server.js file at your project root to serve your built React app:
const express = require("express");const path = require("path");
const app = express();const PORT = 8080; // * Match the Port field in seenodeconst BUILD_DIR = path.join(__dirname, "client", "dist"); // * Vite default output
// * Serve static assets from the build outputapp.use(express.static(BUILD_DIR));
// * SPA fallback: always return index.htmlapp.get("*", (req, res) => { res.sendFile(path.join(BUILD_DIR, "index.html"));});
app.listen(PORT, "0.0.0.0", () => { console.log(`Server running on http://0.0.0.0:${PORT}`);});This server serves your built React app and handles client-side routing by returning index.html for all routes.
Port Configuration
Set the port in server.js to match the Port field you’ll configure in seenode (for example, 8080). On seenode, there is no default container port—traffic is routed to whatever value you set in the Port field.
For more background on how the Port field controls routing on seenode, see Configuring Your Application’s Port.
Package Scripts
Add these scripts to your root package.json:
{ "scripts": { "client:install": "cd client && npm install", "client:build": "cd client && npm run build", "start": "node server.js" }, "dependencies": { "express": "^4.19.2" }}Recommended Project Structure
Directory/your-react-spa-app
- server.js Express static server + SPA fallback
- package.json Root scripts and Express dependency
Directoryclient/ React app (Vite)
- index.html
- package.json
- vite.config.js
Directorysrc/
- main.jsx
- App.jsx
Deploy on seenode
Push to Git
Commit your project and push it to GitHub or GitLab.
Create a Web Service
From the seenode Dashboard, create a new Web Service and connect your repository.
Configure Build & Start
seenode attempts to detect these automatically. Configure:
- Build Command:
npm install && npm run client:install && npm run client:build - Start Command:
node server.js
Set the Port field to
8080(or your chosen value) and ensureserver.jslistens on the same port.- Build Command:
Configure Environment Variables
Add any additional variables your app needs. You do not need to add a
PORTenvironment variable.Deploy
Click Create Web Service and watch logs until your web service is live.
Success
Your React SPA is now accessible via your service’s URL.
:::::tip[Troubleshooting] If your deployment fails, first check the Logs tab in your seenode service dashboard. Build and runtime logs often contain valuable information for diagnosing issues.
Port configuration mismatch
- On seenode, there is no default container port. Ensure your server listens on the port you configured in the Port field.
- Update your
server.jsif needed (for example, changeconst PORT = 8080;to match the Port field). - Seeing a 502 Bad Gateway? Your app may not be listening on the expected port.
Build failures
- Missing
client/distdirectory: Ensure your build command runsclient:buildsuccessfully. Check that Vite builds toclient/dist(verifyvite.config.jsoutput directory). - Build command errors: Check logs for npm install failures. Ensure both root and client
package.jsonfiles are valid JSON. - Client build not found: Verify the build output path in
server.jsmatches your Vite output directory (default isclient/dist).
Runtime issues
- 404 errors on client routes: Ensure the SPA fallback route (
app.get("*", ...)) is placed afterexpress.static()middleware and returnsindex.htmlfor all routes. - Static assets not loading: Verify
BUILD_DIRinserver.jspoints to the correct build output directory. Check that assets are being built toclient/dist. - Server not starting: Check that Express is installed in root
package.jsonand thatserver.jsexists at the repository root.
Monorepo-specific issues
- Multiple lockfiles: If you have
package-lock.jsonin both root andclient/, ensure both are committed to Git. - Nested node_modules: The build process installs dependencies in both root and
client/directories. This is expected behavior for monorepo setups. :::::
Starting from Scratch?
If you don’t have a React SPA project yet:
Option 1: Use our Template (Recommended)
React SPA Template
Deploy a React SPA with Express static server pre-configured for seenode.Option 2: Create from React Docs + seenode Setup
Follow the official React documentation and Vite documentation to create a new project, then follow the Project Configuration steps above to set up the Express server.
Next Steps
Now that your React SPA is deployed, here are some things you might want to do next:
Set up a Custom Domain (Coming Soon)
Configure a custom domain to point to your new web service.Connect to a Database
Instantly scaffold and connect PostgreSQL and MySQL databases