Deployment Guide
Vercel, Railway, and VPS with Nginx and SSL
Dev OnlyRecommended Production Stack
| Service | Provider | Why |
|---|---|---|
| Frontend (Next.js) | Vercel | Zero-config Next.js hosting. Auto SSL. Deploy on git push. |
| Backend (Node.js API) | Railway or Render | One-click Node.js deploy. Easy environment variables. |
| PostgreSQL | Neon or Supabase | Serverless Postgres. Generous free tier. Auto-backups. |
| Redis | Upstash | Serverless Redis. Pay-per-request. Free tier available. |
| Images | Cloudinary | Already configured in the app. No change needed. |
| DNS & SSL | Cloudflare | Free SSL certificates. DDoS protection. Easy DNS. |
Option A — Deploy Frontend to Vercel
The easiest approach for the Next.js frontend.
Create a Vercel account
Go to vercel.com and log in (or create an account).
Import your repository
Click Add New Project and import your pos-frontend repository from
GitHub.
Deploy
Vercel auto-detects Next.js. Click Deploy — it builds and deploys automatically.
Set environment variables
After deployment, go to Settings › Environment Variables and add all
variables from your .env.local file. Set NEXT_PUBLIC_API_URL to your
production backend URL.
Redeploy
Click Redeploy to apply the environment changes. Your frontend is live
at your-project.vercel.app (or your custom domain).
Option B — Deploy Backend to Railway
Create a Railway account
Go to railway.app and create an account.
Deploy from GitHub
Click New Project › Deploy from GitHub repo and select pos-backend.
Configure variables
In the Variables tab, add every key from your .env file.
Set networking
In Settings › Networking, add a custom domain or use the auto-generated
railway.app URL.
Set build commands
Set the build and start commands:
Option C — Deploy to a VPS
For full control — deploy to an Ubuntu VPS with Nginx and PM2.
1 — Initial Server Setup
2 — Clone, Configure, and Start
3 — Nginx Reverse Proxy
4 — Free SSL with Certbot
Production .env Checklist
| Variable | Production Notes |
|---|---|
NODE_ENV Required | Must be exactly: production |
DATABASE_URL Required | Use production Neon/Supabase URL with ?sslmode=require |
REDIS_URL Required | Use Upstash production URL — starts with rediss:// |
JWT_ACCESS_SECRET Required | Generate a fresh 64-char secret. Never reuse the dev value. |
JWT_REFRESH_SECRET Required | Generate another fresh 64-char secret. Must differ from access secret. |
FRONTEND_URL Required | Your real frontend URL: https://pos.yourdomain.com |
CLOUDINARY_* | Same credentials as development — Cloudinary is environment-agnostic. |
Never reuse development JWT secrets in production. Regenerate them with the crypto command from the Backend Configuration section.