Status at submission

Verified on the Android TV emulator, running the real app. We had no Fire TV stick for most of the build, and there is no official Fire OS emulator, so we used the Android TV emulator: system image android-30 (Android 11, the base of Fire OS 8), 1920x1080 at density 320, which is 960x540 dp like a Fire TV Stick. Its WebView was Chromium 90.0.4430.91. Checked end to end there:

  • Demo video: recorded on this Android TV emulator running the real Fire OS APK, labeled "Android TV emulator ยท Fire OS APK" on every TV shot, with the real phone page shown side by side. It runs in on-device mode (no AWS), and the narration says so.
  • A phone joins through the page the TV serves on the local network, and a search typed on the phone opens on the TV in about 2 seconds.
  • "Make it cards" on a Simple English Wikipedia article (Mozilla Readability extraction works on Chromium 90).
  • A Speed Safari quest submit scored "+100 Cheetah!", with the evidence sentence on screen.
  • Drift rescue fired after 4 page hops in 23 seconds in demo mode.
  • The remote: D-pad cursor, click at the cursor, and Back.
  • The backend: the real Lambda handler, run locally with fake AWS clients (backend/dev_server.py --fake) and called by the app on the emulator. /health, /cards, /quest/check (evidence verified against the page) and /speak all returned 200.

Tests: 323 JVM/Robolectric tests for the app, 33 for couchlink, 119 Python tests for the backend (stubbed boto3).

Pending:

  • AWS deployment. The SAM stack is written and tested locally but not deployed, because our new AWS account is restricted: Bedrock answers "Too many tokens per day" on the Nova models with no usage and AccessDeniedException on Claude Haiku 5.5, and S3, Lambda, DynamoDB, API Gateway, CloudFormation, Bedrock Guardrails, Polly and CloudWatch Logs all return AccessDenied "with an explicit deny in a service control policy". As of October 23, 07:50 Bucharest time, it is still blocked. Details are in Friction log #1.
  • A physical Fire TV. Not tested on a stick yet, and nothing in this write-up claims it.

Inspiration

The TV is the biggest, most shared screen in our homes, and the worst one to browse on. Typing a search with a remote means hunting for letters one at a time. Everyone on the couch has an opinion about which link to open, but only one person holds the remote. And on a big bright screen, it's easy to drift: page after page, until nobody remembers what they were looking for.

Moths do that with lamps. They circle a bright light without ever getting anywhere. So our companion is a small, fuzzy moth called Lumo, who knows that feeling and notices when the room starts circling. Instead of a browser that happens to run on a TV, we wanted browsing designed for a room full of people.

What it does

