Trollgorithm Theme Song Booth - customer-facing request form, admin dashboard, kiosk queue, and delivery pipeline for AI-generated theme songs.
| static | ||
| templates | ||
| .env.example | ||
| .gitignore | ||
| app.py | ||
| booth_settings.json | ||
| config.py | ||
| docker-compose.yml | ||
| Dockerfile | ||
| init_db.py | ||
| models.py | ||
| README.md | ||
| requirements.txt | ||
| REVIEW.md | ||
Theme Song Booth
Custom theme-song request and delivery system for a convention booth. Customers fill out a form, the operator generates two AI-made song versions, the customer picks one, and the approved MP3 is delivered by email after payment is collected.
What this project does
- Customer request page (
/request) — booth visitors enter their name, email, hobbies, notable facts, preferred genre, and extra requests. A branded banner image is shown. - Operator dashboard (
/admin) — queue of all requests with status filters, per-request detail page, and system reset. - Prompt generation — the admin page builds a plain-text prompt for Hermes/AI, which returns a Title, Style, and Lyrics block. The operator pastes that response, clicks Extract, then uses Copy buttons to paste into Suno Custom Mode.
- Song upload — operator uploads Version A and Version B MP3s.
- Customer player page — a private
/play/<token>page emails to the customer. They can listen to both versions, choose A/B/both, or request changes. - Payment and delivery — operator enters a Square payment reference and clicks Mark Paid & Deliver. The approved MP3(s) are emailed as attachments.
- System reset — one button in the admin topbar clears all requests and files at the start of an event.
Status flow
pending → prompt_ready → songs_uploaded → awaiting_payment → paid → delivered
| Status | Meaning |
|---|---|
pending |
Customer submitted request; no prompt yet. |
prompt_ready |
Operator saved Title/Style/Lyrics. |
songs_uploaded |
Both MP3s uploaded; preview link can be sent. |
awaiting_payment |
Customer approved a version. |
paid |
Payment reference recorded; delivery email sent. |
delivered |
MP3 attachments emailed. |
File layout
| File | Purpose |
|---|---|
app.py |
Flask routes, helpers, and email logic. |
config.py |
Environment-variable based configuration. |
models.py |
SQLite schema and database helper functions. |
init_db.py |
Standalone script to create the database tables. |
templates/request.html |
Customer request form (with banner). |
templates/thanks.html |
Post-submission confirmation. |
templates/player.html |
Customer audio player and approval page. |
templates/admin/login.html |
Admin password login. |
templates/admin/dashboard.html |
Operator queue with filters and reset. |
templates/admin/request.html |
Single-request detail / prompt / upload / delivery. |
static/Trollgorithm_booth.jpg |
Banner image on the request page. |
Dockerfile |
Production container image. |
docker-compose.yml |
Portainer stack definition. |
requirements.txt |
Python dependencies. |
.env.example |
Template for environment variables. |
REVIEW.md |
Quick reference for returning to this project. |
Local development
cd /home/jess/workspace/theme-song-booth
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
cp .env.example .env
# Edit .env and set APP_SECRET_KEY, ADMIN_PASSWORD, SMTP_PASS, PUBLIC_BASE_URL
.venv/bin/python init_db.py
.venv/bin/python -m flask --app app run --host=0.0.0.0
Visit:
- Customer form: http://127.0.0.1:5000/request
- Admin login: http://127.0.0.1:5000/admin
Deployment with Portainer
- Log in to Portainer.
- Go to Stacks → Add stack.
- Choose Repository:
- URL:
https://gitlab.hallsworth.ca/yrtria/theme-song-booth.git - Branch:
main - Compose path:
docker-compose.yml
- URL:
- Add environment variables:
| Variable | Required | Purpose |
|---|---|---|
APP_SECRET_KEY |
Yes | Long random string for Flask sessions. Generate with python3 -c "import secrets; print(secrets.token_hex(32))". |
ADMIN_PASSWORD |
Yes | Password for /admin. |
SMTP_PASS |
Yes | Password for ai@hallsworth.ca. |
PUBLIC_BASE_URL |
Yes | Public HTTPS URL, e.g. https://booth.dionysismedia.ca. |
HOST_PORT |
No | Host-side port mapping, default 127.0.0.1:8000. |
INTERNAL_PORT |
No | Port gunicorn binds inside container, default 8000. |
BOOTH_NAME |
No | Name used in emails, default Trollgorithm Theme Songs. |
PRICE_PER_VERSION |
No | Shown on receipt page, default 10.00. |
CURRENCY |
No | Currency label, default CAD. |
- Deploy the stack.
- Open a console in the
boothcontainer and run once:
python init_db.py
- Point your reverse proxy at the
HOST_PORTyou chose. - Print or display a QR code pointing to
https://your-domain/request.
Updating the deployment
After each push to GitLab, go to Portainer → Stacks → theme-song-booth → Pull and redeploy to rebuild from the repo.
Important notes
- No
.envfile in production.docker-compose.ymlpasses variables directly from Portainer. This avoids Portainer'senv_file not founderror. - Payments are manual. The app records a Square payment reference but does not integrate with Square's API. Use a Square Terminal/Reader at the booth.
- Operator queue is the dashboard. No operator email alerts are sent; approvals and revision notes appear as status changes in
/admin. - Security: the repo is public on GitLab. No secrets are committed. Admin password is plain text in the Portainer environment.
Common troubleshooting
| Problem | Cause | Fix |
|---|---|---|
| "Send Preview Link" does nothing | Form tags were unbalanced (now fixed). | Redeploy the latest commit. |
| Emails not arriving | SMTP_PASS wrong or messages in spam. | Verify SMTP credentials; check spam folder. |
| Can't reach app through domain | Reverse proxy points to wrong host port. | Match HOST_PORT to your proxy upstream. |
| Static banner not showing | Browser cached old image. | Hard-refresh or redeploy stack. |
License / ownership
Built for Jess's Trollgorithm theme-song booth. All code and assets are private to that project.