Multi-tenant architecture that isolates contacts, templates, sending providers, and campaigns by organization, with owner/admin/member roles
Agentic-Email-Campaign-Management-Platform — Next.js Business Template
By MusfiqDehan
A multi-tenant email marketing platform built on Next.js and Django, supporting contact management, template editing, bulk email/SMS sending, and real-time notifications, with integrated AI template generation and a natural-language contact assistant.
Explore the design
Compare the page layouts and mobile experience. Open any screenshot for a closer look.
Actual screenshot captured by the server browser.
All pages & views 2
Screenshots show visual appearance; interactive behavior may differ.
What stands out
A quick read of the recorded project description.
Supports sending via multiple providers including AWS SES and Gmail/Outlook SMTP, with encrypted credential storage and resolution by organization configuration hierarchy
Integrates Gemini (with DeepSeek fallback) to generate email template content and provides a natural-language contact management assistant endpoint
Includes two-way mailbox sync, first-party open/click tracking, and delivery event webhooks from SES/SendGrid/Brevo
Provides real-time in-app notifications via Django Channels and WebSocket, and supports web push
Offers Docker Compose configuration, a Traefik production deployment guide, and GitHub Actions CI
Template Details
This is a multi-tenant email (and SMS) marketing platform with a Django REST API backend and a Next.js frontend. Each organization has its own contacts, templates, sending providers, and campaigns, with member roles divided into owner/admin/member. Core features include: creating, scheduling, starting, pausing, resuming, canceling, and duplicating email campaigns, with test sends and real-time previews, plus per-campaign delivery/open/click statistics. Contact management supports bulk CSV import, list and group statistics, and an AI assistant endpoint that creates, updates, and searches contacts via natural-language descriptions. For templates, it provides a rich HTML editor, dynamic personalization variables, categories, and previews, and can generate template content with Gemini (DeepSeek as fallback). The sending layer supports AWS SES and Gmail/Outlook SMTP, resolved by organization configuration hierarchy, with encrypted credential storage, health checks, and rate/quota limits; it also receives delivery event webhooks from SES, SendGrid, and Brevo. The platform also includes two-way mailbox sync, first-party open/click tracking, rule-based automated trigger emails, SMS/WhatsApp sending via Twilio, and WebSocket-based in-app notifications and web push. The backend uses PostgreSQL, Redis, Celery and Celery Beat, Django Channels and Daphne, JWT authentication, and drf-spectacular for OpenAPI documentation. The frontend uses App Router, Tailwind CSS, Radix UI, React Hook Form and Zod, next-themes, and more. The repository includes Docker Compose configuration, a Traefik production deployment guide, and GitHub Actions CI. A demo site is accessible, but the mobile directory in the repository is an Expo scaffold and is essentially unused.
Is it right for your project?
Use Cases
- Scenarios where email marketing campaigns and contact lists need to be managed separately for multiple organizations or teams
- Teams that want to bulk-import contacts via CSV and use AI to generate email template content
- Scenarios where sending providers such as AWS SES and Gmail/Outlook SMTP need to be switched within the same platform
- Marketing operations that need to track email opens and clicks and receive delivery event notifications
- Notification scenarios that combine email, SMS, and WhatsApp triggered automation
Suitable For
- Technical teams with Django and Next.js development capabilities that want to self-host an email marketing platform
- Organizations or SaaS product prototypes that need multi-tenant isolation and role-based permission management
- Developers who need to integrate AI template generation and natural-language contact operations
- Operations personnel who want to deploy using Docker Compose and Traefik
Getting started & customization
Use these recorded setup notes alongside the repository instructions for your chosen version.
- 1
PostgreSQL and Redis services need to be prepared, and the corresponding environment variables configured
- 2
The backend depends on Python 3.12 and Django 5.2; the frontend depends on Next.js 16 and React 19
- 3
Email sending requires AWS SES or Gmail/Outlook SMTP credentials; SMS/WhatsApp requires Twilio configuration
- 4
AI template generation and the contact assistant require a Gemini API key, with DeepSeek as fallback
- 5
You can use the Docker Compose provided in the repository or manually start the backend, frontend, and Celery worker processes according to the README
License & source material
Usage conditions & limitations
Free to use · keep license noticeThis listing covers the free version under the Apache-2.0 license in the public repository; the free scope is the code of that version and does not mean that external services or third-party assets are free.
Must comply with when using
- Free use, modification, commercial use, and distribution are permitted; when distributing, the Apache-2.0 license must be included.
- Modified files must prominently indicate changes, and relevant copyright, patent, trademark, and attribution notices must be retained.
- If the original project includes a NOTICE file, applicable attribution notices in it must be retained when distributing derivative works.
- The license includes an applicable contributor patent grant; initiating patent litigation as described in the license terminates that patent grant, and no trademark use rights are granted.
- The code is provided as is; warranties and limitations of liability are governed by the original license and applicable law.
Additional costs & items to verify
- Demo images, fonts, icons, and other third-party assets must be checked against their respective licenses; they cannot be judged solely by the code's Apache-2.0 license.
- External services such as domains, hosting, databases, payments, or AI may incur additional charges.
- The project provides an online demo site, but the demo site is for display purposes only; actual use requires self-deployment.
- The runtime platform must prepare PostgreSQL 14+ and Redis 7+ services on its own, which are external dependency requirements.
- Docker and Docker Compose are optional dependencies, required only when using containerized workflows.
- AI template generation and the natural-language contact assistant require a Gemini API key, with a DeepSeek fallback key.
- Email sending requires configuring SMTP/SES-related environment variables and credentials on your own, which are external service requirements.
- Enabling web push notifications requires generating and configuring VAPID public and private keys and a claim email.
- Sending rates and daily quotas are limited by environment variables and must be configured per organization.
- The unified production Compose requires a Cloudflare Origin TLS certificate and a real reverse proxy, and is not suitable for running standalone on a laptop.
- The standalone backend Compose depends on an external Docker network named dokploy-network, which must be created in advance.
- The standalone frontend Compose depends on an external Docker network named ecmp_network, which must be created in advance.
- apps.notifications, apps.platform_admins, and apps.template_managers are empty placeholder directories; the related functionality is actually located in apps.campaigns.
- The mobile directory is only an Expo scaffold and is essentially unused; it does not constitute usable mobile functionality.
- Bulk email sending and scheduled automation require additionally running Celery worker and beat processes.
- The project is a production-style multi-tenant application, but the README does not guarantee production environment availability.
View Original Text Basis
no-charge, royalty-free, irrevocable copyright license
Original License Text
**Live Demo:** https://emailcampaign.musfiqdehan.com
Original README
**PostgreSQL** (14+) and **Redis** (7+) — locally installed, or run via Docker (see below)
Original README
**Docker** + **Docker Compose** (optional, for the containerized workflow)
Original README
| AI providers | `GEMINI_API_KEY`, `DEEPSEEK_API_KEY` (fallback) |
Original README
| Email / SMTP / SES | `EMAIL_BACKEND`, `EMAIL_HOST(_USER/_PASSWORD)`, `EMAIL_PORT`, `EMAIL_USE_TLS/SSL`, `DEFAULT_FROM_EMAIL` |
Original README
| Web push (VAPID) | `VAPID_PUBLIC_KEY`, `VAPID_PRIVATE_KEY`, `VAPID_CLAIM_EMAIL` |
Original README
| Sending limits | `ORG_PROVIDER_MAX_RATE_PER_SECOND/MINUTE/HOUR`, `ORG_PROVIDER_MAX_DAILY_QUOTA` |
Original README
It expects Cloudflare Origin TLS certs at `nginx/certs/` and a real reverse proxy in front of it, so it isn't meant to be run standalone on a laptop.
Original README
docker network create dokploy-network # skip if it already exists
Original README
docker network create ecmp_network # skip if it already exists
Original README
`apps.notifications`, `apps.platform_admins`, and `apps.template_managers` are empty placeholder > directories — notification and admin functionality actually lives inside `apps.campaigns`.
Original README
├── mobile/ # Expo scaffold (minimal/unused)
Original README
Required for bulk email sending and scheduled automation — run these alongside the backend:
Original README
https://github.com/MusfiqDehan/Agentic-Email-Campaign-Management-Platform/blob/main/LICENSEhttps://github.com/MusfiqDehan/Agentic-Email-Campaign-Management-Platform/blob/main/README.mdIt's built as a production-style **multi-tenant** application
Original README
Compiled by DeepSeek based on repository license and README ·2026-10-04. Results only cover the materials read; dependencies, images, fonts, and subsequent term changes are subject to their respective original texts.
Project checks & description sources
Template Information
- Source platforms
- GitHub
- Documentation and maintenance reference score
- More documented · 88 / 100
- Technologies
- Next.js · Django · React
- Website type
- Corporate Website
How this score is calculated
Our heuristic uses license records (up to 30), a demo link (12), a preview (10), stars (15), recorded maintenance (15), description completeness (8), feature records (5) and classification data (5). It is not a code, security or performance test, or a Google score. A link does not establish tested functionality.
What to verify for this project
- Repository update recorded
- 2026-10-04
- Screenshot last checked
- 2026-10-04
A demo link is listed. Check it with your own content and viewport sizes; its presence does not confirm that forms, authentication or payments work.
The catalog identifies Next.js as the primary stack. Check the actual dependency manifest and lockfile for versions and hosting requirements. These notes use recorded metadata, not a code audit or a deployment test.
Use a selection guide →How this description was prepared
AI-assisted description based on catalog records and repository material. Repository authors are not automatically the reviewers of this description.
Review declaration: [email protected] · 2026-10-04
Inspect the recorded source material
SHA-256: b0bd7ca8554a4d8fb164e4c0446a702101893c54fb0346e42407e880096272b2
2026-10-04T11:17:34.892Z
Source file / repository# 📧 Email Campaign Management Platform
A multi-tenant, AI-assisted email (and SMS) campaign management platform. Organizations manage contacts, build reusable templates, run bulk campaigns across multiple providers (AWS SES, Gmail/Outlook SMTP), and get real-time delivery notifications — with generative AI template creation and an agentic, natural-language contact-management assistant built in.
**Live Demo:** https://emailcampaign.musfiqdehan.com