Wander TV is a web browser for Fire TV built around the couch:

  • Every phone is a controller. Scan the QR code on the TV and a web page opens on your phone: keyboard, touchpad, Back and Home. No app to install. Up to four phones join at once, each with a name and a color, and the shared cursor wears the color of whoever moved it last. The Fire TV remote still drives everything on its own.
  • Make it cards. One press turns a long article into 3-5 big field-guide cards the whole room can read from the couch. Lumo reads them aloud with Amazon Polly, or with the TV's own text-to-speech when the backend can't be reached.
  • Family quests, judged by AI, with proof. "Speed Safari: find three animals faster than a car on the highway." Everyone races from their own phone, steering the shared browser on the TV, and sends the page on screen when it has an answer. Lumo checks it with Amazon Bedrock and shows the sentence from the page that proves it, on screen, next to the finder's name. Wrong answers get a kind "not quite", duplicates score nothing and Lumo says who found it first. There are five curated quests plus "Lumo's pick", a quest generated from what the family browsed tonight.
  • Drift rescue that adapts to the household. On the TV, from timing alone (it keeps no URLs, only a hash of each site's name to spot loops), Wander notices rapid page-hopping, endless scrolling, site loops and late nights. Lumo gets sleepy and offers a quest or a curious detour. Every "we're fine" makes Lumo more patient with that pattern, so each household ends up with its own thresholds.
  • Works offline. Cards, quest checks and Lumo's lines all have on-device fallbacks, so the app keeps working when the network or the backend doesn't.

It is multi-modal by design: phones for touch and typing, the D-pad for quick control (the remote moves the same cursor, Play/Pause makes cards), big visuals everyone in the room can read, and Lumo's voice reading aloud.

Who it's for

Households that share one TV: families with kids who are curious about everything, grandparents who'd rather read big type than squint at a phone (the body font, Atkinson Hyperlegible, was designed by the Braille Institute for low-vision readers), and homeschool or classroom setups where a TV is the shared screen. Wander needs no account, no phone app and no new hardware, and is built for Fire OS 6 and later (minSdk 25).

How we built it

The Fire OS app. Native Kotlin with plain Android Views and Canvas (no UI framework), minSdk 25 so it targets Fire OS 6 and newer. Everything is designed for 960x540dp inside the overscan-safe area, with big type (nothing under 16sp), a lamp-amber focus ring that is always visible, and a lamp-lit-living-room look: deep aubergine, warm amber, cream text. Lumo is drawn on a Canvas with four moods (curious, happy, sleepy, concerned).

Why Fire OS and not Vega. We develop on a Windows 11 PC. Amazon's Vega guide says the Vega developer tools need a Mac or Linux ("Windows and WSL are not currently supported"), and the Vega Virtual Device supports WebView only on Apple-silicon Macs. A web browser built on Windows therefore had to be a Fire OS app.

couchlink. Instead of pulling a web framework into the TV app, we wrote couchlink: a zero-dependency HTTP/1.1 + WebSocket (RFC 6455) server on a plain ServerSocket. It serves the phone controller page and fonts from the APK's assets and carries a small JSON protocol (hello, move, tap, go, type, cards, quest_submit, ...). The TV broadcasts a state snapshot so each phone shows only the controls that make sense on the current screen. Because it's pure JVM, it is unit-tested on the desktop, and a desktop harness simulates the TV so the phone page can be tested in a normal browser.

The browser. An Android WebView with one shared cursor. D-pad and phone touchpads both move it; a click becomes a synthetic touch at the cursor. Mozilla Readability runs inside the page to extract clean text (capped at about 6,000 characters) only when someone asks for cards or submits a quest.

The AWS pipeline. The TV calls one API: API Gateway (HTTP API) -> AWS Lambda (Python 3.12, boto3 only) -> Amazon Bedrock's Converse API with forced tool use, so every answer arrives as JSON in a fixed schema. Bedrock Guardrails keeps output family-safe and runs a prompt-attack filter over the page text, which is untrusted input by definition. DynamoDB caches cards per page (URL plus a hash of its text) with a 7-day TTL. Amazon Polly gives Lumo a voice. Everything is one SAM / CloudFormation stack with CloudWatch logs and metrics. The quest judge must quote the page, and the Lambda checks that the quote is really in the page text before a find counts, so the AI can't invent evidence. The stack is not deployed yet (see "Status at submission"); it was verified with 119 unit tests and by running the real handler locally against the app.

Testing without a Fire TV. During the build, the TV screens were reviewed as Robolectric native-graphics renders at 1920x1080, which works on Windows. Then we ran the integrated app on the Android TV emulator. Its real WebView, showing real pages, caught two bugs the renders couldn't: bright white pages and site logos showed through our 85% overlay scrims (now 94%), and the on-device quest judge quoted an off-topic sentence (it now prefers the sentence with the quest's own measurement and the "It ..." sentences that follow it, and skips infobox runs).

Built with Claude Code. We wrote a product plan and turned it into a build contract (SPEC.md: repo layout, per-package ownership, frozen shared types and design tokens, the phone protocol and the backend API). An orchestrating Claude Code agent then ran parallel sub-agents in separate git worktrees, each owning one area: TV shell, browser, companion, cards and quests, phone + couchlink, AWS backend, docs. After the merge, review agents went seam by seam through the places where those areas meet, and fixer agents closed what they found.

