\documentclass[11pt,a4paper]{article} \usepackage[utf8]{inputenc} \usepackage[T1]{fontenc} \usepackage{amsmath} \usepackage{amssymb} \usepackage{hyperref} \usepackage{xcolor} \usepackage{listings} \usepackage{geometry} \usepackage{graphicx} \usepackage{fancyhdr} \usepackage{titlesec}
% Page geometry \geometry{margin=1in}
% Colors \definecolor{codebackground}{RGB}{250,250,250} \definecolor{vinylred}{RGB}{139,35,50} \definecolor{teal}{RGB}{61,108,122}
% Hyperlink setup \hypersetup{ colorlinks=true, linkcolor=vinylred, filecolor=teal, urlcolor=teal, citecolor=vinylred }
% Code listing setup \lstset{ backgroundcolor=\color{codebackground}, basicstyle=\ttfamily\small, breaklines=true, captionpos=b, frame=single, numbers=left, numbersep=5pt, showstringspaces=false, tabsize=2 }
% Section formatting \titleformat{\section} {\normalfont\Large\bfseries\color{vinylred}}{\thesection}{1em}{} \titleformat{\subsection} {\normalfont\large\bfseries\color{teal}}{\thesubsection}{1em}{}
% Header and footer \pagestyle{fancy} \fancyhf{} \rhead{Euterpe} \lhead{Music Discovery Platform} \cfoot{\thepage}
\title{\Huge\textbf{Euterpe} \[0.3cm] \Large A Human-Centered Music Discovery Platform} \author{} \date{}
\begin{document}
\maketitle \thispagestyle{empty}
\vspace{1cm}
\begin{center} \textit{``Music is the universal language, and everyone deserves a translator they trust.''} \end{center}
\newpage
\tableofcontents
\newpage
\section{Inspiration}
The inspiration for \textbf{Euterpe} (named after the Greek muse of music and lyric poetry) came from a deeply personal frustration with modern music discovery. As a passionate music lover, I found myself constantly juggling between multiple fragmented platforms:
\begin{itemize} \item \textbf{Spotify} for streaming \item \textbf{Discogs} for vinyl collecting \item \textbf{Bandsintown} for concerts \item \textbf{Instagram} for sharing with friends \end{itemize}
But something felt profoundly missing. The \textbf{human connection} that makes music special: the excitement of a friend's recommendation, the serendipity of browsing a record store with a knowledgeable clerk, discovering a band at a local venue. All of this was being lost to cold, algorithmic playlists.
I realized that \textbf{the best music recommendations have always come from people we trust, not data mining}. This insight became the foundation for Euterpe: a platform that puts human curation back at the center of music discovery, unifying all aspects of music culture in one beautiful, social-first experience.
\section{What it does}
Euterpe is a \textbf{unified music discovery platform} that brings together streaming, vinyl collecting, and concert-going into one cohesive social experience.
\subsection{Core Features}
\subsubsection{Curated Music Boards} \begin{itemize} \item Create themed collections of albums, artists, vinyl finds, concerts, or mixed boards \item Public/private visibility controls \item Beautiful, vinyl-inspired visual design \end{itemize}
\subsubsection{Social Discovery Feed} \begin{itemize} \item Browse boards created by the community \item Discover music through people's curated tastes \item Follow friends and tastemakers (coming soon) \end{itemize}
\subsubsection{Personal Profile} \begin{itemize} \item Showcase your music identity \item Display all your boards in one place \item Customizable avatar and bio \end{itemize}
\subsubsection{Secure Authentication} \begin{itemize} \item Email-based signup with Supabase Auth \item Row-level security for data protection \item Privacy-first architecture \end{itemize}
\subsection{The Vision}
Euterpe aims to become the central hub for all music experiences, combining: \begin{itemize} \item Streaming integration (Spotify API) \item Vinyl collection tracking \item Concert history and discovery \item Social recommendations based on human trust \end{itemize}
\section{How we built it}
\subsection{Technology Stack}
\subsubsection{Frontend}
\begin{lstlisting}[language=bash, caption=Frontend Technologies] React 18 + TypeScript # Type-safe components Vite # Lightning-fast builds Tailwind CSS # Utility-first styling shadcn/ui # Accessible components React Router # Client-side routing Tanstack Query # Server state management \end{lstlisting}
\subsubsection{Backend}
\begin{lstlisting}[caption=Backend Infrastructure] Lovable Cloud + Supabase ├── PostgreSQL database with RLS ├── Built-in authentication ├── Real-time subscriptions ├── File storage (avatars) └── Auto-configured environment \end{lstlisting}
\subsection{Architecture Design}
\subsubsection{Database Schema}
The database schema was designed with scalability and relationships in mind:
\begin{lstlisting}[language=SQL, caption=Core Tables Structure] profiles ├── id (auth.uid) ├── username ├── display_name ├── bio └── avatar_url
boards ├── id ├── user_id → profiles(id) ├── title ├── description ├── type (album|artist|vinyl|concert|mixed) ├── is_public └── timestamps
follows (future) ├── follower_id → profiles(id) └── following_id → profiles(id)
board_items (future) ├── id ├── board_id → boards(id) ├── spotify_id ├── metadata └── order_index \end{lstlisting}
\subsubsection{Security Implementation}
Implemented Row Level Security (RLS) policies at the database level:
\begin{lstlisting}[language=SQL, caption=RLS Policies for Board Security] -- Users can view public boards CREATE POLICY "Public boards viewable by everyone" ON boards FOR SELECT USING (is_public = true);
-- Users can manage their own boards CREATE POLICY "Users can manage own boards" ON boards FOR ALL USING (auth.uid() = user_id); \end{lstlisting}
\subsection{Design System}
Created a warm, vinyl-inspired color palette using HSL color space:
\begin{lstlisting}[language=CSS, caption=Design System Variables] :root { /* Deep burgundy warmth */ --vinyl-red: 345 65% 35%;
/* Sophisticated teal accent */ --teal-accent: 190 55% 35%;
/* Soft background */ --warm-cream: 40 60% 95%;
/* Gradients */ --gradient-hero: linear-gradient(135deg, hsl(345 65% 35%), hsl(345 55% 45%));
/* Shadows */ --shadow-album: 0 8px 24px hsl(345 65% 35% / 0.15); } \end{lstlisting}
\subsection{Development Process}
Built iteratively over several phases:
\begin{enumerate} \item \textbf{Authentication & Profiles}: Supabase Auth integration with profile creation \item \textbf{Board System}: CRUD operations with type selection and visibility controls \item \textbf{Social Feed}: Community discovery page with board listings \item \textbf{UI Polish}: Responsive design, animations, and accessibility improvements \item \textbf{Security Hardening}: RLS policies and input validation \end{enumerate}
\section{Challenges we ran into}
\subsection{Challenge 1: Real-Time State Synchronization}
\textbf{Problem:} Keeping authentication state synchronized between Supabase and React components was causing race conditions and stale UI states.
\textbf{Solution:} Implemented proper auth listeners with cleanup:
\begin{lstlisting}[language=JavaScript, caption=Authentication State Management] useEffect(() => { supabase.auth.getSession().then(({ data: { session } }) => { setSession(session); });
const { data: { subscription } } = supabase.auth.onAuthStateChange( (_event, session) => setSession(session) );
return () => subscription.unsubscribe(); }, []); \end{lstlisting}
\textbf{Learning:} Always clean up subscriptions to prevent memory leaks and ensure consistent state.
\subsection{Challenge 2: Type Safety with Dynamic Database Queries}
\textbf{Problem:} Supabase queries returned \texttt{any} types, leading to runtime errors that TypeScript couldn't catch.
\textbf{Solution:} Created comprehensive type definitions for the database schema:
\begin{lstlisting}[language=JavaScript, caption=Type-Safe Database Queries] export interface Database { public: { Tables: { boards: { Row: { id: string; title: string; type: 'album' | 'artist' | 'vinyl' | 'concert' | 'mixed'; is_public: boolean; // ... other fields }; }; }; }; }
// Type-safe queries const { data } = await supabase .from('boards') .select('*') .returns(); \end{lstlisting}
\textbf{Learning:} Investing in proper TypeScript types saves countless hours of debugging.
\subsection{Challenge 3: Responsive Design Complexity}
\textbf{Problem:} Complex layouts like the hero section broke on mobile devices, with elements overlapping and text becoming unreadable.
\textbf{Solution:} Adopted a strict mobile-first approach using Tailwind's responsive utilities:
\begin{lstlisting}[language=HTML, caption=Mobile-First Responsive Grid]
\end{lstlisting}
\textbf{Learning:} Design for mobile constraints first. It forces you to prioritize what truly matters. Desktop becomes additive, not subtractive.
\subsection{Challenge 4: File Upload UX}
\textbf{Problem:} Avatar uploads felt clunky with multiple loading states and error handling.
\textbf{Solution:} Implemented optimistic UI updates with proper error rollback:
\begin{lstlisting}[language=JavaScript, caption=Optimistic File Upload] const handleUpload = async (file) => { // Show preview immediately const previewUrl = URL.createObjectURL(file); setAvatarPreview(previewUrl);
try { // Upload to Supabase storage const { data, error } = await supabase.storage .from('avatars') .upload(filePath, file);
if (error) throw error;
// Update profile with new avatar URL
await updateProfile({ avatar_url: publicUrl });
toast.success('Avatar updated!');
} catch (error) { // Revert optimistic update on error setAvatarPreview(null); toast.error('Upload failed'); } }; \end{lstlisting}
\textbf{Learning:} Optimistic UI updates make applications feel instant, even with network latency.
\subsection{Challenge 5: Scope Creep Temptation}
\textbf{Problem:} The temptation to add ``just one more feature'' before launch was constantly present.
\textbf{Solution:} Created a strict phased roadmap and stuck to the MVP scope:
\begin{itemize} \item \textbf{Phase 1 (MVP):} Auth + Boards + Feed $\leftarrow$ Ship this first \item \textbf{Phase 2:} Spotify integration + Follow system \item \textbf{Phase 3:} Vinyl tracking + Concert history \item \textbf{Phase 4:} Smart recommendations + Advanced features \item \textbf{Phase 5:} Premium features + Mobile apps \end{itemize}
\textbf{Learning:} Ship the MVP and validate with real users. Their feedback is infinitely more valuable than feature completeness.
\section{Accomplishments that we're proud of}
\subsection{Human-Centered Design Philosophy}
We successfully created a platform that prioritizes human connection over algorithms. Every design decision, from board curation to the social feed, emphasizes trust and personal taste.
\subsection{Type-Safe Full-Stack Architecture}
Achieved end-to-end type safety from database queries to React components. This caught hundreds of potential bugs at compile time and made the codebase incredibly maintainable.
\subsection{Database-Level Security}
Implemented Row Level Security (RLS) policies that protect user data at the database layer, not just in application code. This provides robust security that scales with complexity.
\subsection{Beautiful, Accessible UI}
Built a design system inspired by vinyl warmth that works seamlessly across all devices. Used shadcn/ui for accessibility out of the box.
\subsection{Optimistic UI Patterns}
Implemented optimistic updates throughout the app, making interactions feel instant even with network latency.
\subsection{Clean, Maintainable Code}
Structured the codebase with clear separation of concerns, reusable components, and comprehensive TypeScript types that make future development easier.
\section{What we learned}
\subsection{Technical Learnings}
\subsubsection{Row Level Security is Powerful}
RLS policies in PostgreSQL provide security that's enforced at the database level:
\begin{lstlisting}[language=SQL, caption=Database-Level Security] -- Security that can't be bypassed by application bugs CREATE POLICY "name" ON table FOR operation USING (condition); \end{lstlisting}
This approach is more secure than handling permissions in application code.
\subsubsection{TypeScript + React Query = Developer Joy}
The combination creates an incredibly smooth development experience:
\begin{lstlisting}[language=JavaScript, caption=Type-Safe Data Fetching] const { data, isLoading, error } = useQuery({ queryKey: ['boards'], queryFn: fetchBoards }); // Fully typed, cached, and reactive \end{lstlisting}
\subsubsection{Design Systems Scale}
Investing early in a cohesive design system (using shadcn/ui + Tailwind) paid massive dividends as the app grew. Consistent UI became effortless.
\subsubsection{Real-Time Capabilities Open Possibilities}
Supabase's real-time subscriptions enable exciting features:
\begin{lstlisting}[language=JavaScript, caption=Real-Time Database Subscriptions] supabase .channel('boards') .on('postgres_changes', { event: 'INSERT' }, payload => { // Live updates to the feed }) .subscribe(); \end{lstlisting}
\subsection{Product Learnings}
\subsubsection{Start with the Core Loop}
Focus on the essential value proposition first: \begin{center} Create board $\rightarrow$ Share $\rightarrow$ Discover others' boards \end{center}
This tight loop validates the concept before adding complexity.
\subsubsection{Human Connection $>$ Algorithms}
Users crave authentic recommendations from people they trust. The most sophisticated ML can't replace a friend's enthusiastic album recommendation.
\subsubsection{Design for Trust}
Music taste is deeply personal. Features like public/private toggles and RLS policies build trust from day one.
\subsubsection{MVP is a Feature, Not a Bug}
Shipping early with core functionality is better than waiting for perfection. User feedback guides what to build next.
\section{What's next for Euterpe}
\subsection{Immediate Roadmap (Phase 2)}
\subsubsection{Spotify API Integration} \begin{itemize} \item OAuth flow for Spotify authentication \item Import user's top artists and albums \item Search functionality for adding items to boards \item Display rich album artwork and metadata \end{itemize}
\subsubsection{Board Items Management} \begin{itemize} \item Add/remove specific tracks, albums, or artists to boards \item Drag-and-drop reordering \item Rich metadata per item (personal notes, ratings, tags) \end{itemize}
\subsubsection{Follow System} \begin{itemize} \item Follow/unfollow other users \item Personalized feed based on who you follow \item Follower/following counts on profiles \end{itemize}
\subsection{Future Innovations}
\subsubsection{Phase 3: Collections} \begin{itemize} \item Full vinyl collection tracker with pressing variants \item Concert history with setlists and memories \item Wishlist functionality with price tracking \end{itemize}
\subsubsection{Phase 4: Smart Features}
Intelligent recommendations using collaborative filtering with human-centric weighting:
\begin{equation} \text{Score}(\text{item}, \text{user}) = \alpha \cdot \text{FriendOverlap} + \beta \cdot \text{TasteSimilarity} + \gamma \cdot \text{Recency} \end{equation}
where $\alpha > \beta > \gamma$ to prioritize human connections over algorithmic factors.
\begin{itemize} \item \textbf{FriendOverlap}: Number of followed users who have the item in their boards \item \textbf{TasteSimilarity}: Computed using Jaccard similarity of board contents: \begin{equation} J(A, B) = \frac{|A \cap B|}{|A \cup B|} \end{equation} \item \textbf{Recency}: Time-decay factor for trending content: \begin{equation} R(t) = e^{-\lambda(t_{\text{now}} - t_{\text{added}})} \end{equation} \end{itemize}
Additional smart features: \begin{itemize} \item Advanced search and filtering \item Export boards as shareable images or playlists \item Natural language queries: ``Show me jazz albums from the 1960s that my friends love'' \end{itemize}
\subsubsection{Phase 5: Premium & Mobile} \begin{itemize} \item Analytics and listening insights \item Early access to vinyl drops and concert tickets \item Native iOS and Android apps \item Collaborative boards with multiple curators \end{itemize}
\subsection{Long-Term Vision}
Transform Euterpe into the \textbf{central hub for music culture}, a place where: \begin{itemize} \item Every music experience (streaming, collecting, concerts) lives together \item Discovery happens through trusted human connections \item Community thrives around shared musical passion \item Technology enhances rather than replaces the human experience \end{itemize}
\subsection{Mathematical Model for Recommendation Quality}
To ensure our recommendations maintain the human-first philosophy while leveraging data, we propose a quality metric:
\begin{equation} Q = \frac{\text{Human Trust Score}}{\text{Algorithmic Complexity}} \times \text{Diversity Factor} \end{equation}
where: \begin{align} \text{Human Trust Score} &= \sum_{i=1}^{n} w_i \cdot \text{trust}(u, f_i) \ \text{Diversity Factor} &= 1 - \frac{1}{m} \sum_{j=1}^{m} \text{sim}(r_j, r_{j-1}) \end{align}
This ensures that as algorithmic complexity increases (which typically reduces explainability), we maintain proportionally higher human trust signals and diversity in recommendations.
\section*{Conclusion}
\textbf{Euterpe} represents a return to what makes music discovery special: human connection, curation, and trust. By unifying streaming, collecting, and concert-going into one platform, we're creating a space where music culture can thrive in the digital age.
The technical foundation, built with React, TypeScript, Supabase, and a robust security model, provides a scalable platform for growth. But more importantly, the human-centered design philosophy ensures that as we scale, we never lose sight of what matters most: the joy of discovering music through people you trust.
\vspace{1cm}
\begin{center} \textit{``Where music discovery becomes social, intentional, and joyful again.''}
\vspace{0.5cm}
\textbf{Euterpe} - Named after the Greek muse of music and lyric poetry \end{center}
\end{document}
Log in or sign up for Devpost to join the conversation.