Skip to content

feat: add the OpenMedia downloader with API, web UI and docs - #2

Merged
ttncode merged 77 commits into
mainfrom
feat-openmedia
Sep 14, 2026
Merged

ttncode merged 77 commits into
mainfrom
feat-openmedia

Conversation

@ttncode

@ttncode ttncode commented Sep 14, 2026

Copy link
Copy Markdown
Owner

What this changes

This is the first complete OpenMedia release: a self-hosted media downloader with a clean web UI, built on the scaffold toolbox.

API (apps/api, Flask + yt-dlp + FFmpeg)

  • Based on the ReClip backend, now split into an app factory with blueprints.
  • Command safety: yt-dlp runs from argument lists, with the URL placed after --. Formats, containers, languages and trim values are checked against allow lists.
  • Endpoints: info, playlist, download jobs, status, file, settings, storage, cookies and session.
  • Job engine: runs jobs in memory with a concurrency limit, cancel, a stall watchdog, a retention sweeper and storage limits. It kills whole process groups, with SIGKILL after a grace period.
  • Security:
    • optional password with a per-client sign-in limit and a global one
    • cross-site request guard
    • per-client rate limit
    • private network guard
    • changeme placeholder refused at startup
    • cookie files written with mode 0600
    • non-root container
  • Error codes: stable across the API, including too_large, storage_full, conversion_failed, private_network and bot_check.
  • Container: yt-dlp updates itself at start with a timeout and falls back to the locked version. The health check has a start period.

Web (apps/web, Next.js 16)

  • Design: Apple Human Interface style with glass materials, spring animations, iOS sheets with drag to dismiss, a Dynamic Island style notice, segmented controls, and a trim editor.
  • Queue: live progress, cancel, retry, bulk links, one-level playlist expansion and limited fetch concurrency.
  • Inspector: quality, subtitles, cover art, metadata, chapters and trim.
  • Other screens: history, settings (retention, concurrency, cookies, accent, theme, language) and password sign-in with session expiry handling.
  • PWA: installable, with a share target, paste anywhere, drag and drop, and keyboard shortcuts.
  • Look and language: light and dark themes, seven accents (teal by default), English and Vietnamese.
  • API proxy: a runtime /api/* proxy with a request size limit, abort propagation and streamed downloads.

Project

  • Compose stack (web public, API on 127.0.0.1), installer that generates a password, release assets.
  • README in English and Vietnamese, operator docs (getting started, usage, configuration, deployment, troubleshooting, security), five ADRs, MIT license and NOTICE.
  • Spec: docs/superpowers/specs/2026-09-14-openmedia-design.md. Plan: docs/superpowers/plans/2026-09-14-openmedia.md.

How it was verified

  • mise run checklist passes: API 155 tests with ruff and mypy --strict clean; web 112 tests with eslint, tsc and next build; docs VitePress build, path check and ADR check.
  • Production images built locally and run with docker compose up -d: both services healthy, /api/health/live and /api/session return 200.
  • Real downloads in the browser, checked with ffprobe:
    • Direct MP4: H.264/AAC.
    • archive.org film as M4A: AAC with an attached cover picture.
    • Trim from 0:05 to 0:12: 7.04 s MP4.
    • 3 GB Wikimedia download cancelled: the job directory is removed.
    • 26-track archive.org album: expanded, and one entry saved as M4A.
    • Private address: blocked with a clear message.
    • Settings: retention persisted to settings.json.
    • Invalid cookies file: rejected.
    • Password: sign-in works and a wrong password is rejected.
    • Phone at 390x844: tab bar, sheets and drag to dismiss.
    • Dark mode and the pink accent.
  • YouTube and SoundCloud could not be reached from the build network. The same pipeline was verified with direct media, Wikimedia Commons and archive.org sources. Pasting a YouTube link there fails cleanly with a translated timeout.
  • Reviews: every task was reviewed, and the whole branch had a final review (API and web), a fix wave and a scoped re-review.

Checklist

  • mise run checklist passes
  • New behaviour has a test that fails without the change
  • Docs that describe changed behaviour were updated in the same commit
  • No unrelated changes

…over sheet drag

Capsule no longer joins an undefined class for the default gray variant.
AlertDialog now closes on Escape like Sheet and ShortcutsHud. Sheet gains
phone-path drag-to-dismiss test coverage.
…e shake and i18n

Reviewer findings on Task 13: the form-level Enter handler swallowed
Enter presses on the Paste button; the global "/" and "?" shortcuts
fired while a sheet, alert or HUD was open; the prototype's field-shake
CSS was dead; the "Web" platform chip label bypassed i18n; and the
share-link initializer mutated browser history during render.
@ttncode ttncode changed the title feat: OpenMedia 0.1 feat: add the OpenMedia downloader with API, web UI and docs Sep 14, 2026
@ttncode
ttncode merged commit c73527c into main Sep 14, 2026
10 checks passed
@ttncode
ttncode deleted the feat-openmedia branch September 14, 2026 04:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant