Skip to content

adam7rans/9layer

Repository files navigation

9layer Logo

9layer — Local Music Library + Player (Backend + Frontend)

Last updated: 2025-10-12

9layer is a local-first music player with a TypeScript backend and a modern Next.js frontend. It plays audio files from your machine that are indexed in a PostgreSQL database.

Important: You must have music files available locally for playback. The in-app YouTube download feature is experimental/untested and may not work yet.

Features

  • Local library playback with queue, ratings, sequential/random modes, and auto-advance
  • Search across artists/albums/tracks with missing-audio indicators
  • Modern UI built with Tailwind and shadcn/ui
  • TypeScript/Fastify backend with Prisma + PostgreSQL
  • REST API integration (WebSocket realtime planned)
  • Listening analytics with top rated tracks, play session stats, and timeline heatmaps
  • In-app toast notifications for rating changes, downloads, and analytics feedback
  • Improved YouTube playlist downloads with cleaned artist/album metadata

Architecture

  • backend/ — Fastify (TypeScript), Prisma ORM, PostgreSQL, maintenance scripts
  • frontend/ — Next.js app (runs on port 3000+ by default)
  • Shared: audio files reside on your filesystem; the database stores metadata, ratings, and file paths

Prerequisites

  • Node.js 18+
  • PostgreSQL 14+
  • ffmpeg (recommended for future/optional conversion)

macOS:

brew install postgresql@14 ffmpeg

Ubuntu/Debian:

sudo apt update
sudo apt install postgresql-14 ffmpeg

Database Setup

Create a database and user (or use setup_postgres.sql in the repo as a reference):

CREATE DATABASE music_player;
CREATE USER music_user WITH PASSWORD 'your_secure_password';
GRANT ALL PRIVILEGES ON DATABASE music_player TO music_user;

Backend Setup (backend/)

  1. Install deps
npm install
  1. Environment Create backend/.env (see .env.example if present):
DATABASE_URL=postgresql://music_user:your_secure_password@localhost:5432/music_player
PORT=8000
CORS_ORIGIN=http://localhost:3004

If you change the frontend port, remember to update CORS_ORIGIN so it matches.

  1. Prisma
npx prisma generate
npx prisma migrate dev
  1. Run the server
npm run dev
# Server listens on http://localhost:8000

Notes:

  • REST endpoints for playback/queue/search are under backend/src/routes/ (e.g. playback.routes.ts).
  • WebSocket support is planned; a polling fallback is used by the frontend today.

Frontend Setup (frontend/)

  1. Install deps
npm install
  1. Environment (if used) Create frontend/.env.local and point to the backend:
NEXT_PUBLIC_API_BASE=http://localhost:8000
  1. Run the app
npm run dev
# By default opens at http://localhost:3000 (falls back to 3001/3002/... if busy)

Adding Music (Required)

You need audio files on disk and corresponding rows in PostgreSQL so the player can find and play them.

Options:

  1. Manual library entries (recommended for now)

    • Place audio files (mp3/webm/opus) on your filesystem.
    • Insert track metadata and absolute file paths into the DB using Prisma Studio:
    npx prisma studio
    • Or write a small seed script to create Artist, Album, Track records.
  2. In-app YouTube downloader (experimental)

    • The UI exposes a download form, but this path is not fully tested and may fail.
    • Album and artist metadata from YouTube playlists is automatically sanitized (removes generic "Playlist" or "Topic" suffixes) for cleaner library entries.
    • If you try it, ensure ffmpeg is installed. Expect bugs; contributions are welcome.

Usage

  • Start servers together
    1. From the repository root, run npm install -g . once to link the command.
    2. Afterwards run 9layer to launch both servers. The backend binds to http://localhost:8000. The frontend will try http://localhost:3000 first and automatically fall back to 3001, 3002, etc. if earlier ports are busy.
    3. Stop both servers any time with 9layer end (from any directory).
  • Manual start (optional)
    • Start backend on 8000 and frontend on 3000 (or the next available open port) individually if you prefer.
  • Play music
    • Open the app, use search to locate tracks, and click play.
    • Player supports previous/next, volume, sequential album order, and auto-advance after a user interaction (browser policy).
  • Analytics dashboard surfaces top rated tracks, play history, and per-track listening totals.

Troubleshooting

  • "No supported source" errors: ensure your file paths are valid, files exist, and the backend returns correct content-type (e.g., audio/mpeg).
  • CORS: confirm CORS_ORIGIN matches whichever frontend URL you are using (e.g. http://localhost:3000) and the frontend points to http://localhost:8000.
  • Test file: open frontend/public/audio-test.html in a browser to confirm your browser can play basic audio.

Maintenance & Tooling

  • Missing audio scan: backend/scripts/flag_missing_audio.ts checks for tracks whose files are gone. Run with npx ts-node backend/scripts/flag_missing_audio.ts --json backend/missing-audio-report.json to produce a report, then rerun with --apply to null-out missing file paths.
  • Portable launcher: npm install -g . exposes the 9layer CLI wrapper to start/stop both dev servers.

Project Structure (key parts)

9layer/
├── backend/
│   ├── prisma/
│   ├── scripts/
│   └── src/
├── frontend/
│   ├── public/
│   └── src/
├── start-dev.sh
├── package.json
└── README.md

Contributing

Issues and PRs are welcome. Areas of focus: downloader reliability, WebSocket realtime updates, library import tools.

License

MIT

About

A local music player

Resources

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •