A vibe-coded proof-of-concept tool for using AI to generate Spotify playlists.
A NiceGUI-based Python application that allows users to manage their Spotify playlists.
- View your Spotify playlists
- View detailed playlist information with track listings
- Direct links to open tracks and playlists in Spotify
- Settings for application configuration
- Spotify OAuth authentication
- Fixed issue with playlist track loading where tracks were not being displayed in the playlist detail view
- Improved error handling and debugging for track loading functionality
- Enhanced the track rendering component to handle various Spotify API response formats
- Added comprehensive data validation to prevent errors with missing fields
- Python 3.11
- Miniconda or Anaconda
- Spotify Developer Account
- Go to the Spotify Developer Dashboard
- Create a new application
- Set the Redirect URI to
http://127.0.0.1:8080/callback
- Create a
.env
file in the project root with the following variables:
SPOTIFY_CLIENT_ID=your_spotify_client_id
SPOTIFY_CLIENT_SECRET=your_spotify_client_secret
SPOTIFY_REDIRECT_URI=http://127.0.0.1:8080/callback
- Clone this repository
- Create the conda environment:
conda create -n spotify-playlist-generator python=3.11
- Activate the environment:
conda activate spotify-playlist-generator
- Install required packages:
pip install -r requirements.txt
- Run the application:
python app.py
This project implements unit tests for backend components only. UI components (which use NiceGUI) are excluded from automated testing due to their interactive nature and tight coupling with the NiceGUI framework.
Key components tested include:
TemplateLoader
- HTML template loading functionalityTrack
andPlaylist
models - Data model classesSpotifyAuthService
- Spotify authentication serviceSpotifyService
- Spotify API client service- Utility functions in
utils.py
The project includes a testing suite for backend components. To run the tests:
# Run all tests
python run_tests.py
# Run tests with verbose output
python run_tests.py -v
# Run tests for a specific module
python run_tests.py --module tests/unit/test_template_loader.py
# Generate HTML coverage report
python run_tests.py --html
This project uses GitHub Actions to automatically run tests on every push to any branch and all pull requests. The workflow configuration can be found in .github/workflows/python-tests.yml
.
The CI pipeline:
- Runs on the latest Ubuntu environment
- Tests with Python 3.11
- Installs all dependencies
- Runs the test suite with pytest and generates coverage reports
- Uploads coverage reports to Codecov
To manually trigger the workflow, you can use the "Run workflow" button in the Actions tab of the GitHub repository.
Code coverage focuses on backend components. You can generate and view code coverage reports with:
# Generate HTML coverage report for all tests
python run_tests.py --html
# Generate coverage report for a specific module
python run_tests.py --html --module tests/unit/test_template_loader.py
The HTML coverage report provides a detailed view of which lines of backend code are covered by tests. The current test suite covers:
- 100% of the
models
package - 99% of the
auth_service.py
service - 98% of the
lastfm_service.py
service - 91% of the
spotify_service.py
service - 100% of utility functions in
utils.py
- 100% of the
TemplateLoader
class
The overall code coverage is 96%, with only a few edge cases and exception handling scenarios not fully tested. UI components are excluded from coverage calculations as they are tested manually.
├── app.py # Main entry point
├── requirements.txt # Python package requirements
├── src/ # Source code
│ └── spotify_playlist_generator/
│ ├── ui/ # UI components
│ │ ├── templates/ # HTML templates
│ │ └── app.py # Main UI application
│ ├── services/ # Service layer for API interactions
│ └── models/ # Data models
├── tests/ # Test suite
│ └── unit/ # Unit tests for backend components
- Python 3.11
- NiceGUI - UI framework
- Spotipy - Spotify API client
- pytest - Testing framework
- pytest-cov - Code coverage reporting
This section provides guidance for LLMs (Large Language Models) when working with this codebase.
When modifying or extending this codebase, enforce the following SOLID principles:
-
Single Responsibility Principle (SRP)
- Each class should have only one reason to change
- Keep UI components separate from business logic
- Example: The
PlaylistComponents
class handles rendering, whileAppUI
orchestrates application flow
-
Open/Closed Principle (OCP)
- Software entities should be open for extension but closed for modification
- Add new functionality by creating new classes rather than modifying existing ones
- Example: To add a new playlist view type, extend the rendering system without changing core classes
-
Liskov Substitution Principle (LSP)
- Subtypes must be substitutable for their base types
- Ensure any class that inherits from another can be used in the same way
-
Interface Segregation Principle (ISP)
- Clients should not be forced to depend on interfaces they do not use
- Create specific, focused interfaces rather than general-purpose ones
-
Dependency Inversion Principle (DIP)
- High-level modules should not depend on low-level modules; both should depend on abstractions
- Example:
AppUI
depends on abstract interfaces (template loader, auth service) rather than concrete implementations
When working with this codebase:
-
HTML Content
- Never embed HTML directly in Python code
- Always place HTML in template files in the
templates/
directory - Use the
TemplateLoader
class to load HTML templates
-
UI Components
- Place UI rendering logic in the
ui_components.py
file - Create static methods for reusable UI elements
- Keep styling separate from structure
- Place UI rendering logic in the
-
Directory Structure
- Maintain the existing directory structure
- Place new templates in the
templates/
directory - Create new modules for new functionality domains
-
Authentication Logic
- Keep authentication logic in the
auth_service.py
file - Ensure OAuth flow is maintained when modifying authentication
- Keep authentication logic in the
-
Style Consistency
- Follow the existing code style (docstrings, method naming)
- Use type hints for function parameters and return values
- Document complex logic with clear comments
-
Testing
- Write unit tests for backend components
- Test business logic and utilities thoroughly
- UI components are exempt from automated testing requirements
- Focus testing efforts on service layers and utility classes
When adding new features:
- Identify which layer the feature belongs to (UI, service, model)
- Create appropriate classes following SOLID principles
- Update existing orchestration classes to use the new components
- Add comprehensive unit tests for backend components
- Update this README if the feature changes the project structure
By following these guidelines, you'll help maintain a clean, modular, and extensible codebase.
When contributing to this codebase, adhere to these clean code principles:
-
Meaningful Names
- Use intention-revealing names for variables, functions, and classes
- Avoid abbreviations unless they are widely understood
- Classes should have noun names, methods should have verb names
- Example:
get_playlist_tracks()
clearly communicates its purpose
-
Functions
- Keep functions small, focused on a single task
- Limit function length to 20-30 lines where possible
- Follow the "do one thing" rule - functions should have a single responsibility
- Limit function arguments to 3 or fewer; use objects to group related parameters
-
Comments
- Write self-documenting code that needs minimal comments
- Use comments to explain "why" not "what"
- Update comments when code changes
- Use docstrings for all public methods and classes
-
Formatting
- Maintain consistent indentation (4 spaces in Python)
- Keep line length under 100 characters
- Group related code together; separate unrelated code with blank lines
- Follow Python's PEP 8 style guide
-
Error Handling
- Use exceptions rather than error codes
- Don't return None or special values to indicate errors
- Provide context in exception messages
- Always clean up resources in finally blocks
-
Don't Repeat Yourself (DRY)
- Extract duplicate code into shared functions or classes
- Use abstraction to eliminate repetition
- Follow the "Single Source of Truth" principle
-
Test-Driven Development
- Write tests before implementing new features
- Ensure each test verifies one specific behavior
- Maintain independence between tests
- Write tests that are readable and maintainable
-
Dependency Management
- Minimize dependencies between modules
- Use dependency injection to allow for better testing
- Make dependencies explicit in function signatures
These clean code principles complement the SOLID principles and help ensure that the codebase remains maintainable and easy to understand even as it grows in complexity.