rays 162665b010 Phone layout drawn the way iOS draws its apps (#53), clear of the Dynamic Island (#54)
On a phone every control was outlined, hairlines ruled off the bars, corners were 7-9px and
dialogs were centred cards: a desktop page, shrunk. Now, below 820px and in every theme, controls
are filled and round (40px circles and capsules, pills for groups), the feed's name is a 26px
large title, the tabs are a segmented control, rows are 44px with 17px text and an inset hairline,
the reader's type is 17px, and dialogs are sheets from the bottom. --edge is the one switch for the
outlines, left on for the high-contrast theme and for prefers-contrast:more. Glass's desktop radii
moved into a min-width query, because at their specificity they outranked the phone's shapes, and
on a phone its #51 rim only catches the top edge: all round a small capsule it read as an outline.

Text boxes were 13.5px, and Safari zooms the page in on focus below 16px, so tapping search zoomed
it; they are 16-17px on a phone now.

Nothing read safe-area-inset-top, so opened from the home screen the top bar, the reader's back
button and the drawer's head sat under the Dynamic Island. --safe-t pads them, and the phone's own
top-bar rule, a shorthand, had also been discarding the side insets for the notch in landscape.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 13:48:15 +00:00
2026-09-19 23:29:10 +00:00
2026-09-19 23:29:10 +00:00
2026-09-09 19:34:25 +00:00

ipodderx-rs

A self-hosted podcatcher for a household. It checks your feeds, downloads the episodes, and serves a web UI modelled on the 2004 Mac app iPodderX, for any number of people sharing one copy of the files. One Rust binary, ipx, is both the daemon and the command line.

It is a rewrite of ipodderx-core, the Python engine behind iPodderX (2004-2008, Ray Slakinski & August Trometer).

What it does

  • The web UI. It has a toolbar, and a feed list that opens with Directory, Popular and All Subscriptions. Items sit in a sortable table with a Files pane, and there is a player bar. It comes in Dark, Light and Classic themes, and works on a phone.
  • Several people, one copy. Each person has their own subscriptions and their own read, pinned and playback state. There is one file on disk per episode, however many people want it. People sign in with a password or through a proxy (Cloudflare Zero Trust or Authentik), and admins manage accounts and settings.
  • Scanning. Feeds are checked on a schedule, globally or per feed, and a feed's own TTL is honoured. Keyword, explicit-content and media-type filters decide what is downloaded, with a cap on new downloads per scan.
  • Downloads. Files come over HTTP or BitTorrent and are filed into a folder per feed. Retention deletes the oldest files to stay under a disk quota or an age limit, and never touches an item someone has pinned.
  • OPML. You can import and export your own subscriptions. You can also subscribe to an OPML URL, which keeps a whole list in step as a folder.

Run it

With Docker:

docker build -t ipodderx .
docker compose up -d

docker-compose.yml is set up for the author's own server. Point its image and its three volumes (/config, /data and /downloads) at yours first. The UI is on port 8099. BitTorrent uses 6881 over TCP and UDP. Files are written as PUID/PGID, 99:100 by default.

From source:

cargo build --release
./target/release/ipx daemon

The first start creates admin / ipodderx. Sign in at /login, then change it:

echo -n 'a good password' | ipx user passwd admin

The UI is plain HTTP, so put TLS in front of it if it is reachable from outside your network.

Documentation

docs/configuration.md Every config key, path and environment variable
docs/cli.md Every command, including ipx user
docs/users.md Accounts, and what several people share
docs/sso.md Signing in through Cloudflare Zero Trust or Authentik
docs/architecture.md How it works: modules, schema, control socket, HTTP API
CHANGELOG.md What changed, by release
CLAUDE.md Notes for working on the code, including how production is deployed

Tests

cargo test                # the engine: parsing, filters, retention, schedules, SQL, per-user state
node tests/page-smoke.js  # the page script loads without throwing
node tests/native-bridge.js  # the page hands playback to a native shell
npx playwright test       # a real browser against a real daemon on fixture feeds

npm install gets the test runner, and npx playwright install --with-deps chromium gets the browser.

License

MIT, see LICENSE. The icons are Font Awesome Free 7.3.1 by @fontawesome, under CC BY 4.0, embedded as SVG.

Description
No description provided
Readme MIT 14 MiB
Languages
Rust 50.9%
JavaScript 24.8%
TypeScript 14.7%
CSS 6.8%
Python 1.5%
Other 1.3%