The SaaS Platform uses separate subdomains for different services to provide clean separation and better security.
Before deploying, configure the following DNS A records (all pointing to your server's IP):
| Record Type | Name | Example | Purpose |
|---|---|---|---|
| A | @ or root |
example.com |
Main website/Hello World |
| A | console |
console.example.com |
Dashboard/Admin UI |
| A | api |
api.example.com |
REST API endpoints |
| A | wss |
wss.example.com |
WebSocket server |
| A | * (wildcard) |
*.example.com |
User-deployed apps |
Total: 5 DNS records required
Assuming your domain is example.com:
https://example.comhttps://console.example.comhttps://api.example.com/auth/* - Authentication routes/users - User management/applications - Application CRUD/deployments - Deployment operations/database - Database management/rls - RLS policies/storage - File operations/email-queue - Email management/email-templates - Template CRUD/smtp-settings - SMTP configuration/health - Health checkExample API Calls:
# Health check
curl https://api.example.com/health
# Login (get JWT token)
curl -X POST https://api.example.com/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com","password":"password"}'
# Get users (with JWT)
curl https://api.example.com/users \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
# Get users (with API key)
curl https://api.example.com/v1/users \
-H "Authorization: Bearer sk_YOUR_API_KEY"
wss://wss.example.comConnection:
const ws = new WebSocket('wss://wss.example.com?token=YOUR_JWT_TOKEN');
https://app-name.example.comhttps://myapp.example.comhttps://blog.example.comhttps://shop.example.comFor local development (using .env.development):
| Service | Production | Development |
|---|---|---|
| Main Site | https://example.com |
http://localhost:8888 |
| Dashboard | https://console.example.com |
http://localhost:8888 |
| API | https://api.example.com |
http://localhost:8888/api |
| WebSocket | wss://wss.example.com |
ws://localhost:8888/ws |
Note: In development, all services are accessed through a single port (8888) with different paths.
https://console.example.comhttps://console.example.com/api/*wss://console.example.com/wshttps://console.example.comhttps://api.example.com/* ✨ Changedwss://wss.example.com ✨ Changed/api or /ws prefixes// config.js
const API_URL = process.env.NODE_ENV === 'production'
? 'https://api.yourdomain.com'
: 'http://localhost:8888/api';
const WSS_URL = process.env.NODE_ENV === 'production'
? 'wss://wss.yourdomain.com'
: 'ws://localhost:8888/ws';
const CONSOLE_URL = process.env.NODE_ENV === 'production'
? 'https://console.yourdomain.com'
: 'http://localhost:8888';
export { API_URL, WSS_URL, CONSOLE_URL };
# .env.production
VITE_API_URL=https://api.yourdomain.com
VITE_WSS_URL=wss://wss.yourdomain.com
VITE_CONSOLE_URL=https://console.yourdomain.com
# .env.development
VITE_API_URL=http://localhost:8888/api
VITE_WSS_URL=ws://localhost:8888/ws
VITE_CONSOLE_URL=http://localhost:8888
Port 443 (HTTPS):
├── example.com → Hello World (static files)
├── console.example.com → Dashboard (React app)
├── api.example.com → API Service (Node.js)
├── wss.example.com → WebSocket Service (Node.js)
└── *.example.com → User Apps (dynamic routing)
Port 80 (HTTP):
└── All domains → Redirect to HTTPS (301)
Each subdomain has independent CORS:
example.comconsole.example.comapi.example.comwss.example.com*.example.com (requires separate certificate or SAN)# Only open ports 80 and 443
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 22/tcp # SSH
sudo ufw enable
# Check all DNS records
dig +short A example.com
dig +short A console.example.com
dig +short A api.example.com
dig +short A wss.example.com
dig +short A test.example.com # Test wildcard
# All should return the same IP address
Problem: Cannot resolve subdomain Solution: Wait for DNS propagation (up to 48 hours) or check DNS configuration
# Use Google DNS for testing
dig @8.8.8.8 api.example.com
Problem: Certificate doesn't cover subdomain Solution: Regenerate certificate with all subdomains
sudo certbot certonly --standalone \
-d example.com \
-d console.example.com \
-d api.example.com \
-d wss.example.com
Problem: Cannot connect to WSS Solution: Check if wss.example.com resolves and has SSL
# Test WSS domain
curl -I https://wss.example.com
# Should return HTTP 200 or 400 (not 404 or connection refused)
| URL | Service | Port | SSL | Authentication | Purpose |
|---|---|---|---|---|---|
https://example.com |
Nginx | 443 | ✅ | None | Landing page |
https://console.example.com |
Dashboard | 443 | ✅ | JWT | Admin UI |
https://api.example.com |
API | 443 | ✅ | JWT/API Key | REST API |
wss://wss.example.com |
WebSocket | 443 | ✅ | JWT | Real-time |
https://*.example.com |
User Apps | 443 | ✅ | Varies | Hosted apps |
For deployment instructions, see DEPLOYMENT.md