# REVIEW.md — Theme Song Booth Quick reference for future work on this project. ## One-sentence summary Flask app that lets convention attendees request custom AI-generated theme songs, lets an operator manage the queue, and emails MP3s after payment. ## Stack - Python 3.12 + Flask - SQLite (file-based, request-scoped connection via `g`) - Gunicorn in Docker - Portainer stack deployed from GitLab repo - SMTP (SSL port 465) for customer emails - Square Terminal/Reader for manual payment - `mutagen` for MP3 metadata tagging - `flask-limiter` for public form rate limiting - `cryptography` to encrypt the stored SMTP password ## Repository - GitLab: `https://gitlab.hallsworth.ca/yrtria/theme-song-booth` (public) - Deployed at: `https://booth.dionysismedia.ca` ## Key files and what they hold | File | Notes | |---|---| | `app.py` | All routes, helpers, email function, status labels, runtime settings, MP3 tagging, rate limiting, DB health. | | `config.py` | Env vars. `ADMIN_PASSWORD` is plain text. | | `models.py` | SQLite schema + CRUD. `player_token` is a secret URL-safe token. | | `init_db.py` | Run once after deploy: `python init_db.py`. | | `templates/admin/request.html` | Biggest template; prompt copy helpers and JS live here. | | `templates/admin/dashboard.html` | Queue table + filters + auto-refresh + topbar Reset System button. | | `templates/admin/settings.html` | SMTP config, MP3 metadata defaults, DB backup/restore, health check, reset. | | `docker-compose.yml` | No `env_file`; variables come from Portainer. | ## Status meanings ``` pending → prompt_ready → songs_uploaded → awaiting_payment → paid → delivered ``` `revisions_requested` is a branch used when the customer asks for changes. ## Operator workflow 1. Customer fills `/request`. 2. Open `/admin`, click request row (or filter by status). 3. On `/admin/request/`, fix the customer's email if needed, then click **Copy customer info for Hermes**, paste result to Hermes. 4. Paste Hermes response (Title/Style/Lyrics format) into the fields and click **Save Prompt**. 5. Copy Style/Lyrics into Suno Custom Mode, generate two versions. 6. Upload Version A and B MP3s. 7. Click **Send Preview Link**. 8. Customer receives email, visits player, picks version. 9. Operator collects Square payment, enters reference, clicks **Mark Paid & Deliver**. 10. Customer receives MP3 attachment(s) by email. ## Environment variables that matter ``` APP_SECRET_KEY ADMIN_PASSWORD SMTP_PASS PUBLIC_BASE_URL BOOTH_NAME HOST_PORT INTERNAL_PORT MAX_REVISIONS ``` Most can be overridden at runtime from `/admin/settings` and stored in `booth_settings.json`. ## Gotchas - Multiple forms on `admin/request.html` must stay properly closed; nested forms break buttons. - `upload_songs` form needs `enctype="multipart/form-data"` and a matching ``. - The dashboard uses `basename()` as a function, not a Jinja filter. - Reset System deletes DB rows **and** all files under `UPLOAD_FOLDER`, then resets `sqlite_sequence`. - Runtime settings are stored in the persistent uploads volume (`booth_settings.json`). - Container cannot read host paths; all static assets used at runtime (logo, banner, favicons) must be in the repo or a mounted volume. ## How to redeploy 1. Push changes to GitLab `main`. 2. In Portainer: Stacks → `theme-song-booth` → **Pull and redeploy**. 3. If schema changed, open container console and run `python init_db.py`, or use `/admin/settings` → **Fix Missing Columns**.