Files
transmission-manager/project-context.md
Jose Henrique 7d1b868107
Some checks failed
Build and Deploy (internal) / Build Transmission Manager Image (push) Failing after 0s
Build and Deploy (internal) / Deploy Transmission Manager (internal) (push) Has been skipped
adding availability
2026-07-08 20:01:02 -03:00

7.4 KiB

Project Context

This file is the canonical project context for AI agents working on Transmission Manager. Read it before making changes, and keep it updated whenever project purpose, architecture, APIs, file roles, workflows, constraints, or implementation patterns change.

Purpose

Transmission Manager is a lightweight local/LAN web app for viewing and managing torrents from a Transmission RPC daemon. The product goal is a fast, clean, dark-mode SPA that feels modern while remaining simple to build, deploy, and inspect.

The app is intentionally small: one Go binary serves both the API and embedded frontend assets. The frontend is vanilla JavaScript, HTML, and CSS, with no package manager, no compile step, and no JS framework.

Technology Stack

  • Go module: transmission-manager
  • Go version: 1.24
  • Backend dependencies: standard library only
  • Frontend dependencies: none
  • Static assets: embedded with Go embed
  • Runtime port: 8080
  • Docker build: golang:1.24-alpine builder, alpine:latest runtime
  • Default Transmission RPC target: http://192.168.20.22:3210/transmission/rpc
  • Runtime RPC configuration: TRANSMISSION_URL, TRANSMISSION_RPC_USERNAME, and TRANSMISSION_RPC_PASSWORD

Repository Organization

  • main.go: backend entrypoint. Owns the HTTP server, embedded static file serving, environment-driven Transmission RPC client configuration, session-ID handshake, connection warning page, JSON helpers, and API routes.
  • web/index.html: SPA shell. Defines the header, stats pills, filter input, sort buttons, list container, empty state, error state, footer, and script/style links.
  • web/app.js: frontend application logic. Owns state, polling, fetch helpers, formatting, torrent classification, sorting, keyed DOM reconciliation, pause/resume actions, and event wiring.
  • web/styles.css: all styling. Owns dark theme variables, layout, cards, badges, progress bars, action buttons, empty/error states, and responsive rules.
  • go.mod: Go module declaration.
  • Dockerfile: multi-stage production build.
  • AGENTS.md: quick-start guide for coding agents. It must point agents back to this file.

Backend Architecture

The backend uses net/http with a single http.ServeMux. It exposes:

  • GET /api/torrents: sends Transmission torrent-get with the required torrent fields and returns the RPC arguments JSON directly.
  • GET /api/stats: sends Transmission session-stats and returns the RPC arguments JSON directly.
  • POST /api/torrents/{id}/pause: validates a positive numeric torrent id and sends torrent-stop.
  • POST /api/torrents/{id}/resume: validates a positive numeric torrent id and sends queue-respecting torrent-start.
  • /: checks the Transmission connection and serves a warning page with the connection error when setup fails; otherwise serves embedded files from web/.

Transmission RPC calls must reuse the existing Client.rpc path so session-ID handling is consistent. The session ID is cached in Client.sessionID and guarded by sync.Mutex.

API errors return JSON with an error string. Invalid torrent action methods should return 405; invalid ids should return 400; unknown action paths should return 404; Transmission failures should return 502.

Transmission RPC Model

The RPC endpoint defaults to http://192.168.20.22:3210/transmission/rpc and can be overridden with TRANSMISSION_URL. TRANSMISSION_RPC_USERNAME and TRANSMISSION_RPC_PASSWORD are optional; unset, empty, or literal null values mean no credential value. When either credential has a value, the backend sends HTTP Basic Auth on RPC requests.

Transmission usually rejects the first request or an expired session with HTTP 409 and a fresh X-Transmission-Session-Id header. Correct behavior is to drain and close the response body, cache the new session ID, and retry the same JSON request once.

Torrent list requests should include:

id, name, totalSize, downloadedEver, uploadedEver, uploadRatio,
percentDone, status, eta, error, errorString, doneDate, isFinished,
rateDownload, rateUpload, peersConnected, peersGettingFromUs, peersSendingToUs,
availability, peers

Peer objects are expected to include address, clientName, progress, isDownloadingFrom, isUploadingTo, rateToClient, and rateToPeer when available.

The UI definition of "peers at 100%" is an absolute count of peers[] entries whose progress === 1.0. Do not reinterpret it as a percentage of connected peers.

The UI availability value comes from Transmission's availability per-piece array. Render and sort it as a complete-copy estimate, treating -1 entries as pieces available locally.

Frontend Architecture

The frontend is a single page with module-level state in web/app.js. It polls on a user-selectable interval, defaults to 3 seconds, and fetches torrents and stats in parallel.

Important patterns:

  • Polling must not create an F5-style visual refresh. Use keyed DOM reconciliation by torrent id.
  • Existing torrent cards should be updated in place. Create DOM only for new torrents, move existing nodes when sort order changes, and remove nodes only for hidden or removed torrents.
  • Keep syncInFlight / queued-sync behavior or equivalent protection so requests do not overlap.
  • Preserve filter input focus and local UI state during polling.
  • Action buttons are delegated from the torrent list. Pause/resume requests show pending text, disable the clicked button, then trigger an immediate sync on success.
  • Action failures should be shown inline on the card without clearing the list.

Current sort keys:

  • status: default. Orders by status rank, then progress, then name.
  • name
  • progress
  • ratio
  • size
  • speed: orders by combined download and upload speed descending, then download speed, upload speed, and name.
  • availability: orders by computed availability descending, then progress, then name.

UI And Design Rules

  • Dark mode only.
  • Use CSS variables from :root for theme values.
  • Keep the aesthetic modern, compact, and clean: dark background, subtle borders, cyan/purple accent, small badges, smooth progress bars.
  • Cards should have subtle hover effects and stable layout.
  • Card entrance animation should apply only to newly inserted cards, not every poll.
  • The app must remain usable on mobile and desktop.
  • Long torrent names must truncate with ellipsis rather than breaking layout.

Implementation Rules

  • Do not add external Go dependencies.
  • Do not add frontend dependencies, bundlers, or transpilation.
  • Do not add auth unless explicitly requested.
  • Do not add CI/CD, GitHub Actions, or repository setup.
  • Keep changes scoped to the app files unless the user asks for broader project work.
  • Prefer small helper functions over new abstractions unless duplication or complexity justifies the abstraction.
  • Format Go with gofmt when the tool is available.
  • Use frontend formatting helpers for human-readable sizes, speeds, ratios, dates, percentages, and ETA.
  • Keep comments sparse and useful; avoid narrating obvious code.
  • Use ASCII in new documentation unless there is a specific reason to use non-ASCII characters.

Verification

Preferred checks:

gofmt -w main.go
go test ./...
node --check web\app.js
git diff --check
docker build .

Known local environment note from July 8, 2026: go and gofmt were not available in PATH, and Docker was configured to a remote builder with an SSH host-key mismatch. If that remains true, report the limitation instead of changing SSH trust settings automatically.