URL_STRUCTURE.md 7.6 KB

URL Structure

Overview

The SaaS Platform uses separate subdomains for different services to provide clean separation and better security.

DNS Requirements

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


Production URLs

Assuming your domain is example.com:

Main Website

  • URL: https://example.com
  • Purpose: Public-facing hello world landing page
  • SSL: Let's Encrypt
  • Served by: Nginx (static files)

Dashboard (Console)

  • URL: https://console.example.com
  • Purpose: Admin dashboard for managing the platform
  • SSL: Let's Encrypt
  • Features:
    • User management
    • Application deployment
    • Database editor
    • Email templates
    • SMTP settings
    • RLS policy management
    • API key management

API Endpoint

  • URL: https://api.example.com
  • Purpose: REST API for all backend operations
  • SSL: Let's Encrypt
  • Authentication: JWT or API Keys
  • Endpoints:
    • /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 check

Example 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"

WebSocket Server

  • URL: wss://wss.example.com
  • Purpose: Real-time bidirectional communication
  • SSL: Let's Encrypt (WSS protocol)
  • Authentication: JWT token required
  • Connection:

    const ws = new WebSocket('wss://wss.example.com?token=YOUR_JWT_TOKEN');
    

User Applications (Wildcard)

  • URL Pattern: https://app-name.example.com
  • Purpose: Host user-deployed applications
  • SSL: Shared Let's Encrypt wildcard certificate
  • Examples:
    • https://myapp.example.com
    • https://blog.example.com
    • https://shop.example.com

Development URLs

For 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.


Migration from Old URL Structure

Old Structure (Before Update)

  • Dashboard: https://console.example.com
  • API: https://console.example.com/api/*
  • WebSocket: wss://console.example.com/ws

New Structure (Current)

  • Dashboard: https://console.example.com
  • API: https://api.example.com/*Changed
  • WebSocket: wss://wss.example.comChanged

Why Change?

  1. Cleaner URLs: No more /api or /ws prefixes
  2. Better Security: Separate subdomains for different services
  3. Easier CORS: Independent CORS policies per subdomain
  4. Load Balancing: Can scale API and WSS independently
  5. Certificate Management: Dedicated SSL per service
  6. Professional: Industry standard practice

Frontend Configuration

React/JavaScript

// 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 };

Environment Variables

# .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

Nginx Routing

Simplified Routing Map

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)

Security Considerations

CORS Configuration

Each subdomain has independent CORS:

  • console.example.com: Strict CORS (same-origin only)
  • api.example.com: Permissive CORS (allow all origins for API access)
  • wss.example.com: WebSocket CORS (upgrade headers)

SSL/TLS Certificates

  • Single Certificate: Covers all subdomains
    • example.com
    • console.example.com
    • api.example.com
    • wss.example.com
  • Wildcard Support: *.example.com (requires separate certificate or SAN)
  • Auto-renewal: Certbot renews automatically

Firewall Rules

# 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

Testing DNS Configuration

# 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

Troubleshooting

"DNS not found" Error

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

SSL Certificate Error

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

WebSocket Connection Failed

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)

Summary Table

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