Statify is a full-stack music streaming analytics application for exploring a playlist-scale catalog, playing 30-second previews, managing playlists, and turning listening history into personal music insights.
The project is built around the Spotify Million Playlist Dataset, a normalized PostgreSQL database, a NestJS API, and a Next.js web application.
- Browse tracks, albums, artists, and playlists
- Search and filter a normalized music catalog
- Play 30-second track previews through the web player
- Record listening history
- View personal analytics such as top tracks, top artists, trends, heatmaps, and hidden gems
- Create and manage user playlists
- Admin catalog views for users, tracks, albums, artists, and audit logs
- Authentication with email/password, Argon2 password hashing, JWT, and httpOnly cookies
- Shared DTOs, validation schemas, and types across frontend and backend
| Area | Technology |
|---|---|
| Frontend | Next.js 15, React 19, TypeScript, Tailwind CSS 4 |
| Backend | Node.js, NestJS 10, TypeScript |
| Database | PostgreSQL 16, Prisma 5 |
| Auth | Argon2, JWT, httpOnly cookies |
| Monorepo | pnpm workspaces |
| Validation | Zod |
| Testing | Vitest |
| CI | GitHub Actions |
| Deployment | Vercel for web, Render for API |
statify/
├── apps/
│ ├── api/ # NestJS backend API
│ └── web/ # Next.js frontend
├── packages/
│ ├── db/ # Prisma schema, migrations, seed, ingest scripts
│ └── shared/ # Shared DTOs, schemas, constants, and types
├── docs/ # Architecture notes, API docs, runbooks, ERD
├── scripts/ # Project helper scripts
├── .github/ # CI workflows and GitHub templates
├── docker-compose.yml # Local PostgreSQL setup
├── pnpm-workspace.yaml # Workspace configuration
└── package.json # Root scripts and tooling
Install these before running the project:
- Node.js 22 or higher
- pnpm 9.x
- Docker Desktop, or another PostgreSQL 16 database
- Git
Enable pnpm with Corepack if needed:
corepack enable
corepack prepare pnpm@9.15.0 --activateCreate a local environment file:
cp .env.example .envImportant variables:
DATABASE_URL=postgresql://statify:statify@localhost:5432/statify?schema=public
DIRECT_URL=postgresql://statify:statify@localhost:5432/statify?schema=public
API_PORT=4000
API_BASE_URL=http://localhost:4000
ALLOWED_ORIGINS=http://localhost:3000
JWT_ACCESS_SECRET=replace-me-with-a-32-byte-random-string
JWT_REFRESH_SECRET=replace-me-with-a-different-32-byte-random-string
COOKIE_DOMAIN=localhost
COOKIE_SECURE=false
NEXT_PUBLIC_API_BASE_URL=http://localhost:4000Never commit real secrets or production .env files.
Install dependencies:
pnpm installStart local PostgreSQL:
docker compose up -dGenerate Prisma client:
pnpm --filter @statify/db prisma:generateApply database migrations:
pnpm --filter @statify/db prisma:migrate:devSeed a small demo dataset (catalog, accounts, and listening history) so the app has data on first run:
pnpm --filter @statify/db db:seedRun the frontend and backend:
pnpm devThen sign in with a seeded account to see populated analytics:
| Field | Value |
|---|---|
alex@statify.local |
|
| Password | statify123 |
All five seeded accounts (admin, alex, jordan, sam, riley) share the
same password and have listening history.
Default local URLs:
| Service | URL |
|---|---|
| Web app | http://localhost:3000 |
| API | http://localhost:4000 |
| API health check | http://localhost:4000/healthz |
| Adminer | http://localhost:8080 |
| Command | Purpose |
|---|---|
pnpm dev |
Run local development servers |
pnpm build |
Build all workspace projects |
pnpm typecheck |
Run TypeScript checks |
pnpm lint |
Run ESLint |
pnpm lint:fix |
Auto-fix lint issues where possible |
pnpm format |
Format files with Prettier |
pnpm format:check |
Check Prettier formatting |
pnpm test |
Run tests |
pnpm --filter @statify/db prisma:generate |
Generate Prisma client |
pnpm --filter @statify/db prisma:migrate:dev |
Apply local migrations |
pnpm --filter @statify/db prisma:migrate:deploy |
Apply production migrations |
The database package contains the Prisma schema, migrations, seed scripts, and ingestion utilities.
Common database workflow:
pnpm --filter @statify/db prisma:generate
pnpm --filter @statify/db prisma:migrate:dev
pnpm --filter @statify/db db:seedFor production or hosted databases, use:
pnpm --filter @statify/db prisma:migrate:deployRecommended branch flow:
git checkout dev
git pull origin dev
git checkout -b feat/your-featureBefore pushing:
pnpm format:check
pnpm typecheck
pnpm lint
pnpm buildCommit messages follow Conventional Commits:
<type>(<scope>): <subject>
Examples:
git commit -m "feat(web): add listening history page"
git commit -m "fix(api): validate playlist ownership"
git commit -m "refactor(db): simplify catalog query helpers"Common types:
feat, fix, chore, docs, refactor, test, perf, ci, build, style
GitHub Actions runs checks on pushes and pull requests to main and dev.
The CI pipeline checks:
- dependency installation
- Prisma client generation
- TypeScript type checking
- ESLint
- Prettier formatting
- production build
The project is designed for split deployment:
| Service | Platform |
|---|---|
| Web frontend | Vercel |
| API backend | Render |
| Database | PostgreSQL / Neon |
Production environment variables must be configured separately in the deployment dashboards.
Recommended production settings:
NODE_ENV=production
COOKIE_SECURE=true
ALLOWED_ORIGINS=https://your-web-domain.com
NEXT_PUBLIC_API_BASE_URL=https://your-api-domain.com- Aykhan Ahmadzada
- Elshad Toklayev
- Rahila Dashdiyeva
- Eljan Mammadli
MIT License.