Built with Kiro Crew. One feature, Family SafeSearch everywhere, was built by Kiro Crew on October 22 from our steering files (.kiro/steering: product, tech, structure) and a written brief. It added SearchUrls.enforceSearch, hooked it into every main-frame navigation, and wrote 20 unit tests. We reviewed the diff, hardened one edge case (a ? inside a URL fragment) and verified the feature on the Android TV emulator.

Challenges we ran into

  • Typing on a TV without a keyboard. The fix became the product: phones as keyboards. Making four phones share one cursor without fighting meant a cursor that takes the color of whoever moved it last, and a protocol where the TV is the single source of truth.
  • No Fire TV to test on, and nothing official to emulate one on Windows. Vega's tools don't support Windows, the Vega Virtual Device runs WebView only on Apple-silicon Macs, and there is no official Fire OS emulator. We built for Fire OS, reviewed screens as Robolectric renders, and ran the app on the Android TV emulator (Android 11, the base of Fire OS 8) as a stand-in.
  • Bugs only a real WebView shows. Renders looked right, but real pages under a real WebView showed through our overlays, and the offline judge picked the wrong sentence on a real article. Both were found on the emulator and fixed.
  • An AWS account that couldn't deploy. As of October 22, our new AWS account still couldn't call Bedrock ("Too many tokens per day" with no usage on the Nova models, AccessDeniedException on Claude Haiku 5.5), and every other service in the stack was denied by a service control policy. We verified the backend by running the real Lambda handler locally with fake AWS clients and pointing the app on the emulator at it.
  • Making an AI judge the family can trust. A judge that says "yes" without proof is worse than no judge. We force a structured verdict, require a near-verbatim quote, and verify the quote against the page server-side.
  • Untrusted text in the prompt. Every web page is someone else's text. Page text only goes to the model inside guarded content with the prompt-attack filter on, and the model can only answer through the tool schema.
  • Nudging without nagging. A companion that interrupts too often gets switched off. Drift rules adapt per household on the device, and Lumo's copy offers instead of scolding.

Accomplishments that we're proud of

  • Up to four phones driving one TV browser with nothing to install, over a WebSocket server we wrote ourselves with zero dependencies.
  • An AI quest judge that shows its evidence on screen, and can't pass a page that doesn't contain the quote.
  • A companion with a real personality that adapts to the household while keeping page text on the TV unless someone asks.
  • Every AI feature still works offline.
  • A complete, consistent look made for a TV across the room, not a phone UI scaled up.
  • 475 automated tests across the app, couchlink and the backend.

What we learned

  • On a TV, the interaction model is the product. The phone-as-controller decision mattered more than any feature on top of it.
  • Forced tool use plus a server-side check turns an LLM into something you can build a scoreboard on.
  • Privacy is easiest when it's architectural: drift detection keeps only timings and a hash of each site's name, never URLs or page text.
  • Open a new AWS account and deploy a hello-world stack on day one. New-account checks and limits can outlast a hackathon, and the errors don't say when they lift.
  • Screenshot tests are good for layout, but bright real-world pages and real article text found bugs that no render did.

What's next for Wander TV

  • Deploy the AWS stack as soon as the account restrictions lift, then measure each route's latency against the TV's timeouts (8 s for cards and quest checks).
  • Test on Fire TV hardware, including the WebView version real devices ship.
  • Vega OS port. The phone controller page and the whole AWS backend carry over unchanged; the TV shell would be rebuilt with React Native for Vega once WebView is available where we develop.
  • Alexa+ voice. "Alexa, ask Lumo to make cards" or "start a quest about planets" as a fourth input mode next to D-pad, phones and screen.
  • Amazon Appstore launch. Store listing, more quests (including teacher-made packs), and parental controls for the detour suggestions.
  • Household profiles. Per-player stats and streaks, a kids mode with a curated site list, and the drift thresholds per profile instead of per TV.

Built With

Share this project:

Updates

Submission history