Inspiration

Watching a subscription on a TV is still painful: typing passwords with a remote, players that stutter on cheap TV sticks, apps that only work on one kind of device, and no way to see or control which devices use your account. I wanted one service that feels the same on a laptop, a phone, an Android TV box and a Fire TV Stick, and that respects the people using it (their language, their devices, their privacy).

What it does

AromaOtt is a subscription TV platform with a web app and an Android app (phones, Android TV, Fire TV):

  • Watch anywhere: live channels, movies and series in the browser or the Android app.
  • Built for the big screen: a TV mode with full remote-control navigation (arrows, OK, Back, play/pause, channel up/down) that switches on automatically on TVs.
  • Sign in on a TV with a code: the TV shows a short code and a QR code; you approve it on your phone. No password typing with a remote.
  • Native player in the app: video plays through Android's Media3 ExoPlayer with hardware decoding, behind a transparent web interface, so the app keeps the site's controls, guide and menus.
  • Pick up where you left off: resume for movies and episodes, watched / in-progress marks on every episode, and a next-episode countdown.
  • Fair, transparent device rules: each plan has a device limit and a simultaneous-stream limit. If you start watching on a second device, the newer one takes over and the first shows "Playing on another device" with a Watch here button.
  • 9 languages, including full right-to-left Arabic, chosen automatically and easy to change.
  • Self-updating Android app: distributed directly from the site, checks for updates daily, verifies every download (SHA-256) before installing.
  • Admin panel: members, plans, devices, live viewers, capacity and activity, plus security (2-step login, session revocation, "sign out everywhere").

How we built it

  • Web: Next.js 16 (App Router, Server Components, Server Actions), React 19, TypeScript, Tailwind CSS.
  • Data: PostgreSQL with Prisma ORM 7.
  • Playback on the web: hls.js and mpegts.js through an encrypted, session-bound stream proxy, so provider addresses and credentials never reach a device.
  • Android: a native Kotlin shell around the web app with a JavaScript bridge to a Media3 ExoPlayer engine, one APK for phones, Android TV and Fire TV.
  • TV navigation: a small in-house spatial-navigation library (focus memory per row, Back handling, TV key codes for Fire TV, Android TV, Samsung and LG).
  • Security: TOTP 2-step login, Cloudflare Turnstile, rate limits, session versioning for instant sign-out, strict CSP, SSRF protection on every outbound fetch.
  • Infrastructure: Docker Compose on a VPS behind nginx and Cloudflare.
  • Built with AI assistance: much of the code was written and tested together with Claude Code (Anthropic), with every change reviewed, type-checked and tested on emulators before release.

Challenges we ran into

  • Video on many devices: Android WebView claims it can play HLS natively but fails on proxied playlists, so the app falls back to hls.js or the native player automatically.
  • Making a web UI work with a remote: hidden player controls kept "trapping" focus; spatial navigation had to learn to skip invisible elements and wake the controls on the first key press.
  • One provider connection, many viewers: movies need one upstream connection per viewer, so we built a connection pool with fallback copies and a calm "getting your movie ready" screen instead of an error.
  • Right-to-left layout: small details (a hidden form field at -9999px, numbers inside Arabic sentences) broke Arabic pages in surprising ways.
  • Updating an app outside a store: safe self-updates needed hash checks, the right Android install-permission flow on every version, and a release key that can never be lost.

Accomplishments that we're proud of

  • One code base that runs on the web, phones, Android TV and Fire TV.
  • Signing in on a TV in seconds without typing a password.
  • A privacy page that is generated from what the code actually stores, in 9 languages.

What we learned

  • TVs are a different medium: focus, distance and the remote matter more than layout.
  • Native playback plus a web interface gives the best of both worlds.
  • Small accessibility and RTL details decide whether an app feels finished.

What's next for AromaOtt

  • Samsung Tizen and LG webOS apps (the playback engine is already pluggable).
  • Desktop apps for Windows and macOS.
  • An electronic programme guide (EPG) and picture-in-picture in the native player.

Built With

Share this project:

Updates

Submission history