9ea40bec61
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
11 KiB
11 KiB
AI Agent Instructions for Quizzical Beats
This document provides guidelines for AI coding agents working on the Quizzical Beats repository.
Project Overview
Quizzical Beats is a Flask-based web application for creating music quiz rounds for pub quizzes. It integrates with multiple music APIs (Spotify, Deezer, Last.fm) and provides PDF/MP3 export capabilities.
Technology Stack
- Backend: Python 3.11+, Flask 3.x
- Database: SQLAlchemy ORM (SQLite dev, PostgreSQL/MySQL production)
- Frontend: Jinja2 templates, vanilla JavaScript
- APIs: Spotify, Deezer, Last.fm, OpenAI, Dropbox
- Authentication: Flask-Login, Authlib (OAuth)
- Deployment: Docker, Docker Compose
Repository Structure
musicround/ # Main application package
├── __init__.py # Application factory
├── config.py # Configuration management
├── models.py # Database models (SQLAlchemy)
├── helpers/ # Utility modules
├── routes/ # Flask blueprints (auth, api, core, generate, etc.)
├── static/ # CSS, JavaScript, images
└── templates/ # Jinja2 HTML templates
tests/ # Test suite
docs/ # MkDocs documentation
migrations/ # Database migration scripts
Code Style Guidelines
Python Style
- Follow PEP 8 with maximum line length of 100 characters
- Use 4 spaces for indentation (no tabs)
- Provide docstrings for all functions and classes (Google style)
- Use type hints where beneficial
def process_playlist(playlist_id: str, user_id: int) -> dict:
"""Process a Spotify playlist and import songs.
Args:
playlist_id: The Spotify playlist ID
user_id: The user's database ID
Returns:
Dictionary containing import results with keys:
- success: Boolean indicating success
- songs_imported: Number of songs imported
- errors: List of error messages (if any)
"""
pass
Flask Best Practices
- Organize routes using blueprints
- Prefer class-based views for complex endpoints
- Use Flask-WTF for form handling
- Always validate and sanitize user inputs
- Use SQLAlchemy ORM (never raw SQL without parameterization)
Security Requirements
- NEVER commit API keys, secrets, or passwords
- ALWAYS use environment variables for sensitive data
- Validate all user inputs
- Use parameterized queries (SQLAlchemy ORM does this)
- Escape all template outputs (Jinja2 auto-escaping)
- Check SECURITY.md before making security-related changes
Development Workflow
Before Making Changes
-
Understand the codebase:
- Read related code in
musicround/routes/andmusicround/helpers/ - Check existing tests in
tests/ - Review documentation in
docs/
- Read related code in
-
Check existing issues and roadmap:
- Review TODO.md for planned features
- Check ROADMAP.md for strategic direction
- Search GitHub issues for related discussions
-
Set up development environment:
python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate pip install -r requirements.txt
Making Changes
-
Create minimal, focused changes:
- Make the smallest change that solves the problem
- Don't refactor unrelated code
- Don't fix unrelated bugs or style issues
-
Write tests:
- Add tests for new functionality in
tests/ - Update existing tests if behavior changes
- Run tests:
pytest tests/ -v
- Add tests for new functionality in
-
Update documentation:
- Update docstrings for modified functions
- Update
docs/if user-facing changes - Update
README.mdif installation/setup changes
Testing
# Run all tests
pytest tests/ -v
# Run specific test file
pytest tests/test_metadata.py -v
# Run with coverage
pytest --cov=musicround tests/
Linting and Code Quality
# Format code (if black is installed)
black musicround/ --line-length 100
# Check code style
flake8 musicround/ --max-line-length=100
# Type checking (if mypy is installed)
mypy musicround/
Common Tasks
Adding a New Route
# In musicround/routes/new_feature.py
from flask import Blueprint, render_template, request
from flask_login import login_required, current_user
new_feature_bp = Blueprint('new_feature', __name__)
@new_feature_bp.route('/new-feature')
@login_required
def index():
"""Display the new feature page."""
return render_template('new_feature/index.html')
Then register in musicround/__init__.py:
from musicround.routes.new_feature import new_feature_bp
app.register_blueprint(new_feature_bp)
Adding a Database Model
# In musicround/models.py
class NewModel(db.Model):
"""Description of what this model represents."""
__tablename__ = 'new_model'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
def __repr__(self):
return f'<NewModel {self.name}>'
Then create a migration:
flask db migrate -m "Add NewModel"
flask db upgrade
Adding a Configuration Variable
# In musicround/config.py
class Config:
NEW_SETTING = os.getenv("NEW_SETTING", "default_value")
Add to .env.example:
# Description of what this does
NEW_SETTING=default_value
Database Migrations
- Migration files are in
migrations/ - Use
run_migration.pyto run migrations - Always test migrations on a backup database first
- Document schema changes in migration message
# Create a new migration
python run_migration.py
# Or manually
flask db migrate -m "Description of change"
flask db upgrade
API Integration Guidelines
Spotify API
- Token management in
musicround/helpers/spotify_helper.py - Use existing client manager:
SpotifyClientManager - Handle rate limits gracefully (retry with backoff)
- Always refresh expired tokens
OAuth Integration
- OAuth routes in
musicround/routes/auth.py - Store tokens encrypted in database (User model)
- Implement token refresh before expiration
- Follow existing patterns for new OAuth providers
Error Handling
# Use Flask error handlers
from musicround.errors import APIError
@app.errorhandler(APIError)
def handle_api_error(error):
return render_template('error.html', error=error), error.status_code
# In your code
if not valid:
raise APIError("Invalid input", status_code=400)
Logging
import logging
logger = logging.getLogger(__name__)
# Use appropriate log levels
logger.debug("Detailed debugging information")
logger.info("Informational messages")
logger.warning("Warning messages")
logger.error("Error messages")
logger.critical("Critical errors")
Commit Messages
Follow conventional commit format:
<type>(<scope>): <subject>
<body>
<footer>
Types:
feat: New featurefix: Bug fixdocs: Documentation changesstyle: Code style changes (formatting)refactor: Code refactoringtest: Adding or updating testschore: Maintenance taskssecurity: Security fixes
Examples:
feat(import): Add support for Deezer playlist import
Implemented Deezer API client and playlist parsing.
Supports public and user playlists.
Fixes #123
---
fix(auth): Refresh Spotify tokens before expiration
Previously tokens would expire during long operations.
Now checks expiration 5 minutes in advance.
---
security: Upgrade authlib to 1.6.5
Fixes CVE-2024-XXXXX (JWT validation bypass)
Pull Request Guidelines
- Fill out the PR template completely
- Reference related issues with
Fixes #123orRelates to #456 - Include before/after screenshots for UI changes
- List any database migrations required
- Note any breaking changes
- Ensure all tests pass
- Check security implications
Testing Strategy
What to Test
- Business logic in helpers and models
- API integration error handling
- Authentication and authorization
- Database operations
- Input validation
What Not to Test
- Third-party library internals
- Database engine specifics
- Flask framework itself
Test Structure
# tests/test_feature.py
import pytest
from musicround import create_app, db
from musicround.models import User
@pytest.fixture
def app():
"""Create application for testing."""
app = create_app('testing')
with app.app_context():
db.create_all()
yield app
db.session.remove()
db.drop_all()
def test_feature(app):
"""Test description."""
# Arrange
user = User(username='test', email='test@example.com')
# Act
result = some_function(user)
# Assert
assert result == expected_value
Documentation
- User documentation in
docs/user-guide/ - Admin documentation in
docs/admin-guide/ - Developer documentation in
docs/developer-guide/ - API documentation in
docs/developer-guide/api-reference.md - Use MkDocs markdown format
Common Pitfalls to Avoid
- Don't use default SECRET_KEY: Must be set via environment variable
- Don't commit .env files: Use .env.example as template
- Don't store credentials in code: Use environment variables
- Don't make breaking changes without migration path: Document upgrade steps
- Don't skip input validation: All user input is untrusted
- Don't use raw SQL: Use SQLAlchemy ORM for safety
- Don't forget CSRF protection: Use Flask-WTF forms
- Don't expose sensitive data in logs: Sanitize before logging
Useful Commands
# Development server
python run.py
# Run migrations
python run_migration.py
# Run tests
pytest tests/ -v
# Check dependencies for vulnerabilities
pip install safety
safety check
# Docker commands
docker-compose up -d
docker-compose logs -f
docker-compose down
# Database backup
# (Use built-in backup functionality in web UI or /backup endpoint)
Getting Help
- Check documentation
- Review FAQ
- Search GitHub issues
- Read CONTRIBUTING.md
- Contact: christian@kaufdeinquiz.com
References
- Flask Documentation
- SQLAlchemy Documentation
- Spotify Web API
- PEP 8 Style Guide
- Google Python Style Guide
Last updated: February 2026