Skip to content

Repository files navigation

ElixirTorrent Web

GitHub release GitHub CI codecov Last commit Engine macOS

Phoenix (LiveView) Web UI for the elixir_torrent BitTorrent engine.

Goal

Build a stable, correct, long-running BitTorrent client UI on top of an Elixir/OTP engine. The engine lives in a separate project and this repo is the UI + desktop product shell.

Features

  • Torrent dashboard — list with progress, speeds, peers, ETA, expandable file rows
  • Lifetime statistics — persisted downloaded/uploaded totals and current aggregate speeds, with an atomic Reset Statistics action in Settings
  • Add & remove torrents.torrent upload, clipboard magnet ingestion, persisted pending magnets, and optional downloaded-data removal
  • Download settings — persistent default download directory with a native macOS picker
  • Media actions — range-streamed video playback plus lazy previews for completed images; image clicks open in the operating system's default application
  • International UI — all user-facing strings are maintained across 64 Gettext locales
  • macOS desktop appmix mac.dmg bundles a Swift launcher + release into ElixirTorrent Web.app (browser UI on loopback), registers .torrent/magnet: handlers, rotates logs, and shows active torrents in the Dock menu

Architecture

  • Engine: elixir_torrent (Hex docs · GitHub) — session persistence, graceful shutdown (stop_and_serialize/1), peer disconnect
  • UI server: Phoenix + LiveView (local HTTP + WebSocket)
  • Desktop (macOS): Swift launcher starts the release, opens the browser, graceful shutdown on Quit

Process model

On boot, ElixirTorrentWebUI.Application calls Application.ensure_all_started(:elixir_torrent). The Phoenix endpoint listens on loopback only by default (127.0.0.1).

UI code talks to the engine through ElixirTorrentWebUI.Engine — not ElixirTorrent.* directly.

Tech stack

  • Elixir: 1.20.x
  • Phoenix: 1.8.x
  • Phoenix LiveView: 1.2.x
  • Bandit: HTTP server
  • Tailwind + ESBuild: assets pipeline

Development setup

From the repo root:

mix setup
mix phx.server

Open http://127.0.0.1:4000.

mix phx.server and the macOS .app share catalog, UI state, and .torrent files via ~/Library/Application Support/ElixirTorrentWebUI/ (see ElixirTorrentWebUI.DataDir).

In dev, the process working directory stays in the project root so Phoenix code reloading works; engine session files and downloads land under the repo unless you symlink .elixir_torrent to Application Support. The desktop app uses that folder as its cwd, so torrent data and the catalog stay in sync there.

Override the data root with ELIXIR_TORRENT_DATA_DIR if needed.

mix setup also runs mix mac.icon to generate app icons. That step needs Python 3 and Pillow (pip install Pillow).

macOS desktop app

Build a local .app bundle and .dmg installer:

mix mac.dmg

Output lands in dist/ (e.g. ElixirTorrent Web.app, ElixirTorrent Web-0.1.0-macos-arm64.dmg on Apple Silicon, or …-macos-x64.dmg on Intel).

Icon generation (mix mac.icon, also part of mix setup):

  • Liquid Glass (Assets.car for macOS 26+): requires Xcode 26+ (xcrun actool). Without it, the build still produces a classic .icns fallback icon.
  • Python 3 + Pillow for priv/scripts/macos/generate-app-icon.py.

Engine dependency

The committed dependency remains the published Hex package. While both projects evolve together, validate the WebUI against a local Engine checkout by setting:

export ELIXIR_TORRENT_PATH=../ElixirTorrent
mix deps.get

The local path and Engine revision are development inputs, not committed pins. Do not commit lock-file changes caused only by switching dependency sources.

Tests and quality

The deterministic ExUnit/ConnTest/LiveViewTest suite has a 60-second ceiling. ExCoveralls currently enforces the first 55% project gate (57.2% at introduction); the roadmap raises this to 70% and then above 80%.

export ELIXIR_TORRENT_PATH=../ElixirTorrent
mix format --check-formatted
mix quality
perl -e 'alarm shift; exec @ARGV' 60 mix coveralls

GitHub Actions currently validates only Elixir: locked dependencies, Hex audit, formatting, warnings-as-errors compilation in dev/test, Credo, Dialyzer, and coverage. Native packaging remains a separate future workflow.

Security notes (local UI)

  • The endpoint is bound to loopback (127.0.0.1) in dev config.
  • Media routes accept only torrent id/file index, resolve server-side Engine state, and reject traversal, absolute, drive, UNC, and NUL paths.
  • Completed image previews are allow-listed, private-cache responses with X-Content-Type-Options: nosniff; paths are never accepted from HTTP clients.
  • Before exposing anything beyond localhost, add auth (token/cookie) and review endpoints that control downloads or read files.

About

Phoenix LiveView UI for the ElixirTorrent engine

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages