An open-source, community-focused event management platform.
This repository contains the backend API and business logic for Revel. The complete platform consists of:
- revel-backend (this repository) - Django Ninja REST API, business logic, database models
- revel-frontend - SvelteKit web application, user interface
- infra - Docker Compose setup, reverse proxy, observability stack, deployment configurations
Revel is an event management and ticketing platform designed with community at its heart. Initially created to serve the specific needs of queer, LGBTQ+, and sex-positive communities, it is built to be event-agnostic, scalable, and a powerful tool for any group that values privacy, control, and transparency.
Unlike monolithic, corporate platforms that treat events as transactions, Revel treats them as part of a larger community ecosystem.
You can try out an early version of Revel yourself at https://demo.letsrevel.io
The api lives at https://demo-api.letsrevel.io/api/docs
NOTE: Emails are dry, and the data is reset every day at 00:00 CET.
More info on what's available here.
Revel is being built to address the shortcomings of existing event platforms, especially for communities that prioritize safety, autonomy, and trust.
- For Communities, Not Corporations: Mainstream platforms often have restrictive content policies or a lack of privacy features, creating challenges for adult, queer, or activist-oriented events. Revel is explicitly designed to support these communities.
- Open, Transparent & Self-Hostable: Avoid vendor lock-in. You can host Revel on your own infrastructure for free, giving you complete control over your data and eliminating platform commissions. Its open-source nature means you can trust the code you run.
- Fair & Simple Pricing: For those who choose our future hosted version, the model is simple: no charge for free events or events where you handle payments yourself; a 1.5% + 0.25€ commission on paid tickets sold and bought through Revel. This significantly undercuts the high fees of major platforms and helps us keep the platform online, free and open source.
Revel combines the ticketing power of platforms like Eventbrite with the community-building tools of Meetup, all under a privacy-minded, open-source framework.
- Organizations: Create and manage your community's central hub. Customize its visibility (Public, Members-Only).
- Roles & Permissions: Assign roles like Owner, Staff, and Member, with a granular permission system to control who can create events, manage members, and more.
- Membership System: Manage a roster of members, enabling members-only events and fostering a sense of belonging.
- Advanced Attendee Screening: Gate event eligibility with custom questionnaires. Automatically review submissions or use a manual/hybrid approach to ensure attendees align with your community's values.
- Full Data Ownership: When self-hosting, you control your data. No third-party trackers, no selling of event data. Keep your community's information safe.
- Tailored Invitations: Send direct invitations that can waive specific requirements (like questionnaires, membership or purchase) for trusted guests.
- Event & Series Management: Easily create single events or recurring event series under your organization.
- Ticketing & RSVPs: Support for both paid/free ticketed events (powered by Stripe) and simpler RSVP-based gatherings.
- Batch Ticket Purchases: Buy multiple tickets in a single transaction with individual guest names for each ticket holder.
- Venue & Seat Management: Define venues with sectors and individual seats. Support for general admission, random seat assignment, or user-selected seating.
- QR Code Check-In: Manage event entry smoothly with QR code tickets and a staff-facing check-in flow.
- Apple Wallet Integration: Tickets can be added to Apple Wallet for easy access at events (optional, requires Apple Developer certificate).
- Potluck Coordination: A unique, built-in system for attendees to coordinate bringing items, dietary restrictions and preferences, moving logistics off messy spreadsheets.
Event detail page with eligibility status, invitation requests, and rich event information
Questionnaire-based screening |
Interactive seat selection |
Potluck coordination |
Dietary preferences & restrictions |
Revel is built with a modern and robust backend, designed for performance and scalability.
- 🐍 Backend: Python 3.13+ with Django 5.2 LTS
- 🚀 API: Django Ninja and Django Ninja Extra for a fast, modern, and auto-documenting REST API.
- 🐘 Database: PostgreSQL with PostGIS for powerful geo-features.
- ⚙️ Async Tasks: Celery with Redis for background jobs (emails, evaluations).
- 🐳 Deployment: Fully containerized with Docker for easy setup and deployment.
We intentionally stay on Django 5.2 LTS rather than upgrading to Django 6.x. Our policy:
- LTS stability - Django 5.2 is a Long-Term Support release with security updates until April 2028
- Upgrade when it matters - We'll upgrade for compelling features, performance improvements, or security CVEs
- No bleeding edge for its own sake - Django 6.0 is only ~3 months old; we prefer battle-tested releases
Get a local development environment running in minutes. You'll need make, Docker, Python 3.13+, and UV.
-
Clone the repository:
git clone https://github.com/letsrevel/revel-backend.git cd revel-backend -
Make sure you have the necessary geo data:
- You must download IP2LOCATION-LITE-DB5.BIN and place it in
src/geo/data/ - You must download the worldcities.csv and place it in
src/geo/data/(or for dev purposes just copyworldcities.mini.csvintoworldcities.csv)
- You must download IP2LOCATION-LITE-DB5.BIN and place it in
-
Run the setup command: This command fully automates the setup process.
make setup
-
You're ready!
- The API is running at
http://localhost:8000 - Interactive API docs (Swagger UI) are at
http://localhost:8000/api/docs - A default superuser is created (
admin@letsrevel.io/password). - Mailpit (email testing) is at
http://localhost:8025
- The API is running at
The project uses multiple Docker Compose files for different purposes:
| File | Purpose | Usage |
|---|---|---|
compose.yaml |
Local development - includes Mailpit for email testing | docker compose up -d |
docker-compose-ci.yml |
CI/CD pipeline - minimal services for testing | docker compose -f docker-compose-ci.yml up -d |
docker-compose-base.yml |
Shared services - extended by other compose files | Not used directly |
docker-compose-observability.yml |
Full stack with observability - standalone (includes core services + Grafana, Prometheus, Loki, etc.) | Alternative to compose.yaml |
For local development, simply run:
docker compose up -dThis starts PostgreSQL, Redis, ClamAV, and Mailpit. All emails sent by the application are captured by Mailpit and viewable at http://localhost:8025.
Revel includes a comprehensive observability stack built on the LGTM (Loki, Grafana, Tempo, Mimir) framework.
The observability stack requires a separate Docker Compose file. After make setup, only the core services (PostgreSQL, Redis, ClamAV, Mailpit) are running. To enable full observability:
docker compose -f docker-compose-observability.yml up -d!!! note
docker-compose-observability.yml is a standalone compose file that includes both core services and the observability stack. Do not run it alongside compose.yaml.
| Service | Purpose | URL | Credentials |
|---|---|---|---|
| Mailpit | Email testing - catches all outgoing emails | http://localhost:8025 | - |
| Grafana | Unified dashboard for logs, traces, and metrics | http://localhost:3000 | admin / admin |
| Prometheus | Metrics collection and querying | http://localhost:9090 | - |
| Loki | Log aggregation | http://localhost:3100 | - |
| Tempo | Distributed tracing | http://localhost:3200 | - |
| Django Metrics | Application metrics endpoint | http://localhost:8000/metrics | - |
- Structured Logging: All logs in JSON format with automatic context (request_id, user_id, task_id, etc.)
- Distributed Tracing: Automatic tracing of HTTP requests, database queries, Redis operations, and Celery tasks
- Metrics: Django, PostgreSQL, Redis, and Celery metrics automatically collected
- PII Scrubbing: Automatic redaction of sensitive data (passwords, card numbers, emails, etc.)
- Trace-to-Log Correlation: Jump from traces to related logs and vice versa in Grafana
- Grafana Alerting: Production-ready alerts for errors, payments, auth failures, and more (no DB overhead)
!!! warning "Pyroscope SDK Disabled"
The Pyroscope Python SDK (pyroscope-io) is currently disabled due to incompatibility with Grafana Pyroscope 1.6+. Profiling can be provided externally (e.g., via a Grafana Alloy eBPF agent at the infrastructure level). This may change when the SDK is updated.
-
View logs in Grafana: Go to
http://localhost:3000→ Explore → Select "Loki" datasource{service="revel"} | json | level="error" -
View traces in Grafana: Explore → Select "Tempo" datasource → Search by service or endpoint
-
View metrics in Prometheus: Go to
http://localhost:9090→ Graphrate(django_http_requests_total[5m]) -
Set up alerts: Configure Grafana alert rules for production monitoring
- See GRAFANA_ALERTING.md for 10+ ready-to-use alert examples
- Supports Email, Slack, Discord, PagerDuty notifications
Observability can be configured via environment variables in .env:
ENABLE_OBSERVABILITY=True # Enable/disable all observability features
TRACING_SAMPLE_RATE=1.0 # 100% in dev (auto-switches to 0.1 in production)
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318!!! note
make setup runs with ENABLE_OBSERVABILITY=False to avoid connection errors to non-existent services. If you start the observability stack later, set ENABLE_OBSERVABILITY=True in your .env.
After starting the observability stack and Django with make run, verify the setup:
-
Check startup logs: Look for initialization messages:
OpenTelemetry tracing initialized: service=revel, sample_rate=1.0, endpoint=http://localhost:4318 -
Check metrics endpoint: Visit http://localhost:8000/metrics - should show Prometheus metrics
-
Generate some traffic: Make API requests to create traces and logs
curl http://localhost:8000/api/docs
-
Check Grafana: Go to http://localhost:3000 → Explore → Select datasource
- Loki for logs:
{service="revel"} | json - Tempo for traces: Search by service name "revel"
- Prometheus for metrics:
rate(django_http_requests_total[5m])
- Loki for logs:
For detailed documentation, see:
- OBSERVABILITY_SPEC.md - Full specification and implementation plan
- OBSERVABILITY_IMPLEMENTATION.md - What's implemented and how to use it
- GRAFANA_ALERTING.md - Production-ready alert rules and notification setup
- ASYNC_LOGGING.md - Async logging architecture (50-100x faster)
The project uses a Makefile to streamline common development tasks.
| Command | Description |
|---|---|
make setup |
Runs the complete one-time setup for the dev environment. |
make run |
Starts the Django development server. |
make check |
Runs all checks: formatting, linting, type checking, migration check, i18n check, and file length. |
make test |
Runs the full pytest test suite and generates a coverage report. |
make run-celery |
Starts the Celery worker for processing background tasks. |
make run-celery-beat |
Starts the Celery beat scheduler for periodic tasks. |
make migrations |
Creates new database migrations based on model changes. |
make migrate |
Applies pending database migrations. |
make shell |
Opens the Django shell. |
make restart |
Destructive: Deletes all migrations, regenerates them, restarts Docker, and bootstraps. |
make nuke-db |
Destructive: Resets database and regenerates migrations (preserves special data migrations). |
Revel implements HMAC-signed URLs for protected file access, allowing certain media files to require authorization while being served efficiently by Caddy.
Client → Caddy → forward_auth → Django /api/media/validate/*
↓
Validates HMAC signature + expiry
↓
Returns 200 (serve file) or 401
We evaluated MinIO but chose HMAC signing for these reasons:
- FOSS-friendly: MinIO moved to AGPL v3 and now distributes community edition as source-only (no pre-compiled binaries)
- No additional services: Caddy already handles file serving
- Simple is better: For our use case (<100MB files, no streaming), HMAC signing is sufficient
- No vendor lock-in: Pure Django + Caddy, no external dependencies
- Any file in
protected/requires signed URL access - Caddy configuration routes
/media/protected/*throughforward_auth - Django validates the signature and expiry, returns 200 or 401
- Caddy serves the file if validation passes
Use ProtectedFileField or ProtectedImageField for files requiring signed access:
from common.fields import ProtectedFileField, ProtectedImageField
class MyModel(models.Model):
# Stored in protected/attachments/ - requires signed URL
attachment = ProtectedFileField(upload_to="attachments")
# Stored in protected/profile-pics/ - requires signed URL
profile_pic = ProtectedImageField(upload_to="profile-pics")Use get_file_url() with a static resolver to generate signed URLs in your schemas:
from ninja import ModelSchema
from common.signing import get_file_url
class MyResourceSchema(ModelSchema):
file_url: str | None = None
@staticmethod
def resolve_file_url(obj: MyModel) -> str | None:
"""Return signed URL for protected files, direct URL for public files."""
return get_file_url(obj.file)
class Meta:
model = MyModel
fields = ["id", "name"]The get_file_url() function automatically:
- Returns a signed URL (with
expandsigparams) for protected paths - Returns a direct URL for public paths
- Returns
Noneif the file field is empty
- Signatures use Django's
SECRET_KEYwith domain separation - URLs expire after 1 hour by default (configurable)
- Timing-safe comparison prevents timing attacks
- Rate limiting on validation endpoint prevents brute-force attacks
See the Protected Files architecture docs for details. The Caddy configuration lives in the infra repository.
The codebase is organized into a src directory with a clear separation of concerns, following modern Django best practices.
src/revel/: The core Django project settings.src/accounts/: User authentication, registration, and profile management.src/events/: The core logic for organizations, events, tickets, and memberships.src/questionnaires/: The questionnaire building, submission, and evaluation system. 📖 Read moresrc/notifications/: Multi-channel notification system (in-app, email, Telegram) with user preferences, digest support, and event-driven delivery.src/wallet/: Apple Wallet pass generation for event tickets (.pkpass files).src/geo/: Geolocation features (cities, IP lookups).src/telegram/: Telegram Bot integration with FSM-based conversation flows, inline keyboards, and organizer notifications.src/api/: Main API configuration, exception handlers, and global endpoints.src/common/: Shared utilities, authentication backends, base models, and admin customizations.
Most apps contain controllers and service modules for API endpoints and business logic respectively, either as directories or single files depending on complexity.
We welcome contributions! Please read our CONTRIBUTING.md to learn how you can get involved, from reporting bugs to submitting code.
Revel aims to support multiple languages (currently English, German, and Italian). See i18n.md for details on how the translation system works and how to add new languages.
This is currently heavily WIP.
This project is licensed under the MIT license. See LICENSE.
- Revel uses the IP2Location LITE database for IP geolocation.
- Revel uses the World Cities Database from SimpleMaps, available under CC BY 4.0.



