- Updated project structure to reflect current domain-based organization - Added detailed local development setup with lvh.me explanation - Added production deployment instructions (quick deploy and fresh server) - Documented environment variables configuration - Added architecture diagrams for multi-tenancy and request flow - Included troubleshooting section for common issues - Updated role hierarchy documentation - Added configuration files reference table 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
471 lines
12 KiB
Markdown
471 lines
12 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
git clone https://github.com/your-repo/smoothschedule.git
|
|
cd smoothschedule
|
|
```
|
|
|
|
### Step 2: Start the Backend (Django in Docker)
|
|
|
|
```bash
|
|
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)
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
cd smoothschedule
|
|
docker compose -f docker-compose.local.yml exec django python manage.py shell
|
|
```
|
|
|
|
```python
|
|
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:
|
|
- `A` record: `yourdomain.com` → Server IP
|
|
- `A` record: `*.yourdomain.com` → Server IP (wildcard)
|
|
- SSH access to the server
|
|
|
|
### Quick Deploy (Existing Server)
|
|
|
|
For routine updates to an existing production server:
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
cd ~
|
|
git clone https://github.com/your-repo/smoothschedule.git smoothschedule
|
|
cd smoothschedule
|
|
```
|
|
|
|
#### Step 3: Configure Environment Variables
|
|
|
|
Create production environment files:
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# Check nginx has /ws/ proxy configured
|
|
# Verify django is running ASGI (Daphne)
|
|
# Check production traefik/nginx logs
|
|
```
|
|
|
|
### Multi-tenant issues
|
|
|
|
```bash
|
|
# 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](CLAUDE.md)** - Development guide, coding standards, architecture details
|
|
- **[DEPLOYMENT.md](DEPLOYMENT.md)** - Comprehensive deployment guide
|
|
- **[PRODUCTION_DEPLOYMENT.md](PRODUCTION_DEPLOYMENT.md)** - Step-by-step manual deployment
|
|
|
|
---
|
|
|
|
## License
|
|
|
|
MIT
|