2025-12-17 00:42:57 +02:00

13 KiB

Development & Architecture Guide

Project Structure Overview

aws-final-project/
├── backend/                    # FastAPI Python application
├── frontend/                   # React Vite SPA
├── helm/dating-app/           # Kubernetes Helm chart
├── docker-compose.yml         # Local dev environment
├── README.md                  # Main documentation
├── DEPLOYMENT.md              # Deployment instructions
└── DEVELOPMENT.md             # This file

Backend Architecture

Core Components

app/db.py - Database Connection

  • SimpleConnectionPool for connection management
  • Auto-initialization of tables on startup
  • Safe context manager for connections

app/config.py - Configuration Management

  • Environment variable loading with defaults
  • Settings validation
  • Centralized config source

app/auth/ - Authentication

  • utils.py: Password hashing (bcrypt), JWT creation/validation
  • __init__.py: Authorization dependency for FastAPI

app/models/ - Database Models

  • Pure Python classes representing database entities
  • User, Profile, Photo, Like, Conversation, Message
  • to_dict() methods for serialization

app/schemas/ - Pydantic Schemas

  • Request/response validation
  • Type hints and documentation
  • Automatic OpenAPI schema generation

app/services/ - Business Logic

  • auth_service.py: Registration, login
  • profile_service.py: Profile CRUD, discovery
  • photo_service.py: Upload, storage, deletion
  • like_service.py: Like tracking, match detection
  • chat_service.py: Message operations, conversations

app/routers/ - API Endpoints

  • Modular organization by feature
  • Protected endpoints with get_current_user dependency
  • Consistent error handling

Database Design

users table

id (PK), email (UNIQUE), hashed_password, created_at, updated_at

profiles table

id (PK), user_id (FK UNIQUE), display_name, age, gender, 
location, bio, interests (JSONB), created_at, updated_at

photos table

id (PK), profile_id (FK), file_path, display_order, created_at

likes table

id (PK), liker_id (FK), liked_id (FK), created_at
UNIQUE(liker_id, liked_id)

conversations table

id (PK), user_id_1 (FK), user_id_2 (FK), created_at, updated_at
UNIQUE(user_id_1, user_id_2)

messages table

id (PK), conversation_id (FK), sender_id (FK), content, created_at

Key Design Decisions

  1. Synchronous psycopg2 - Per requirements, enables simpler debugging
  2. Connection Pooling - SimpleConnectionPool provides basic pooling
  3. Auto-initialization - Tables created on startup, no separate migration step
  4. JWT Tokens - Stateless auth, no session storage needed
  5. Local File Storage - Disk-based for lab, easily swappable to S3
  6. Match Logic - Dual-directional like check in database

Adding New Features

Example: Add "message read receipts"

  1. Add schema to app/schemas/message.py:
class MessageResponse(BaseModel):
    # ... existing fields ...
    read_at: Optional[str] = None
  1. Update database in app/db.py:
cur.execute("""
    ALTER TABLE messages ADD COLUMN read_at TIMESTAMP
""")
  1. Add method to app/services/chat_service.py:
@staticmethod
def mark_message_read(message_id: int):
    # Implementation
  1. Add endpoint to app/routers/chat.py:
@router.patch("/messages/{message_id}/read")
def mark_read(message_id: int, current_user: dict = Depends(get_current_user)):
    # Implementation

Frontend Architecture

Project Structure

frontend/src/
├── pages/              # Full page components
│   ├── Login.jsx
│   ├── Register.jsx
│   ├── ProfileEditor.jsx
│   ├── Discover.jsx
│   ├── Matches.jsx
│   └── Chat.jsx
├── styles/            # CSS for each page
│   ├── auth.css
│   ├── profileEditor.css
│   ├── discover.css
│   ├── matches.css
│   └── chat.css
├── api.js            # Centralized API client
├── App.jsx           # Main app component
├── App.css           # Global styles
├── main.jsx          # React entry point
└── index.css         # Global CSS

API Client Pattern

src/api.js provides:

  • Axios instance with base configuration
  • Request interceptor for JWT token injection
  • Response interceptor for 401 handling
  • Organized API methods by feature:
    • authAPI.register(), authAPI.login()
    • profileAPI.getMyProfile(), profileAPI.discoverProfiles()
    • etc.

