IMFestival SMS Dashboard

A web-based SMS notification system for managing festival attendees and delivering workshop reminders via [Clickatell](https://www.clickatell.com/). ![alt text](./dashboard.jpg "Title") ## Architecture Three Docker services work together: | Service | Tech | Role | |---------|------|------| | `db` | MariaDB 11 | Persistent storage for attendees, templates, schedules, and delivery logs | | `web` | PHP 8.3 + Apache | Dashboard UI and REST API | | `worker` | Python 3 + Flask | SMS dispatch service; polls for due scheduled rules every 60 s | ## Features - **CSV import** — upload an attendee export from splash; the importer auto-detects common column names for first name, last name, email, and mobile number - **Workshop sessions** — attendees are linked to named sessions with a start time, enabling per-workshop targeting - **SMS templates** — reusable message bodies (≤ 160 chars) with `{name}`, `{workshop}`, and `{workshop_time}` placeholders - **Scheduled texts** — rules fire relative to a workshop start time (e.g. *30 minutes before*) or at a specific datetime - **Send now** — dispatch immediately to all attendees or a single workshop group - **Delivery log** — per-recipient status tracking (`sent` / `failed`) - **Sandbox mode** — tag sends as tests so they are excluded from sent stats or cost calculations without disabling the API - **Admin panel** — configure the Clickatell API key, cost-per-SMS, and sender ID through the UI ## Getting started ### Prerequisites - Docker and Docker Compose ### 1. Create a `.env` file Create a `.env` file in the project root. All three services read from it. ```env # MariaDB MYSQL_ROOT_PASSWORD=changeme MYSQL_DATABASE=imf_sms MYSQL_USER=imf_user MYSQL_PASSWORD=changeme MYSQL_HOST=db # Optional — defaults to Europe/London TZ=Europe/London ``` ### 2. Start the stack ```bash docker compose up --build ``` The dashboard will be available at **http://localhost:8000**. ### 3. Configure Clickatell Open **Admin** in the dashboard and enter your Clickatell API key. You can also set a cost-per-SMS and a default sender ID here. ### 4. Import attendees Go to **Attendees** and upload a CSV export from your event management tool. The required columns are `first_name` (or `First Name`), `last_name`, and `mobile_number` (or `Custom: Mobile number`). `email` and workshop session columns are optional but recommended. ## CSV column mapping The importer accepts comma- or tab-separated files and recognises these column names (case-insensitive): | Field | Accepted column names | |-------|-----------------------| | First name | `first name`, `first_name`, `firstname`, `first` | | Last name | `last name`, `last_name`, `lastname`, `last` | | Mobile | `custom: mobile number`, `mobile_number`, `mobile number`, `mobile`, `phone`, `telephone`, `cell` | | Email | `email` | | Workshop | `custom: please pick one workshop…` (and similar variants) | ## SMS placeholders | Placeholder | Replaced with | |-------------|---------------| | `{name}` | Recipient's first name | | `{workshop}` | Workshop name | | `{workshop_time}` | Workshop start time | The character counter in the template editor calculates length against the longest possible substitution so the 160-character limit is never misrepresented.