Reverie — Personal Music Journal
Overview
Reverie is a personal music journaling web app that connects to Spotify and automatically tracks every song you listen to. It analyzes the mood and emotional energy of your music in real time — detecting vibes like Focus, Energetic, Calm, Happy, and Sad — and builds your emotional story throughout the day.
Users can write journal entries tied to their listening history, or let the AI write one for them. Everything happens automatically — just listen to music and Reverie does the rest.
Problem
Music is deeply tied to how we feel, but there's no way to look back and understand your emotional patterns through what you listened to. Spotify shows you what you played — but not what it meant. Journals capture how you felt — but nobody writes in them consistently.
Reverie bridges this gap automatically, turning passive listening into a rich emotional archive without any extra effort from the user.
Approach
Built a FastAPI backend that polls Spotify's Web API every 5 seconds to detect the currently playing track. Each track is analyzed using audio features (valence, energy, danceability, tempo) to classify its mood.
A 30-second minimum play threshold filters out accidental skips before logging to the database. The React frontend displays live now-playing data with mood-tinted cards, a today's listening history grouped by play count, and a mood journey timeline showing how emotional energy shifted throughout the day.
System Architecture
Key Features
Reverie is built around a set of features that work together to create a seamless, automatic journaling experience.
- Real-time Spotify tracking with live now-playing card that updates as songs change
- Mood detection from audio features — card background color shifts based on detected vibe
- Today's Listening history grouped by play count, sorted most-played first, updates live
- Today's Mood Journey — timeline showing mood shifts across Morning, Afternoon, Evening, Night
- AI-powered journal writing — generates a journal entry based on the day's listening history
- Multi-step signup flow — collects name, email, password, then optionally connects Spotify
- Spotify OAuth with compound state parameter (no cookies needed for CSRF protection)
- 30-second minimum play threshold before a track is recorded
Technical Stack
- Frontend: React, TypeScript, Vite, Tailwind CSS, React Router
- Backend: FastAPI (Python), Uvicorn, PostgreSQL, psycopg2
- Auth: JWT session tokens, bcrypt password hashing, Spotify OAuth 2.0
- Infrastructure: Oracle Cloud (Ubuntu 22.04), Nginx reverse proxy, Let's Encrypt SSL
- APIs: Spotify Web API, Groq AI (journal generation)
Deployment
Deployed on Oracle Cloud Free Tier with a custom domain (reverie.ddns.net) via DDNS. Nginx handles SSL termination and reverse proxies to Uvicorn running on port 8000. PostgreSQL runs locally on the same server, accessible only via localhost. SSL certificates managed by Certbot with auto-renewal.
Challenges & Solutions
Several non-trivial engineering problems were encountered and solved during development.
- Spotify OAuth state cookie lost on cross-site redirect — solved by encoding both the CSRF token and flow intent directly in the OAuth state parameter as a compound string, eliminating cookie dependency entirely
- Blocking Spotipy calls hanging uvicorn's event loop — replaced all Spotipy HTTP calls in the OAuth callback with native httpx.AsyncClient async calls, preventing event loop starvation
- Spotify /v1/me rate limiting during development — added retry logic with backoff cap, and cached profile data in oauth_accounts table after first successful fetch so subsequent logins don't re-fetch
- Duplicate listen history entries — implemented a 30-second consecutive polling threshold and server-side deduplication before inserting to listen_history
Future Improvements
Several directions could extend Reverie meaningfully.
- Push notifications when a listening streak is at risk
- Weekly mood report email digest
- Spotify playlist generation based on mood history
- Mobile app (React Native)
- Social features — share your mood journey with friends