Usage in components:

import { profileAPI } from '../api'

const response = await profileAPI.getMyProfile()
const profiles = await profileAPI.discoverProfiles()

State Management

Simple localStorage approach:

  • JWT stored in localStorage, auto-attached to requests
  • User ID stored for context
  • Component-level state with useState for forms
  • No Redux/MobX needed for MVP

Example:

// After login
localStorage.setItem('token', response.data.access_token)
localStorage.setItem('user_id', response.data.user_id)

// On API calls
// Automatically added by axios interceptor
Authorization: `Bearer ${token}`

// On logout
localStorage.removeItem('token')
localStorage.removeItem('user_id')

Component Patterns

Page Component Template:

export default function FeaturePage() {
  const [data, setData] = useState([])
  const [isLoading, setIsLoading] = useState(false)
  const [error, setError] = useState('')

  useEffect(() => {
    loadData()
  }, [])

  const loadData = async () => {
    try {
      setIsLoading(true)
      const response = await featureAPI.getData()
      setData(response.data)
    } catch (err) {
      setError(err.response?.data?.detail || 'Error')
    } finally {
      setIsLoading(false)
    }
  }

  return (
    <div className="feature-page">
      {error && <div className="error-message">{error}</div>}
      {/* JSX */}
    </div>
  )
}

Styling Approach

  • CSS modules for component isolation
  • Global styles in index.css and App.css
  • BEM naming convention for clarity
  • Mobile-responsive with flexbox/grid

Environment Configuration

Frontend uses Vite's import.meta.env:

// In src/api.js
const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:8000'

In frontend/.env:

VITE_API_URL=http://localhost:8000

Docker Build Process

Backend Dockerfile

# Multi-stage not needed
# Single stage with Python 3.11
# System dependencies: gcc, postgresql-client
# Python dependencies: fastapi, uvicorn, etc.
# Health check via /health endpoint
# CMD: uvicorn main:app

Frontend Dockerfile

# Multi-stage: builder + runtime
# Stage 1: Build with Node
#   - npm install
#   - npm run build -> dist/
# Stage 2: Runtime with nginx
#   - nginx:alpine
#   - Copy dist to /usr/share/nginx/html
#   - Custom nginx.conf for SPA routing
#   - Health check via /health endpoint

Nginx Configuration

Handles:

  • SPA routing: try_files fallback to index.html
  • Static file caching: 1-year expiry for assets
  • Deny access to hidden files
  • Health check endpoint

Kubernetes Deployment

Helm Chart Structure

Chart.yaml - Chart metadata

values.yaml - Default configuration (override for different environments)

values-lab.yaml - Home-lab specific values

  • Single replicas
  • Local storage classes
  • Default passwords (change in production)

values-aws.yaml - AWS specific values

  • Multiple replicas
  • EBS storage class
  • ALB ingress class
  • RDS database URL

Templates:

  • namespace.yaml - Creates dedicated namespace
  • configmap.yaml - Backend and frontend config
  • secret.yaml - PostgreSQL credentials
  • postgres.yaml - PostgreSQL deployment + PVC + service
  • backend.yaml - Backend deployment + service
  • frontend.yaml - Frontend deployment + service
  • ingress.yaml - Ingress for both services

Deployment Flow

  1. Helm reads values file
  2. Templates rendered with values
  3. Kubernetes resources created in order:
    • Namespace
    • ConfigMap, Secret
    • PVC
    • Postgres deployment waits for PVC
    • Backend deployment waits for postgres
    • Frontend deployment (no deps)
    • Services for each
    • Ingress routes traffic

Network Architecture

Internet
    |
  Ingress (nginx/traefik)
    |
    +-> Frontend Service (80) -> Frontend Pods
    |
    +-> Backend Service (8000) -> Backend Pods
                                       |
                                    Postgres Service (5432)
                                       |
                                    Postgres Pod

Storage

PVC for Postgres:

  • ReadWriteOnce access mode
  • Survives pod restarts
  • Data persists across deployments

