Dev.to WebDev πŸ›  Dev πŸ‘ 0 πŸ“– 4 min read

Building Songfetti: How I Made Personalized Songs Work Entirely in the Browser

Most "personalized gift" apps feel like a black box. You type a name, click submit, wait three seconds, and get a generic jingle. It works, but it feels cold. I wanted to build something warmer: a tool that takes a name

Most "personalized gift" apps feel like a black box. You type a name, click submit, wait three seconds, and get a generic jingle. It works, but it feels cold. I wanted to build something warmer: a tool that takes a name and a few specific memories and turns them into a genuine, heartfelt song. But I also hated the friction of server-side processing. If I wanted this to feel instant and private, it had to run locally.

Songfetti is the result. It’s a lightweight web app that generates custom songs using AI, but everything happens right in your browser. No waiting for a server response, no uploading your personal memories to a cloud database. Just type, listen, and share. Here is how I approached the architecture and why local processing mattered more than I initially thought.

The Constraint: Privacy and Latency

My primary goal was simplicity for the user, which meant minimizing steps. Traditional AI audio pipelines often involve sending text prompts to an API, waiting for a response, fetching audio files, and rendering them. This introduces latency and privacy concerns. If a user is typing intimate memories ("My daughter loves dinosaurs," or "Our first trip to Kyoto"), they shouldn't have to worry about where that data goes.

By keeping the inference engine on-device, I removed the network bottleneck. The app loads a compact model directly into the browser’s memory. When the user inputs their name and memories, the text is tokenized and processed immediately. The audio generation happens in real-time. For a short, personalized track, this means the transition from "input" to "playback" is nearly seamless. It feels less like a cloud service and more like a native app feature.

Handling Multilingual Output Without Heavy Assets

One of the trickier parts was supporting multiple languages without bloating the bundle size. If I shipped separate models for English, Spanish, French, and Japanese, the initial load time would suffer. Instead, I utilized a multilingual foundation model that handles tokenization and phonetic mapping across languages efficiently.

The logic is straightforward but requires careful tuning. When a user enters a name and memories, the app parses the phonetic structure of the name to ensure the melody aligns with natural speech rhythms. For example, a two-syllable name needs a different melodic contour than a four-syllable name to sound natural. The model analyzes the input text’s syllabic stress and matches it to the generated melody. This ensures that even if the song is sung in Japanese or Portuguese, the vocals don’t sound robotic or misaligned with the beat.

I focused heavily on the "preview" experience. The first 15 seconds of the song are generated instantly. This is crucial because users need to know if the tone matches their intent before committing to the full track. By optimizing the inference steps for the initial segment, the app provides immediate feedback. If the user likes the vibe, the full track renders in the background while they review the lyrics. This parallel processing keeps the UI responsive.

Why Local Execution Changes the Experience

There is a psychological benefit to local processing that I didn’t anticipate. Because the app responds instantly, users are more likely to tweak their inputs. They’ll change "loves hiking" to "loves hiking with her dog" and hear the difference in seconds. This iterative loop is where the personalization actually happens. In server-heavy apps, the delay between input and output breaks this flow. Users tend to accept the first result. With Songfetti, the low friction encourages refinement.

The visual design reflects this speed. The interface is minimal: a text area for the name, a text area for memories, and a large play button. There are no complex settings or style selectors. The AI handles the stylistic choices based on the emotional tone detected in the memories. If the memories are happy and concise, the tempo increases. If they are reflective, the melody slows down. This automation reduces decision fatigue for the user.

Lessons from Shipping a Lightweight AI Tool

Building Songfetti taught me that "fast" is a feature, not just a metric. Users don’t care about the underlying architecture; they care about how quickly their idea becomes reality. By pushing the compute to the client, I traded a bit of initial load time for a much smoother interaction loop. The bundle size is kept tight by using optimized WASM modules for the inference engine, ensuring it runs smoothly even on older laptops.

Another lesson was about transparency. Since the processing is local, I made sure the UI clearly indicates when generation is happening. Simple visual cues, like a pulsing waveform during generation, help users understand the system state without needing complex loading spinners. It feels more like a conversation than a transaction.

If you’re building similar tools, I’d be curious to hear your thoughts. Do you find that on-device processing significantly improves the perceived quality of interaction in your own projects, or do you prefer the raw power of server-side models?

πŸ“° Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.