- TypeScript 37.6%
- Rust 34.8%
- Vue 22.9%
- Shell 2.6%
- CSS 1%
- Other 1.1%
| .husky | ||
| backend | ||
| deploy | ||
| docs | ||
| frontend | ||
| scripts | ||
| .dockerignore | ||
| .gitignore | ||
| docker-compose.yml | ||
| Dockerfile | ||
| package.json | ||
| pnpm-workspace.yaml | ||
| README.md | ||
| TODO.md | ||
| turbo.json | ||
TOCATA
Overview
Tocata is a modern web-based frontend for the MPD (Music Player Daemon) server. Built with a focus on visual music collection management, it leverages a database generated by beets combined with a custom SQLite database to provide a rich, album-centric browsing experience.
The application transforms your music library into an interactive visual collection, allowing you to explore and manage your albums with powerful filtering capabilities by genre, release year, artist, title, and more. Unlike traditional MPD clients, Tocata emphasizes the album as the fundamental unit, creating a more natural and engaging way to interact with your music collection.
Features
Responsive Design
Tocata offers a fully responsive interface that adapts seamlessly across devices - from desktop to mobile.
Advanced Filtering
Navigate your music library with sophisticated filtering options. Search and filter by artist, album, genre, year, and more to quickly find exactly what you're looking for.
Album Detail View
Get comprehensive information about each album with a dedicated detail view that displays track listings, metadata, and playback controls.
Floating Player Controls
Access playback controls directly from the album list view with a floating player that shows current track information and progress.
Vim-Style Navigation
Power users can navigate the album grid using Vim-inspired keyboard shortcuts, making it fast and efficient to browse and select albums without touching the mouse.
Technical Stack
Tocata is built as a modern monorepo managed by pnpm and Turbo, enabling efficient development workflows and optimized build processes.
Backend (Rust)
The backend is a high-performance REST API built with Rust, designed for speed, safety, and reliability.
Core Technologies:
- Axum - Modern async web framework with excellent type safety
- Tokio - Asynchronous runtime powering concurrent request handling
- SQLx - Compile-time verified SQL queries with SQLite
- mpd_client - Direct integration with Music Player Daemon
Security & Authentication: The backend implements a robust JWT-based authentication system with:
- Secure HTTP-only cookies - Tokens stored in HTTP-only cookies to prevent XSS attacks
- Access & Refresh token pattern - Short-lived access tokens (15 minutes) with long-lived refresh tokens (30 days)
- Token rotation - Automatic token refresh for seamless user experience
- HTTPS/TLS support - Built-in TLS using rustls for secure communication
Additional Features:
- CORS middleware - Configured for cross-origin requests
- Structured logging - Using tracing for observability
- Type-safe API - TypeScript bindings auto-generated from Rust types using ts-rs
Frontend (Vue 3)
A modern, reactive single-page application built with the Vue 3 Composition API.
Core Technologies:
- Vue 3 - Progressive JavaScript framework with Composition API
- Vue Router - Client-side routing
- Pinia - Intuitive state management
- TanStack Query - Powerful async state management for server data
UI & Styling:
- Tailwind CSS 4 - Utility-first CSS framework
- Reka UI - Accessible, unstyled UI components
- @heroicons/vue - Beautiful hand-crafted SVG icons
- @radix-ui/colors - Professional color system
Developer Experience:
- Vite - Lightning-fast build tool and dev server
- TypeScript - Type-safe development
- Vitest - Fast unit testing framework
- ESLint + Oxlint - Code quality and linting
- Prettier - Code formatting
Data & API:
Project Structure
tocata/
├── backend/ # Rust/Axum API server
│ ├── src/
│ │ ├── routes/ # API endpoints
│ │ ├── db/ # Database layer (SQLite)
│ │ └── utils/ # Utilities & helpers
│ └── Cargo.toml
├── frontend/ # Vue 3 SPA
│ ├── src/
│ │ ├── features/ # Feature-based modules
│ │ ├── shared/ # Shared components & utilities
│ │ └── router.ts
│ └── package.json
├── docs/
│ └── assets/ # Documentation images
├── scripts/ # Build & deployment scripts
└── turbo.json # Turbo monorepo config
Getting Started
Prerequisites
- Node.js 20.19+ or 22.12+
- Rust 1.70+ (2024 edition)
- pnpm 10.28+
- MPD server running and accessible
- beets music library tool (optional, for database generation)
Installation
- Clone the repository:
git clone https://github.com/yourusername/tocata.git
cd tocata
- Install dependencies:
pnpm install
- Set up environment variables:
# Backend (.env in backend/)
JWT_SECRET=your-secret-key
DATABASE_URL=sqlite:./db/tocata.db
MPD_HOST=localhost
MPD_PORT=6600
# Frontend (.env in frontend/)
VITE_APP_API_HOST=https://localhost:3000
Development
Run both frontend and backend in development mode:
pnpm dev
Or run them separately:
# Backend only
cd backend && pnpm dev
# Frontend only
cd frontend && pnpm dev
Configuration for Raspberry Pi
Before building for Raspberry Pi, create the environment configuration file:
# Copy template
cp deploy/.env.pi.example deploy/.env.pi
# Edit with your actual Raspberry Pi values
nano deploy/.env.pi
Important: The .env.pi file contains secrets and environment-specific paths. It should never be committed to the repository (already excluded in .gitignore).
Required values to configure:
JWT_SECRET- Strong random secret for JWT signingASSETS_COVER_DIR- Path to album covers on RPi (e.g.,/opt/tocata/covers)DB_BEETS_ABSOLUTE_PATH- Path to beets database on RPiMUSIC_ABSOLUTE_PATH- Path to music library on RPiALLOWED_CORS_URL- Frontend URL (e.g.,http://raspberrypi.local:8080)MPD_TOCATA_URL- MPD server address (usuallylocalhost:6600)
Building for Production
Build native binary:
pnpm build:release
Build for Raspberry Pi (ARM64):
pnpm build:pi
Docker Build (Recommended for Cross-Compilation)
For building the Raspberry Pi version on macOS (or any platform without aarch64-linux-gnu toolchain), use the Docker-based build environment:
Prerequisites
- Docker Desktop with arm64 support (native on Apple Silicon)
First-Time Setup
Build the Docker image (takes ~10-15 minutes on first run):
docker compose build
Building for Raspberry Pi Zero 2W
Use the automated build script:
bash scripts/docker-build-pi.sh
To rebuild the Docker image:
bash scripts/docker-build-pi.sh --rebuild
The build process generates:
deploy/out/- Assembled files ready for deploymentdeploy/releases/tocata-{version}-aarch64.tar.gz- Compressed release package
Transfer to your Raspberry Pi:
scp deploy/releases/tocata-*.tar.gz pi@raspberrypi:/tmp/
# On Raspberry Pi
ssh pi@raspberrypi
cd /tmp
tar -xzf tocata-*.tar.gz -C /opt/tocata/
Running Tests
Execute all tests (frontend + backend) inside the Docker container:
bash scripts/docker-test.sh
Or run tests individually:
# Frontend tests
docker compose run --rm tocata-builder pnpm --filter frontend test
# Backend tests
docker compose run --rm tocata-builder cargo test --manifest-path backend/Cargo.toml
Interactive Development
Open a shell inside the container for manual operations:
bash scripts/docker-shell.sh
Inside the container you have access to:
cargo- Rust toolchain with aarch64-unknown-linux-gnu targetpnpm- Node.js package manageraarch64-linux-gnu-gcc- Cross-compilation toolchain
Verifying Build Output
Check that the binary was correctly cross-compiled:
file deploy/out/bin/tocata-service
# Should output: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV)...
# Check the release package
ls -lh deploy/releases/
# Should show: tocata-1.0.0-aarch64.tar.gz
Cache Management
Docker volumes persist build artifacts between runs for faster builds:
tocata-cargo-cache- Rust dependenciestocata-pnpm-store- Node.js packagestocata-target-cache- Compiled Rust artifacts
To clean all caches:
docker compose down -v
License
ISC
Built with ❤️ for music lovers who appreciate both great sound and great code.
