Deployment Guide
Deploy your React/Vite static site to Dokku and connect it to the Users API.
Overview
This guide covers:
- Preparing your project for Dokku deployment
- Setting up Dokku app
- Building and deploying your static site
- Configuring nginx for SPA routing
Prerequisites
- Dokku instance with SSH access
- Git repository for your project
- Users API configuration already set in
src/config/users.ts(hardcoded production values)
Step 1: Prepare Your Project
Package.json Scripts
Ensure your package.json has these scripts:
{
"scripts": {
"dev": "vite",
"build": "vite build",
"start": "npx serve -s dist -l $PORT",
"preview": "vite preview"
}
}
Key points:
build: Creates production build indist/directorystart: Serves the static site (uses$PORTfor Dokku compatibility)- Uses
npx servefor minimal runtime (no Node.js needed after build)
Create Procfile
Create a Procfile in your project root:
web: npm run start
This tells Dokku how to run your app.
Create Dockerfile (Optional but Recommended)
For a smaller runtime image (nginx-only, no Node.js), create a multi-stage Dockerfile:
# ---- build stage ----
FROM node:20-alpine AS build
WORKDIR /app
# Enable pnpm (if using pnpm)
RUN corepack enable
# Copy manifests first for better caching
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
# Copy source and build
COPY . .
RUN pnpm build
# ---- runtime stage (no node) ----
FROM nginxinc/nginx-unprivileged:1.27-alpine AS runtime
EXPOSE 8080
# SPA routing configuration
COPY nginx/default.conf /etc/nginx/conf.d/default.conf
# Copy built static files
COPY --from=build /app/dist /usr/share/nginx/html
Note: If using npm instead of pnpm, adjust the Dockerfile accordingly.
Create Nginx Configuration
Create nginx/default.conf:
server {
listen 8080;
server_name _;
root /usr/share/nginx/html;
index index.html;
# Cache Vite hashed assets aggressively
location /assets/ {
expires 1y;
add_header Cache-Control "public, immutable";
try_files $uri =404;
}
# SPA fallback: serve index.html for all routes
location / {
try_files $uri $uri/ /index.html;
}
}
Important: The port must be 8080 for Dokku compatibility.
Verify Configuration
Ensure your src/config/users.ts has production values hardcoded:
export const USERS_API_BASE_URL =
import.meta.env.VITE_USERS_API_BASE_URL || "https://users-api.brainylab.io";
export const USERS_APP_ID = "my-app-id";
Note: No environment variables needed in production - values are hardcoded in the config file.
Step 2: Configure Dokku App
Create Dokku App
SSH into your Dokku host and create the app:
dokku apps:create my-static-app
Configure Port (if using Procfile)
Dokku automatically sets PORT, but ensure your start script uses it:
{
"scripts": {
"start": "npx serve -s dist -l $PORT"
}
}
Step 3: Deploy
Add Dokku Remote
Add Dokku as a git remote:
git remote add dokku dokku@YOUR_DOKKU_HOST:my-static-app
Replace YOUR_DOKKU_HOST with your Dokku server's hostname or IP.
Deploy
Push to Dokku:
git push dokku main
Or if your default branch is master:
git push dokku master
What Happens During Deploy
- Dokku detects your
Dockerfile(if present) or uses buildpacks - Builds your app (
npm install+npm run build) - Runs your
startscript or serves via nginx (if using Dockerfile) - App becomes available at
http://my-static-app.your-domain.com
Step 4: Verify Deployment
Check App Status
dokku ps:report my-static-app
View Logs
dokku logs my-static-app
Test Your Site
Visit your app URL and verify:
- Site loads correctly
- Form submission works
- API calls succeed (check browser console)
Step 5: Update Configuration
If you need to change the API URL or App ID:
- Update
src/config/users.tswith new values - Commit and push changes:
git add src/config/users.ts
git commit -m "Update API configuration"
git push dokku main
Note: Configuration is hardcoded in the source code, so changes require a new deployment.
Alternative: Using Buildpacks (Simpler)
If you prefer not to use Docker:
1. Remove Dockerfile
Dokku will use Node.js buildpacks automatically.
2. Ensure package.json has build script
{
"scripts": {
"build": "vite build",
"start": "npx serve -s dist -l $PORT"
}
}
3. Deploy
git push dokku main
Dokku will:
- Detect Node.js project
- Run
npm install - Run
npm run build(ifheroku-postbuildscript exists, or manually) - Run
npm startvia Procfile
4. Add Build Script (Optional)
To ensure build runs automatically, add to package.json:
{
"scripts": {
"heroku-postbuild": "npm run build"
}
}
Troubleshooting
Build Fails
Check logs:
dokku logs my-static-app -t
Common issues:
- Build script errors
- Dependency installation failures
- Configuration errors in
src/config/users.ts
App Won't Start
Check process status:
dokku ps:report my-static-app
Common issues:
- Port conflicts
- Missing
startscript - Procfile syntax errors
API Connection Issues
Verify configuration:
- Check
src/config/users.tshas correct production API URL - Ensure
USERS_APP_IDmatches your app identifier - For local testing, create
.envfile withVITE_USERS_API_BASE_URLoverride
SPA Routing Not Working
If using nginx Dockerfile, ensure nginx/default.conf has the SPA fallback:
location / {
try_files $uri $uri/ /index.html;
}
If using serve, it should handle SPA routing automatically with -s flag.
CORS Errors
Ensure your Users API has your Dokku domain in CORS_ORIGINS:
# On Users API instance
dokku config:set users-api \
CORS_ORIGINS=https://my-static-app.your-domain.com
Best Practices
1. Use Dockerfile for Smaller Images
The nginx-based Dockerfile produces smaller runtime images (~50MB vs ~200MB+ with Node.js).
2. Verify Configuration Before Deploy
Ensure src/config/users.ts has correct production values before deploying.
3. Use Git Tags for Releases
Tag releases for easier rollbacks:
git tag v1.0.0
git push dokku v1.0.0
4. Monitor Logs
Regularly check logs for errors:
dokku logs my-static-app -t
5. Test Locally First
Build and test locally before deploying:
npm run build
npm run start
# Visit http://localhost:3000
Example: Complete Project Structure
my-static-app/
├── .env.example
├── .gitignore
├── Dockerfile # Optional: for nginx runtime
├── Procfile # Required: for Dokku
├── nginx/
│ └── default.conf # Required if using Dockerfile
├── package.json
├── pnpm-lock.yaml # or package-lock.json
├── src/
│ ├── components/
│ ├── config/
│ │ └── users.ts
│ ├── lib/
│ │ └── api.ts
│ └── App.tsx
├── index.html
└── vite.config.ts
Next Steps
- React/Vite Integration - Complete integration guide
- API Reference - Complete API documentation