URL Patterns Reference¶
Complete specification for Airbase application URLs
This document provides the authoritative reference for URL patterns used in Airbase, including environment-specific URLs, custom domains, and routing behavior.
Overview¶
Every deployed application in Airbase gets a unique URL based on its project handle and environment. URLs follow a predictable pattern that ensures no conflicts between applications.
Key concepts: - Automatic URL generation: Based on project handle and environment - Environment isolation: Each environment gets its own subdomain - HTTPS by default: All URLs use TLS encryption - Internal routing: Ingress controller routes traffic to containers
URL Structure¶
Standard URL Format¶
Pattern:
Components: - {environment}: Environment name (staging, production, or custom) - {project-name}: Project name from project handle (namespace/name) - {cluster-domain}: Airbase cluster domain
Examples:
# Staging environment
https://staging--myapp.app.tc1.airbase.sg
# Production environment (no environment prefix)
https://myapp.app.tc1.airbase.sg
# Custom environment
https://dev--myapp.app.tc1.airbase.sg
Environment-Specific URLs¶
Production Environment¶
Format: No environment prefix (clean URL)
Pattern:
Example:
Notes: - Production gets the "clean" URL without environment prefix - Default environment when deploying with airbase container deploy - Most user-facing applications use this URL
Staging Environment¶
Format: With staging-- prefix
Pattern:
Example:
Notes: - Used for pre-production testing - Deploy with airbase container deploy --yes staging - Isolated from production environment
Custom Environments¶
Format: With custom name prefix
Pattern:
Examples:
# Development environment
https://dev--myapp.app.tc1.airbase.sg
# UAT environment
https://uat--myapp.app.tc1.airbase.sg
# Feature branch
https://feature-auth--myapp.app.tc1.airbase.sg
Deploy command:
airbase container deploy --yes dev
airbase container deploy --yes uat
airbase container deploy --yes feature-auth
Notes: - Any alphanumeric name is allowed for environments - Use lowercase with hyphens (no underscores or spaces) - Each environment is fully isolated
URL Components Reference¶
Project Name¶
Derived from: Project handle in airbase.json
Format: namespace/project-name
URL uses: Only the project-name part (after /)
Example:
Results in:
Production: https://dashboard.app.tc1.airbase.sg
Staging: https://staging--dashboard.app.tc1.airbase.sg
Environment Name¶
Valid characters: - Lowercase letters: a-z - Numbers: 0-9 - Hyphens: -
Restrictions: - Cannot start or end with hyphen - Cannot contain spaces or underscores - Maximum length: 63 characters
Valid examples:
Invalid examples:
Staging # Uppercase not allowed
_dev # Underscore not allowed
dev_feature # Underscore not allowed
feature branch # Spaces not allowed
-feature # Cannot start with hyphen
feature- # Cannot end with hyphen
Cluster Domain¶
Format: tc1.airbase.sg, tc2.airbase.sg, etc.
Managed by: Airbase platform
Cannot be changed: Set at cluster level
Different clusters:
# Training Cluster 1
https://myapp.app.tc1.airbase.sg
# Training Cluster 2
https://myapp.app.tc2.airbase.sg
Notes: - Each cluster has its own domain - Projects deployed to different clusters get different URLs - Check with platform team for your cluster assignment
URL Examples by Scenario¶
Simple Single-Word Project¶
airbase.json:
URLs:
Production: https://api.app.tc1.airbase.sg
Staging: https://staging--api.app.tc1.airbase.sg
Dev: https://dev--api.app.tc1.airbase.sg
Multi-Word Project Name¶
airbase.json:
{
"framework": "container",
"handle": "analytics/user-dashboard",
"port": 3000,
"instanceType": "nano"
}
URLs:
Production: https://user-dashboard.app.tc1.airbase.sg
Staging: https://staging--user-dashboard.app.tc1.airbase.sg
Multiple Environments¶
airbase.json:
{
"framework": "container",
"handle": "platform/api-gateway",
"port": 3000,
"instanceType": "nano"
}
URLs:
Production: https://api-gateway.app.tc1.airbase.sg
Staging: https://staging--api-gateway.app.tc1.airbase.sg
Development: https://dev--api-gateway.app.tc1.airbase.sg
UAT: https://uat--api-gateway.app.tc1.airbase.sg
Testing: https://test--api-gateway.app.tc1.airbase.sg
Path Routing¶
Application Paths¶
Your application handles all paths:
Base URL: https://myapp.app.tc1.airbase.sg/
Path routing: https://myapp.app.tc1.airbase.sg/api
https://myapp.app.tc1.airbase.sg/api/users
https://myapp.app.tc1.airbase.sg/dashboard
https://myapp.app.tc1.airbase.sg/static/style.css
All paths are forwarded to your container: - Your application receives the full path - No URL rewriting by Airbase - Configure routing in your application
Example: Express.js Routing¶
const express = require('express');
const app = express();
// https://myapp.app.tc1.airbase.sg/
app.get('/', (req, res) => {
res.send('Home');
});
// https://myapp.app.tc1.airbase.sg/api/users
app.get('/api/users', (req, res) => {
res.json({ users: [] });
});
// https://myapp.app.tc1.airbase.sg/dashboard
app.get('/dashboard', (req, res) => {
res.send('Dashboard');
});
Example: Flask Routing¶
from flask import Flask
app = Flask(__name__)
# https://myapp.app.tc1.airbase.sg/
@app.route('/')
def home():
return 'Home'
# https://myapp.app.tc1.airbase.sg/api/users
@app.route('/api/users')
def users():
return {'users': []}
# https://myapp.app.tc1.airbase.sg/dashboard
@app.route('/dashboard')
def dashboard():
return 'Dashboard'
Static Site Routing¶
Single Page Applications (SPA)¶
Challenge: Client-side routing vs server-side routing
Solution: Configure fallback to index.html
Example Nginx configuration:
server {
listen 3000;
root /usr/share/nginx/html;
index index.html;
# Try file, then fallback to index.html
location / {
try_files $uri $uri/ /index.html;
}
}
Enables these URLs to work:
https://myapp.app.tc1.airbase.sg/ → index.html
https://myapp.app.tc1.airbase.sg/dashboard → index.html (React Router handles /dashboard)
https://myapp.app.tc1.airbase.sg/profile → index.html (React Router handles /profile)
Static Files¶
Serve static assets with correct MIME types:
Nginx configuration:
server {
listen 3000;
root /usr/share/nginx/html;
# Static files
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# SPA fallback for other routes
location / {
try_files $uri $uri/ /index.html;
}
}
HTTPS and TLS¶
Automatic HTTPS¶
All Airbase URLs use HTTPS: - TLS certificates are automatically provisioned - Certificate renewal is automatic - HTTP requests are redirected to HTTPS
Example:
TLS Version¶
Minimum TLS version: TLS 1.2
Supported versions: - TLS 1.2 ✅ - TLS 1.3 ✅
Cipher suites: Modern secure ciphers only
URL Discovery¶
Getting Your URL After Deployment¶
During deployment:
$ airbase container deploy --yes staging
Deployed myapp in staging (team/myapp:staging)
Visit https://staging--myapp.app.tc1.airbase.sg
The URL is displayed in the deployment output.
Listing Deployments¶
View all environments and their URLs:
$ airbase container list
Environment URL
----------- ----------------------------------------
production https://myapp.app.tc1.airbase.sg
staging https://staging--myapp.app.tc1.airbase.sg
dev https://dev--myapp.app.tc1.airbase.sg
Programmatic URL Construction¶
Building URLs in Code¶
Node.js:
function getAppUrl(environment = 'production') {
const projectName = 'myapp';
const clusterDomain = 'tc1.airbase.sg';
if (environment === 'production') {
return `https://${projectName}.app.${clusterDomain}`;
}
return `https://${environment}--${projectName}.app.${clusterDomain}`;
}
console.log(getAppUrl('production')); // https://myapp.app.tc1.airbase.sg
console.log(getAppUrl('staging')); // https://staging--myapp.app.tc1.airbase.sg
Python:
def get_app_url(environment='production'):
project_name = 'myapp'
cluster_domain = 'tc1.airbase.sg'
if environment == 'production':
return f'https://{project_name}.app.{cluster_domain}'
return f'https://{environment}--{project_name}.app.{cluster_domain}'
print(get_app_url('production')) # https://myapp.app.tc1.airbase.sg
print(get_app_url('staging')) # https://staging--myapp.app.tc1.airbase.sg
URL Best Practices¶
✅ Do's¶
- Use environment variables: Store base URL in configuration
- Build URLs dynamically: Don't hardcode URLs in multiple places
- Test in staging first: Verify URLs work before production
- Use HTTPS in references: Always reference
https://URLs - Handle trailing slashes: Be consistent with or without trailing slash
Example configuration:
// config.js
const BASE_URL = process.env.BASE_URL || 'https://myapp.app.tc1.airbase.sg';
module.exports = {
apiUrl: `${BASE_URL}/api`,
authUrl: `${BASE_URL}/auth`,
staticUrl: `${BASE_URL}/static`
};
❌ Don'ts¶
- Don't hardcode production URLs: Use environment variables
- Don't assume URL format: Use provided URLs from deployment
- Don't use HTTP: Always use HTTPS
- Don't ignore environment: Different URLs for staging vs production
- Don't expose internal URLs: Use public URLs in client-side code
Cross-Origin Requests (CORS)¶
Allowing Requests from Your Frontend¶
If your API and frontend are on different URLs:
Example: - Frontend: https://app.app.tc1.airbase.sg - API: https://api.app.tc1.airbase.sg
Enable CORS in API (Express.js):
const cors = require('cors');
const corsOptions = {
origin: 'https://app.app.tc1.airbase.sg',
credentials: true
};
app.use(cors(corsOptions));
Enable CORS in API (Flask):
from flask_cors import CORS
cors_config = {
'origins': ['https://app.app.tc1.airbase.sg'],
'supports_credentials': True
}
CORS(app, **cors_config)
Environment-Specific CORS¶
Use environment variables:
Node.js:
const allowedOrigins = process.env.CORS_ORIGINS?.split(',') || [
'https://app.app.tc1.airbase.sg'
];
app.use(cors({
origin: allowedOrigins,
credentials: true
}));
.env.staging:
.env (production):
URL Limitations¶
Length Limits¶
Maximum URL length: 2048 characters (practical limit)
Components: - Domain: Up to 253 characters - Path: Up to 2000 characters
For extremely long URLs: - Use POST requests instead of GET - Store data server-side, pass ID in URL
Reserved Names¶
Cannot use these as project names: - api (reserved for platform) - auth (reserved for authentication) - admin (reserved for administration) - console (reserved for platform console)
Check availability: Contact platform team if unsure
Troubleshooting¶
URL Returns 404¶
Possible causes: 1. Application not deployed to that environment 2. Wrong environment name 3. Application container not responding
Solutions:
# Verify deployment
airbase container list
# Check application logs in Airbase Console
# Navigate to project → Logs → Select staging environment
# Redeploy if needed
airbase container deploy --yes staging
URL Returns 503 (Service Unavailable)¶
Possible causes: 1. Application crashed 2. Health check failing 3. Container not listening on correct port
Solutions:
# Check logs for errors in Airbase Console
# Navigate to project → Logs → Select staging environment
# Verify PORT binding
# Ensure app binds to process.env.PORT
# Verify health check endpoint works
# Ensure /health endpoint returns 200
CORS Errors¶
Error: "No 'Access-Control-Allow-Origin' header"
Solution: Enable CORS in your API (see CORS section above)
SSL/TLS Errors¶
Error: "SSL certificate error"
Possible causes: 1. Using HTTP instead of HTTPS 2. Outdated TLS version on client
Solutions: - Always use https:// URLs - Update client to support TLS 1.2+ - Contact platform team if certificate issues persist
See Also¶
- Reference: airbase.json Configuration - Project configuration
- How-To: Manage Environments - Creating and managing environments
- How-To: Build and Deploy - Deployment workflow