· apps · musica · music · streaming
Musica: vault experiment — embed locks, SoundCloud only worked
Honest post: Musica is not a real streaming product yet. It is a React scratchpad where we learned most platforms block in-app playback; SoundCloud was the only reliable embed path.
We wanted a universal jukebox. The industry wanted every listener inside their own app.
What this is (read this first)
Musica is not a comprehensive music streaming app. It barely qualifies as a product: a Vault experiment where we flexed frontend and parsing skills (URLs, iframes, a little search, playlists in storageService). In practice we learned what everyone in the industry already knew the hard way: Spotify, Apple Music, YouTube, and friends have playback and embed rules locked down — frame busting, auth walls, CSP, “open in our app,” and terms that assume you are not allowed to be the shell. In our build, SoundCloud was the only provider that consistently let us actually hear music inside our UI. Everything else is mostly labels and hope.
If you came from marketing language about a “hub” or “unified platform,” that was aspiration, not shipping reality. This page and the changelog below are the correction.
Coming soon / maybe never as a “real” streamer. Treat Musica as a lab: paste links, keep playlists, see what breaks. Do not expect Spotify-class reliability or catalog coverage.
Changelog
| Date | What changed (product story) |
|---|---|
| 2026-04-24 | Blog honesty pass: dropped “comprehensive streaming / glass morphism centerpiece” framing. Musica is described as an experiment; SoundCloud-only called out as the embed path that actually worked; noted industry lock-down on other providers. UI copy: we’re not selling heavy glass-morphism anymore—we cleaned up the shell toward something simpler and more readable (any leftover translucent panels in code are incidental, not the headline). |
| 2026-04-23 | Earlier draft posts went live describing multi-provider streaming; reality check after trying embeds end-to-end: most providers do not cooperate in a third-party web shell. |
What exists in the code (narrow scope)
-
Multi-provider picker (mostly UI + parsers) — Nine source names so we can parse URLs and attempt embeds or streams. Only SoundCloud reliably played inside the app for us; the rest taught us what is blocked or brittle.
-
Library + lightweight search — Search playlists you already saved; Audius and Internet Archive have browser-friendly search paths where CORS allows; big commercial apps mostly get “open their site” links, not in-app audio.
-
Playlists — Create lists and attach links. That part works as data. Playback is the part that does not generalize.
-
SoundCloud downloads (Electron only, when allowed) — Optional file download when SoundCloud marks a track downloadable; local HTML5 audio for those files.
-
Layout — Single-file React UI, shared landscape background helper, playlist side panel. Not a flagship design system showcase; more “prove we could wire the pieces.”
Provider Architecture and Integration
Supported Streaming Services
const PROVIDERS = [
{ id: 'soundcloud', label: 'SoundCloud' },
{ id: 'youtube', label: 'YouTube' },
{ id: 'spotify', label: 'Spotify' },
{ id: 'applemusic', label: 'Apple Music' },
{ id: 'deezer', label: 'Deezer' },
{ id: 'mixcloud', label: 'Mixcloud' },
{ id: 'audius', label: 'Audius' },
{ id: 'archive', label: 'Archive' },
{ id: 'vimeo', label: 'Vimeo' }
]
URL Parsing and Normalization
The app includes sophisticated URL parsing for each provider:
// SoundCloud: https://soundcloud.com/user/track-name
async parseSoundCloudUrl(url) {
const urlMatch = url.match(/soundcloud\.com\/([^\/]+)\/([^\/\?]+)/)
const [, user, trackSlug] = urlMatch
return {
provider: 'soundcloud',
id: `soundcloud:${user}:${trackSlug}`,
title: trackSlug.replace(/-/g, ' '),
artist: user.replace(/-/g, ' ')
}
}
Similar parsers handle YouTube video IDs, Spotify URI formats, Apple Music country paths, and Audius canonical URLs.
Embedded Player System
Each provider renders through its official embed system:
// YouTube embedded player
<iframe
width="100%" height="315"
src={`https://www.youtube.com/embed/${videoId}?autoplay=1`}
allow="autoplay; encrypted-media"
/>
// SoundCloud embedded player
<iframe
width="100%" height="166"
src={`https://w.soundcloud.com/player/?url=${encodeURIComponent(url)}&auto_play=true`}
/>
Search and Discovery Architecture
Local Library Search
Every search starts with the local library:
// Search across all playlists and tracks
const libraryMatches = []
for (const pid of Object.keys(playlists)) {
const tracks = playlists[pid].tracks || []
for (const track of tracks) {
const searchText = `${track.title} ${track.artist} ${track.url}`.toLowerCase()
if (searchText.includes(query.toLowerCase())) {
libraryMatches.push({ playlistId: pid, track })
}
}
}
Live Web Search
Direct API integration with CORS-friendly endpoints:
// Audius discovery provider search
async searchAudius(query, limit = 8) {
const url = `https://discoveryprovider.audius.co/v1/tracks/search?query=${encodeURIComponent(query)}`
const response = await fetch(url)
const data = await response.json()
return data.data.map(track => ({
provider: 'audius',
id: `audius:${track.track_id}`,
title: track.title,
artist: track.user.name,
audiusTrackId: track.track_id // For direct streaming
}))
}
Fallback Provider Integration
For providers requiring API keys or blocking CORS, the app generates search URLs:
buildProviderSearchUrl(provider, query) {
const q = encodeURIComponent(query)
switch (provider) {
case 'spotify': return `https://open.spotify.com/search/${q}`
case 'applemusic': return `https://music.apple.com/us/search?term=${q}`
case 'youtube': return `https://www.youtube.com/results?search_query=${q}`
}
}
Playlist Management and Storage
Data Structure
Playlists use a clean, provider-agnostic schema:
{
id: "playlist-uuid",
name: "My Playlist",
tracks: [
{
provider: "soundcloud",
id: "soundcloud:user:track",
url: "https://soundcloud.com/user/track",
title: "Track Title",
artist: "Artist Name",
filePath: "/path/to/downloaded/file.mp3", // Optional
downloadedAt: "2026-04-23T10:00:00Z" // If downloaded
}
],
createdAt: "2026-04-23T09:00:00Z",
updatedAt: "2026-04-23T10:30:00Z"
}
Storage Architecture
All playlist data flows through the unified storage service:
// Service layer abstraction
await musicaService.savePlaylist(id, name, tracks)
// ↓
await storageService.saveMusicaPlaylist(id, name, tracks)
// ↓
await storageBackend.setItem('MUSICA_PLAYLISTS', id, playlistData)
// ↓
localStorage (web) or PostgreSQL (Electron)
This pattern means replacing the storage backend with a Musica microservice API only requires changing the storage layer — all UI components remain unchanged.
Dual Playback Architecture
Embedded streaming (what we tried)
The happy path in practice was SoundCloud’s iframe. The code attempts other provider embeds; in the wild, many never reliably play inside our shell because of platform policy and browser security, not because we forgot an import.
const handlePlayTrack = (track) => {
const embedTarget = buildEmbedTargetFromTrack(track)
setEmbedTarget({
provider: track.provider,
url: track.url,
videoId: track.videoId, // YouTube
spotifyId: track.spotifyId, // Spotify
// ... provider-specific IDs
})
}
Direct Audio Playback
For local files and Audius streams:
// Local downloaded files
if (track.filePath && window.electronAPI) {
const fileUrl = await window.electronAPI.getFileUrl(track.filePath)
audioRef.current.src = fileUrl.data.url
audioRef.current.play()
}
// Audius direct streaming (bypasses embed for better Electron compatibility)
if (track.provider === 'audius') {
const streamUrl = await musicaService.getAudiusStreamUrl(track.audiusTrackId)
audioRef.current.src = streamUrl.data.url
audioRef.current.play()
}
Architecture: Microservice-Ready and Agent-Aware
The Musica app follows Gato’s app-per-directory pattern with clear service boundaries:
Services Layer
- musicaService.js — Main facade: playlist CRUD, URL parsing, downloads, Audius streaming
- musicaSearchService.js — Provider search: Audius/Archive API calls, search URL generation
- storageService — Unified persistence via collection key
MUSICA_PLAYLISTS
Component architecture
- Main interface — Single-file React component (
index.jsx); layout cleaned up from earlier heavy frosted-glass marketing; still a simple Vault screen, not a design-system trophy. - Embedded players — Provider-specific iframes where the platform allows.
- Playlist management — Slide-out panel: create/delete playlists, add/remove tracks (no fancy reorder UI—don’t expect DAW-grade editing).
- Search — Library + Audius/Archive where fetch works; outbound links for the rest.
Storage and Migration Path
- Current State — Rich client with localStorage (web) or PostgreSQL (Electron)
- Future State — Same UI components talking to Musica microservice API
- Migration Strategy — Replace service layer while preserving all component interfaces
Key User Flows
Discovery and Adding Tracks
- Search — Enter query → get local + web results
- External Discovery — Click provider search links to find tracks on native platforms
- Add to Playlist — Paste URL → auto-detect provider → parse metadata → add to playlist
Playlist management
- Create playlist — “New playlist” → name → add tracks from URLs or search.
- Edit list — Remove tracks; switch playlists from the side panel. (There is no drag-and-drop reorder in the current UI—this post previously claimed one; that was wrong.)
- Cross-provider links — One playlist can store links for many sites; hearing them in-app still collapses to SoundCloud (plus occasional Audius stream / local file edge cases).
Playback Modes
- Embedded streaming (best effort) — Click track → provider iframe or stream when allowed; SoundCloud is what we ship expecting to work
- Downloaded Files — SoundCloud tracks with local files use HTML5 audio
- Audius Direct — Bypasses embed with direct MP3 stream for better performance
Download Integration (Electron)
SoundCloud Downloads
When running in Electron and tracks are marked downloadable:
const downloadResult = await window.electronAPI.downloadSoundCloudTrack(url, trackInfo)
if (downloadResult.success) {
// Add file path to track metadata
track.filePath = downloadResult.data.filePath
track.downloadedAt = new Date().toISOString()
}
File Management
- Storage Location — Electron handles file system integration
- Format — Downloads preserve original quality and format
- Metadata — Rich metadata stored alongside file references
- Playback — Switch between local files (downloads) and embed/stream paths in one playlist; day-to-day trust is still SoundCloud
UI direction (not the selling point)
We stepped back from “glass morphism as the product”—that was easy to over-promise in copy while the real lesson was embed politics. The screen still uses a full-width landscape from getLandscapeForApp('musica') and some translucent panels in Tailwind because that is what shipped in the repo; the intent now is a cleaner, flatter read of controls and text, not a demo reel of blur filters. If a line of code still says backdrop-blur, read it as legacy styling, not a commitment to a glass brand.
Responsive layout
- Single column shell with a fixed playlist drawer on wide screens.
- Touch targets are usable on small viewports, but this was never tuned like a native music app.
Tests and Quality Assurance
The Musica app is covered by integration-style tests in test/musica.test.js:
npm test
The tests verify:
- Playlist CRUD — Create, read, update, delete operations
- URL Parsing — Provider-specific URL parsing accuracy
- Search Integration — API calls and response handling
- Storage Contracts — Service layer data consistency
Summary
Musica is a frontend experiment in the Vault: playlists and parsers are real, “stream the whole industry inside gato” is not. We learned—again—that most music companies do not want third-party apps embedding their catalog, and only SoundCloud gave us a dependable in-app listen path for this scratchpad. The storageService wiring is fine engineering practice; it is not proof we shipped a streaming product.
Maybe a future Musica uses official APIs and OAuth and becomes serious. Today’s Musica is flex + homework, not Spotify.
One working embed. A pile of lessons. No illusions.
Sources: src/apps/musica/index.jsx, src/apps/musica/services/musicaService.js, src/apps/musica/services/musicaSearchService.js, src/apps/musica/dir_agent/BRAIN.md, and the Gato platform documentation.