{"id":49085717,"url":"https://github.com/scobru/shogun-tunecamp","last_synced_at":"2026-04-20T15:33:59.479Z","repository":{"id":329594443,"uuid":"1080471932","full_name":"scobru/shogun-tunecamp","owner":"scobru","description":"A modern static site generator for musicians and music labels, written in JavaScript/TypeScript.","archived":false,"fork":false,"pushed_at":"2026-04-15T07:40:19.000Z","size":117654,"stargazers_count":2,"open_issues_count":3,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-15T09:37:29.331Z","etag":null,"topics":["audio","bandcamp","indie","music","publishing","self-hosted","static-site-generator"],"latest_commit_sha":null,"homepage":"https://tunecamp.vercel.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/scobru.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-21T12:22:39.000Z","updated_at":"2026-04-15T07:40:24.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/scobru/shogun-tunecamp","commit_stats":null,"previous_names":["scobru/tunecamp","scobru/shogun-tunecamp"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/scobru/shogun-tunecamp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scobru%2Fshogun-tunecamp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scobru%2Fshogun-tunecamp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scobru%2Fshogun-tunecamp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scobru%2Fshogun-tunecamp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/scobru","download_url":"https://codeload.github.com/scobru/shogun-tunecamp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scobru%2Fshogun-tunecamp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32053289,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-20T11:35:06.609Z","status":"ssl_error","status_checked_at":"2026-04-20T11:34:48.899Z","response_time":94,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["audio","bandcamp","indie","music","publishing","self-hosted","static-site-generator"],"created_at":"2026-04-20T15:33:57.994Z","updated_at":"2026-04-20T15:33:59.461Z","avatar_url":"https://github.com/scobru.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"./logo.svg\" alt=\"Tunecamp Logo\" width=\"150\" height=\"150\"\u003e\n  \u003ch1\u003eTunecamp\u003c/h1\u003e\n  \u003cp\u003e\u003cstrong\u003eA self-hosted, federated music platform for independent artists and labels.\u003c/strong\u003e\u003c/p\u003e\n\u003c/div\u003e\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n## Why This Exists\n\nStreaming platforms take significant cuts from artists and lock their communities into walled gardens. Tunecamp allows you to host your own music with a beautiful web interface, fully compatible with existing Subsonic mobile apps. It connects you to the Fediverse (via ActivityPub) and uses a hybrid federation model—GunDB for instance discovery and identity, direct HTTP for content sharing—giving artists ownership of their distribution without sacrificing reach.\n\n## Quick Start\n\nThe fastest way to run Tunecamp is using Docker Compose.\n\n```bash\n# 1. Clone the repository\ngit clone https://github.com/scobru/shogun-tunecamp.git\ncd shogun-tunecamp\n\n# 2. Edit docker-compose.yml to set your music directory\n#    Change /path/to/your/music to your actual music folder\n\n# 3. Start the server in the background\ndocker-compose up -d --build\n\n# 4. Access the dashboard\n# Open http://localhost:1970 in your browser\n```\n\n\u003e **First Run**: Tunecamp will create a default admin account (`admin`/`admin`). You will be prompted to change the password on first login.\n\n## Features\n\n### Core\n- 🎵 **Audio-first**: Automatically reads metadata, generates waveforms, and processes cover art from your audio files (MP3, FLAC, WAV, etc.).\n- 🖥️ **Streaming Server**: Personal streaming server with a modern, responsive web interface.\n- 🎨 **Customizable**: Theming, background images, cover images, site branding, and per-artist profiles.\n- 🔍 **Full-text Search**: Search across artists, albums, and tracks with fuzzy matching.\n\n### Decentralization \u0026 Federation\n- 🔐 **GunDB Identity**: Cryptographic keypairs (SEA) for signing, identity roaming across instances, and decentralized comments/stats.\n- 📡 **ActivityPub**: Connect with the Fediverse (Mastodon, Funkwhale, Pleroma). Artists are ActivityPub actors with followers, posts, and release broadcasts.\n- 🌐 **Community Network**: Discover other Tunecamp instances via GunDB signaling, then fetch catalogs directly via HTTP REST for always-fresh content.\n- 🔗 **HTTP Federation**: Instances expose a public `/api/catalog` endpoint, enabling direct instance-to-instance content discovery without intermediary replication.\n\n### Streaming \u0026 Clients\n- 🔊 **Subsonic/OpenSubsonic API**: Full compatibility (v1.16.1) with mobile apps like DSub, Symfonium, Tempo, Substreamer, Amuse, and play:Sub.\n- 🎧 **Built-in Player**: Waveform visualization, queue management, lyrics display, and keyboard shortcuts.\n- 📋 **Playlists**: Create and share playlists (public/private).\n\n### Web3 \u0026 Monetization\n- 💰 **On-chain Payments**: NFT-based purchases (ERC-1155) with USDC and ETH on the Base Network.\n- 🏭 **Factory Contract**: Self-hosters deploy their own NFT + Checkout contract instances via EIP-1167 minimal proxies.\n- 🔑 **Unlock Codes**: Generate and distribute access codes for gated releases.\n- 👛 **Wallet Integration**: Client-side wallet derived from GunDB credentials (no private key leaves the browser).\n\n### Administration\n- 🛡️ **Role-Based Access (RBAC)**: Root Admin, Admin, and Artist/User roles with granular permissions. See [ROLES.md](ROLES.md).\n- 📤 **Bulk Upload**: Multi-file upload with automatic metadata extraction and album assignment.\n- ✏️ **Batch Editing**: Edit cover art, metadata, and pricing across multiple tracks at once.\n- 📁 **File Browser**: Browse the server filesystem and attach files to the library.\n- 💾 **Backup \u0026 Restore**: Full database backup/restore via the admin panel or CLI.\n- 📊 **Statistics**: Play counts, listening time, top tracks/artists, and library stats.\n\n### Content Acquisition\n- 🔎 **Content Search**: Search Soulseek from the admin panel with one-click import.\n- 🏷️ **Discogs Metadata**: Match tracks against the Discogs database for accurate tagging.\n\n### Deployment\n- 📦 **Docker Ready**: Multi-stage Dockerfile with health checks, optimized for production.\n- 🚀 **CapRover Support**: One-click deploy with automatic cache busting.\n- 📱 **PWA Support**: Installable as a Progressive Web App with offline service worker.\n\n## Installation \u0026 Setup\n\n### Using Docker Compose (Production)\n\n**Prerequisites**: Docker 20+, Docker Compose\n\n```bash\ngit clone https://github.com/scobru/shogun-tunecamp.git\ncd shogun-tunecamp\n\n# Edit docker-compose.yml to configure your music path and environment\ndocker-compose up -d --build\n```\n\n### Using Node.js (Development)\n\n**Prerequisites**: Node.js 18+, npm 9+, FFmpeg installed\n\n```bash\n# Clone the repository\ngit clone https://github.com/scobru/shogun-tunecamp.git\ncd shogun-tunecamp\n\n# Install dependencies and build backend\nnpm install\nnpm run build\n\n# Install frontend dependencies and build\ncd webapp\nnpm install\ncd ..\n\n# Start the server (runs migrations automatically)\nnpm start\n```\n\nFor development with hot-reload:\n```bash\n# Terminal 1: Watch backend TypeScript\nnpm run dev\n\n# Terminal 2: Watch frontend (Vite dev server with HMR)\ncd webapp \u0026\u0026 npm run dev\n```\n\n### CLI Usage\n\nAfter building, the CLI is available:\n\n```bash\n# Start the server\nnpx tunecamp server ./music --port 1970 --db ./tunecamp.db\n\n# Backup the database\nnpx tunecamp backup ./backups --db ./tunecamp.db\n\n# Restore from a backup\nnpx tunecamp restore ./backups/tunecamp-2026-01-01.db --db ./tunecamp.db --force\n```\n\n### Configuration\n\nConfiguration is managed via environment variables (or an `.env` file).\n\n| Variable | Description | Default |\n|:---------|:------------|:--------|\n| `TUNECAMP_PORT` | Server listen port | `1970` |\n| `TUNECAMP_MUSIC_DIR` | Path to the music library | `./music` |\n| `TUNECAMP_DB_PATH` | Path to the SQLite database | `./tunecamp.db` |\n| `TUNECAMP_JWT_SECRET` | JWT signing secret (auto-generated if not set) | *auto* |\n| `TUNECAMP_ADMIN_USER` | Default admin username | `admin` |\n| `TUNECAMP_ADMIN_PASS` | Default admin password | `admin` |\n| `TUNECAMP_PUBLIC_URL` | Public HTTPS URL (required for ActivityPub federation) | — |\n| `TUNECAMP_SITE_NAME` | Human-readable instance name | `My TuneCamp Server` |\n| `TUNECAMP_GUN_PEERS` | Comma-separated GunDB relay peer URLs | — |\n| `VITE_GUN_PEERS` | Same as above, for the frontend build | — |\n| `TUNECAMP_RELAY_URL` | ActivityPub relay URL for broadcasting | — |\n| `TUNECAMP_CORS_ORIGINS` | Comma-separated allowed CORS origins | *all* |\n| `TUNECAMP_RPC_URL` | Base Network RPC endpoint (Web3) | `https://mainnet.base.org` |\n| `TUNECAMP_OWNER_ADDRESS` | Ethereum wallet address for payment collection | — |\n| `TUNECAMP_CURRENCY_CONTRACT` | ERC-20 token contract (USDC on Base) | `0x833589...02913` |\n| `TUNECAMP_DOWNLOAD_DIR` | Directory for soulseek downloads | `/data/downloads` |\n| `DISCOGS_TOKEN` | Discogs API token for metadata matching | — |\n\n## API \u0026 Integrations\n\n### Subsonic API\n\nTunecamp exposes a full Subsonic API (version 1.16.1) at `/rest`. This allows you to use your Tunecamp library with major mobile clients like DSub, Symfonium, Tempo, and Substreamer.\n\n**Connection settings for your app:**\n- **Server URL**: `https://your-server.com`\n- **Username/Password**: Your Tunecamp credentials\n\n\u003e **Roaming Users**: To use Subsonic on a new instance, first log in via the web interface to trigger lazy account creation.\n\nSee the [Subsonic API Reference →](./docs/SUBSONIC.md)\n\n### REST API\n\nThe platform is driven by a REST JSON API under `/api/`.\n\nSee the [OpenAPI Reference →](./docs/openapi.yml)\n\n### Nginx Reverse Proxy\n\nFor production deployments, using Nginx as a reverse proxy is recommended for SSL and WebSocket support.\n\nSee the [Nginx Configuration Guide →](./docs/NGINX.md)\n\n### Federation \u0026 Network Architecture\n\nTunecamp uses a **hybrid federation model**:\n\n| Layer | Protocol | Purpose |\n|:------|:---------|:--------|\n| **Discovery** | GunDB | Instance URL signaling — announces presence to the network |\n| **Identity** | GunDB SEA | Cryptographic keypairs, wallet derivation, comments, play/like stats |\n| **Content** | HTTP REST | Direct catalog fetching between instances (`/api/catalog`) |\n| **Social** | ActivityPub | Artist federation, followers, release broadcasts, posts |\n\nInstances register their URL on GunDB. The Network page then fetches catalogs directly from each discovered instance via HTTP, ensuring content is always fresh and eliminating stale CRDT data. ActivityPub handles artist-level social features and is compatible with Mastodon and Funkwhale.\n\nSee the [Federation Guide →](./docs/FEDERATION.md)\n\n### Smart Contracts\n\nThe Web3 payment system uses three Solidity contracts deployed on the Base Network:\n- **TuneCampFactory**: Deploys per-instance NFT + Checkout contracts via EIP-1167 minimal proxies.\n- **TuneCampNFT**: ERC-1155 multi-role tokens (License, Ownership, Collectible) for music tracks.\n- **TuneCampCheckout**: Handles purchases with ETH or USDC with a configurable artist/platform revenue split (85/15 default, 100% for Pro artists).\n\nSee the [contracts/](./contracts/) directory.\n\n## Roles \u0026 Permissions\n\nTunecamp uses a role-based access control (RBAC) system with three tiers:\n- **Root Admin**: Full system control, user management, server identity keys.\n- **Admin**: Federation management, content moderation, own releases.\n- **Artist/User**: Upload music, manage own releases, use Subsonic, manage profile.\n\nSee the [Roles \u0026 Permissions Guide →](ROLES.md)\n\n## Contributing\n\nContributions are welcome! Please open an issue or pull request on GitHub.\n\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feature/my-feature`)\n3. Commit your changes (`git commit -m 'Add my feature'`)\n4. Push to the branch (`git push origin feature/my-feature`)\n5. Open a Pull Request\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscobru%2Fshogun-tunecamp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fscobru%2Fshogun-tunecamp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscobru%2Fshogun-tunecamp/lists"}