Admin ebfd41b160 Add track publication, album types, optional track pictures and batch upload URLs
Tracks
- Track.IsPublished (migration marks existing tracks as published). New
  tracks are created unpublished.
- PUT /tracks/{id}/published and PUT /tracks/published change the flag;
  publishing requires completed audio processing (the batch endpoint
  reports skipped tracks).
- An unpublished track is only visible to its owner. A WherePublished /
  VisibleTo filter is applied to search, genres, listening history, last
  listened, likes, mixes, album and playlist contents and counts, recently
  listened albums, public user tracks, track details and stream tickets.
- isPublished is part of the track responses, GET /tracks/users/{userId}
  accepts a published filter and status-counts reports published and
  unpublished totals.
- CreateTrackRequest.pictureIntentId is optional: without it the track
  uses the album cover or the preset picture and no picture processing
  runs. CreateTrackResourcesEvent carries nullable picture fields, so
  queues must be drained before deploying.
- POST /tracks/upload-urls accepts an audios list and one optional picture
  shared by all of them, and returns an intent per file. The upload intent
  limits are raised so a batch fits.

Albums
- AlbumType (Album, EP, Single) on create, update and responses.
- CreateAlbumRequest.trackIds creates the album and links the tracks in a
  single save.
2026-09-25 01:37:55 +02:00
2026-09-24 18:02:52 +02:00

Musify

A music streaming app. Upload your own tracks, organize them into playlists and albums, and stream them back with a web player built around your listening habits: auto-generated mixes, a home feed, search, likes, and an Explore page for finding something new.

What it does

  • Upload and organize your own music: tracks, albums, cover art, artist credits.
  • Playlists, likes, and a "recently played" history.
  • Mixes, playlists generated automatically from what you actually listen to.
  • Explore, genre browsing and search across tracks, albums, playlists and people.
  • Real streaming, not just file downloads: seek, queue, shuffle, repeat.
  • Accounts via OIDC login, with an optional anonymous listening mode.
  • Light and dark themes, and a layout that works on both desktop and mobile.

How it's built

Backend: .NET 10, split into a REST API, a background worker, and a dedicated streaming gateway.

  • Clean architecture (Domain / Application / Infrastructure) with CQRS (Mediator) and ErrorOr results.
  • PostgreSQL via EF Core for metadata. RabbitMQ and MassTransit handle async processing (audio transcoding, thumbnails) with saga-based rollback.
  • SeaweedFS (S3-compatible) for file storage. Uploads and downloads go straight between the client and storage, never through the API.
  • ffmpeg for audio transcoding, ImageSharp for thumbnails.
  • A YARP reverse proxy that streams the audio and checks a signed, short-lived ticket on every request.
  • Zitadel for login (OIDC/OAuth2).

Web client: SvelteKit 2 on Svelte 5 (runes), TypeScript, Tailwind 4. The session lives on the server, so the backend access token never reaches the browser.

Infrastructure: Musify's own apps run from Docker Compose (dev and production overlays). Postgres, RabbitMQ, SeaweedFS, Zitadel and Jaeger are shared infrastructure that lives in a separate Infrastructure git repository, used by Musify and by other projects that need the same OIDC provider and object storage.

Project layout

backend/      .NET solution: Api, Worker, StreamingGateway, and the shared Domain/Application/Infrastructure
web-player/   the SvelteKit web client
deploy/       Docker Compose stacks for dev and production
docs/         architecture notes, one file per area

Postgres, Zitadel, SeaweedFS, RabbitMQ and Jaeger are not part of this layout. They live in the separate Infrastructure repository instead.

Digging deeper

docs/ covers how each piece works and why: architecture, authentication, storage, streaming, media processing, and the local dev setup. deploy/README.md has the full instructions for running the stack, in development or on a production server.

S
Description
No description provided
Readme
5.1 MiB
Languages
C# 73.1%
Svelte 12.1%
TypeScript 9%
Kotlin 4.1%
CSS 1.1%
Other 0.6%