# 5avis/playlist-a-live architecture

> Architecture diagram of the GitHub repository 5avis/playlist-a-live, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-08-12). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/5avis/playlist-a-live
- Repository: https://github.com/5avis/playlist-a-live

## Overview

#### Purpose and Entry Points
`playlist-a-live` is a Python automation pipeline that gathers trending music, enriches tracks with features, clusters them, makes playlist decisions, and updates a Spotify playlist. The main orchestrator is `run_pipeline.py`; scheduled execution is configured in `.github/workflows/daily.yml`.

#### Pipeline Orchestration
`run_pipeline.py` coordinates the end-to-end stages and their file-based handoffs. The repository uses CSV artifacts as durable boundaries between collection, analysis, decisioning, and playlist mutation:
- `trending_tracks.csv`
- `tracks_with_features.csv`
- `tracks_clustered.csv`
- `decisions.csv`

#### Trend Collection
`fetch_trending.py` obtains the source set of trending tracks and writes the initial track dataset. This is the ingestion boundary: downstream code operates on persisted track records rather than directly on the trend source.
- `fetch_trending.py`
- `trending_tracks.csv`

#### Feature Enrichment
`fetch_with_features.py` augments collected tracks with music metadata/features needed for analysis. It consumes the trending-track output and produces the feature-bearing dataset used by clustering.
- `fetch_with_features.py`
- `trending_tracks.csv`
- `tracks_with_features.csv`

#### Analysis and Decisioning
`clustering.py` groups enriched tracks, likely creating the analytical representation for playlist selection. `decision.py` converts clustered results into explicit add/remove or selection decisions, persisted for the playlist-update stage.
- `clustering.py`
- `tracks_with_features.csv`
- `tracks_clustered.csv`
- `decision.py`
- `decisions.csv`

#### Spotify Authentication and Playlist Mutation
Spotify access is separated from the pipeline’s data stages. `spotify_login.py`, `login_fresh.py`, and `reauth.py` handle authentication/session recovery; `update_playlist.py` is the external side-effect boundary that applies `decisions.csv` to Spotify. This separation allows analysis to complete before mutating the live playlist.
- `spotify_login.py`
- `login_fresh.py`
- `reauth.py`
- `update_playlist.py`

#### Operational State and Runtime
The project is Python-script based, with local CSV files serving as both pipeline outputs and operational history. `activity_log.py` and `activity_log.csv` provide an execution/activity record. GitHub Actions supplies the scheduled runtime, so credentials for Spotify and any trend/feature providers must be available to the workflow environment.
- `activity_log.py`
- `activity_log.csv`
- `.github/workflows/daily.yml`

