feat: add /faq page and link from request form
This commit is contained in:
parent
382b05d7f8
commit
023b4fade7
5 changed files with 168 additions and 1 deletions
|
|
@ -8,6 +8,7 @@ A Flask web app for a convention booth where visitors request a custom AI-genera
|
||||||
|
|
||||||
- **Request form** (`/request`) — visitors enter name, email, hobbies, notable facts, preferred style/genre, vocal gender preference, and extra requests. A branded banner image is shown. The email field is validated to reduce delivery problems.
|
- **Request form** (`/request`) — visitors enter name, email, hobbies, notable facts, preferred style/genre, vocal gender preference, and extra requests. A branded banner image is shown. The email field is validated to reduce delivery problems.
|
||||||
- **Confirmation page** (`/thanks/<id>`) — shows the request number after submission.
|
- **Confirmation page** (`/thanks/<id>`) — shows the request number after submission.
|
||||||
|
- **FAQ page** (`/faq`) — answers common customer questions.
|
||||||
- **Private player page** (`/play/<token>`) — customer receives an email with a unique link. They can stream Version A and Version B, pick one (or both), or request a limited number of revisions.
|
- **Private player page** (`/play/<token>`) — customer receives an email with a unique link. They can stream Version A and Version B, pick one (or both), or request a limited number of revisions.
|
||||||
- **Revision workflow** — when a customer asks for changes, the current MP3s are archived and the operator sees the request as "Revisions Requested" in the dashboard.
|
- **Revision workflow** — when a customer asks for changes, the current MP3s are archived and the operator sees the request as "Revisions Requested" in the dashboard.
|
||||||
- **Rate limiting** — the public request form is capped at 5 submissions per minute per IP.
|
- **Rate limiting** — the public request form is capped at 5 submissions per minute per IP.
|
||||||
|
|
@ -60,6 +61,7 @@ pending → prompt_ready → songs_uploaded → awaiting_payment → paid → de
|
||||||
| `init_db.py` | Standalone script to create the database tables. |
|
| `init_db.py` | Standalone script to create the database tables. |
|
||||||
| `templates/request.html` | Customer request form. |
|
| `templates/request.html` | Customer request form. |
|
||||||
| `templates/thanks.html` | Post-submission confirmation. |
|
| `templates/thanks.html` | Post-submission confirmation. |
|
||||||
|
| `templates/faq.html` | Customer FAQ page. |
|
||||||
| `templates/player.html` | Customer audio player, approval, and revision form. |
|
| `templates/player.html` | Customer audio player, approval, and revision form. |
|
||||||
| `templates/admin/login.html` | Admin login page. |
|
| `templates/admin/login.html` | Admin login page. |
|
||||||
| `templates/admin/dashboard.html` | Operator queue with filters and auto-refresh. |
|
| `templates/admin/dashboard.html` | Operator queue with filters and auto-refresh. |
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,10 @@ Flask app that lets convention attendees request custom AI-generated theme songs
|
||||||
| `config.py` | Env vars. `ADMIN_PASSWORD` is plain text. |
|
| `config.py` | Env vars. `ADMIN_PASSWORD` is plain text. |
|
||||||
| `models.py` | SQLite schema + CRUD. `player_token` is a secret URL-safe token. |
|
| `models.py` | SQLite schema + CRUD. `player_token` is a secret URL-safe token. |
|
||||||
| `init_db.py` | Run once after deploy: `python init_db.py`. |
|
| `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/request.html` | Biggest template; prompt copy helpers and JS live here. Customer email is editable here. |
|
||||||
| `templates/admin/dashboard.html` | Queue table + filters + auto-refresh + topbar Reset System button. |
|
| `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. |
|
| `templates/admin/settings.html` | SMTP config, MP3 metadata defaults, DB backup/restore, health check, reset. |
|
||||||
|
| `templates/faq.html` | Customer FAQ page. |
|
||||||
| `docker-compose.yml` | No `env_file`; variables come from Portainer. |
|
| `docker-compose.yml` | No `env_file`; variables come from Portainer. |
|
||||||
|
|
||||||
## Status meanings
|
## Status meanings
|
||||||
|
|
|
||||||
6
app.py
6
app.py
|
|
@ -377,6 +377,12 @@ def thanks(rid):
|
||||||
return render_template('thanks.html', req=req)
|
return render_template('thanks.html', req=req)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/faq')
|
||||||
|
def faq():
|
||||||
|
"""Customer-facing frequently asked questions page."""
|
||||||
|
return render_template('faq.html')
|
||||||
|
|
||||||
|
|
||||||
@app.route('/play/<token>')
|
@app.route('/play/<token>')
|
||||||
def play(token):
|
def play(token):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
157
templates/faq.html
Normal file
157
templates/faq.html
Normal file
|
|
@ -0,0 +1,157 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>FAQ — Trollgorithm Theme Song Booth</title>
|
||||||
|
<style>
|
||||||
|
/*
|
||||||
|
Customer FAQ page.
|
||||||
|
Simple, readable dark layout matching the request page style.
|
||||||
|
*/
|
||||||
|
*{box-sizing:border-box;}
|
||||||
|
body{
|
||||||
|
font-family:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
|
||||||
|
background:linear-gradient(135deg,#111827 0%,#1e3a8a 50%,#111827 100%);
|
||||||
|
color:#f3f4f6;
|
||||||
|
margin:0;
|
||||||
|
padding:1rem;
|
||||||
|
line-height:1.6;
|
||||||
|
min-height:100vh;
|
||||||
|
}
|
||||||
|
.container{max-width:760px;margin:0 auto;}
|
||||||
|
.card{
|
||||||
|
background:rgba(31,41,55,.95);
|
||||||
|
padding:1.5rem;
|
||||||
|
border-radius:1rem;
|
||||||
|
box-shadow:0 10px 25px rgba(0,0,0,.3);
|
||||||
|
border:1px solid rgba(96,165,250,.2);
|
||||||
|
}
|
||||||
|
h1{
|
||||||
|
margin-top:0;
|
||||||
|
color:#60a5fa;
|
||||||
|
text-align:center;
|
||||||
|
font-size:1.9rem;
|
||||||
|
}
|
||||||
|
h2{
|
||||||
|
color:#93c5fd;
|
||||||
|
margin-top:2rem;
|
||||||
|
font-size:1.25rem;
|
||||||
|
border-bottom:1px solid #374151;
|
||||||
|
padding-bottom:.4rem;
|
||||||
|
}
|
||||||
|
h2:first-of-type{margin-top:0;}
|
||||||
|
p{margin:.6rem 0;}
|
||||||
|
strong{color:#fbbf24;}
|
||||||
|
a{color:#93c5fd;text-decoration:none;}
|
||||||
|
a:hover{text-decoration:underline;}
|
||||||
|
.back{
|
||||||
|
display:block;
|
||||||
|
text-align:center;
|
||||||
|
margin-top:1.5rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="card">
|
||||||
|
<h1>❓ Frequently Asked Questions</h1>
|
||||||
|
|
||||||
|
<h2>The basics</h2>
|
||||||
|
<p><strong>What is the Trollgorithm Song Booth?</strong></p>
|
||||||
|
<p>We create a custom, AI-generated theme song just for you based on your personality, hobbies, and style preferences.</p>
|
||||||
|
|
||||||
|
<p><strong>How long does it take to get my song?</strong></p>
|
||||||
|
<p>Most songs are ready to preview within a few minutes to an hour, depending on how busy the booth is!</p>
|
||||||
|
|
||||||
|
<p><strong>How much does it cost?</strong></p>
|
||||||
|
<p>Pricing is displayed at the booth; you pay after listening to and choosing the version you want.</p>
|
||||||
|
|
||||||
|
<p><strong>What do I actually receive?</strong></p>
|
||||||
|
<p>You get an MP3 file of the version you selected, delivered straight to your email. WAV format is available for a slight additional charge.</p>
|
||||||
|
|
||||||
|
<h2>How it works</h2>
|
||||||
|
<p><strong>What info do I need to give you?</strong></p>
|
||||||
|
<p>Your name, email, hobbies, notable facts about you, a preferred style or genre, and any extra requests you want included.</p>
|
||||||
|
|
||||||
|
<p><strong>Can I pick the style or genre?</strong></p>
|
||||||
|
<p>Yes — tell us anything from “80s power ballad” to “cinematic orchestral” and we will aim for that vibe.</p>
|
||||||
|
|
||||||
|
<p><strong>What if I want a specific singer voice?</strong></p>
|
||||||
|
<p>You can select a vocal preference such as female, male, androgynous, or non-binary on the request form. We are unable to create specific singers due to copyright laws.</p>
|
||||||
|
|
||||||
|
<p><strong>Can I request specific lyrics or topics?</strong></p>
|
||||||
|
<p>Absolutely — put any specific lyrics, themes, or things to avoid in the “Extra requests” field.</p>
|
||||||
|
|
||||||
|
<p><strong>What happens after I submit the form?</strong></p>
|
||||||
|
<p>We generate a custom prompt, produce two versions of your song, and email you a private link to listen.</p>
|
||||||
|
|
||||||
|
<p><strong>How do I hear my song when it's ready?</strong></p>
|
||||||
|
<p>Click the private link in your email — it works on any phone, tablet, or computer.</p>
|
||||||
|
|
||||||
|
<h2>Versions & revisions</h2>
|
||||||
|
<p><strong>What's the difference between Version A and Version B?</strong></p>
|
||||||
|
<p>They are two different takes or arrangements of your theme song, so you can choose the one you like best.</p>
|
||||||
|
|
||||||
|
<p><strong>Can I get both versions?</strong></p>
|
||||||
|
<p>Yes — just select “I want both” on the preview page.</p>
|
||||||
|
|
||||||
|
<p><strong>What if I don't like either version?</strong></p>
|
||||||
|
<p>You can request a limited number of changes through the preview page, or speak to the booth operator.</p>
|
||||||
|
|
||||||
|
<p><strong>Can I ask for changes? How many times?</strong></p>
|
||||||
|
<p>Yes, a small number of revisions are allowed; the exact limit is shown on your preview page.</p>
|
||||||
|
|
||||||
|
<p><strong>What if I change my mind after picking a version?</strong></p>
|
||||||
|
<p>Let the booth operator know right away; if payment has not been finalized, we can usually fix it.</p>
|
||||||
|
|
||||||
|
<h2>Payment & delivery</h2>
|
||||||
|
<p><strong>How do I pay?</strong></p>
|
||||||
|
<p>We accept payment at the booth through Square, including card, tap, and cash where available.</p>
|
||||||
|
|
||||||
|
<p><strong>Do you pay before or after hearing the song?</strong></p>
|
||||||
|
<p>You hear the preview first, pick a version, and then pay before the final MP3 is emailed to you.</p>
|
||||||
|
|
||||||
|
<p><strong>Where is my song delivered?</strong></p>
|
||||||
|
<p>To the email address you gave us, so double-check it for typos before submitting.</p>
|
||||||
|
|
||||||
|
<p><strong>What file format is it?</strong></p>
|
||||||
|
<p>The delivered song is a standard MP3 file that plays on virtually any device. WAV files can be provided upon request.</p>
|
||||||
|
|
||||||
|
<p><strong>Can you send it to someone else's email?</strong></p>
|
||||||
|
<p>At the booth we can update the email address if needed, but the original request needs a valid email to start.</p>
|
||||||
|
|
||||||
|
<h2>Ownership & usage</h2>
|
||||||
|
<p><strong>Do I own my theme song?</strong></p>
|
||||||
|
<p>Once you have paid, you do! You can use it for whatever you want, commercially or privately. Trollgorithm does reserve the right to use any music it makes as part of its demonstration playlist.</p>
|
||||||
|
|
||||||
|
<p><strong>Can I post it online?</strong></p>
|
||||||
|
<p>Yes, for personal, or commercial use — feel free to share it on social media.</p>
|
||||||
|
|
||||||
|
<p><strong>Can I use it in a video/stream/podcast?</strong></p>
|
||||||
|
<p>Personal, non-commercial use is fine; commercial projects require separate written permission.</p>
|
||||||
|
|
||||||
|
<p><strong>Is this AI-generated music? Is that legal?</strong></p>
|
||||||
|
<p>Trollgorithm is a privately built AI music Writer, Producer, Sound Engineer, and Band. It does each step (with human input, of course!) and produces finished songs. Since the music and lyrics are generated from scratch, no copyright rules are broken.</p>
|
||||||
|
|
||||||
|
<h2>Privacy & support</h2>
|
||||||
|
<p><strong>Is my personal information kept private?</strong></p>
|
||||||
|
<p>Yes, your info is only used to create and deliver your song and is not shared or sold. Your information is only stored for a few days, to ensure you have received the end product you want. After that it is deleted.</p>
|
||||||
|
|
||||||
|
<p><strong>What if I made a typo in my email?</strong></p>
|
||||||
|
<p>Tell the booth operator; they can edit your email address so your song reaches you.</p>
|
||||||
|
|
||||||
|
<p><strong>What if I don't get the email?</strong></p>
|
||||||
|
<p>Check your spam or junk folder first, then ask the operator to resend or verify your address.</p>
|
||||||
|
|
||||||
|
<p><strong>What if there's a technical problem?</strong></p>
|
||||||
|
<p>Let the booth operator know and we will do our best to fix it or retry delivery.</p>
|
||||||
|
|
||||||
|
<p><strong>Who do I talk to for help?</strong></p>
|
||||||
|
<p>The booth operator is your best point of contact for any questions or issues.</p>
|
||||||
|
|
||||||
|
<a class="back" href="{{ url_for('request_form') }}" target="_blank" rel="noopener noreferrer">← Back to the request form</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -122,6 +122,7 @@
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h1><span class="sparkle">🎵</span> Get Your Custom Theme Song <span class="sparkle">🎶</span></h1>
|
<h1><span class="sparkle">🎵</span> Get Your Custom Theme Song <span class="sparkle">🎶</span></h1>
|
||||||
<p class="subtitle">Tell us about yourself and we'll craft a one-of-a-kind song just for you.</p>
|
<p class="subtitle">Tell us about yourself and we'll craft a one-of-a-kind song just for you.</p>
|
||||||
|
<p class="subtitle"><a href="{{ url_for('faq') }}" target="_blank" rel="noopener noreferrer">Questions? Read our FAQ →</a></p>
|
||||||
|
|
||||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||||
{% if messages %}
|
{% if messages %}
|
||||||
|
|
|
||||||
Reference in a new issue