A Telegram-based image swipe platform built with Django, Svelte, and Celery.
backend/ Django project settings
bot/ Telegram bot, image models, swipe API
common/ Shared models, middleware, utilities
frontend/ Svelte SPA (Telegram Mini App)
users/ User model and Telegram auth
dockerfiles/ Dockerfiles for all services
fixtures/ Local development fixtures
run/ Gunicorn / Celery entrypoint scripts
templates/ Django HTML templates
Copy the environment template and fill in your values:
cp .env.example .env
Required credentials:
API_ID and API_HASH at https://my.telegram.org/appsBOT_TOKENRun tests (SQLite in-memory, no external services needed):
uv run manage.py test
Start all services:
./up.sh
This command builds the images and starts the full stack with local overrides (Django dev server, fixture user, 5 placeholder images, no catcher).
On first run the following happens automatically:
tlg_id=1, superuser)Open http://localhost:8001 in your browser.
Note:
up.shusesdocker-compose.local.yamloverrides — it is intended for local use only, not production.
In local mode (LOCAL=1) authentication is bypassed: every request is authenticated as the fixture user and /api/tlg-token/ returns a JWT token without Telegram WebApp validation.
Set TLG_LONG_POLLING=1 in .env to use long polling instead of webhooks (no ngrok needed locally).
Use this when you need real Telegram auth — for example, to test the Mini App from your phone. Unlike up.sh, this mode does not bypass authentication.
Traefik runs as part of the stack and routes traffic:
/cdn/* → MinIO/bot/* → Telegram bot webhook/* → Djangongrok tunnels port 80 to a public HTTPS URL set as EXTERNAL_HOST, baked into the frontend build.
.envEXTERNAL_HOST set in .env to your ngrok static domain — get one free at dashboard.ngrok.com/domainsIn @BotFather: set the Menu Button URL to https://<your-ngrok-domain>/.
Start ngrok tunnel (run in a separate terminal):
ngrok http --url="$EXTERNAL_HOST" 80
Deploy the stack:
./up-ngrok.sh
Builds the image with the correct EXTERNAL_HOST and starts all services including Traefik.
Note: ngrok must be running before requests reach the stack. Keep the ngrok terminal open.
The project uses Docker Swarm with Traefik for TLS termination.
Set up a server with Docker Swarm initialized.
Fill .env with production values (EXTERNAL_HOST, etc.).
Deploy:
docker stack deploy -c docker-compose.yaml -c docker-compose.traefik.yaml timage
See .env.example for a full list of required variables.