CoverForm.svelte es el esqueleto compartido (form + enhance + portada
+ mensaje de error + botones) de AlbumForm y PlaylistForm, que quedan
solo con sus campos propios vía snippets `fields` (junto a la
portada) y `extra` (a ancho completo, no está en la spec literal pero
necesario: la descripción del álbum y el selector de visibilidad de
playlist no caben en la columna junto al arte).
ImageDropzone gana `size="hero"` (size-cover-hero + rounded-art-lg) y
un callback `onselect`; la página de subir canción usa ahora este
componente en vez de reimplementar el selector de portada a mano
(envuelto en {#key} para poder resetear tras publicar). Su icono de
posición vacía pasa de 64px a icon-xl (36px), como recomienda el plan.
SegmentedControl.svelte (genérico, N opciones) sustituye el selector
Privada/Pública de PlaylistForm. Chip.svelte sustituye los chips de
filtro de Explorar (selected/count) y los chips de género sugeridos en
"Sin resultados" (href, estilo outline).
@utility field-control en layout.css unifica la cadena de clases
repetida de Input y Textarea.
Verificado con npm run check/build; sin QA visual autenticada (Docker
no disponible en esta sesión).
Musify
Music streaming platform: upload your own tracks, process them asynchronously
(audio transcoded to .m4a, thumbnails generated) and stream them without the
bytes ever going through the API.
backend/ .NET 10 — Domain / Application / Infrastructure / Api / Worker / StreamingGateway / Tests
web-player/ SvelteKit 2 + Svelte 5 + Tailwind 4 web client
deploy/ Docker Compose stacks — self-contained, no wrapper scripts
docs/ What each piece does and why (in Spanish)
dotnet test backend/Musify.slnx # backend/Tests/ — Docker running (Testcontainers: Postgres, SeaweedFS)
Run it
Development (Docker Desktop):
docker compose -f deploy/compose.yml -f deploy/compose.dev.yml up -d
Infrastructure plus stream-ticket keys, database migrations and Zitadel OIDC
provisioning — all as one-shot jobs baked into the compose file. Apps run from
the IDE by default; add --profile apps up -d --build as a second command to
run them in Docker instead.
Production, on a server with a domain:
cp deploy/.env.prod.example deploy/.env.prod # fill in the domain and secrets
docker compose --env-file deploy/.env.prod -f deploy/compose.yml -f deploy/compose.prod.yml up -d
docker compose --env-file deploy/.env.prod -f deploy/compose.yml -f deploy/compose.prod.yml --profile apps up -d --build
Idempotent — run the same commands again to deploy an update. See deploy/README.md for the details, the port map and the production prerequisites.
Components
| Service | Port (dev) | Role |
|---|---|---|
Musify.Api |
5111 | REST API, issues presigned upload URLs and stream tickets |
Musify.StreamingGateway |
8081 | YARP proxy that validates the stream ticket and serves the audio |
Musify.Worker |
— | MassTransit consumers: transcoding, thumbnails |
web-player |
5173 / 3000 | Web client (SvelteKit, server-side OIDC session) |
| Zitadel | 8080 | Identity (OIDC/OAuth2) |
| PostgreSQL / RabbitMQ / SeaweedFS / Jaeger | 59000 / 5672 / 8333 / 16686 | Metadata, messaging, object storage, traces |
More in docs/: architecture, authentication, storage, streaming, media processing, development.