π΅ Portify
The Universal Playlist Converter

Portify is an open-source tool that breaks down the walled gardens of music streaming. It allows users to seamlessly convert and synchronize their carefully curated playlists across multiple music platforms β moving your music freely between services like Spotify, YouTube Music, and more.
β¨ Built with AI: This entire application was vibe-coded from scratch with the help of Antigravity and the Gemini 3.1 Pro model.
β¨ Key Features
- Real-Time Streaming Conversion: ConnectRPC leverages Server-Sent Events (SSE) to stream granular track-by-track conversion progress directly into a live React progress bar.
- Stateless Authentication: Completely database-free. OAuth 2.0 flows are securely brokered through Go and pinned to the browser's lightweight
sessionStorage.
- Dynamic Playlist Generation:
Create New destination playlists, or fetch your existing provider playlists to Append tracks without overwriting.
- Robust Error Handling: Unmatched songs are precisely flagged in a collapsible UI element, and expired OAuth credentials are silently invalidated under the hood.
π Current Status
- Core Canonical Model: Protobuf-based universal data structures for cross-platform track translation.
- Spotify Adapter (Source): Full support for fetching tracks from public and private Spotify playlists.
- YouTube Adapter (Destination): Algorithmic track matching and YouTube playlist generation.
- React Frontend: Web UI with OAuth login, provider selection, playlist browsing, and streaming conversion progress.
- CI/CD Pipeline: Automated GitHub Actions for linting, testing, and build verification on every push and PR.
- Security Scanning: CodeQL Advanced Security analysis and Dependabot dependency monitoring.
- Additional Providers: Apple Music, Tidal, Amazon Music, etc.
π οΈ Technology Stack
| Layer |
Technology |
| Backend |
Go 1.25, ConnectRPC, Protocol Buffers |
| Frontend |
React 19, Vite 7, TypeScript 5.9, Vitest |
| Authentication |
OAuth 2.0 (Spotify Web API, Google/YouTube Data API v3) |
| Linting |
go vet + gofmt (Backend), ESLint + TypeScript-ESLint (Frontend) |
| CI/CD |
GitHub Actions, CodeQL, Dependabot |
| Protobuf Tooling |
Buf (generation, linting, formatting) |
π Project Structure
portify/
βββ cmd/
β βββ server/ # Main Go backend entrypoint
β βββ testspotify/ # Spotify adapter integration test harness
β βββ testyoutube/ # YouTube adapter integration test harness
βββ internal/
β βββ adapters/
β β βββ spotify/ # Spotify API adapter (source)
β β βββ youtube/ # YouTube API adapter (destination)
β β βββ mock/ # Mock adapter for unit testing
β βββ domain/ # Core provider interface & canonical model
β βββ server/ # ConnectRPC service handler (converter.go)
βββ proto/ # Protobuf service & model definitions
βββ gen/ # Auto-generated Go & TypeScript code (buf generate)
βββ frontend/ # React + Vite + TypeScript SPA
β βββ src/
βββ .github/
β βββ workflows/
β β βββ ci.yml # CI/CD Pipeline (Go + React)
β β βββ codeql.yml # CodeQL security scanning
β βββ dependabot.yml # Automated dependency updates
βββ .githooks/
β βββ pre-commit # Local pre-commit hook (format + lint)
βββ Makefile # Developer commands (format, lint, test, build)
βββ setup.sh # Bootstrap script (macOS/Linux/WSL)
βββ setup.ps1 # Bootstrap script (Windows PowerShell)
βββ .env.example # Template for backend OAuth credentials
π Environment Configuration
The application uses .env files for credentials and feature toggles.
Backend (/.env)
Create a .env file in the project root with your OAuth developer keys:
SPOTIFY_ID="your_spotify_client_id"
SPOTIFY_SECRET="your_spotify_client_secret"
YOUTUBE_ID="your_google_cloud_client_id"
YOUTUBE_SECRET="your_google_cloud_client_secret"
FRONTEND_URL="http://127.0.0.1:5175/"
Important: The FRONTEND_URL must exactly match the authorized Redirect URI configured in both the Spotify and Google Cloud developer consoles (including the trailing slash).
Frontend (/frontend/.env)
# Set to 'true' to display a debug overlay showing raw state and sessionStorage.
VITE_SHOW_DEBUG_PANEL=false
π Getting Started
Prerequisites
1. Quick Setup (Recommended)
The bootstrap script installs developer tools (buf), configures git hooks, scaffolds .env files, and installs frontend dependencies:
make setup
2. Generate Protobufs
Generate Go server stubs and TypeScript ConnectRPC client code from .proto definitions:
buf generate
3. Run the App
Start both the Go backend and React frontend with a single command:
make dev
This launches the ConnectRPC server on http://localhost:8080 and the Vite dev server on http://127.0.0.1:5175 concurrently. Vite proxies all /converter.v1.ConverterService/* requests to the Go backend automatically. Press Ctrl+C to stop both.
You can also start them individually with make dev-backend or make dev-frontend.
π§ͺ Testing & Quality
Makefile Commands
| Command |
Description |
make setup |
Bootstrap the full developer environment |
make dev |
Start both backend + frontend in one terminal |
make dev-backend |
Start only the Go backend server |
make dev-frontend |
Start only the Vite dev server |
make format |
Format Go files (gofmt -s) and Protobufs (buf format) |
make lint |
Run go vet and buf lint |
make test |
Run Go backend unit tests with coverage |
make build |
Compile the Go server binary |
make frontend-lint |
Run ESLint on the React frontend |
make frontend-test |
Run Vitest unit tests |
make frontend-build |
Production build of the React app |
make all |
Run format β lint β test β build |
CI/CD Pipeline
Every push and pull request to master triggers two parallel GitHub Actions jobs:
- Go Backend & Lint β Sets up Go 1.25, runs
buf lint, gofmt formatting check, go vet, and go test with coverage.
- React Frontend & Lint β Sets up Node.js 20, runs
npm ci, ESLint, Vitest, and a production build compilation check.
Pre-Commit Hook
The make setup script configures a local git hook (.githooks/pre-commit) that runs formatting, go vet, buf lint, and frontend ESLint checks before every commit. Use --no-verify to skip when needed.
π License
This project is licensed under the MIT License.