Added Readme
This commit is contained in:
parent
a515df90de
commit
41418679bd
|
|
@ -0,0 +1,140 @@
|
|||
# Tunes
|
||||
|
||||
A self-contained music website: browse and listen to songs and playlists,
|
||||
with user accounts and an admin upload UI. Everything runs from a single
|
||||
Node.js process with an embedded SQLite database and local media storage —
|
||||
no external services required.
|
||||
|
||||
## Features (v1)
|
||||
|
||||
- **Public browse & listen**
|
||||
- Home page with featured playlists and recently added songs
|
||||
- Paginated, searchable song list (title / artist / album)
|
||||
- Playlist grid and detail view with "Play all"
|
||||
- Persistent bottom-of-page audio player with queue support
|
||||
- HTTP Range streaming, so seeking/scrubbing works correctly
|
||||
- **User accounts**
|
||||
- Email + password registration (argon2id hashing)
|
||||
- Login / logout with SQLite-backed sessions (survive restarts)
|
||||
- Account page: update display name, change password
|
||||
- CSRF protection on all state-changing routes
|
||||
- **Admin**
|
||||
- Upload songs with cover art; title/artist/album/genre/year metadata
|
||||
- Duration auto-extracted from the audio file
|
||||
- Create and edit playlists, add/remove tracks
|
||||
- Toggle songs and playlists between public and private
|
||||
- First user who registers with `ADMIN_BOOTSTRAP_EMAIL` is auto-promoted
|
||||
to admin (only while no admin exists yet)
|
||||
|
||||
## Roadmap (not in v1)
|
||||
|
||||
- Generate new music via an external API from within the app
|
||||
- Let logged-in users publish their own songs and create playlists
|
||||
- Tune into streaming radio stations
|
||||
|
||||
## Tech stack
|
||||
|
||||
- **Node.js + Express 4** — server and routing
|
||||
- **SQLite** via `better-sqlite3` — embedded database, WAL mode
|
||||
- **EJS** + `express-ejs-layouts` — server-rendered views
|
||||
- **argon2** — password hashing
|
||||
- **express-session** + `better-sqlite3-session-store` — persistent sessions
|
||||
- **multer** — file uploads (audio + cover art)
|
||||
- **music-metadata** — extract duration from uploaded audio
|
||||
- **csrf-sync**, **zod**, **pino** — CSRF, validation, logging
|
||||
- **htmx** (vendored) — small sprinklings of interactivity, no build step
|
||||
|
||||
## Getting started
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Node.js 18+ (tested on 18.19)
|
||||
- npm
|
||||
|
||||
### Install and run
|
||||
|
||||
```bash
|
||||
git clone <your-repo-url> tunes
|
||||
cd tunes
|
||||
npm install
|
||||
cp .env.example .env
|
||||
# Edit .env:
|
||||
# SESSION_SECRET=<a long random string>
|
||||
# ADMIN_BOOTSTRAP_EMAIL=<your email>
|
||||
node server.js
|
||||
```
|
||||
|
||||
The server boots at http://localhost:3000 and runs database migrations
|
||||
automatically against `tunes.db` in the project root.
|
||||
|
||||
For auto-reload during development:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Creating the first admin
|
||||
|
||||
1. Open http://localhost:3000/register
|
||||
2. Register with the email you set as `ADMIN_BOOTSTRAP_EMAIL` in `.env`.
|
||||
That first matching registration is automatically given the `admin` role.
|
||||
3. Once logged in, visit `/admin/songs` to upload audio and `/admin/playlists`
|
||||
to create playlists.
|
||||
|
||||
Any subsequent registrations are normal users.
|
||||
|
||||
### Adding music
|
||||
|
||||
1. Go to `/admin/songs/new`
|
||||
2. Fill in title, artist, and (optionally) album/genre/year
|
||||
3. Choose an audio file (mp3, m4a, ogg, flac, wav, opus, webm — up to 100 MB)
|
||||
4. Optionally add a cover image
|
||||
5. Check "Public" so visitors can see and play it, then click **Upload**
|
||||
|
||||
Uploaded files live under `media/audio/` and `media/covers/`. The database
|
||||
stores relative paths, so you can move the whole project folder freely as
|
||||
long as `media/` and `tunes.db` stay together.
|
||||
|
||||
## Configuration
|
||||
|
||||
All settings come from environment variables (loaded from `.env` via
|
||||
`dotenv`):
|
||||
|
||||
| Variable | Default | Purpose |
|
||||
| --- | --- | --- |
|
||||
| `PORT` | `3000` | HTTP port |
|
||||
| `SESSION_SECRET` | *(insecure default)* | Session cookie signing secret — **set this in production** |
|
||||
| `ADMIN_BOOTSTRAP_EMAIL` | *(unset)* | Email that auto-becomes admin on first registration |
|
||||
| `DB_PATH` | `./tunes.db` | SQLite database file |
|
||||
| `MEDIA_DIR` | `./media` | Root directory for audio and cover uploads |
|
||||
|
||||
## Project layout
|
||||
|
||||
```
|
||||
tunes/
|
||||
├── server.js # entry point: loads env, runs migrations, starts app
|
||||
├── db/
|
||||
│ ├── index.js # SQLite connection + migration runner
|
||||
│ └── migrations/*.sql # schema migrations
|
||||
├── src/
|
||||
│ ├── app.js # Express wiring (sessions, CSRF, views, routes)
|
||||
│ ├── middleware/auth.js # requireUser / requireAdmin
|
||||
│ ├── routes/
|
||||
│ │ ├── public.js # /, /songs, /playlists, /stream/:id
|
||||
│ │ ├── auth.js # /register, /login, /logout
|
||||
│ │ ├── account.js # /account
|
||||
│ │ └── admin.js # /admin/songs, /admin/playlists
|
||||
│ ├── services/ # users, songs, playlists (DB access)
|
||||
│ └── views/ # EJS templates
|
||||
├── public/ # static CSS, JS, vendored htmx
|
||||
└── media/ # runtime audio + cover uploads (git-ignored)
|
||||
```
|
||||
|
||||
## Data and backups
|
||||
|
||||
Everything you care about lives in two places:
|
||||
|
||||
- `tunes.db` — users, songs, playlists, sessions
|
||||
- `media/` — audio files and cover art
|
||||
|
||||
Back up both together to preserve the full state of the site.
|
||||
Loading…
Reference in New Issue