Main entry points: [`run_pipeline.py`](https://github.com/5avis/playlist-a-live/blob/main/run_pipeline.py) (Pipeline Orchestrator), [`update_playlist.py`](https://github.com/5avis/playlist-a-live/blob/main/update_playlist.py) (Playlist Updater), [`spotify_login.py`](https://github.com/5avis/playlist-a-live/blob/main/spotify_login.py) (Spotify Login), [`fetch_with_features.py`](https://github.com/5avis/playlist-a-live/blob/main/fetch_with_features.py) (Feature Enricher)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_pipeline["Data Pipeline"]
  node_orchestrator["Pipeline Orchestrator<br/>Python entry point<br/>[run_pipeline.py]"]
  node_trend_fetcher["Trend Collector<br/>ingestion script<br/>[fetch_trending.py]"]
  node_trending_csv["Trending Tracks<br/>CSV artifact"]
  node_feature_fetcher["Feature Enricher<br/>enrichment script"]
  node_features_csv["Tracks with Features<br/>CSV artifact"]
  node_clustering["Track Clustering<br/>analysis script<br/>[clustering.py]"]
  node_clustered_csv["Clustered Tracks<br/>CSV artifact"]
  node_decisioning["Playlist Decisioning<br/>decision script<br/>[decision.py]"]
  node_decisions_csv["Playlist Decisions<br/>CSV artifact<br/>[decisions.csv]"]
end

subgraph group_spotify["Spotify Integration"]
  node_spotify_login["Spotify Login<br/>authentication<br/>[spotify_login.py]"]
  node_fresh_login["Fresh Login<br/>authentication flow<br/>[login_fresh.py]"]
  node_reauth["Session Recovery<br/>authentication flow<br/>[reauth.py]"]
  node_playlist_updater["Playlist Updater<br/>mutation script<br/>[update_playlist.py]"]
  node_spotify_api(("Spotify<br/>external API"))
end

subgraph group_operations["Operations"]
  node_scheduler{{"Daily GitHub Actions<br/>scheduled runtime<br/>[daily.yml]"}}
  node_activity_log["Activity Logger<br/>logging script<br/>[activity_log.py]"]
  node_activity_csv["Activity History<br/>CSV log<br/>[activity_log.csv]"]
end

node_scheduler -->|"scheduled run"| node_orchestrator
node_orchestrator -->|"collect"| node_trend_fetcher
node_trend_fetcher -->|"writes"| node_trending_csv
node_orchestrator -->|"enrich"| node_feature_fetcher
node_trending_csv -->|"reads"| node_feature_fetcher
node_feature_fetcher -->|"writes"| node_features_csv
node_orchestrator -->|"analyze"| node_clustering
node_features_csv -->|"reads"| node_clustering
node_clustering -->|"writes"| node_clustered_csv
node_orchestrator -->|"decide"| node_decisioning
node_clustered_csv -->|"reads"| node_decisioning
node_decisioning -->|"writes"| node_decisions_csv
node_orchestrator -->|"update playlist"| node_playlist_updater
node_decisions_csv -->|"applies"| node_playlist_updater
node_spotify_login -.->|"initial auth"| node_fresh_login
node_spotify_login -.->|"session recovery"| node_reauth
node_playlist_updater -->|"requires access"| node_spotify_login
node_playlist_updater -->|"mutates playlist"| node_spotify_api
node_orchestrator -.->|"records activity"| node_activity_log
node_activity_log -->|"writes"| node_activity_csv

click node_scheduler "https://github.com/5avis/playlist-a-live/blob/main/.github/workflows/daily.yml"
click node_orchestrator "https://github.com/5avis/playlist-a-live/blob/main/run_pipeline.py"
click node_trend_fetcher "https://github.com/5avis/playlist-a-live/blob/main/fetch_trending.py"
click node_trending_csv "https://github.com/5avis/playlist-a-live/blob/main/trending_tracks.csv"
click node_feature_fetcher "https://github.com/5avis/playlist-a-live/blob/main/fetch_with_features.py"
click node_features_csv "https://github.com/5avis/playlist-a-live/blob/main/tracks_with_features.csv"
click node_clustering "https://github.com/5avis/playlist-a-live/blob/main/clustering.py"
click node_clustered_csv "https://github.com/5avis/playlist-a-live/blob/main/tracks_clustered.csv"
click node_decisioning "https://github.com/5avis/playlist-a-live/blob/main/decision.py"
click node_decisions_csv "https://github.com/5avis/playlist-a-live/blob/main/decisions.csv"
click node_spotify_login "https://github.com/5avis/playlist-a-live/blob/main/spotify_login.py"
click node_fresh_login "https://github.com/5avis/playlist-a-live/blob/main/login_fresh.py"
click node_reauth "https://github.com/5avis/playlist-a-live/blob/main/reauth.py"
click node_playlist_updater "https://github.com/5avis/playlist-a-live/blob/main/update_playlist.py"
click node_activity_log "https://github.com/5avis/playlist-a-live/blob/main/activity_log.py"
click node_activity_csv "https://github.com/5avis/playlist-a-live/blob/main/activity_log.csv"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_orchestrator,node_trend_fetcher,node_trending_csv,node_feature_fetcher,node_features_csv,node_clustering,node_clustered_csv,node_decisioning,node_decisions_csv toneBlue
class node_spotify_login,node_fresh_login,node_reauth,node_playlist_updater,node_spotify_api toneAmber
class node_scheduler,node_activity_log,node_activity_csv toneMint
```

## Components

### Data Pipeline

CSV-backed collection, analysis, and decision stages.

- [Pipeline Orchestrator](https://github.com/5avis/playlist-a-live/blob/main/run_pipeline.py): Python entry point · Coordinates the end-to-end file-based pipeline. · `run_pipeline.py`
- [Trend Collector](https://github.com/5avis/playlist-a-live/blob/main/fetch_trending.py): ingestion script · `fetch_trending.py`
- [Trending Tracks](https://github.com/5avis/playlist-a-live/blob/main/trending_tracks.csv): CSV artifact · `trending_tracks.csv`
- [Feature Enricher](https://github.com/5avis/playlist-a-live/blob/main/fetch_with_features.py): enrichment script · `fetch_with_features.py`
- [Tracks with Features](https://github.com/5avis/playlist-a-live/blob/main/tracks_with_features.csv): CSV artifact · `tracks_with_features.csv`
- [Track Clustering](https://github.com/5avis/playlist-a-live/blob/main/clustering.py): analysis script · `clustering.py`
- [Clustered Tracks](https://github.com/5avis/playlist-a-live/blob/main/tracks_clustered.csv): CSV artifact · `tracks_clustered.csv`
- [Playlist Decisioning](https://github.com/5avis/playlist-a-live/blob/main/decision.py): decision script · `decision.py`
- [Playlist Decisions](https://github.com/5avis/playlist-a-live/blob/main/decisions.csv): CSV artifact · Persisted selection or add/remove actions. · `decisions.csv`

### Spotify Integration

Authentication and live playlist mutation.

- [Spotify Login](https://github.com/5avis/playlist-a-live/blob/main/spotify_login.py): authentication · `spotify_login.py`
- [Fresh Login](https://github.com/5avis/playlist-a-live/blob/main/login_fresh.py): authentication flow · `login_fresh.py`
- [Session Recovery](https://github.com/5avis/playlist-a-live/blob/main/reauth.py): authentication flow · `reauth.py`
- [Playlist Updater](https://github.com/5avis/playlist-a-live/blob/main/update_playlist.py): mutation script · Applies persisted decisions to the live playlist. · `update_playlist.py`
- **Spotify**: external API

### Operations

Scheduled execution and activity history.

- [Daily GitHub Actions](https://github.com/5avis/playlist-a-live/blob/main/.github/workflows/daily.yml): scheduled runtime · `.github/workflows/daily.yml`
- [Activity Logger](https://github.com/5avis/playlist-a-live/blob/main/activity_log.py): logging script · `activity_log.py`
- [Activity History](https://github.com/5avis/playlist-a-live/blob/main/activity_log.csv): CSV log · `activity_log.csv`

## Connections

- Daily GitHub Actions → Pipeline Orchestrator: scheduled run
- Pipeline Orchestrator → Trend Collector: collect
- Trend Collector → Trending Tracks: writes
- Pipeline Orchestrator → Feature Enricher: enrich
- Trending Tracks → Feature Enricher: reads
- Feature Enricher → Tracks with Features: writes
- Pipeline Orchestrator → Track Clustering: analyze
- Tracks with Features → Track Clustering: reads
- Track Clustering → Clustered Tracks: writes
- Pipeline Orchestrator → Playlist Decisioning: decide
- Clustered Tracks → Playlist Decisioning: reads
- Playlist Decisioning → Playlist Decisions: writes
- Pipeline Orchestrator → Playlist Updater: update playlist
- Playlist Decisions → Playlist Updater: applies
- Spotify Login → Fresh Login: initial auth
- Spotify Login → Session Recovery: session recovery
- Playlist Updater → Spotify Login: requires access
- Playlist Updater → Spotify: mutates playlist
- Pipeline Orchestrator → Activity Logger: records activity
- Activity Logger → Activity History: writes
