mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 08:11:08 -05:00
- Add complete backend/ directory with full Django application - Add frontend/ directory with Vite + TypeScript setup ready for Next.js - Add comprehensive shared/ directory with: - Complete documentation and memory-bank archives - Media files and avatars (letters, park/ride images) - Deployment scripts and automation tools - Shared types and utilities - Add architecture/ directory with migration guides - Configure pnpm workspace for monorepo development - Update .gitignore to exclude .django_tailwind_cli/ build artifacts - Preserve all historical documentation in shared/docs/memory-bank/ - Set up proper structure for full-stack development with shared resources
628 lines
13 KiB
Markdown
628 lines
13 KiB
Markdown
# ThrillWiki Monorepo Deployment Guide
|
|
|
|
This document outlines deployment strategies, build processes, and infrastructure considerations for the ThrillWiki Django + Vue.js monorepo.
|
|
|
|
## Build Process Overview
|
|
|
|
```mermaid
|
|
graph TB
|
|
A[Source Code] --> B[Backend Build]
|
|
A --> C[Frontend Build]
|
|
B --> D[Django Static Collection]
|
|
C --> E[Vue.js Production Build]
|
|
D --> F[Backend Container]
|
|
E --> G[Frontend Assets]
|
|
F --> H[Production Deployment]
|
|
G --> H
|
|
```
|
|
|
|
## Development Environment
|
|
|
|
### Prerequisites
|
|
- Python 3.11+ with UV package manager
|
|
- Node.js 18+ with pnpm
|
|
- PostgreSQL (production) / SQLite (development)
|
|
- Redis (for caching and sessions)
|
|
|
|
### Local Development Setup
|
|
```bash
|
|
# Clone repository
|
|
git clone <repository-url>
|
|
cd thrillwiki-monorepo
|
|
|
|
# Install root dependencies
|
|
pnpm install
|
|
|
|
# Backend setup
|
|
cd backend
|
|
uv sync
|
|
uv run manage.py migrate
|
|
uv run manage.py collectstatic
|
|
|
|
# Frontend setup
|
|
cd ../frontend
|
|
pnpm install
|
|
|
|
# Start development servers
|
|
cd ..
|
|
pnpm run dev # Starts both backend and frontend
|
|
```
|
|
|
|
## Build Strategies
|
|
|
|
### 1. Containerized Deployment (Recommended)
|
|
|
|
#### Multi-stage Dockerfile for Backend
|
|
```dockerfile
|
|
# backend/Dockerfile
|
|
FROM python:3.11-slim as builder
|
|
|
|
WORKDIR /app
|
|
COPY pyproject.toml uv.lock ./
|
|
RUN pip install uv
|
|
RUN uv sync --no-dev
|
|
|
|
FROM python:3.11-slim as runtime
|
|
|
|
WORKDIR /app
|
|
COPY --from=builder /app/.venv /app/.venv
|
|
ENV PATH="/app/.venv/bin:$PATH"
|
|
|
|
COPY . .
|
|
RUN python manage.py collectstatic --noinput
|
|
|
|
EXPOSE 8000
|
|
CMD ["gunicorn", "config.wsgi:application", "--bind", "0.0.0.0:8000"]
|
|
```
|
|
|
|
#### Dockerfile for Frontend
|
|
```dockerfile
|
|
# frontend/Dockerfile
|
|
FROM node:18-alpine as builder
|
|
|
|
WORKDIR /app
|
|
COPY package.json pnpm-lock.yaml ./
|
|
RUN npm install -g pnpm
|
|
RUN pnpm install --frozen-lockfile
|
|
|
|
COPY . .
|
|
RUN pnpm run build
|
|
|
|
FROM nginx:alpine as runtime
|
|
COPY --from=builder /app/dist /usr/share/nginx/html
|
|
COPY nginx.conf /etc/nginx/nginx.conf
|
|
EXPOSE 80
|
|
CMD ["nginx", "-g", "daemon off;"]
|
|
```
|
|
|
|
#### Docker Compose for Development
|
|
```yaml
|
|
# docker-compose.dev.yml
|
|
version: '3.8'
|
|
|
|
services:
|
|
db:
|
|
image: postgres:15
|
|
environment:
|
|
POSTGRES_DB: thrillwiki
|
|
POSTGRES_USER: thrillwiki
|
|
POSTGRES_PASSWORD: password
|
|
volumes:
|
|
- postgres_data:/var/lib/postgresql/data
|
|
ports:
|
|
- "5432:5432"
|
|
|
|
redis:
|
|
image: redis:7-alpine
|
|
ports:
|
|
- "6379:6379"
|
|
|
|
backend:
|
|
build:
|
|
context: ./backend
|
|
dockerfile: Dockerfile.dev
|
|
ports:
|
|
- "8000:8000"
|
|
volumes:
|
|
- ./backend:/app
|
|
- ./shared/media:/app/media
|
|
environment:
|
|
- DEBUG=1
|
|
- DATABASE_URL=postgresql://thrillwiki:password@db:5432/thrillwiki
|
|
- REDIS_URL=redis://redis:6379/0
|
|
depends_on:
|
|
- db
|
|
- redis
|
|
|
|
frontend:
|
|
build:
|
|
context: ./frontend
|
|
dockerfile: Dockerfile.dev
|
|
ports:
|
|
- "3000:3000"
|
|
volumes:
|
|
- ./frontend:/app
|
|
- /app/node_modules
|
|
environment:
|
|
- VITE_API_URL=http://localhost:8000
|
|
|
|
volumes:
|
|
postgres_data:
|
|
```
|
|
|
|
#### Docker Compose for Production
|
|
```yaml
|
|
# docker-compose.prod.yml
|
|
version: '3.8'
|
|
|
|
services:
|
|
db:
|
|
image: postgres:15
|
|
environment:
|
|
POSTGRES_DB: ${POSTGRES_DB}
|
|
POSTGRES_USER: ${POSTGRES_USER}
|
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
|
volumes:
|
|
- postgres_data:/var/lib/postgresql/data
|
|
restart: unless-stopped
|
|
|
|
redis:
|
|
image: redis:7-alpine
|
|
restart: unless-stopped
|
|
|
|
backend:
|
|
build:
|
|
context: ./backend
|
|
dockerfile: Dockerfile
|
|
environment:
|
|
- DEBUG=0
|
|
- DATABASE_URL=${DATABASE_URL}
|
|
- REDIS_URL=${REDIS_URL}
|
|
- SECRET_KEY=${SECRET_KEY}
|
|
- ALLOWED_HOSTS=${ALLOWED_HOSTS}
|
|
volumes:
|
|
- ./shared/media:/app/media
|
|
- static_files:/app/staticfiles
|
|
depends_on:
|
|
- db
|
|
- redis
|
|
restart: unless-stopped
|
|
|
|
frontend:
|
|
build:
|
|
context: ./frontend
|
|
dockerfile: Dockerfile
|
|
restart: unless-stopped
|
|
|
|
nginx:
|
|
image: nginx:alpine
|
|
ports:
|
|
- "80:80"
|
|
- "443:443"
|
|
volumes:
|
|
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
|
|
- ./nginx/ssl:/etc/nginx/ssl
|
|
- static_files:/usr/share/nginx/html/static
|
|
- ./shared/media:/usr/share/nginx/html/media
|
|
depends_on:
|
|
- backend
|
|
- frontend
|
|
restart: unless-stopped
|
|
|
|
volumes:
|
|
postgres_data:
|
|
static_files:
|
|
```
|
|
|
|
### 2. Static Site Generation (Alternative)
|
|
|
|
For sites with mostly static content, consider pre-rendering:
|
|
|
|
```bash
|
|
# Frontend build with pre-rendering
|
|
cd frontend
|
|
pnpm run build:prerender
|
|
|
|
# Serve static files with minimal backend
|
|
```
|
|
|
|
## CI/CD Pipeline
|
|
|
|
### GitHub Actions Workflow
|
|
```yaml
|
|
# .github/workflows/deploy.yml
|
|
name: Deploy ThrillWiki
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
branches: [main]
|
|
|
|
jobs:
|
|
test:
|
|
runs-on: ubuntu-latest
|
|
|
|
services:
|
|
postgres:
|
|
image: postgres:15
|
|
env:
|
|
POSTGRES_PASSWORD: postgres
|
|
options: >-
|
|
--health-cmd pg_isready
|
|
--health-interval 10s
|
|
--health-timeout 5s
|
|
--health-retries 5
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v4
|
|
with:
|
|
python-version: '3.11'
|
|
|
|
- name: Install UV
|
|
run: pip install uv
|
|
|
|
- name: Backend Tests
|
|
run: |
|
|
cd backend
|
|
uv sync
|
|
uv run manage.py test
|
|
uv run flake8 .
|
|
uv run black --check .
|
|
|
|
- name: Set up Node.js
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '18'
|
|
|
|
- name: Install pnpm
|
|
run: npm install -g pnpm
|
|
|
|
- name: Frontend Tests
|
|
run: |
|
|
cd frontend
|
|
pnpm install --frozen-lockfile
|
|
pnpm run test
|
|
pnpm run lint
|
|
pnpm run type-check
|
|
|
|
build:
|
|
needs: test
|
|
runs-on: ubuntu-latest
|
|
if: github.ref == 'refs/heads/main'
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Build and push Docker images
|
|
run: |
|
|
docker build -t thrillwiki-backend ./backend
|
|
docker build -t thrillwiki-frontend ./frontend
|
|
# Push to registry
|
|
|
|
- name: Deploy to production
|
|
run: |
|
|
# Deploy using your preferred method
|
|
# (AWS ECS, GCP Cloud Run, Azure Container Instances, etc.)
|
|
```
|
|
|
|
## Platform-Specific Deployments
|
|
|
|
### 1. Vercel Deployment (Frontend + API)
|
|
|
|
```json
|
|
// vercel.json
|
|
{
|
|
"version": 2,
|
|
"builds": [
|
|
{
|
|
"src": "frontend/package.json",
|
|
"use": "@vercel/static-build",
|
|
"config": {
|
|
"distDir": "dist"
|
|
}
|
|
},
|
|
{
|
|
"src": "backend/config/wsgi.py",
|
|
"use": "@vercel/python"
|
|
}
|
|
],
|
|
"routes": [
|
|
{
|
|
"src": "/api/(.*)",
|
|
"dest": "backend/config/wsgi.py"
|
|
},
|
|
{
|
|
"src": "/(.*)",
|
|
"dest": "frontend/dist/$1"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### 2. Railway Deployment
|
|
|
|
```toml
|
|
# railway.toml
|
|
[environments.production]
|
|
|
|
[environments.production.services.backend]
|
|
dockerfile = "backend/Dockerfile"
|
|
variables = { DEBUG = "0" }
|
|
|
|
[environments.production.services.frontend]
|
|
dockerfile = "frontend/Dockerfile"
|
|
|
|
[environments.production.services.postgres]
|
|
image = "postgres:15"
|
|
variables = { POSTGRES_DB = "thrillwiki" }
|
|
```
|
|
|
|
### 3. DigitalOcean App Platform
|
|
|
|
```yaml
|
|
# .do/app.yaml
|
|
name: thrillwiki
|
|
services:
|
|
- name: backend
|
|
source_dir: backend
|
|
github:
|
|
repo: your-username/thrillwiki-monorepo
|
|
branch: main
|
|
run_command: gunicorn config.wsgi:application
|
|
environment_slug: python
|
|
instance_count: 1
|
|
instance_size_slug: basic-xxs
|
|
envs:
|
|
- key: DEBUG
|
|
value: "0"
|
|
|
|
- name: frontend
|
|
source_dir: frontend
|
|
github:
|
|
repo: your-username/thrillwiki-monorepo
|
|
branch: main
|
|
build_command: pnpm run build
|
|
run_command: pnpm run preview
|
|
environment_slug: node-js
|
|
instance_count: 1
|
|
instance_size_slug: basic-xxs
|
|
|
|
databases:
|
|
- name: thrillwiki-db
|
|
engine: PG
|
|
version: "15"
|
|
```
|
|
|
|
## Environment Configuration
|
|
|
|
### Environment Variables
|
|
|
|
#### Backend (.env)
|
|
```bash
|
|
# Django Settings
|
|
DEBUG=0
|
|
SECRET_KEY=your-secret-key-here
|
|
ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com
|
|
|
|
# Database
|
|
DATABASE_URL=postgresql://user:password@host:port/database
|
|
|
|
# Redis
|
|
REDIS_URL=redis://host:port/0
|
|
|
|
# File Storage
|
|
MEDIA_ROOT=/app/media
|
|
STATIC_ROOT=/app/staticfiles
|
|
|
|
# Email
|
|
EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend
|
|
EMAIL_HOST=smtp.yourmailprovider.com
|
|
EMAIL_PORT=587
|
|
EMAIL_USE_TLS=True
|
|
EMAIL_HOST_USER=your-email@yourdomain.com
|
|
EMAIL_HOST_PASSWORD=your-email-password
|
|
|
|
# Third-party Services
|
|
SENTRY_DSN=your-sentry-dsn
|
|
AWS_ACCESS_KEY_ID=your-aws-key
|
|
AWS_SECRET_ACCESS_KEY=your-aws-secret
|
|
```
|
|
|
|
#### Frontend (.env.production)
|
|
```bash
|
|
VITE_API_URL=https://api.yourdomain.com
|
|
VITE_APP_TITLE=ThrillWiki
|
|
VITE_SENTRY_DSN=your-frontend-sentry-dsn
|
|
VITE_GOOGLE_ANALYTICS_ID=your-ga-id
|
|
```
|
|
|
|
## Performance Optimization
|
|
|
|
### Backend Optimizations
|
|
```python
|
|
# backend/config/settings/production.py
|
|
|
|
# Database optimization
|
|
DATABASES = {
|
|
'default': {
|
|
'ENGINE': 'django.db.backends.postgresql',
|
|
'CONN_MAX_AGE': 60,
|
|
'OPTIONS': {
|
|
'MAX_CONNS': 20,
|
|
}
|
|
}
|
|
}
|
|
|
|
# Caching
|
|
CACHES = {
|
|
'default': {
|
|
'BACKEND': 'django.core.cache.backends.redis.RedisCache',
|
|
'LOCATION': 'redis://127.0.0.1:6379/1',
|
|
'OPTIONS': {
|
|
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
|
|
},
|
|
'KEY_PREFIX': 'thrillwiki'
|
|
}
|
|
}
|
|
|
|
# Static files with CDN
|
|
AWS_S3_CUSTOM_DOMAIN = 'cdn.yourdomain.com'
|
|
STATICFILES_STORAGE = 'storages.backends.s3boto3.StaticS3Boto3Storage'
|
|
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.MediaS3Boto3Storage'
|
|
```
|
|
|
|
### Frontend Optimizations
|
|
```typescript
|
|
// frontend/vite.config.ts
|
|
export default defineConfig({
|
|
build: {
|
|
rollupOptions: {
|
|
output: {
|
|
manualChunks: {
|
|
vendor: ['vue', 'vue-router', 'pinia'],
|
|
ui: ['@headlessui/vue', '@heroicons/vue']
|
|
}
|
|
}
|
|
},
|
|
sourcemap: false,
|
|
minify: 'terser',
|
|
terserOptions: {
|
|
compress: {
|
|
drop_console: true,
|
|
drop_debugger: true
|
|
}
|
|
}
|
|
}
|
|
})
|
|
```
|
|
|
|
## Monitoring and Logging
|
|
|
|
### Application Monitoring
|
|
```python
|
|
# backend/config/settings/production.py
|
|
import sentry_sdk
|
|
from sentry_sdk.integrations.django import DjangoIntegration
|
|
|
|
sentry_sdk.init(
|
|
dsn="your-sentry-dsn",
|
|
integrations=[DjangoIntegration()],
|
|
traces_sample_rate=0.1,
|
|
send_default_pii=True
|
|
)
|
|
|
|
# Logging configuration
|
|
LOGGING = {
|
|
'version': 1,
|
|
'disable_existing_loggers': False,
|
|
'handlers': {
|
|
'file': {
|
|
'level': 'INFO',
|
|
'class': 'logging.FileHandler',
|
|
'filename': '/var/log/django/thrillwiki.log',
|
|
},
|
|
},
|
|
'root': {
|
|
'handlers': ['file'],
|
|
},
|
|
}
|
|
```
|
|
|
|
### Infrastructure Monitoring
|
|
- Use Prometheus + Grafana for metrics
|
|
- Implement health check endpoints
|
|
- Set up log aggregation (ELK stack or similar)
|
|
- Monitor database performance
|
|
- Track API response times
|
|
|
|
## Security Considerations
|
|
|
|
### Production Security Checklist
|
|
- [ ] HTTPS enforced with SSL certificates
|
|
- [ ] Security headers configured (HSTS, CSP, etc.)
|
|
- [ ] Database credentials secured
|
|
- [ ] Secret keys rotated regularly
|
|
- [ ] CORS properly configured
|
|
- [ ] Rate limiting implemented
|
|
- [ ] File upload validation
|
|
- [ ] SQL injection protection
|
|
- [ ] XSS protection enabled
|
|
- [ ] CSRF protection active
|
|
|
|
### Security Headers
|
|
```python
|
|
# backend/config/settings/production.py
|
|
SECURE_SSL_REDIRECT = True
|
|
SECURE_HSTS_SECONDS = 31536000
|
|
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
|
|
SECURE_HSTS_PRELOAD = True
|
|
SECURE_CONTENT_TYPE_NOSNIFF = True
|
|
SECURE_BROWSER_XSS_FILTER = True
|
|
X_FRAME_OPTIONS = 'DENY'
|
|
|
|
# CORS for API
|
|
CORS_ALLOWED_ORIGINS = [
|
|
"https://yourdomain.com",
|
|
"https://www.yourdomain.com",
|
|
]
|
|
```
|
|
|
|
## Backup and Recovery
|
|
|
|
### Database Backup Strategy
|
|
```bash
|
|
# Automated backup script
|
|
#!/bin/bash
|
|
pg_dump $DATABASE_URL | gzip > backup_$(date +%Y%m%d_%H%M%S).sql.gz
|
|
aws s3 cp backup_*.sql.gz s3://your-backup-bucket/database/
|
|
```
|
|
|
|
### Media Files Backup
|
|
```bash
|
|
# Sync media files to S3
|
|
aws s3 sync ./shared/media/ s3://your-media-bucket/media/ --delete
|
|
```
|
|
|
|
## Scaling Strategies
|
|
|
|
### Horizontal Scaling
|
|
- Load balancer configuration
|
|
- Database read replicas
|
|
- CDN for static assets
|
|
- Redis clustering
|
|
- Auto-scaling groups
|
|
|
|
### Vertical Scaling
|
|
- Database connection pooling
|
|
- Application server optimization
|
|
- Memory usage optimization
|
|
- CPU-intensive task optimization
|
|
|
|
## Troubleshooting Guide
|
|
|
|
### Common Issues
|
|
1. **Build failures**: Check dependencies and environment variables
|
|
2. **Database connection errors**: Verify connection strings and firewall rules
|
|
3. **Static file 404s**: Ensure collectstatic runs and paths are correct
|
|
4. **CORS errors**: Check CORS configuration and allowed origins
|
|
5. **Memory issues**: Monitor application memory usage and optimize queries
|
|
|
|
### Debug Commands
|
|
```bash
|
|
# Backend debugging
|
|
cd backend
|
|
uv run manage.py check --deploy
|
|
uv run manage.py shell
|
|
uv run manage.py dbshell
|
|
|
|
# Frontend debugging
|
|
cd frontend
|
|
pnpm run build --debug
|
|
pnpm run preview
|
|
```
|
|
|
|
This deployment guide provides a comprehensive approach to deploying the ThrillWiki monorepo across various platforms while maintaining security, performance, and scalability. |