7.1 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-alpinebuilder,alpine:latestruntime - Runtime RPC configuration:
TRANSMISSION_URL,TRANSMISSION_RPC_USERNAME, andTRANSMISSION_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.README.md: public project documentation, configuration guide, and deployment instructions.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 Transmissiontorrent-getwith the required torrent fields and returns the RPCargumentsJSON directly.GET /api/stats: sends Transmissionsession-statsand returns the RPCargumentsJSON directly.POST /api/torrents/{id}/pause: validates a positive numeric torrent id and sendstorrent-stop.POST /api/torrents/{id}/resume: validates a positive numeric torrent id and sends queue-respectingtorrent-start./: checks the Transmission connection and serves a warning page with the connection error when setup fails; otherwise serves embedded files fromweb/.
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 is configured via TRANSMISSION_URL (which must be set). 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.nameprogressratiosizespeed: 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
:rootfor 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
gofmtwhen 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 .