DEV Community

Cover image for Horizon: A Shelved App Idea I Finally Built Before Breakfast
Taminoturoko Briggs
Taminoturoko Briggs Subscriber

Posted on

Horizon: A Shelved App Idea I Finally Built Before Breakfast

DEV Weekend Challenge: Passion Edition Submission

This is a submission for Weekend Challenge: Passion Edition

What I Built

I built Horizon, a voice translator for travelers — speak a sentence in one language, and it translates and speaks it back in another, live, so two people who don't share a language can still have a conversation.

The passion behind this isn't really about translation, though. It's about not giving up on building something real.

For a couple of years now I've wanted to start a business of my own. My first real attempt was back in university, and it didn't go the way I hoped. My second attempt has been looking pretty grim too. Currently, due to a lack of funds, I am considering putting my passion on hold. Ironically it's right now that a lot of ideas are coming to mind, and this translation one is actually a fairly recent addition to the list. I pictured it as a mobile app, and I only have web development skills, not app development. Learning app development and covering the time and cost to actually get something onto the Play Store wasn't realistic for me right now, so it just stayed an idea.

This challenge, landing the same weekend as the World Cup, gave me an excuse to build something. There's a nice parallel there too: right now there are thousands of fans traveling to stadiums and cities where they don't speak the language, trying to order food, ask for directions, or just talk to someone in the stands next to them. Horizon is built for exactly that moment — no app store, no install, just open a link and talk.

You pick two languages once — say, English and Spanish — and from then on you just speak. Horizon figures out which of the two languages you used and automatically translates into the other one and speaks it back. No toggling a "who's talking" switch mid-conversation, no menus to dig through — just a mic button and a shared conversation log of everything that's been said, in both languages, replayable at any time.

Demo

🔗 Live app: https://horizon-voice.vercel.app/

Open it on a phone or laptop, allow microphone access, pick your two languages, and talk.

Code

Horizon — live voice translation

Speak on one shore, hear it on the other. A Next.js app that listens to your voice, translates it with Gemini, and speaks the translation back with ElevenLabs — architected to run entirely on Vercel (HTTP in, audio stream out no persistent server needed).

Client (mic clip) ──HTTP POST──► /api/translate ──► Gemini (audio in, translated text out)
                                        │
Client (mic clip) ──HTTP POST──► /api/speak      ──► ElevenLabs (text in, mp3 stream out)
Client (plays audio) ◄──stream───────────┘

What's inside

  • Client-side voice activity detection@ricky0123/vad-web (Silero VAD, runs on-device via ONNX/WASM) listens continuously and clips out each finished utterance automatically. If the VAD model can't load (e.g. restrictive network), the app falls back to a hold-to-talk button automatically — no code changes needed.
  • /api/translate — a Vercel serverless function that sends the raw audio clip straight to Gemini (@google/genai) and asks it to identify the…

https://github.com/Tammibriggs/horizon-voice-translator

How I Built It

Horizon is a Next.js app, deployed entirely on Vercel — no separate backend, no server to manage, which mattered a lot given I was working solo with no infrastructure budget.
The pipeline, end to end:

  1. Client-side voice activity detection. The browser runs Silero VAD (via @ricky0123/vad-web, on-device through ONNX/WASM) to continuously listen and automatically clip out each finished sentence — no manual record button needed. If VAD can't load for any reason, the app quietly falls back to a hold-to-talk button instead, so it still works.
  2. Detection + translation in one call. The audio clip is POSTed to a Vercel serverless function, which sends it straight to Gemini along with the two languages the user configured. Gemini is asked to (a) work out which of the two languages was actually spoken, (b) transcribe it, and (c) translate it into the other one — all in a single structured JSON response. That's the piece I'm most pleased with: instead of asking the user to manually flag who's speaking, the direction of translation is inferred automatically every single turn.
  3. Voice synthesis. The translated text is sent to ElevenLabs (eleven_flash_v2_5), and the resulting audio is streamed straight back to the browser and played.

A few decisions worth calling out:

  • No native app, on purpose. Given where I am right now — no app dev skills, no App Store/Play Store budget — a web app that works instantly from a link was the only realistic way to actually ship this. Vercel's serverless functions meant I didn't need to run or pay for a backend server either.
  • Two-way by default. My first version had the user manually declare which language they were speaking. It worked, but it defeated the point of a "live conversation" — real conversations don't have a toggle switch. Moving that decision into the Gemini prompt itself (detect and translate in one pass) made the whole thing feel much closer to a real interpreter.
  • Graceful fallback everywhere. VAD failing to load, the mic being denied, an API error mid-translation — all of these surface as a clear message in the UI rather than a dead end.

Top comments (0)