docs: Update README with comprehensive setup and deployment guide
- 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>
This commit is contained in:
647
README.md
647
README.md
@@ -1,257 +1,470 @@
|
||||
# SmoothSchedule - Multi-Tenant Scheduling Platform
|
||||
|
||||
A production-ready multi-tenant SaaS platform for resource scheduling and orchestration.
|
||||
A production-ready multi-tenant SaaS platform for resource scheduling, appointments, and business management.
|
||||
|
||||
## 🎯 Features
|
||||
## Features
|
||||
|
||||
- ✅ **Multi-Tenancy**: PostgreSQL schema-per-tenant using django-tenants
|
||||
- ✅ **8-Tier Role Hierarchy**: From SUPERUSER to CUSTOMER with strict permissions
|
||||
- ✅ **Modern Stack**: Django 5.2 + React 18 + Vite
|
||||
- ✅ **Docker Ready**: Complete production & development Docker Compose setup
|
||||
- ✅ **Cloud Storage**: DigitalOcean Spaces (S3-compatible) for static/media files
|
||||
- ✅ **Auto SSL**: Let's Encrypt certificates via Traefik reverse proxy
|
||||
- ✅ **Task Queue**: Celery + Redis for background jobs
|
||||
- ✅ **Real-time**: Django Channels + WebSockets support
|
||||
- ✅ **Production Ready**: Fully configured for deployment
|
||||
- **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
|
||||
|
||||
## 📚 Documentation
|
||||
## Project Structure
|
||||
|
||||
- **[PRODUCTION_DEPLOYMENT.md](PRODUCTION_DEPLOYMENT.md)** - **Manual step-by-step production deployment** (start here for fresh deployments)
|
||||
- **[QUICK-REFERENCE.md](QUICK-REFERENCE.md)** - Common commands and quick start
|
||||
- **[PRODUCTION-READY.md](PRODUCTION-READY.md)** - Production deployment status
|
||||
- **[DEPLOYMENT.md](DEPLOYMENT.md)** - Comprehensive deployment guide
|
||||
- **[CLAUDE.md](CLAUDE.md)** - Development guide and architecture
|
||||
```
|
||||
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
|
||||
```
|
||||
|
||||
## 🚀 Quick Start
|
||||
---
|
||||
|
||||
### Local Development
|
||||
## Local Development Setup
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- **Docker** and **Docker Compose** (for backend)
|
||||
- **Node.js 22+** and **npm** (for frontend)
|
||||
- **Git**
|
||||
|
||||
### Step 1: Clone the Repository
|
||||
|
||||
```bash
|
||||
# Start backend (Django in Docker)
|
||||
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
|
||||
|
||||
# Start frontend (React with Vite)
|
||||
cd ../frontend
|
||||
npm install
|
||||
npm run dev
|
||||
# Wait for services to initialize (first time takes longer)
|
||||
sleep 30
|
||||
|
||||
# Access the app
|
||||
# Frontend: http://platform.lvh.me:5173
|
||||
# Backend API: http://lvh.me:8000/api
|
||||
# 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
|
||||
```
|
||||
|
||||
See [CLAUDE.md](CLAUDE.md) for detailed development instructions.
|
||||
|
||||
### Production Deployment
|
||||
|
||||
For **fresh deployments or complete reset**, follow [PRODUCTION_DEPLOYMENT.md](PRODUCTION_DEPLOYMENT.md) for manual step-by-step instructions.
|
||||
|
||||
For **routine updates**, use the automated script:
|
||||
### Step 3: Start the Frontend (React with Vite)
|
||||
|
||||
```bash
|
||||
# Deploy to production server (code changes only)
|
||||
./deploy.sh poduck@smoothschedule.com
|
||||
cd ../frontend
|
||||
|
||||
# Install dependencies
|
||||
npm install
|
||||
|
||||
# Start development server
|
||||
npm run dev
|
||||
```
|
||||
|
||||
See [PRODUCTION-READY.md](PRODUCTION-READY.md) for deployment checklist and [DEPLOYMENT.md](DEPLOYMENT.md) for detailed steps.
|
||||
### Step 4: Access the Application
|
||||
|
||||
## 🏗️ Architecture
|
||||
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 │
|
||||
├─────────────────────────────────────────┤
|
||||
│ tenant_demo (schema for Demo Company) │
|
||||
│ ├─ Appointments │
|
||||
│ ├─ Resources │
|
||||
│ └─ Customers │
|
||||
├─────────────────────────────────────────┤
|
||||
│ tenant_acme (schema for Acme Corp) │
|
||||
│ ├─ Appointments │
|
||||
│ ├─ Resources │
|
||||
│ └─ Customers │
|
||||
└─────────────────────────────────────────┘
|
||||
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 Scope |
|
||||
|---------------------|----------|---------------------------|
|
||||
| Role | Level | Access |
|
||||
|------|-------|--------|
|
||||
| SUPERUSER | Platform | All tenants (god mode) |
|
||||
| PLATFORM_MANAGER | Platform | All tenants |
|
||||
| PLATFORM_SALES | Platform | Demo accounts only |
|
||||
| PLATFORM_SUPPORT | Platform | Tenant users |
|
||||
| TENANT_OWNER | Tenant | Own tenant (full access) |
|
||||
| TENANT_MANAGER | Tenant | Own tenant |
|
||||
| TENANT_STAFF | Tenant | Own tenant (limited) |
|
||||
| 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 |
|
||||
|
||||
### Masquerading Matrix
|
||||
|
||||
| Hijacker Role | Can Masquerade As |
|
||||
|--------------------|----------------------------------|
|
||||
| SUPERUSER | Anyone |
|
||||
| PLATFORM_SUPPORT | Tenant users |
|
||||
| PLATFORM_SALES | Demo accounts (`is_temporary=True`) |
|
||||
| TENANT_OWNER | Staff in same tenant |
|
||||
| Others | No one |
|
||||
|
||||
**Security Rules:**
|
||||
- Cannot hijack yourself
|
||||
- Cannot hijack SUPERUSERs (except by other SUPERUSERs)
|
||||
- Maximum depth: 1 (no hijack chains)
|
||||
- All attempts logged to `logs/masquerade.log`
|
||||
|
||||
## 📁 Project Structure
|
||||
### Request Flow
|
||||
|
||||
```
|
||||
smoothschedule/
|
||||
├── config/
|
||||
│ └── settings.py # Multi-tenancy & security config
|
||||
├── core/
|
||||
│ ├── models.py # Tenant, Domain, PermissionGrant
|
||||
│ ├── permissions.py # Hijack permission matrix
|
||||
│ ├── middleware.py # Masquerade audit logging
|
||||
│ └── admin.py # Django admin for core models
|
||||
├── users/
|
||||
│ ├── models.py # Custom User with 8-tier roles
|
||||
│ └── admin.py # User admin with hijack button
|
||||
├── logs/
|
||||
│ ├── security.log # General security events
|
||||
│ └── masquerade.log # Hijack activity (JSON)
|
||||
└── setup_project.sh # Automated setup script
|
||||
Browser → Traefik (SSL) → nginx (frontend) or django (API)
|
||||
↓
|
||||
React SPA
|
||||
↓
|
||||
/api/* → django:5000
|
||||
/ws/* → django:5000 (WebSocket)
|
||||
```
|
||||
|
||||
## 🔐 Security Features
|
||||
|
||||
### Audit Logging
|
||||
|
||||
All masquerade activity is logged in JSON format:
|
||||
|
||||
```json
|
||||
{
|
||||
"timestamp": "2024-01-15T10:30:00Z",
|
||||
"action": "HIJACK_START",
|
||||
"hijacker_email": "support@smoothschedule.com",
|
||||
"hijacked_email": "customer@demo.com",
|
||||
"ip_address": "192.168.1.1",
|
||||
"session_key": "abc123..."
|
||||
}
|
||||
```
|
||||
|
||||
### Permission Grants (30-Minute Window)
|
||||
|
||||
Time-limited elevated permissions:
|
||||
|
||||
```python
|
||||
from core.models import PermissionGrant
|
||||
|
||||
grant = PermissionGrant.create_grant(
|
||||
grantor=admin_user,
|
||||
grantee=support_user,
|
||||
action="view_billing",
|
||||
reason="Customer requested billing support",
|
||||
duration_minutes=30,
|
||||
)
|
||||
|
||||
# Check if active
|
||||
if grant.is_active():
|
||||
# Perform privileged action
|
||||
pass
|
||||
```
|
||||
|
||||
## 🧪 Testing Masquerading
|
||||
|
||||
1. Access Django Admin: `http://localhost:8000/admin/`
|
||||
2. Create test users with different roles
|
||||
3. Click "Hijack" button next to a user
|
||||
4. Verify audit logs: `docker-compose exec django cat logs/masquerade.log`
|
||||
|
||||
## 📊 Admin Interface
|
||||
|
||||
- **Tenant Management**: View tenants, domains, subscription tiers
|
||||
- **User Management**: Color-coded roles, masquerade buttons
|
||||
- **Permission Grants**: Active/expired/revoked status, bulk revoke
|
||||
- **Domain Verification**: AWS Route53 integration status
|
||||
|
||||
## 🛠️ Development
|
||||
|
||||
### Adding Tenant Apps
|
||||
|
||||
Edit `config/settings.py`:
|
||||
|
||||
```python
|
||||
TENANT_APPS = [
|
||||
'django.contrib.contenttypes',
|
||||
'appointments', # Your app
|
||||
'resources', # Your app
|
||||
'billing', # Your app
|
||||
]
|
||||
```
|
||||
|
||||
### Custom Domain Setup
|
||||
|
||||
```python
|
||||
domain = Domain.objects.create(
|
||||
domain="app.customdomain.com",
|
||||
tenant=tenant,
|
||||
is_custom_domain=True,
|
||||
route53_zone_id="Z1234567890ABC",
|
||||
)
|
||||
```
|
||||
|
||||
Then configure Route53 CNAME: `app.customdomain.com` → `smoothschedule.yourhost.com`
|
||||
|
||||
## 📖 Key Files Reference
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `setup_project.sh` | Automated project initialization |
|
||||
| `config/settings.py` | Multi-tenancy, middleware, security config |
|
||||
| `core/models.py` | Tenant, Domain, PermissionGrant models |
|
||||
| `core/permissions.py` | Masquerading permission matrix |
|
||||
| `core/middleware.py` | Audit logging for masquerading |
|
||||
| `users/models.py` | Custom User with 8-tier roles |
|
||||
|
||||
## 📝 Important Notes
|
||||
|
||||
- **Django Admin**: The ONLY HTML interface (everything else is API)
|
||||
- **Middleware Order**: `TenantMainMiddleware` must be first, `MasqueradeAuditMiddleware` after `HijackUserMiddleware`
|
||||
- **Tenant Isolation**: Each tenant's data is in a separate PostgreSQL schema
|
||||
- **Production**: Update `SECRET_KEY`, database credentials, and AWS keys via environment variables
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
**Cannot create tenant users:**
|
||||
- Error: "Users with role TENANT_STAFF must be assigned to a tenant"
|
||||
- Solution: Set `user.tenant = tenant_instance` before saving
|
||||
|
||||
**Hijack button doesn't appear:**
|
||||
- Check `HIJACK_AUTHORIZATION_CHECK` in settings
|
||||
- Verify `HijackUserAdminMixin` in `users/admin.py`
|
||||
- Ensure user has permission per matrix rules
|
||||
|
||||
**Migrations fail:**
|
||||
- Run shared migrations first: `migrate_schemas --shared`
|
||||
- Then run tenant migrations: `migrate_schemas`
|
||||
|
||||
## 📄 License
|
||||
|
||||
MIT
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
This is a production skeleton. Extend `TENANT_APPS` with your business logic.
|
||||
|
||||
---
|
||||
|
||||
**Built with ❤️ for multi-tenant SaaS perfection**
|
||||
## 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
|
||||
|
||||
Reference in New Issue
Block a user