changes
Some checks failed
Build and Deploy (internal) / Build Transmission Manager Image (push) Failing after 2m56s
Build and Deploy (internal) / Deploy Transmission Manager (internal) (push) Has been skipped

This commit is contained in:
2026-07-08 17:27:30 -03:00
parent 9981d0bc19
commit ec3e1ee6a3
7 changed files with 933 additions and 219 deletions

141
AGENTS.md
View File

@@ -1,99 +1,58 @@
# Transmission Manager AGENTS.md
# Transmission Manager - Agent Guide
## Project Overview
A lightweight single-binary Go web app that provides a beautiful dark-mode SPA for managing/viewing torrents in a Transmission RPC client.
## First Rule
Always read `project-context.md` before making code or documentation changes. If a change alters project purpose, architecture, APIs, file roles, workflows, constraints, or implementation patterns, update `project-context.md` in the same change.
## Architecture
- **Backend**: Go (stdlib net/http only, no external dependencies). Serves on port 8080.
- `GET /` → serves embedded static files (index.html, app.js, styles.css)
- `GET /api/torrents` → proxies to Transmission RPC, returns clean JSON
- `GET /api/stats` → global session stats
- **Frontend**: Vanilla HTML + CSS + JS. No frameworks. Single page. Dark mode only.
## Quick Summary
Transmission Manager is a lightweight single-binary Go web app for managing and viewing torrents in a Transmission RPC client. It serves a dark-mode vanilla HTML/CSS/JS SPA and proxies Transmission RPC calls through a minimal Go backend.
## Transmission RPC Details
- RPC URL: `http://192.168.20.22:3210/transmission/rpc`
- No auth required (open on LAN)
- The RPC requires a session-ID handshake:
1. POST to the RPC URL
2. If response is 409, read the `X-Transmission-Session-Id` header from the response
3. Re-send the request with that header
4. Cache the session-ID for future requests
- For torrent list, request these fields:
```
id, name, totalSize, downloadedEver, uploadedEver, uploadRatio,
percentDone, status, eta, error, errorString, doneDate, isFinished,
rateDownload, rateUpload, peersConnected, peersGettingFromUs, peersSendingToUs,
peers (array of {address, clientName, progress, isDownloadingFrom, isUploadingTo, rateToClient, rateToPeer})
```
- "Peers with 100%" = count of peers in the `peers` array where `progress === 1.0`
- "Finished date" = `doneDate` (Unix timestamp, 0 means not finished)
## Stack
- Backend: Go 1.24, standard library only.
- Frontend: Vanilla HTML, CSS, and JavaScript. No framework or build step.
- Static assets: embedded with Go `embed` from `web/`.
- Runtime port: `8080`.
- Container: multi-stage Docker build from `golang:1.24-alpine` to `alpine:latest`.
## Design Requirements (CRITICAL)
- **Dark mode only** — deep dark background (#0a0a0f or similar)
- **Modern, stylish, clean** — think Linear, Vercel, Raycast aesthetic
- **Accent color**: Use a vibrant accent (cyan/teal #00d4ff or purple #8b5cf6)
- **Typography**: System font stack, -apple-system, Inter-like
- **Torrent cards or rows** with:
- Name (truncated with ellipsis if long)
- Size (human-readable: GB, MB, etc.)
- Progress bar (animated, smooth)
- Percentage done
- Ratio (uploadRatio)
- Downloaded / Uploaded amounts
- Download/Upload speeds
- ETA (when downloading)
- Status badge (downloading, seeding, paused, finished, error)
- Finish date (formatted nicely, e.g. "Jul 8, 2026")
- Peer count with 100% (e.g. "3/7 peers at 100%")
- **Auto-refresh** every 3 seconds
- **Header** with app title and global stats (total download/upload speed, torrent count)
- **Responsive** — works on mobile and desktop
- Use CSS variables for theming
- Smooth transitions and micro-animations
- Cards with subtle borders and hover effects
## Current Files
- `project-context.md` - canonical project context and implementation rules for agents.
- `main.go` - HTTP server, embedded static file serving, environment-driven Transmission RPC client, connection warning page, API routes.
- `web/index.html` - SPA shell and toolbar controls.
- `web/app.js` - frontend state, polling, in-place rendering, sorting, pause/resume actions.
- `web/styles.css` - dark-only UI theme and responsive layout.
- `go.mod` - module `transmission-manager`, Go 1.24.
- `Dockerfile` - production container build.
## Code Structure
```
main.go — Go backend (HTTP server, Transmission RPC proxy, static file serving via embed)
web/
index.html — SPA shell
app.js — Frontend logic (fetch API, render, auto-refresh)
styles.css — All styling
Dockerfile — Multi-stage: golang:1.24-alpine (build) → alpine:latest (runtime)
go.mod — module transmission-manager, go 1.24
```
## Core API Surface
- `GET /` serves a Transmission connection warning page when setup fails; otherwise it serves the embedded frontend.
- `GET /api/torrents` returns Transmission torrent data.
- `GET /api/stats` returns global session stats.
- `POST /api/torrents/{id}/pause` maps to Transmission `torrent-stop`.
- `POST /api/torrents/{id}/resume` maps to queue-respecting Transmission `torrent-start`.
## Go Implementation Notes
- Use `embed` package to embed web/ directory into the binary
- Transmission RPC communication via net/http client
- Implement session-ID handshake with retry on 409
- Use sync.Mutex to protect session-ID cache
- Format numbers nicely (human-readable sizes) in the frontend, not backend
- CORS not needed (same origin)
- The Go server should be minimal and fast
## Implementation Guidelines
- Keep the backend stdlib-only. Do not add Gin, Fiber, Chi, Gorilla, or other Go web frameworks.
- Keep the frontend dependency-free. Do not add React, Vue, Svelte, bundlers, package managers, or transpilers.
- Preserve the single-binary model: static frontend files should remain embedded via `embed`.
- Format display numbers in the frontend unless there is a clear backend reason.
- Preserve in-place frontend updates during polling. Do not replace the whole torrent list on each refresh.
- Keep polling lightweight and avoid overlapping refresh requests.
- Keep UI dark-only, modern, compact, responsive, and based on CSS variables.
## Dockerfile
```dockerfile
FROM golang:1.24-alpine AS builder
WORKDIR /app
COPY go.mod ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o transmission-manager .
## Transmission RPC Notes
- Default RPC URL: `http://192.168.20.22:3210/transmission/rpc`.
- Override the RPC URL with `TRANSMISSION_URL`.
- Optional HTTP Basic Auth credentials come from `TRANSMISSION_RPC_USERNAME` and `TRANSMISSION_RPC_PASSWORD`; unset, empty, or literal `null` values mean no credential value.
- Handle the Transmission session-ID handshake:
1. POST to the RPC URL.
2. If the response is `409`, read `X-Transmission-Session-Id`.
3. Retry the same request with that header.
4. Cache the session ID behind a mutex.
- "Peers at 100%" means count `peers[]` entries where `progress === 1.0`.
- `doneDate` is a Unix timestamp; `0` means unfinished.
FROM alpine:latest
RUN apk add --no-cache ca-certificates
WORKDIR /app
COPY --from=builder /app/transmission-manager .
EXPOSE 8080
CMD ["./transmission-manager"]
```
## Do NOT
- Do not use any Go web framework (gin, fiber, etc.) — stdlib only
- Do not use any JS framework (React, Vue, etc.) — vanilla only
- Do not add authentication
- Do not add CI/CD or GitHub Actions
- Do not create any GitHub repository
- Do not add vendored dependencies
- Do not add tests unless necessary — keep it simple
## Do Not
- Do not add authentication unless explicitly requested.
- Do not add CI/CD or GitHub Actions.
- Do not create a GitHub repository.
- Do not vendor dependencies.
- Do not add broad tests or infrastructure for small changes; keep verification proportional.