A local-only web-based torrent client that runs on macOS. Downloads files from magnet URLs directly to a local folder with a clean, minimal UI built with React and Tailwind CSS.
- ✅ Full BitTorrent support (TCP/UDP/DHT) via webtorrent
- ✅ Modern React + Tailwind CSS interface
- ✅ Real-time download progress tracking
- ✅ Multiple simultaneous downloads
- ✅ File-level download access
- ✅ Clean, minimal programmer aesthetic UI
- ✅ Component-based architecture for easy feature additions
- ✅ Local-only (no external networking beyond torrenting)
- ✅ No authentication required
- Backend: Node.js + Express + WebTorrent
- Frontend: Vite + React 18 + Tailwind CSS 3
- Architecture: Separate API server (port 3001) and Vite dev server (port 5173)
/torrent-client
/server # Backend API server
app.js # Express server with WebTorrent
package.json # Backend dependencies
/src # Frontend source
/components # React components
AddTorrent.jsx # Magnet URL input form
TorrentCard.jsx # Individual torrent display
StatusMessage.jsx # Status notifications
App.jsx # Main application component
main.jsx # React entry point
index.css # Tailwind directives
/downloads # Downloaded files (auto-created)
index.html # Entry HTML
vite.config.js # Vite configuration
tailwind.config.js # Tailwind configuration
postcss.config.js # PostCSS configuration
package.json # Frontend dependencies
npm installcd server
npm install
cd ..You need to run both the backend server and the frontend dev server.
cd server
node app.jsYou should see:
✓ Torrent server running on http://localhost:3001
✓ Downloads will be saved to: /path/to/downloads
npm run devYou should see:
VITE v5.x.x ready in xxx ms
➜ Local: http://localhost:5173/
- Open your browser and navigate to
http://localhost:5173 - Paste a magnet URL into the input field
- Click "Add Torrent" button
- Watch the download progress in real-time (auto-refreshes every 2 seconds)
- Click the "▶ Files" dropdown to see all files in the torrent
- Once complete, download individual files from the torrent
All downloaded files are saved to:
/torrent-client/downloads/
Files are organized by torrent name in subdirectories.
The backend server exposes these endpoints:
-
POST /api/add- Add a new torrent from magnet URL- Body:
{ "magnet": "magnet:?xt=urn:btih:..." } - Returns:
{ "infoHash": "..." }
- Body:
-
GET /api/list- Get all active torrents with progress- Returns array of torrent objects with progress, speeds, peers, etc.
-
GET /api/file/:infoHash/:fileIndex- Download a specific file- Streams the file with proper Content-Disposition headers
The app uses a component-based architecture for easy extensibility:
- App.jsx - Main app with state management (torrents, status messages)
- AddTorrent.jsx - Form for adding new magnet URLs
- TorrentCard.jsx - Display individual torrent with progress, stats, and files
- StatusMessage.jsx - Toast-style status notifications
With React components, you can easily:
- Add new torrent actions (pause, remove, etc.)
- Create custom views (grid layout, list layout)
- Add filtering and sorting
- Implement settings/preferences
- Add more detailed statistics
npm run buildThis creates optimized static files in the dist/ directory.
npm run previewThe app uses Tailwind CSS with a dark theme. Key color scheme:
- Background: Gray 950
- Cards: Gray 900
- Borders: Gray 800
- Accent: Blue 500/600
- Success: Green 500/600
Modify tailwind.config.js to customize the theme.
- Torrents stop seeding 5 seconds after completion to save bandwidth
- The app only works locally - no external web access
- No authentication or user management
- Auto-refresh stops when no torrents are active
- Browser compatibility: Modern browsers (Chrome, Firefox, Safari, Edge)
- React components use hooks for state management
If port 3001 or 5173 is already in use:
Backend: Edit server/app.js and change PORT constant
Frontend: Vite will automatically suggest an alternative port
- Check that the magnet URL is valid
- Ensure you have write permissions to the downloads folder
- Check server logs for errors
- Ensure both backend and frontend servers are running
- Check browser console for errors
- Verify the Vite proxy is configured correctly in
vite.config.js - Make sure React dependencies are installed (
npm install)
- Ensure PostCSS and Tailwind are properly configured
- Check that
index.csshas the Tailwind directives - Clear cache and restart Vite dev server
MIT
