Inspiration

The TV is the biggest screen in most homes, and most of the day it is either off or showing something nobody asked for. We wanted it to feel like a wall in a small gallery: a few photographs, well arranged, changing slowly. Rainshadow is built for Fire TV with Vega OS.

What it does

Rainshadow plays public photo feeds as calm, uncropped compositions:

  • Five layouts: One photograph, Pairing, Triptych, One + two, and Offset pairing. Each scene is laid out from the photographs' real aspect ratios, so nothing is ever cropped.
  • Photo color backgrounds: each scene's dominant and companion colors are sampled from the photographs, and the canvas crossfades to match. Color: Natural keeps the photo's most common midtone; Vivid picks its most colorful one for a bolder wall.
  • A living canvas: Grain or Drift texture, built for Vega. A soft color wash and diagonal folds, tinted with each scene's companion color, drift slowly on native animations over a fixed grain.
  • Grain control: Fine draws single-pixel grain for a clean HD finish, Medium and Coarse give a film look, and Off leaves only the drift.
  • Photo size: Standard keeps gallery margins, Large and Fill screen grow the whole arrangement toward the edges without cropping.
  • Smart sequencing: photos from the same post stay together, the previous scene is never repeated, and multiple feeds are interleaved post by post.
  • Remote-first controls: Select shows a quiet controls card, Right skips, Play/Pause pauses, and a Display panel covers layout, photo size, hold time, fade, background, color, brightness, texture, grain, captions, clock and photo sources.
  • Feeds: a fresh install shows Mount Rainier National Park, NASA and Glacier National Park, all public domain. Photo sources suggests more public domain and open-license collections to add with one press, and takes up to 12 public Tumblr photo blogs or tags.

How we built it

  • React Native for Vega (React Native 0.83, new architecture) with TypeScript on Vega SDK 0.24.
  • A framework-free core in plain TypeScript: feed parsing, feed address normalization, the layout engine, the scene planner, palette sampling and the playlist engine. It takes an injected clock, fetcher and image loader, so all of it runs under Jest without a device.
  • 88 Jest tests cover the layout math, feed parsing, color sampling, preferences, the scene engine, the texture, and the remote and settings UI.
  • Sharp grain: grain tiles are drawn one image pixel to one screen pixel using PixelRatio, so Fine grain stays crisp on HD and 4K screens.
  • Palette sampling with no canvas: each photo's smallest Tumblr rendition is fetched, decoded in pure JavaScript, downsampled to 32x32 and binned into 4-bit color buckets, with midtone filtering so deep shadows and blown highlights do not win.
  • Testing on the Vega Virtual Device, fully scripted: builds, installs, remote key presses through inputd-cli inside the device, plus screenshots and video from the emulator console. Nothing touched the host's keyboard or mouse, and every screenshot in this submission came from that loop.

Challenges we ran into

  • The Vega Virtual Device hung about 15 seconds after boot on macOS 26 when started with --no-gui. We traced it to the windowless emulator blocking on the Mac's camera and microphone. Launching it with audio and cameras turned off fixed it. The details are in our friction log.
  • There is no canvas or pixel API in React Native, so color sampling needed a pure JavaScript decode path that falls back gracefully if anything fails.
  • Vega has no shader API. Our first animated background used SVG gradients, which did not draw on the Virtual Device, so we rendered the texture layers into images and animated those instead.
  • Focus on a 10-foot UI: making focus states obvious from across the room without letting them clip inside their containers.

Accomplishments that we're proud of

  • A calm, remote-first TV app built for Vega, with photographs that are never cropped.
  • A framework-free core engine with 88 unit tests.
  • A headless, scriptable test and capture loop for Vega that other developers can reuse (scripts/vvd.sh).

What we learned

  • React Native for Vega felt like React Native: the template, Metro, Hermes and the TV focus model worked as expected.
  • inputd-cli is a great automation hook for TV apps and deserves a spot in the docs.

What's next for Rainshadow

  • A one-time unlock and gifting with Amazon in-app purchasing.
  • Your own photo folders: scan a code on the TV, sign in on your phone, and pick the Dropbox, Google Drive or OneDrive folders to show.
  • Amazon Photos albums, as soon as Vega apps can read them (see our product feedback).
  • Licensed premium collections.
  • Publishing on the Amazon Appstore for Fire TV.

Built With

Share this project:

Updates

Submission history