---
## 📑 Table of Contents
- [Project Overview](#-project-overview)
- [Features](#-features)
- [Tech Stack](#-tech-stack)
- [Architecture](#-architecture)
- [Project Structure](#-project-structure)
- [Root Directory](#root-directory)
- [Backend (`backend/`)](#backend-backend)
- [Frontend (`frontend/`)](#frontend-frontend)
- [Getting Started](#-getting-started)
- [Prerequisites](#prerequisites)
- [Environment Variables](#environment-variables)
- [Running Locally (Manual Setup)](#-running-locally-manual-setup)
- [1. Backend (Django)](#1-backend-django)
- [2. Frontend (Next.js)](#2-frontend-nextjs)
- [3. Background Workers (Celery)](#3-background-workers-celery)
- [Running with Docker](#-running-with-docker)
- [Per-service Compose (local development)](#per-service-compose-local-development)
- [Unified Production Compose](#unified-production-compose)
- [API Documentation](#-api-documentation)
- [Testing & Linting](#-testing--linting)
- [AI Tools Used](#-ai-tools-used)
- [Key Learnings](#-key-learnings)
- [Areas for Improvement](#-areas-for-improvement)
- [License](#-license)
---
## 🧭 Project Overview
This is an end-to-end **Email Campaign Management Platform** that allows organizations to manage contacts, create reusable templates, launch bulk email/SMS campaigns, and monitor delivery progress from a single system. It's built as a production-style **multi-tenant** application — each organization owns its own contacts, templates, providers, and campaigns, with role-based membership (owner/admin/member).
Beyond core campaign management, the platform includes:
- **Generative AI** support for email template creation (Gemini, with a DeepSeek fallback)
- An **agentic, natural-language contact-management** endpoint — manage contacts by describing what you want in plain English
- A **bidirectional mailbox** with first-party email open/click tracking
- **Multi-provider** sending (AWS SES, Gmail/Outlook SMTP) resolved per-organization at send time
- **Real-time** in-app and web-push notifications over WebSockets
---
## ✨ Features
### 🎯 Campaign Management
- Create, schedule, launch, pause, resume, cancel, and duplicate email campaigns
- Test-send and live preview before launch
- Per-campaign analytics with delivery/open/click stats and stat refresh
### 👥 Contact Management
- Contacts and contact lists with bulk CSV import
- Agentic, natural-language contact operations (create/update/search contacts via AI)
- Contact segmentation and list-level stats
### 📝 Templates
- Rich HTML template editor with dynamic personalization variables
- AI-generated template content (Gemini primary, DeepSeek fallback)
- Template categories, admin-curated templates, and previews
### 📬 Multi-Provider Email Delivery
- AWS SES and Gmail/Outlook SMTP, resolved per-organization via a config hierarchy
- Encrypted storage of provider credentials
- Provider health checks and rate/quota limiting (per-second/minute/hour/day)
- Delivery event webhooks from SES, SendGrid, and Brevo, plus a delivery log with resend/forward
### 📥 Mailbox & Tracking
- Bidirectional mailbox sync (send & receive) with a message inbox
- First-party open/click tracking pixels & redirect links
### 🔁 Automation
- Rule-based automation for triggered emails
- SMS and WhatsApp trigger campaigns (via Twilio)
### 🔔 Real-Time Notifications
- WebSocket-based in-app notifications (Django Channels)
- Web push notifications (VAPID)
### 🏢 Multi-Tenancy & Admin
- Organizations, membership roles (owner/admin/member), and per-org settings
- Platform-admin views for cross-tenant provider/organization management
### 🎨 Modern UI/UX
- Responsive dashboard with dark/light theme (system-aware)
- Animated, interactive landing page (SVG micro-interactions, pricing, growth/process visuals)
### 🔐 Security
- JWT authentication (access + refresh) with real DB-backed users
- Encrypted provider credentials, soft-delete on core models, org-scoped permissions
---
## 🛠 Tech Stack
### Backend
| Technology | Purpose |
|---|---|
| **Python 3.12** | Core language |
| **Django 5.2** + **DRF 3.15** | Web framework & REST API |
| **PostgreSQL** | Primary database |
| **Redis** | Celery broker/result backend & Channels layer |
| **Celery 5.3** + **Celery Beat** | Async & scheduled tasks (bulk email/SMS, automation) |
| **Django Channels** + **Daphne** | WebSocket notifications (ASGI) |
| **SimpleJWT** | JWT authentication |
| **drf-spectacular** | OpenAPI schema, Swagger UI, ReDoc |
| **django-ses**, **boto3** | AWS SES email provider |
| **Twilio** | SMS / WhatsApp sending |
| **SendGrid**, Brevo webhooks | Alternate delivery provider + inbound/event webhooks |
| **pywebpush** / **py-vapid** | Web push notifications |
| **google-genai** (Gemini) | AI template generation & the agentic contact assistant |
| **django-health-check** | `/api/v1/healthz/` liveness endpoint |
| **Gunicorn** / **Daphne** | Production servers (WSGI/ASGI) |
| **pytest**, **flake8**, **black** | Testing & code quality |
### Frontend
| Technology | Purpose |
|---|---|
| **Next.js 16** (App Router) | React framework |
| **React 19** + **TypeScript 5** | UI & type safety |
| **Tailwind CSS 4** | Styling |
| **Radix UI** + `class-variance-authority` | Accessible UI primitives (shadcn/ui-style) |
| **React Hook Form** + **Zod** | Forms & validation |
| **next-themes** | Dark/light theming |
| **Axios** | HTTP client |
| **React Quill (new)** | Rich text template editor |
| **Sonner** | Toast notifications |
| **Lucide React** | Icons |
### DevOps & Tooling
| Technology | Purpose |
|---|---|
| **Docker** / **Docker Compose** | Containerization (per-service & unified) |
| **Traefik** | Reverse proxy & TLS termination in production |
| **GitHub Actions** | CI (`check`, migration check, `manage.py test --parallel` against Postgres+Redis service containers) |
| **Nginx** | Static/reverse-proxy config for select deployments |
---
## 🏗 Architecture
```
┌──────────────────────────────────────────────────────────────────┐
│ CLIENT LAYER │
│ Next.js 16 (React 19 + TypeScript) │
│ App Router · Tailwind + Radix UI · Axios · WebSocket hooks │
└──────────────────────────────────────────────────────────────────┘
│ REST (JSON) + WebSocket
▼
┌──────────────────────────────────────────────────────────────────┐
│ API LAYER │
│ Django REST Framework · JWT Auth · Org-scoped permissions │
│ Django Channels (ws/notifications/) served over Daphne (ASGI) │
└──────────────────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────┐
│ APPLICATION LAYER (apps.campaigns) │
│ Campaigns · Contacts · Templates · Providers · Automation │
│ Mailbox & Tracking · SMS/WhatsApp · Notifications · Admin │
└──────────────────────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ PostgreSQL │ │ Redis │ │ Celery │
│ (database) │ │ (broker/cache/ │ │ (async & beat │
│ │ │ channel layer) │ │ scheduled tasks)│
└─────────────────┘ └─────────────────┘ └─────────────────┘
│
▼
┌───────────────────────────────┐
│ AWS SES · Gmail/Outlook SMTP │
│ Twilio (SMS/WhatsApp) │
│ SendGrid / Brevo webhooks │
└───────────────────────────────┘
```
Email sending flow: organization config → `hierarchy_resolver` resolves the effective provider config → `ProviderBackendResolver` builds the right Django email backend → `unified_email_sender` sends it — one code path supporting SES, SMTP, or console/test sending interchangeably.
---
## 📁 Project Structure
### Root Directory
```
Email-Campaign-Management-Platform/
├── README.md # This file
├── DEPLOYMENT.md # Full production/VPS deployment guide (Traefik + Cloudflare)
├── LICENSE # Apache 2.0
├── docker-compose.yml # Unified production stack (Postgres, Redis, backend, Celery, frontend)
├── .env.example # Environment variable reference for the unified compose
├── backend/ # Django REST API
├── frontend/ # Next.js dashboard & landing site
├── frontend-newsletter/ # Static embeddable newsletter signup widget
├── mobile/ # Expo scaffold (minimal/unused)
└── nginx/ # Reverse proxy config for select deployments
```
### Backend (`backend/`)
```
backend/
├── manage.py
├── requirements.txt
├── Dockerfile / docker-compose.yml / docker_entrypoint.sh
├── config/ # Django project config
│ ├── settings.py
│ ├── urls.py # /api/v1/auth, /api/v1/campaigns, /api/v1/healthz, /api/v1/schemas
│ ├── asgi.py # Channels ProtocolTypeRouter (WebSocket)
│ ├── wsgi.py
│ └── celery.py
├── core/ # Response envelope & centralized exception handling
│ ├── mixins.py # ResponseMixin (aliased as CustomResponseMixin)
│ ├── exceptions.py # custom_exception_handler (DRF EXCEPTION_HANDLER)
│ └── utils.py
├── apps/
│ ├── authentication/ # User, Organization, OrganizationMembership, JWT, permissions
│ │ ├── models.py / views.py / serializers.py / permissions.py / signals.py
│ │ ├── services/
│ │ └── management/commands/ # create_superuser, create_platform_admin,
│ │ create_user_organizations, assign_user_organization, list_users_orgs
│ ├── campaigns/ # Core app — the bulk of the business logic
│ │ ├── models/ # campaign, contact, email_config, provider, automation_rule,
│ │ │ email_tracking, notification, push, sms_config, mailbox, org_email_config
│ │ ├── views/ # campaign, admin, enhanced, template_operations, admin_templates,
│ │ │ organization_admin, notification, push, sms_automation,
│ │ │ email_automation, variable, ai_gen, contact_agent, mailbox,
│ │ │ tracking, provider_webhooks, unsubscribe, debug
│ │ ├── serializers/ # campaign, admin, enhanced, push, mailbox, base
│ │ ├── utils/ # email_providers, unified_email_sender, hierarchy_resolver,
│ │ │ tenant_service, crypto, template_utils, variable_registry,
│ │ │ ai_client, sms_utils, push_utils, mailbox_sync, email_tracking
│ │ ├── management/commands/ # generate_encryption_key, sync_email_providers,
│ │ │ check_email_providers_health
│ │ ├── tasks.py # Celery tasks for async/bulk sending
│ │ ├── backends.py # ProviderBackendResolver (SES/SMTP/console)
│ │ ├── consumers.py / routing.py # WebSocket notification consumer
│ │ ├── ses_event_handlers.py
│ │ └── migrations/
│ ├── notifications/, platform_admins/, template_managers/ # placeholder apps (not wired up)
│ └── utils/ # BaseModel (soft-delete), pagination, filters, throttles, mixins
├── static/ · staticfiles/ # Collected static assets
└── media/ · media_files/ # User-uploaded assets (logos, profile images)
```
> `apps.notifications`, `apps.platform_admins`, and `apps.template_managers` are empty placeholder
> directories — notification and admin functionality actually lives inside `apps.campaigns`.
### Frontend (`frontend/`)
```
frontend/
├── package.json / tsconfig.json / next.config.ts / eslint.config.mjs
├── Dockerfile / docker-compose.yml
├── app/ # Next.js App Router
│ ├── page.tsx # Marketing landing page
│ ├── layout.tsx / globals.css
│ ├── login/ · signup/ · reset-password/ · verify-email/ · unsubscribe/
│ └── dashboard/ # Authenticated app
│ ├── layout.tsx / page.tsx
│ ├── campaigns/ · contacts/ · templates/ · inbox/
│ ├── logs/ · notifications/ · team/ · admin/
│ └── settings/ · profile/
├── components/
│ ├── ui/ # Radix-based primitives (button, dialog, table, tabs, ...)
│ ├── dashboard/ # sidebar, header, notification settings, floating AI agent input
│ ├── landing/ # Animated SVG landing sections (hero, growth chart, network bg, ...)
│ ├── brand-logo.tsx / editor.tsx / providers.tsx
├── config/ # axios client, constants, template & general utils
├── contexts/ # AuthContext
├── hooks/ # useNotifications, usePushNotifications, useRealtimeUpdates, ...
├── services/ # auth.ts, campaigns.ts, notifications.ts — thin API wrappers
└── public/ # Static assets (logo, icons, service worker)
```
---
## 🚀 Getting Started
### Prerequisites
- **Python 3.12+**
- **Node.js 20+** and npm
- **PostgreSQL** (14+) and **Redis** (7+) — locally installed, or run via Docker (see below)
- **Docker** + **Docker Compose** (optional, for the containerized workflow)
### Environment Variables
The backend and frontend each read from their own `.env` files, plus the repo root has a `.env.example` used by the unified Docker Compose stack. Copy the example and fill in values before running anything:
```bash
cp .env.example .env # for the unified/root docker-compose.yml
cp backend/.env.example backend/.env
```
Key variable groups (see `.env.example` for the full list with comments):
| Group | Variables |
|---|---|
| Django core | `DEBUG`, `SECRET_KEY`, `SIGNING_KEY`, `EMAIL_CONFIG_ENCRYPTION_KEY`, `ALLOWED_HOSTS` |
| PostgreSQL | `POSTGRES_ENGINE`, `POSTGRES_DB`, `POSTGRES_USER`, `POSTGRES_PASSWORD`, `POSTGRES_HOST`, `POSTGRES_PORT` |
| Redis | `REDIS_HOST`, `REDIS_PASSWORD` |
| Frontend build args | `NEXT_PUBLIC_API_URL`, `NEXT_PUBLIC_WS_URL`, `NEXT_PUBLIC_VAPID_PUBLIC_KEY` |
| Email / SMTP / SES | `EMAIL_BACKEND`, `EMAIL_HOST(_USER/_PASSWORD)`, `EMAIL_PORT`, `EMAIL_USE_TLS/SSL`, `DEFAULT_FROM_EMAIL` |
| Web push (VAPID) | `VAPID_PUBLIC_KEY`, `VAPID_PRIVATE_KEY`, `VAPID_CLAIM_EMAIL` |
| AI providers | `GEMINI_API_KEY`, `DEEPSEEK_API_KEY` (fallback) |
| Sending limits | `ORG_PROVIDER_MAX_RATE_PER_SECOND/MINUTE/HOUR`, `ORG_PROVIDER_MAX_DAILY_QUOTA` |
| Bootstrap superuser | `DJANGO_SUPERUSER_USERNAME/EMAIL/PASSWORD/FIRST_NAME/LAST_NAME` |
Generate the required secrets with:
```bash
# EMAIL_CONFIG_ENCRYPTION_KEY
python manage.py generate_encryption_key
# SECRET_KEY / SIGNING_KEY
python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"
# VAPID keys (web push)
python -c "from py_vapid import Vapid; v = Vapid(); v.generate_keys(); print(v.private_pem().decode()); print(v.public_key)"
```
---
## 💻 Running Locally (Manual Setup)
### 1. Backend (Django)
```bash
cd backend
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env # then fill in DB/Redis/secret values
# Make sure PostgreSQL & Redis are running and reachable per your .env
python manage.py migrate
python manage.py create_superuser --username admin --email [email protected] --password <password> --force
python manage.py create_user_organizations # backfill an org for the new user, if needed
python manage.py runserver 8001 # plain dev server — fine for non-WebSocket work
# or, to exercise WebSocket notifications:
daphne -p 8001 -b 0.0.0.0 config.asgi:application
```
> The checked-in `frontend/.env.local` already points to `http://localhost:8001` — running the backend on
> port `8001` (as above) means the frontend works with zero extra config. Use plain `runserver` on its
> default port 8000 instead and the frontend just needs `NEXT_PUBLIC_API_URL`/`NEXT_PUBLIC_WS_URL` updated
> to match.
The API is now available at `http://localhost:8001/api/v1/`.
### 2. Frontend (Next.js)
```bash
cd frontend
npm install # use `npm ci --legacy-peer-deps` if npm complains (React 19 peer deps)
# frontend/.env.local already sets NEXT_PUBLIC_API_URL / NEXT_PUBLIC_WS_URL to http://localhost:8001 — edit if needed
npm run dev
```
The dashboard is now available at `http://localhost:3000`.
### 3. Background Workers (Celery)
Required for bulk email sending and scheduled automation — run these alongside the backend:
```bash
cd backend
celery -A config.celery worker --loglevel=info
celery -A config.celery beat --loglevel=info --scheduler django_celery_beat.schedulers:DatabaseScheduler
```
---
## 🐳 Running with Docker
### Per-service Compose (local development)
Each app ships its own `docker-compose.yml` for spinning it up in isolation. Both reference an **external** Docker network, so create it once before the first run:
```bash
# Backend — Django, PostgreSQL, Redis, Celery worker & beat
cd backend
cp .env.example .env
docker network create dokploy-network # skip if it already exists
docker compose up -d --build
docker compose exec backend python manage.py migrate
docker compose exec backend python manage.py create_superuser --username admin --email [email protected] --password <password> --force
docker compose logs -f backend
```
- API → `http://localhost:8001/api/v1/`
- PostgreSQL → `localhost:5441`, Redis → `localhost:6391`
```bash
# Frontend — Next.js (standalone build)
cd frontend
docker network create ecmp_network # skip if it already exists
docker compose up -d --build
```
- App → `http://localhost:3001` (defaults to talking to the backend above via `NEXT_PUBLIC_API_URL=http://localhost:8001/api/v1`)
Stop either stack with `docker compose down` from its directory.
### Unified Production Compose
The root [`docker-compose.yml`](docker-compose.yml) builds the **full stack** (PostgreSQL, Redis, backend on Daphne, Celery worker + beat, and the frontend) as it's actually deployed in production — fronted by **Traefik** on an external `traefik_proxy` network, with the app services only `expose`d (not published) to the host. It expects Cloudflare Origin TLS certs at `nginx/certs/` and a real reverse proxy in front of it, so it isn't meant to be run standalone on a laptop.
For the full VPS deployment walkthrough (DNS, certs, firewall, `docker compose up -d --build`, health checks, and troubleshooting), see **[DEPLOYMENT.md](DEPLOYMENT.md)**.
---
## 📚 API Documentation
Once the backend is running (adjust the port to match how you started it — `8001` in the examples above):
- **Swagger UI** — `http://localhost:8001/api/v1/schemas/swagger-ui/`
- **ReDoc** — `http://localhost:8001/api/v1/schemas/redoc`
- **OpenAPI schema (JSON)** — `http://localhost:8001/api/v1/schemas/swagger.json`
- **Health check** — `http://localhost:8001/api/v1/healthz/`
All application endpoints are namespaced under `/api/v1/auth/` (authentication) and `/api/v1/campaigns/` (campaigns, contacts, templates, providers, automation, SMS, mailbox, tracking, webhooks, admin).
---
## ✅ Testing & Linting
```bash
# Backend (Django's own test runner, not pytest, despite pytest-django being installed)
cd backend
python manage.py test
python manage.py test apps.campaigns.tests.test_email_logs
python manage.py check
python manage.py migrate --check --dry-run
flake8
black --check .
# Frontend
cd frontend
npm run lint
npx tsc --noEmit
```
CI (`.github/workflows/deploy.yml`) runs the same `check` → migration check → `manage.py test --verbosity=2 --parallel` sequence against Postgres + Redis service containers — mirror that locally before opening a PR.
---
## 🤖 AI Tools Used
- **Claude Code CLI** — code generation, problem-solving, and architectural guidance
- **GitHub Copilot** — real-time code suggestions and productivity improvements
---
## 📖 Key Learnings
During development, this project was an exercise in both system design and real-world production challenges:
**AI Integration**
- Integrated GenAI features across frontend and backend within an existing codebase
- Designed workflows for AI-assisted template generation and natural-language-driven operations
**Email Campaign System Design**
- Studied industry-standard email marketing platforms to understand campaign workflows and best practices
- Implemented dynamic email templates with variables and trigger-based campaign execution
- Built subscriber collection mechanisms using external APIs
**Email Infrastructure & Deliverability**
- Integrated **AWS SES** for scalable email automation
- Supported multiple email providers (SES, Gmail SMTP) with dynamic, per-organization provider selection
- Applied DNS-level configuration (SPF, DKIM, DMARC) to improve deliverability and avoid spam classification
**Backend Engineering & Scalability**
- Designed asynchronous email processing with **Celery** for bulk delivery
- Implemented real-time notifications using **WebSockets** for in-app and push notifications
**DevOps & Deployment**
- Deployed frontend and backend behind **Traefik**/**Nginx** on a cloud VPS
- Managed static assets and backups
- Built CI/CD pipelines with **GitHub Actions** for automated testing and deployment
**Security & Best Practices**
- Implemented unsubscribe mechanisms and email compliance standards
- Applied best practices for secure email template rendering, credential encryption, and campaign execution
---
## 🔭 Areas for Improvement
- Expanding support for additional email providers beyond AWS SES and Gmail/Outlook SMTP
- Extending agentic (AI-driven) capabilities across more workflows within the platform
- Enhancing analytics with additional metrics — bounce rate, deliverability scoring, cohort engagement, etc.
- Wiring up the currently-placeholder `apps.notifications`, `apps.platform_admins`, and `apps.template_managers` apps
---
## 📄 License
Licensed under the **Apache License 2.0** — see [LICENSE](LICENSE) for details.
Explore similar templates
Compare previews and descriptions within the same stack and category.

SaaS-Boilerplate
SaaS-Boilerplate is an open-source SaaS starter template built with Next.js App Router, React 19, TypeScript, Tailwind CSS, and Shadcn UI.
Next.js · SaaS

Next-JS-Landing-Page-Starter-Template
A free Next.js landing page starter template written in Tailwind CSS and TypeScript, featuring built-in navbar, hero, features, CTA banner, and footer sections.
Next.js · Corporate Website

next-saas-starter
A free Next.js SaaS marketing landing page template from Blazity, using static generation and styled-components with no extra UI library.
Next.js · SaaS

startup-nextjs
Startup is a free, MIT-licensed Next.js template from NextJSTemplates for SaaS startups and corporate landing pages.
Next.js · SaaS

shadcn-landing-page
A Next.js landing page template built with Shadcn, TypeScript, and Tailwind, converted from a Shadcn-Vue version. It includes sections such as Navbar, mobile Sidebar, Hero, Pricing, FAQ, and Footer, and highlights responsive design, navigation, and dark mode.
Next.js · Corporate Website

shadcn-dashboard-landing-template
An open-source admin dashboard and marketing landing page template built on shadcn/ui and Tailwind CSS, with both Vite + React and Next.js versions in one repository.
Next.js · Admin dashboard
