# NewPipe-fork decisions — 2026-05-23 ## Name: `straw` - Single short word, on-pattern with the rest of Sulkta's app family (cwho, tny, hawk, adhdo, tny). - Evokes "drawing content through a thin pipe" — fits the YouTube-extractor metaphor without leaning on the "pipe" word (NewPipe already owns that). - Easy to type, easy to read. If Cobb hates it, alts: `siphon`, `decant`, `funnel`, `kettle`. ## Approach: fork NewPipe master, rebrand, build on `:shared` Not starting fresh. NewPipe has already done the gradle/CI/buildSrc/Koin/nav3 scaffold work — we'd be reinventing wheels to redo it. Forking lets us: - Keep upstream as a remote, cherry-pick their improvements as they land. - Build directly on `:shared` (the KMP module that has the scaffold but no features). - Keep the legacy `:app` module around as **reference for working extractor wiring patterns** (search, channel, video resolve, player setup). Eventually drop it once `:shared` is feature-complete. ## Repo: `Sulkta-Coop/straw` on LAN Gitea - License: keep GPL-3.0-or-later (upstream's license, required for derivative). - Branches: - `master` — tracks upstream NewPipe master for clean rebase pulls. - `sulkta` — our work branch, default branch for clones. - Remote `upstream` pointing at `github.com:TeamNewPipe/NewPipe.git` for periodic merges. ## App identity | Field | Value | |---|---| | Application ID | `com.sulkta.straw` (replaces `net.newpipe.app`) | | App name | "Straw" (debug suffix `Straw debug`) | | Min SDK | 24 (Android 7, NewPipe is 23 — minor bump for Media3) | | Target SDK | 35 (NewPipe matches) | | Compile SDK | 36 (NewPipe matches) | | Java toolchain | 21 (NewPipe matches) | | Kotlin | 2.3.21 (NewPipe matches) | Legacy `:app` (id `org.schabi.newpipe`) stays unchanged for now — we don't ship it but we read it. ## Stack (matches NewPipe + 1 modernization) - **UI**: Jetpack Compose + Compose Multiplatform (commonMain Composables, androidMain ComposeActivity host). - **Nav**: androidx-navigation3 (type-safe sealed `Screen` interface). - **DI**: Koin 4.x with `koin-plugin` annotation processor (`@KoinApplication`, `@Single`, `@KoinViewModel`). - **State**: ViewModels + StateFlow. - **HTTP for SponsorBlock + RYD**: **Ktor 3.x client** (KMP-ready). NewPipe uses OkHttp; we use Ktor because we want SB/RYD clients to live in `commonMain` for future iOS/desktop. - **Player**: **`androidx.media3` 1.4+** — NewPipe is still on legacy ExoPlayer 2.19.1. Media3 is the upstream-replacement, better lifecycle, better DASH. - **Image loading**: Coil 3 (NewPipe matches). - **Serialization**: kotlinx-serialization (NewPipe matches). - **Extractor**: `NewPipeExtractor v0.26.2` via JitPack (NewPipe matches). JVM-only — lives in `androidMain` source set; `commonMain` declares an expected interface, `androidMain` wires the actual extractor. ## What we don't try to do on day 1 - **iOS target.** Extractor port is multi-week. iosApp stays a stub. - **Desktop target.** Same constraint; no point until extractor ported. - **History/subscriptions persistence.** Room is Android-only, fine for v0, but we want SQLDelight (KMP) eventually. - **Settings.** Use `:shared/SettingsModule` interface that already exists; Android impl backed by DataStore. - **F-Droid metadata.** Worry about it later. - **Background audio + queue + autoplay.** Phase 2 work. - **DRM / age-gated content.** Phase 2. ## Day-1 deliverable scope A working APK with: 1. **Search screen** — type a query, list video results from YouTube. Tap opens video detail. 2. **Video detail screen** — title, channel, description, RYD like/dislike row, "Play" button. 3. **Player screen** — Media3 ExoPlayer playing the resolved video stream. SponsorBlock segments auto-skip during playback. Shows skip toast each time. 4. **Settings sketch** — toggle for SponsorBlock categories (sponsor on by default). That's the demo. **No** channel pages, subscriptions, history, downloads, PiP, background audio, kiosks, comments, related videos. Those are Phase 2+.