Building Dhunzza: How I Built a Modern Music Streaming
Building Dhunzza: How I Built a Modern Music Streaming Platform with Next.js, Cloudflare D1 & R2 I recently built Dhunzza, a music streaming platform focused on discovering music through moods and different musical era
Building Dhunzza: How I Built a Modern Music Streaming Platform with Next.js, Cloudflare D1 & R2
I recently built Dhunzza, a music streaming platform focused on discovering music through moods and different musical eras.
๐ Live project: https://dhunzza.in/
But the interesting part wasn't building the music player.
The real challenge was figuring out how to handle music metadata, media files, user requests, and database traffic efficiently without creating unnecessary infrastructure costs.
This post explains some of the architectural decisions behind Dhunzza and what I learned while building it.
๐ง The Idea Behind Dhunzza
The concept was simple:
Give users a place to discover music based on their mood and the era they want to explore.
Instead of building another complicated streaming application, I wanted the interface to feel simple:
Choose a mood โ choose an era โ press play.
The application needed:
- Music playback
- Mood-based discovery
- Era-based discovery
- Song metadata
- Song requests
- Admin music management
- A lightweight user experience
- Scalable media storage
๐๏ธ The Initial Architecture
The first version relied heavily on Firebase services.
Firebase made development extremely fast, especially for:
- Realtime data
- Authentication
- Database operations
- File storage
- Rapid prototyping
For an early-stage application, this was convenient.
However, music streaming introduces a different problem.
Audio files are relatively large compared with normal application data, and playback can generate significant bandwidth and storage activity.
That made me rethink the architecture.
โ๏ธ Moving Media to Cloudflare R2
One of the major changes was separating application data from media storage.
The architecture became:
โโโโโโโโโโโโโโโโโโโ
โ Next.js App โ
โ Vercel โ
โโโโโโโโโโฌโโโโโโโโโ
โ
โโโโโโโโโโโโโโดโโโโโโโโโโโโโ
โ โ
โผ โผ
โโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ
โ Cloudflare D1 โ โ Cloudflare R2 โ
โ Metadata โ โ Audio / Media โ
โโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ
The idea is straightforward:
D1 stores information about the song.
R2 stores the actual media.
For example, a D1 record might contain:
{
"title": "Example Song",
"artist": "Example Artist",
"album": "Example Album",
"era": "2000s",
"mood": "happy",
"audio_url": "https://..."
}
The database doesn't need to contain the actual audio file.
It only needs to know where the media lives.
๐๏ธ Why Separate Metadata and Media?
This separation makes the system easier to reason about.
Database
The database handles things like:
- Song title
- Artist
- Album
- Mood
- Era
- Song requests
- Admin information
- Public feed information
Object Storage
R2 handles:
- MP3 files
- Images
- Other media assets
This gives each service a clear responsibility.
โก Keeping the Frontend Fast
Another important consideration was reducing unnecessary requests.
A music application can easily become request-heavy if every interaction causes another database query.
For example:
User opens application
โ
Fetch songs
โ
User changes mood
โ
Fetch songs again
โ
User changes era
โ
Fetch songs again
โ
Player changes song
โ
More requests
Instead, I wanted to minimize repeated metadata fetching and keep the client responsible for as much local state as possible.
The goal was:
Initial Load
โ
Fetch required metadata
โ
Cache / maintain client state
โ
Reuse existing data
โ
Only request what actually changed
This becomes particularly important when the application is continuously playing music.
๐ Handling Song Requests
Dhunzza also includes a song-request workflow.
Users can submit a request for a song.
The flow looks roughly like this:
User
โ
โผ
Submit Song Request
โ
โผ
D1
โ
โผ
Admin Reviews Request
โ
โผ
Admin Adds Song
โ
โผ
Song Metadata โ D1
Audio File โ R2
โ
โผ
Request Completed
โ
โผ
Public Feed Update
This keeps the workflow separate from the actual music playback system.
๐งฉ Why Next.js?
Next.js gives me a convenient foundation for the application.
It provides:
- React-based UI
- Routing
- Server-side capabilities
- API endpoints
- Deployment flexibility
- Good performance tooling
The frontend is deployed separately while Cloudflare handles the storage/data layer.
This separation also means the application isn't tightly coupled to one backend provider.
๐ One of the Most Important Lessons
Building a streaming application taught me something important:
Don't treat every piece of data the same way.
A song title is tiny.
An audio file can be several megabytes.
A chat message is temporary.
A song request has a different lifecycle.
Trying to put all of these into one system can make the architecture unnecessarily expensive or difficult to scale.
Instead, I started thinking in terms of:
What is this data?
โ
How often does it change?
โ
How large is it?
โ
How long should it exist?
โ
How frequently will users access it?
Those questions helped determine where each type of data should live.
๐ What's Next for Dhunzza?
Dhunzza is still evolving.
Some areas I'm exploring include:
- Better music discovery
- More mood categories
- More musical eras
- Improved playlists
- Better caching
- Performance optimization
- Better mobile experience
- More intelligent recommendations
The goal isn't simply to add more features.
It's to make the experience of finding and listening to music better.
๐ต Final Thoughts
Dhunzza started as a music streaming idea, but building it became an interesting lesson in architecture, storage, performance, and data management.
The biggest takeaway for me was simple:
Build the architecture around the behavior of your application, not just the features you want to add.
If you're interested in checking out the project:
๐ง Dhunzza: https://dhunzza.in/
If you're building a similar application, I'd also love to hear how you're handling media storage, caching, and streaming infrastructure.
Tech stack:
Next.js ยท React ยท Cloudflare D1 ยท Cloudflare R2 ยท Vercel ยท JavaScript ยท Firebase (migration/legacy components)
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes โ full credit and traffic to the original publisher.
