Skip to content
/ ChattyM Public

Minimal social network built with Django 5, PostgreSQL, and Bootstrap 5. It ships with email‑based auth, profiles, posts, comments, likes, follows, DMs, notifications, and a small REST API.

Notifications You must be signed in to change notification settings

p95max/ChattyM

Repository files navigation

ChattyM — Social Network (Django)

Minimal social network built with Django 5, PostgreSQL, and Bootstrap 5. Focuses on clean architecture, security-first authentication, and production-ready features: email-based auth with CAPTCHA protection, user profiles, posts, comments, likes, follows, DMs, notifications, and a small but well-structured REST API.


Features

👤🔐 User Authentication

  • Custom User model with email as login (USERNAME_FIELD = email)
  • Sign up / sign in / sign out
  • Email confirmation & password reset (console backend in dev)
  • Auth via Google (OAuth2)

🛡️ Authentication protected with CAPTCHA

  • Login & registration are protected with Cloudflare Turnstile CAPTCHA
  • Implemented via django-turnstile

📝 Content

  • Create / edit / delete posts (image + tags)
  • Comments with reply support, soft-delete and edit tracking
  • Likes with a likes_count counter on posts

📄 User Profiles

  • Avatar, birthday, editable profile fields
  • Profile page with posts, followers and stats

🔁 Subscriptions / Follow

  • Follow / unfollow users with follower counts
  • Personalized feeds (posts from followed users)

🔔 Notifications

  • In-app notification model
  • Small internal API to mark notifications as read

💬 Messaging

  • Direct messages with Conversation / Participant / Message models

🔌 REST API

  • DRF-based endpoints (posts CRUD, search, ordering)
  • Swagger / OpenAPI docs at /api/docs/ (via drf-spectacular)

🌓 Theme Switcher

  • Built-in light / dark mode toggle for the UI
  • Respects system preferences and persists user choice

🧊 Snowfall Effect

  • Modern snowfall animation rendered on a full-page canvas
  • Automatically adapts to the active UI theme (light/dark) for optimal contrast
  • Non-intrusive (pointer-events: none) and performance-friendly (requestAnimationFrame)

📊 Monitoring (Prometheus + Grafana + Alertmanager)

  • Application-level metrics (Django)
  • Infrastructure and container metrics
  • Health checks and uptime monitoring
  • Alerting (ready for future extensions)

⚙️ Admin & Dev Tooling

  • Django admin configured for users, posts, comments and notifications
  • Fully Dockerized application
  • Entrypoint script runs migrations and collects static files

Tech stack

  • Python: 3.11+
  • Django: 5.x
  • DB: PostgreSQL (docker compose uses postgres:15)
  • API: DRF, drf‑spectacular (optional)
  • Auth: django‑allauth (email login)
  • Storage: local filesystem by default (S3/MinIO optional)
  • Deps: Poetry
  • UI: Django Templates + Bootstrap 5

Data model (excerpt)

Post (simplified) used in this build:

class Post(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="posts")
    title = models.CharField(max_length=100)
    text = models.TextField(max_length=2500)
    image = models.ImageField(null=True, blank=True, upload_to="posts/img/")
    likes_count = models.PositiveIntegerField(default=0)  # denormalized counter
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    is_active = models.BooleanField(default=True)
    tags = TaggableManager(blank=True)

    class Meta:
        ordering = ["-created_at"]
        indexes = [
            models.Index(fields=["created_at"]),
            models.Index(fields=["user"]),
        ]

Notes:

  • likes_count is maintained in code (signals/service layer) as a denormalized counter.
  • tags requires django‑taggit; run migrations after enabling the app.
  • Images are user uploads. For demo fixtures, we copy seed images from static/ to media/ (see below).

Requirements

Make sure these are in pyproject.toml (or requirements.txt):

  • Django>=5
  • djangorestframework
  • drf-spectacular (optional, for /api/docs)
  • django-allauth
  • django-taggit
  • Pillow
  • psycopg2-binary (or psycopg[binary] when using psycopg3)

Environment

Create .env from .env.example:

## test secret key for quick launch
SECRET_KEY=django-insecure-8z&v%h6@p_c7!zq^m8y4$w2u1r0t9q3f5k1n7b4e0d6g2j8l5
DJANGO_DEBUG=1
POSTGRES_DB=chattym
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
DB_HOST=db
DB_PORT=5432
ALLOWED_HOSTS=*
EMAIL_BACKEND=django.core.mail.backends.console.EmailBackend

# S3/MinIO (optional)
USE_S3=0
MINIO_ENDPOINT=
MINIO_ACCESS_KEY=
MINIO_SECRET_KEY=
MINIO_BUCKET=

Media configuration (defaults in settings):

MEDIA_URL=/media/
MEDIA_ROOT=/app/media
STATIC_URL=/static/
STATIC_ROOT=/app/staticfiles

Quick start — Docker

Project includes Dockerfile and docker-compose.yml.

# build and run
docker compose up --build

The entrypoint waits for DB, runs migrate, optional superuser creation (via DJANGO_SUPERUSER_EMAIL/DJANGO_SUPERUSER_PASSWORD), collectstatic, then launches the dev server.


Test access (fixtures)

Default admin (if present in fixtures):

Email:

admin@users.com

Password:

TestUser#2025

All seed users share the same password for convenience in local dev.


Load demo fixtures (/fixtures)

docker compose run --rm --entrypoint "" web python manage.py loaddata   fixtures/users_fixture.json   fixtures/users_emails_fixture.json   fixtures/posts_fixture.json   fixtures/comments_fixture.json

