07f49cb45725c48ef37d169850da950e84111534
Instead of redirecting business users to their business subdomain when they access the platform subdomain, clear their session and show the platform login page. This is cleaner when masquerading changes tokens to a tenant user - they can simply log back in as a platform user. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…
…
…
…
SmoothSchedule - Multi-Tenant Scheduling Platform
A production-ready multi-tenant SaaS platform for resource scheduling, appointments, and business management.
Features
- Multi-Tenancy: PostgreSQL schema-per-tenant using django-tenants
- 8-Tier Role Hierarchy: SUPERUSER, PLATFORM_MANAGER, PLATFORM_SALES, PLATFORM_SUPPORT, TENANT_OWNER, TENANT_MANAGER, TENANT_STAFF, CUSTOMER
- Modern Stack: Django 5.2 + React 19 + TypeScript + Vite
- Real-time Updates: Django Channels + WebSockets
- Background Tasks: Celery + Redis
- Auto SSL: Let's Encrypt certificates via Traefik
- Cloud Storage: DigitalOcean Spaces (S3-compatible)
- Docker Ready: Complete Docker Compose setup for dev and production
Project Structure
smoothschedule2/
├── frontend/ # React + Vite + TypeScript
│ ├── src/
│ │ ├── api/ # API client and hooks
│ │ ├── components/ # Reusable UI components
│ │ ├── hooks/ # React Query hooks
│ │ ├── pages/ # Page components
│ │ └── types.ts # TypeScript interfaces
│ ├── nginx.conf # Production nginx config
│ └── Dockerfile.prod # Production frontend container
│
├── smoothschedule/ # Django backend
│ ├── config/ # Django settings
│ │ └── settings/
│ │ ├── base.py # Base settings
│ │ ├── local.py # Local development
│ │ └── production.py # Production settings
│ ├── smoothschedule/ # Django apps (domain-based)
│ │ ├── identity/ # Users, tenants, authentication
│ │ │ ├── core/ # Tenant, Domain, middleware
│ │ │ └── users/ # User model, MFA, auth
│ │ ├── scheduling/ # Core scheduling
│ │ │ ├── schedule/ # Resources, Events, Services
│ │ │ ├── contracts/ # E-signatures
│ │ │ └── analytics/ # Business analytics
│ │ ├── communication/ # Notifications, SMS, mobile
│ │ ├── commerce/ # Payments, tickets
│ │ └── platform/ # Admin, public API
│ ├── docker-compose.local.yml
│ └── docker-compose.production.yml
│
├── deploy.sh # Automated deployment script
└── CLAUDE.md # Development guide
Local Development Setup
Prerequisites
- Docker and Docker Compose (for backend)
- Node.js 22+ and npm (for frontend)
- Git
Step 1: Clone the Repository
git clone https://github.com/your-repo/smoothschedule.git
cd smoothschedule
Step 2: Start the Backend (Django in Docker)
cd smoothschedule
# Start all backend services
docker compose -f docker-compose.local.yml up -d
# Wait for services to initialize (first time takes longer)
sleep 30
# Run database migrations
docker compose -f docker-compose.local.yml exec django python manage.py migrate
# Create a superuser (optional)
docker compose -f docker-compose.local.yml exec django python manage.py createsuperuser
Step 3: Start the Frontend (React with Vite)
cd ../frontend
# Install dependencies
npm install
# Start development server
npm run dev
Step 4: Access the Application
The application uses lvh.me (resolves to 127.0.0.1) for subdomain-based multi-tenancy:
| URL | Purpose |
|---|---|
| http://platform.lvh.me:5173 | Platform admin dashboard |
| http://demo.lvh.me:5173 | Demo tenant (if created) |
| http://lvh.me:8000/api/ | Backend API |
| http://lvh.me:8000/admin/ | Django admin |
Why lvh.me? Browsers don't allow cookies with domain=.localhost, but lvh.me resolves to 127.0.0.1 and allows proper cookie sharing across subdomains.
Local Development Commands
# Backend commands (always use docker compose)
cd smoothschedule
# View logs
docker compose -f docker-compose.local.yml logs -f django
# Run migrations
docker compose -f docker-compose.local.yml exec django python manage.py migrate
# Django shell
docker compose -f docker-compose.local.yml exec django python manage.py shell
# Run tests
docker compose -f docker-compose.local.yml exec django pytest
# Stop all services
docker compose -f docker-compose.local.yml down
# Frontend commands
cd frontend
# Run tests
npm test
# Type checking
npm run typecheck
# Lint
npm run lint
Creating a Test Tenant
cd smoothschedule
docker compose -f docker-compose.local.yml exec django python manage.py shell
from smoothschedule.identity.core.models import Tenant, Domain
# Create tenant
tenant = Tenant.objects.create(
name="Demo Business",
schema_name="demo",
)
# Create domain
Domain.objects.create(
domain="demo.lvh.me",
tenant=tenant,
is_primary=True,
)
print(f"Created tenant: {tenant.name}")
print(f"Access at: http://demo.lvh.me:5173")
Production Deployment
Prerequisites
- Ubuntu/Debian server with Docker and Docker Compose
- Domain name with DNS configured:
Arecord:yourdomain.com→ Server IPArecord:*.yourdomain.com→ Server IP (wildcard)
- SSH access to the server
Quick Deploy (Existing Server)
For routine updates to an existing production server:
# From your local machine
./deploy.sh user@yourdomain.com
# Or deploy specific services
./deploy.sh user@yourdomain.com nginx
./deploy.sh user@yourdomain.com django
Fresh Server Deployment
Step 1: Server Setup
SSH into your server and install Docker:
ssh user@yourdomain.com
# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER
# Logout and login for group changes
exit
ssh user@yourdomain.com
Step 2: Clone Repository
cd ~
git clone https://github.com/your-repo/smoothschedule.git smoothschedule
cd smoothschedule
Step 3: Configure Environment Variables
Create production environment files:
mkdir -p smoothschedule/.envs/.production
# Django configuration
cat > smoothschedule/.envs/.production/.django << 'EOF'
DJANGO_SECRET_KEY=your-random-secret-key-here
DJANGO_DEBUG=False
DJANGO_ALLOWED_HOSTS=yourdomain.com,*.yourdomain.com
DJANGO_ADMIN_URL=your-secret-admin-path/
FRONTEND_URL=https://platform.yourdomain.com
PLATFORM_BASE_URL=https://platform.yourdomain.com
REDIS_URL=redis://redis:6379/0
CELERY_BROKER_URL=redis://redis:6379/0
# DigitalOcean Spaces (or S3)
DJANGO_AWS_ACCESS_KEY_ID=your-access-key
DJANGO_AWS_SECRET_ACCESS_KEY=your-secret-key
DJANGO_AWS_STORAGE_BUCKET_NAME=your-bucket
DJANGO_AWS_S3_ENDPOINT_URL=https://nyc3.digitaloceanspaces.com
DJANGO_AWS_S3_REGION_NAME=nyc3
# SSL
DJANGO_SECURE_SSL_REDIRECT=True
DJANGO_SESSION_COOKIE_SECURE=True
DJANGO_CSRF_COOKIE_SECURE=True
# Cloudflare (for wildcard SSL)
CF_DNS_API_TOKEN=your-cloudflare-api-token
EOF
# PostgreSQL configuration
cat > smoothschedule/.envs/.production/.postgres << 'EOF'
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
POSTGRES_DB=smoothschedule
POSTGRES_USER=smoothschedule_user
POSTGRES_PASSWORD=your-secure-database-password
EOF
Step 4: Build and Start
cd ~/smoothschedule/smoothschedule
# Build all images
docker compose -f docker-compose.production.yml build
# Start services
docker compose -f docker-compose.production.yml up -d
# Wait for startup
sleep 30
# Run migrations
docker compose -f docker-compose.production.yml exec django python manage.py migrate
# Collect static files
docker compose -f docker-compose.production.yml exec django python manage.py collectstatic --noinput
# Create superuser
docker compose -f docker-compose.production.yml exec django python manage.py createsuperuser
Step 5: Verify Deployment
# Check all containers are running
docker compose -f docker-compose.production.yml ps
# View logs
docker compose -f docker-compose.production.yml logs -f
# Test endpoints
curl https://yourdomain.com/api/health/
Production URLs
| URL | Purpose |
|---|---|
| https://yourdomain.com | Marketing site |
| https://platform.yourdomain.com | Platform admin |
| https://*.yourdomain.com | Tenant subdomains |
| https://api.yourdomain.com | API (if configured) |
| https://yourdomain.com:5555 | Flower (Celery monitoring) |
Production Management Commands
ssh user@yourdomain.com
cd ~/smoothschedule/smoothschedule
# View logs
docker compose -f docker-compose.production.yml logs -f django
# Restart services
docker compose -f docker-compose.production.yml restart
# Run migrations
docker compose -f docker-compose.production.yml exec django python manage.py migrate
# Django shell
docker compose -f docker-compose.production.yml exec django python manage.py shell
# Database backup
docker compose -f docker-compose.production.yml exec postgres pg_dump -U smoothschedule_user smoothschedule > backup.sql
Architecture
Multi-Tenancy Model
PostgreSQL Database
├── public (shared schema)
│ ├── Tenants
│ ├── Domains
│ ├── Users
│ └── PermissionGrants
├── demo (tenant schema)
│ ├── Resources
│ ├── Events
│ ├── Services
│ └── Customers
└── acme (tenant schema)
├── Resources
├── Events
└── ...
Role Hierarchy
| Role | Level | Access |
|---|---|---|
| SUPERUSER | Platform | All tenants (god mode) |
| PLATFORM_MANAGER | Platform | All tenants |
| PLATFORM_SALES | Platform | Demo accounts only |
| PLATFORM_SUPPORT | Platform | Can masquerade as tenant users |
| TENANT_OWNER | Tenant | Full tenant access |
| TENANT_MANAGER | Tenant | Most tenant features |
| TENANT_STAFF | Tenant | Limited tenant access |
| CUSTOMER | Tenant | Own data only |
Request Flow
Browser → Traefik (SSL) → nginx (frontend) or django (API)
↓
React SPA
↓
/api/* → django:5000
/ws/* → django:5000 (WebSocket)
Configuration Files
Backend
| File | Purpose |
|---|---|
smoothschedule/docker-compose.local.yml |
Local Docker services |
smoothschedule/docker-compose.production.yml |
Production Docker services |
smoothschedule/.envs/.local/ |
Local environment variables |
smoothschedule/.envs/.production/ |
Production environment variables |
smoothschedule/config/settings/ |
Django settings |
smoothschedule/compose/production/traefik/traefik.yml |
Traefik routing config |
Frontend
| File | Purpose |
|---|---|
frontend/.env.development |
Local environment variables |
frontend/.env.production |
Production environment variables |
frontend/nginx.conf |
Production nginx config |
frontend/vite.config.ts |
Vite bundler config |
Troubleshooting
Backend won't start
# Check Docker logs
docker compose -f docker-compose.local.yml logs django
# Common issues:
# - Database not ready: wait longer, then restart django
# - Missing migrations: run migrate command
# - Port conflict: check if 8000 is in use
Frontend can't connect to API
# Verify backend is running
curl http://lvh.me:8000/api/
# Check CORS settings in Django
# Ensure CORS_ALLOWED_ORIGINS includes http://platform.lvh.me:5173
WebSockets disconnecting
# Check nginx has /ws/ proxy configured
# Verify django is running ASGI (Daphne)
# Check production traefik/nginx logs
Multi-tenant issues
# Check tenant exists
docker compose exec django python manage.py shell
>>> from smoothschedule.identity.core.models import Tenant, Domain
>>> Tenant.objects.all()
>>> Domain.objects.all()
Additional Documentation
- CLAUDE.md - Development guide, coding standards, architecture details
- DEPLOYMENT.md - Comprehensive deployment guide
- PRODUCTION_DEPLOYMENT.md - Step-by-step manual deployment
License
MIT
Description
Languages
TypeScript
58.2%
Python
21.8%
HTML
18.8%
JavaScript
0.4%
Shell
0.3%
Other
0.4%