PVC for Backend Media:

  • ReadWriteMany access mode (for multiple replicas)
  • Shared media storage across pods
  • Migrates to S3 for cloud deployments

Development Workflow

Local Testing

# 1. Modify code
# 2. Test with compose
docker-compose up -d
curl http://localhost:8000/docs

# 3. Modify Helm values
# 4. Test with Helm (dry-run)
helm install dating-app ./helm/dating-app \
  -n dating-app --dry-run --debug

# 5. Test with Helm (actual)
helm install dating-app ./helm/dating-app \
  -n dating-app --create-namespace

# 6. Verify
kubectl get all -n dating-app

Code Changes

Backend changes:

  • Edit Python files in app/
  • Changes automatically available in dev environment
  • Production requires rebuilding Docker image

Frontend changes:

  • Edit .jsx files
  • Changes automatically available in dev environment
  • Production requires rebuilding and redeploying

Database schema changes:

  • Modify app/db.py init_db()
  • For Alembic (future): alembic revision --autogenerate
  • Existing migrations: Update manually or recreate database

Performance Considerations

Backend

  • Connection pooling limits: Currently 1-20 connections
  • Query optimization: Use indexes on foreign keys
  • Response caching: Can add for discover endpoint
  • Pagination: Not implemented yet, add for large datasets

Frontend

  • Image optimization: Profile pictures should be compressed
  • Lazy loading: Add for discover card images
  • Code splitting: Can split by route
  • Caching: Service workers for offline support

Database

  • Indexes created on common query columns
  • JSONB for interests enables efficient queries
  • Unique constraints prevent duplicates
  • Foreign keys maintain referential integrity

Testing Strategy

Unit Tests (Future)

# backend/tests/
# test_auth.py - Auth functions
# test_services.py - Service logic
# test_routers.py - API endpoints

Integration Tests (Future)

# Full workflow testing
# Database interactions
# API contract validation

E2E Tests (Future)

# frontend/tests/
# User registration flow
# Profile creation
# Swiping and matching
# Chat functionality

Manual Testing Checklist

  • Registration with new email
  • Login with correct password
  • Create and update profile
  • Upload multiple photos
  • Delete photos
  • View discover profiles
  • Like a user
  • Check matches
  • Send message to match
  • View conversation history
  • Logout

Security Considerations

Current Implementation

  • Password hashing with bcrypt
  • JWT with expiration
  • CORS configured
  • Protected endpoints
  • SQL injection prevention (parameterized queries)
  • Rate limiting on auth endpoints
  • HTTPS/TLS enforcement
  • CSRF token for state-changing operations
  • Input validation and sanitization
  • Audit logging
  • API key authentication for service-to-service
  • Secrets management (Vault)
  • Regular security scanning
  • Penetration testing

Data Protection

  • Encrypt sensitive data in transit (HTTPS)
  • Encrypt sensitive data at rest
  • Implement data retention policies
  • GDPR compliance (right to delete, data export)
  • Regular backups with encryption
  • Secure backup storage

Common Issues & Solutions

Issue: Photo uploads fail

Cause: Media directory not writable Solution: Check MEDIA_DIR permissions, ensure PVC mounted

Issue: Matches not showing

Cause: Mutual like check query fails Solution: Verify both users liked each other, check database

Issue: Slow profile discovery

Cause: N+1 query problem Solution: Add query optimization, batch load photos

Issue: Connection pool exhausted

Cause: Too many concurrent requests Solution: Increase pool size, add connection timeout

Future Enhancements

  1. WebSocket Chat

    • Real-time messages without polling
    • Typing indicators
    • Read receipts
  2. Image Optimization

    • Automatic compression
    • Multiple sizes for responsive design
    • CDN distribution
  3. Recommendation Engine

    • Machine learning for match suggestions
    • Interest-based filtering
    • Location-based matching
  4. Advanced Features

    • Video calls
    • Story features
    • Search and filtering
    • Blocking/reporting
    • Verification badges
  5. Infrastructure

    • Load balancing improvements
    • Caching layer (Redis)
    • Message queue (RabbitMQ) for async tasks
    • Monitoring and alerting
    • CI/CD pipeline
    • Database read replicas