FlightTube
A desktop app that merges all your YouTube subscriptions into one newest-first feed, downloads the videos you pick, and — when you have no connection — shows only what you already downloaded. Built for the flight.
Tauri 2 · Rust · React · Tailwind CSS 4 · SQLite
Styled to DESIGN-SYSTEM.md: slate and sky, a 9–15px type ladder, outline-first
controls, borders for separation and shadows only for elevation, with light and dark
both designed rather than one derived from the other.
How it works
Subscriptions come from Google Takeout, not the API. Export YouTube subscriptions
from Takeout and import the subscriptions.csv in
Settings — which carries a seven-step walkthrough with the exact URLs. No OAuth, no API
key, no Google Cloud project, nothing secret on disk.
Importing replaces your subscription list: the CSV becomes the whole truth. Channels no longer in it are removed along with their videos and downloaded files. A confirmation dialog names exactly what will be deleted before anything happens.
Video metadata comes from YouTube's public Atom feed — one request per channel to
youtube.com/feeds/videos.xml?channel_id=…, fetched 8 at a time and merged into a single
feed sorted by publish date. Thumbnails are mirrored to local disk so the feed still
renders with no network.
Downloads shell out to yt-dlp, pinned to H.264 video + AAC audio in an MP4
container. That caps quality at 1080p — YouTube only serves H.264 that high, and anything
above it is VP9 or AV1, which the app's own player cannot reliably decode. The tradeoff is
deliberate: every download is guaranteed to play inside FlightTube.
Requirements
brew install yt-dlp ffmpeg
Both are checked at startup; Settings shows their versions and this command if either is
missing. ffmpeg is required because best-quality H.264 and AAC arrive as separate
streams that must be merged.
Running it
npm install && npm run tauri dev
Build and install a real app bundle:
npm run tauri build -- --bundles app && cp -R src-tauri/target/release/bundle/macos/FlightTube.app /Applications/
Using it
- Settings — follow the seven-step Takeout guide, then Import subscriptions.csv.
- Refresh — pulls the latest videos from every channel.
- Download on any video — progress shows live on the button; click again to cancel.
- Click a downloaded video to play it in the app. Click an undownloaded one to open it on YouTube.
- Offline — the app detects a lost connection and collapses the feed to your downloads. The connectivity pill also toggles a forced offline mode for testing.
Videos land in ~/Movies/FlightTube (changeable in Settings). Appearance follows the
system by default; Settings offers System / Light / Dark.
Limitations
- The Atom feed returns only the ~15 most recent videos per channel. There is no backfill and no pagination — this is a rolling recent window, not an archive.
- Quality tops out at 1080p, by the deliberate choice described above.
yt-dlpneeds occasional updating (brew upgrade yt-dlp) as YouTube changes.- Downloading videos is contrary to YouTube's Terms of Service.
Tests
cd src-tauri && cargo test
42 unit tests cover the three places malformed input actually bites: Takeout CSV parsing,
Atom feed parsing (against a captured real response), and yt-dlp progress-line parsing —
plus the database rules that a refresh must never clobber download state and that a
replacing import drops exactly the right channels.
Two network-dependent tests are excluded by default:
cargo test --test pipeline -- --ignored --nocapture # full pipeline vs. live feeds
cargo test --test seed_real_db -- --ignored --nocapture # populate the installed app's db
Layout
src-tauri/src/
takeout.rs subscriptions.csv -> channels (pure, tested)
feed.rs Atom XML -> videos, plus fetching (parse is pure, tested)
downloader.rs yt-dlp arguments and progress lines (pure, tested)
db.rs schema and every SQL statement
thumbs.rs local thumbnail cache
net.rs reachability probe
commands.rs Tauri command surface — delegates only
src/
components/ Sidebar, TopBar, VideoRow, DownloadButton, Player, Settings
components/ui.tsx the design system's component vocabulary, in one place
components/TakeoutGuide the seven-step export walkthrough
hooks/ useFeed, useDownloads, useConnectivity, useAppearance
Design notes and the implementation plan are in docs/superpowers/.