Local development (non‑Docker)

poetry install
poetry run python manage.py migrate
poetry run python manage.py runserver

Useful:

poetry run python manage.py loaddata fixtures/users_fixture.json
poetry run pytest -q

Monitoring (Prometheus + Grafana + Alertmanager)

🧩 Stack Overview

  • Prometheus — metrics collection and storage
  • Grafana — visualization and dashboards
  • Alertmanager — alert routing and notifications
  • django-prometheus — Django application metrics
  • node_exporter — host-level metrics (CPU, RAM, disk, network)
  • cAdvisor — Docker container metrics
  • blackbox-exporter — external HTTP endpoint probing

All services run in a shared Docker network and are orchestrated via Docker Compose.

🚀 How to Start Monitoring Stack

Run from the project root:

docker compose \
  -f docker-compose.yml \
  -f monitoring/docker-compose.monitoring.yml \
  up --build

If you encounter network/DNS issues after changing compose files, use a CLEAN RESTART:

docker compose \
  -f docker-compose.yml \
  -f monitoring/docker-compose.monitoring.yml \
  down && \
docker network rm chattym_monitoring chattym_default 2>/dev/null || true && \
docker compose \
  -f docker-compose.yml \
  -f monitoring/docker-compose.monitoring.yml \
  up --build

🌐 Service Endpoints

Service URL
Django App http://localhost:8000
Prometheus http://localhost:9090
Grafana http://localhost:3000
Alertmanager http://localhost:9093

📊 Grafana Dashboards (Recommended)

You can import ready-to-use dashboards from Grafana Marketplace:

  • Node Exporter Full — 1860
  • cAdvisor — 14282
  • Blackbox Exporter — 7587
  • Django / Python Metrics — 7990, 17868

🚨 Alerting

Alerting rules are defined in: monitoring/prometheus/alert_rules.yml

Alertmanager is configured and running. Currently, alerts are routed to a placeholder receiver (dev-null). The setup is ready for future integrations:

  • Telegram
  • Slack
  • Email (SMTP)
  • Webhooks

📈 Metrics Collection

Prometheus collects metrics from:

  1. Django application
  • endpoint: /metrics
  • request latency, status codes, DB queries, exceptions
  1. Node Exporter
  • CPU, memory, disk, filesystem, network
  1. cAdvisor
  • container CPU/memory usage
  • restart counts
  • container lifecycle
  1. Blackbox Exporter
  • HTTP availability checks (e.g. https://google.com)

You can verify targets here: http://localhost:9090/targets

All targets should be in UP state.

✅ Status

✔ Monitoring stack is fully operational

✔ Metrics collection verified

✔ Ready for dashboards and alerting extensions


API

When drf-spectacular is enabled:

  • OpenAPI JSON: /api/schema/
  • Swagger UI: /api/docs/

Posts API (examples):

# list posts
curl -s http://localhost:8000/api/posts/

# search by text/title
curl -s "http://localhost:8000/api/posts/?search=django"

# create with tags and optional image
curl -s -X POST http://localhost:8000/api/posts/   -F "title=Hello"   -F "text=World"   -F "tags=django,chattym"   -F "image=@/path/to/file.jpg"

Common query params: ?search=, ?ordering=, ?user=, ?active=1, ?q=.


Testing (Pytest)

The project uses Pytest and runs tests inside Docker to ensure a consistent environment (Python, dependencies, and PostgreSQL).

# clean start (app only) + run tests
docker compose down --remove-orphans -v \
  && docker network prune -f \
  && docker compose build --no-cache \
  && docker compose up -d --build \
  && docker compose exec web sh -lc "poetry run pytest -v"

Note:

  • Tests are executed inside the web container.
  • Volumes are removed (-v), so the database is reset (expected for tests).

Troubleshooting

  • Images 404 in dev → copy seed images (static/… → media/…, see above). Verify MEDIA_URL=/media/ and dev server serves media in urls.py.
  • Tagging fails → ensure django-taggit is in INSTALLED_APPS, run makemigrations/migrate.
  • Auth emails not received → dev uses console backend; switch to SMTP in .env for real emails.
  • DB issues in Dockerdocker compose down -v to clear volumes, then up --build.
  • Swagger missing → install/enable drf-spectacular and include schema URLs in urls.py.

Project paths

  • apps/ — users, posts, comments, likes, follows, messaging, notifications
  • config/ — settings & urls
  • docker/entrypoint.sh — boot logic for containers
  • fixtures/ — demo data
  • static/, templates/ — client assets and templates

Roadmap / TODO

  • One-command service startup via Docker Compose (docker compose up --build)

  • Comprehensive container init script (docker/entrypoint.sh)

  • Fixture set for fast, end-to-end service testing (fixtures/)

  • Hide the admin URL in urls via .env

  • Auth via Google (OAuth2)

  • Grafana + Prometheus + Alertmanager integration

  • Auth protected with CAPTCHA (django-turnstile)

  • CI for tests/linters (flake8)

  • Snowfall visual effect for the UI (with switcher)

  • Test coverage of the service


Author: Maksym Petrykin
Email: m.petrykin@gmx.de
Telegram: @max_p95

About

Minimal social network built with Django 5, PostgreSQL, and Bootstrap 5. It ships with email‑based auth, profiles, posts, comments, likes, follows, DMs, notifications, and a small REST API.

Topics

Resources

Stars

Watchers

Forks