Cascading-comments SPA with image/text attachments, CAPTCHA, real-time updates via WebSocket, async tasks, and JWT auth.
Backend
- Django 5 + Django REST Framework
- Django Channels (WebSocket, real-time new comments)
- Celery + Redis (async image resize, email events)
- PostgreSQL
- SimpleJWT (optional auth — anonymous comments allowed)
- bleach (HTML allowlist), Pillow (image resize), django-simple-captcha
Frontend
- Vue 3 + Vite + Pinia
- Axios, native WebSocket
- Lightbox via CSS modal + transition
Infra
- Docker Compose: web (Django+Daphne), worker (Celery), postgres, redis, frontend (nginx serving Vue build)
- Form: User Name (latin+digits), Email, Home page (URL, optional), CAPTCHA, Text
- Allowed HTML in Text:
<a href="" title="">,<code>,<i>,<strong>(XHTML validated — tag closure check) - Cascading replies (unlimited depth)
- Top-level comments table — sortable by User Name / Email / Date (asc + desc)
- Pagination 25/page
- Default order LIFO (newest first)
- XSS + SQLi protection (bleach + Django ORM)
- File attachments:
- Image JPG/GIF/PNG → auto-resize to max 320×240 (proportional)
- Text file TXT → max 100 KB
- Lightbox-style file preview
- Live preview without page reload
- HTML-tag insert buttons
[i] [strong] [code] [a] - Server + client validation
- Queue: Celery tasks (image resize, email notifications)
- Cache: Redis caches top-level comment listing
- Events: Django signals broadcast new comments to WS group
- JWT: SimpleJWT (optional login — anonymous still allowed)
- GraphQL (Strawberry) at
/graphql/— Query.topComments (cursor-paginated), Query.searchComments, Mutation.createComment - Message broker: RabbitMQ (AMQP) for Celery — 3 queues (
images,notifications,search) - NoSQL: Elasticsearch — comments indexed asynchronously,
/api/search/?q=with DB fallback - Cloud: Hetzner + AWS deployment blueprints in
deploy/
- Scale architecture for 1M comments + 100k users / 24h — see
docs/ARCHITECTURE.md - Read replica router (
DATABASE_URL_REPLICA→PrimaryReplicaRouter) - Partitioning template at
db/partitioning.sql(monthly bycreated_at) - S3 attachments + CDN via
USE_S3=1 - Idempotency-Key middleware (Redis-backed, 24 h TTL)
- Rate limiting on POST (django-ratelimit)
- Prometheus
/metricsfor observability - Load test:
loadtest/locustfile.py— mixed 85/10/4/1 read/reply/preview/write profile hitting the ТЗ target
cp .env.example .env
docker compose up --build
# Frontend → http://localhost:8080
# API → http://localhost:8000/api/
# GraphQL → http://localhost:8000/graphql/
# Admin → http://localhost:8000/admin/
# Metrics → http://localhost:8000/metrics
# RabbitMQ → http://localhost:15672 (comments/comments)
# ES → http://localhost:9200/_cat/indices?vFull step-by-step launch guide → RUNBOOK.md. Architecture rationale (1M / 100k target) → docs/ARCHITECTURE.md.
dzencode-comments/
├── backend/ # Django project
├── frontend/ # Vue 3 SPA
├── nginx/ # Vue build serve config
├── db/ # schema.sql + ER (MySQL Workbench)
├── docs/ # additional docs
├── docker-compose.yml
└── .env.example
See db/schema.sql. Compatible with MySQL Workbench import for ER diagram.
docker compose down -v
docker compose up --build
# verify frontend, post comment, see WS update in second tab, attach image