Project: SPA and API Gateway

Introduction

This project runs a single domain with a Vite/React static frontend at / and a Spring Boot or Node API at /api/. Nginx routes by path—the standard production pattern for hello_code full-stack apps.

Prerequisites

Architecture

text
https://app.example.com/
  /           → /var/www/app (SPA)
  /api/...    → proxy → 127.0.0.1:8080

Step 1: Deploy Frontend

bash
sudo mkdir -p /var/www/app
sudo rsync -av ./dist/ /var/www/app/
sudo chown -R www-data:www-data /var/www/app

Step 2: Start Backend on Localhost

Spring Boot:

bash
java -jar app.jar --server.address=127.0.0.1 --server.port=8080

Or Node on 8080—adjust proxy_pass port if using 3000.

Confirm:

bash
curl http://127.0.0.1:8080/api/health

Step 3: Nginx Config

/etc/nginx/sites-available/app:

Code explanation:

  • /api/ strip prefix if backend serves /users not /api/users—match your API design
  • try_files ... /index.html — SPA client routes

Enable and test:

bash
sudo ln -sf /etc/nginx/sites-available/app /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
curl http://app.example.com/api/health
curl -I http://app.example.com/

Step 4: HTTPS

bash
sudo certbot --nginx -d app.example.com

CORS: Backend vs Nginx

ApproachWhen
Backend CORS (@CrossOrigin, Express cors)Same domain /api/ — often no CORS needed
Nginx add_headerSplit domains (api. vs www.) or legacy setups

Same-origin SPA + /api/ avoids browser CORS for fetch to relative /api/....

If API on different subdomain:

nginx
add_header Access-Control-Allow-Origin "https://www.example.com" always;

Prefer configuring CORS in the API for dynamic origins.

Acceptance Checklist

  • SPA loads at /
  • Client route /dashboard refresh works (not 404)
  • curl https://app.example.com/api/... returns JSON
  • No 502 when API running; clear 502 when API stopped (expected)
  • sudo nginx -t clean

FAQ

API 404 through proxy?

Fix proxy_pass trailing slash vs backend context path.

Frontend calls wrong URL?

Use relative /api/... in frontend env, not hardcoded :8080.

WebSocket on same host?

Add upgrade headers under /api/ws/ location—WebSocket chapter.