Portfolio Overview
Modern Stack
Built with Next.js 15, TypeScript, Django 5, and WebSockets for real-time interaction.
Cloud Native
Deployed on Render and Heroku with distributed services, Redis for pub/sub, and S3 for storage.
Secure & Reliable
Protected with WAF, rate limiting, and automatic health checks to ensure high availability.
Key Features
Interactive Terminal
Live in-browser terminal that allows users to run and interact with projects in real-time.
Multi-Service Architecture
Separated frontend, API, and terminal services for better scalability and isolation.
CI/CD Pipeline
Automated GitHub Actions workflows for continuous integration and deployment.
Security First
Implemented WAF, CSP headers, rate limiting, and sandbox environments for terminal sessions.
System Performance
Technical Architecture
Key Components
Frontend Service
- Next.js 15 with TypeScript
- Tailwind CSS for styling
- React Query for data fetching
- Deployed on Heroku
- Xterm.js for terminal UI
Backend Service
- Django 5 REST API
- Django Channels for WebSockets
- PostgreSQL database
- Redis for caching/pub-sub
- S3 storage for media
Terminal Service
- FastAPI with WebSockets
- PTY process management
- Sandboxed Docker environment
- Command validation & security
- Project file management
Data Flow
- Request Initiation: User requests arrive through Cloudflare CDN, which provides edge caching and WAF protection.
- API Handling: Next.js frontend communicates with Django backend via REST API for project data.
- WebSocket Connection: For terminal sessions, the browser establishes a WebSocket connection to Django Channels.
- Terminal Proxying: Django forwards terminal commands to the isolated terminal service via internal WebSocket.
- PTY Execution: Terminal service executes commands in a sandboxed environment with resource limits.
- Response Flow: Command outputs flow back through the chain to the user's browser terminal.
Cloud Deployment Architecture
Multi-Cloud Strategy Benefits
- Provider Specialization: Each service runs on the platform best suited for it
- Cost Optimization: Leveraging free tiers across multiple providers
- Vendor Lock-in Avoidance: Distributed across multiple cloud providers
- Increased Reliability: Reduced risk of single provider outages
- Service Isolation: Each component can scale independently
- Security Compartmentalization: Limited access between services
- Geographic Distribution: Services closer to their dependencies
- Custom Optimization: Each service configured optimally for its platform
Platform-Specific Optimizations
Heroku Optimizations
- Build cache for faster deployments
- Brotli compression for assets
- Automatic HTTPS certification
- Eco dyno for cost efficiency
- Integrated logging and monitoring
Render Optimizations
- Private service networking
- Persistent disk for terminal sessions
- Zero-downtime deployments
- Custom deployment scripts
- Automated health checks
AWS Integrations
- S3 for persistent media storage
- CloudFront for global asset delivery
- IAM roles for secure access
- Versioned object storage
- Lifecycle rules for cost management
My Architecture Choices
When designing this portfolio, I made deliberate architectural choices that balance modern web best practices with practical constraints:
Why a Multi-Service Architecture?
I chose to split the application across multiple services to demonstrate microservice principles while keeping each component focused on its core responsibility. This separation allowed me to select the best technology for each specific need - Next.js for a snappy UI, Django for a robust API, and a dedicated terminal service for secure command execution.
Why These Technologies?
My technology stack reflects my full-stack expertise. I selected Next.js and React for frontend as they provide the best developer experience and performance. For backend, Django offers a mature ecosystem with excellent security features. I added Redis for inter-service communication and PostgreSQL for robust data storage. This combination delivers high performance while showcasing my versatility across the stack.
My Cloud Deployment Strategy
Rather than using a single cloud provider, I intentionally distributed services across multiple platforms to optimize cost efficiency and demonstrate multi-cloud orchestration skills. This approach also avoids vendor lock-in and allows each component to run in its most suitable environment.
Interactive Terminal
Interactive Code Execution
The terminal feature allows users to interact with project code directly in the browser. This provides:
- Hands-on experience with project functionality
- Ability to test commands and see outputs in real-time
- Understanding of project structure and workflow
- Deeper engagement than static code samples
Example Commands:
$ cd projects/minirt $ make $ ./miniRT scenes/demo.rt # Renders a raytraced image directly in the terminal
Terminal Implementation
WebSocket Protocol Flow:
- Browser connects to Django backend via secure WebSocket
- Django validates user permissions & project access
- Backend connects to internal terminal service
- Terminal service spawns PTY process in sandbox
- User input is forwarded through the chain
- Terminal output streams back in real-time
Security Measures:
- Command allowlist with regex validation
- Resource limits (512MB RAM, 2 CPU cores)
- 30-minute session timeout
- Read-only filesystem (except project directories)
Key Technologies:
DevOps & Infrastructure
CI/CD Pipeline
Code Push
GitHub Actions
Tests & Validation
Build Containers
Deploy
Key Features:
- Path Filtering: Only rebuild and deploy services affected by changes
- Automatic Database Migrations: Safe application of schema changes
- Force Deploy Flag: Deploy all services with commit message flag [deploy-all]
- Rollback Support: Quick rollback to previous version if needed
Infrastructure as Code
# Docker Compose for local development version: '3.8' services: frontend: build: ./portfolio_ui ports: - "3000:3000" volumes: - ./portfolio_ui:/app backend: build: ./portfolio_api ports: - "8000:8000" env_file: .env depends_on: - postgres - redis terminal: build: ./portfolio-terminal ports: - "8001:8001" env_file: .env volumes: - project_files:/home/coder/projects postgres: image: postgres:15 volumes: - postgres_data:/var/lib/postgresql/data redis: image: redis:7-alpine volumes: postgres_data: project_files:
Service Health Monitoring
To prevent free-tier services from shutting down due to inactivity, a mutual health check system was implemented:
# Django App Config - Health Checks def ready(self): if os.environ.get('RUN_MAIN') != 'true': def check_services_health(): """Ping other services to keep them alive""" services = { "terminal": os.environ.get( "TERMINAL_SERVICE_URL" ), "frontend": os.environ.get( "FRONTEND_URL" ) } for name, url in services.items(): try: response = requests.get( f"{url}/healthz", timeout=5 ) logger.info( f"{name} health check: {response.status_code}" ) except Exception as e: logger.error( f"{name} health check failed: {str(e)}" ) # Schedule health checks scheduler = BackgroundScheduler() scheduler.add_job( check_services_health, 'interval', minutes=15 ) scheduler.start()
Cloud Provider Integration
Render
- Django backend web service
- Terminal service (internal only)
- PostgreSQL database
- Redis cache service
- Private networking between services
Heroku
- Next.js frontend
- Node.js runtime
- Automatic HTTPS
- SSL certificate management
- Custom domain support
AWS
- S3 storage for media files
- CloudFront for CDN delivery
- IAM for access management
- Custom storage adapters
- Secure uploads and downloads
Security & Reliability
Web Application Security
Content Security Policy
Strict CSP headers prevent XSS attacks by controlling resource loading.
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https://*.amazonaws.com; connect-src 'self' wss://*.aouichou.me api.aouichou.me;
Rate Limiting Middleware
API endpoints are protected from abuse with rate limiting.
class RateLimitMiddleware: def __init__(self, get_response): self.get_response = get_response self.r = redis.Redis.from_url(settings.REDIS_URL) self.rate_limit = 60 # requests per minute def __call__(self, request): if not settings.DEBUG: ip = self.get_client_ip(request) key = f"ratelimit:{ip}:{int(time.time() / 60)}" requests = self.r.incr(key) self.r.expire(key, 60) if requests > self.rate_limit: return JsonResponse( {"error": "Rate limit exceeded"}, status=429 ) return self.get_response(request)
Terminal Security
Running interactive terminals in the browser presents unique security challenges. The following measures were implemented:
Command Validation
All terminal input is validated against an allowlist of safe commands.
# Allowed commands and patterns ALLOWED_COMMANDS = [ r"^ls(s+-[altrh1]+)?(s+[w./-]+)?$", r"^cd(s+[w./-]+)?$", r"^cats+[w./-]+$", r"^make(s+[w-]+)?$", r"^gccs+[w./-]+.c(s+-[ow]+)?$", r"^./[w-]+(s+[w./-]+)?$", # Additional safe commands... ] def is_command_allowed(cmd): return any(re.match(pattern, cmd) for pattern in ALLOWED_COMMANDS)
Container Isolation
Each terminal session runs in an isolated container with limited resources.
# Resource limits CONTAINER_CONFIG = { "memory": "512m", "memory-swap": "512m", "cpus": "2", "pids-limit": 100, "network-mode": "none", # No network access "read-only": True, # Read-only filesystem "tmpfs": { # Writable temp directories "/tmp": "rw,noexec,nosuid,size=100m", "/home/coder/projects": "rw,noexec,nosuid,size=100m" } }
Reliability Features
Error Handling & Reporting
- Structured logging with severity levels
- Automatic error reporting to admin
- User-friendly error messages
- Session recovery for interrupted connections
Backup & Disaster Recovery
- Daily database backups
- Versioned S3 storage for media files
- Configuration stored as environment variables
- Infrastructure as code for quick recovery
Automated Testing
Comprehensive test suite ensures system reliability and prevents regressions.