Translate all of docs/ from Spanish to English and rewrite the root README as a short project overview instead of a technical run guide. Remove web-player/design_handoff_musify_player, an old design-tool export that was no longer needed.
4.3 KiB
Projects
The .NET projects live under backend/ (solution Musify.slnx, folders
Core/, Hosts/ and Tests/); the web client lives under web-player/.
Musify.Api (:5111)
The public REST API (Minimal APIs, .NET 10). The thin public face of the system.
- Endpoints:
UserEndpoints,TrackEndpoints,PlayListEndpoints. - Authentication: JWT Bearer against Zitadel (
Authentication/), with aJwtBearerEventsHandlerthat syncs the user on every validated token. CurrentUser: an abstraction bound as an endpoint parameter (IBindableFromHttpContext) that exposes the basic claims (Idaslong?,RequiredId, name, etc.) without readingClaimsPrincipalby hand.- Issues: presigned upload URLs (via
IStorageService) and stream tickets (viaIStreamTicketService, RS256). - OpenAPI + Scalar for docs/testing; OAuth2 (PKCE) set up for logging in from Scalar.
- CORS wide open, but only in Development (for the local frontend).
- Translates
ErrorOrinto HTTP inResultHttpExtensions.
Purpose: keep the public surface (authorization + metadata) separate from processing and byte-serving.
Musify.Domain + Musify.Application + Musify.Infrastructure
The core, split into three projects (clean architecture):
Domain
Entities (Entities/) and value objects/enums (ValueObjects/: ProcessingStatus, LifeCycleStatus, UploadIntentStatus, …). No infrastructure dependencies.
Application
Use cases (CQRS with Mediator):
Tracks/,PlayLists/,Users/→Commands,Queries,Handlers,Responses.Contracts/→ interfaces that infrastructure implements (IDatabase,IStorageService,IAudioTranscoderService,IPictureService,IEventBus,IStreamTicketService).Configuration/→ typed options (Track, PlayList, ApplicationStorage, UploadIntent…) bound and validated at startup.Shared/→ cross-cutting helpers (StorageKey.Combine,ImageSize).Pagination/→PaginatedResponse<T>.
Why: business logic doesn't know about EF, S3, or RabbitMQ, only interfaces. Shared by both the API and the Worker.
Infrastructure
Concrete implementations:
Persistence/→Database(EF Core/Npgsql), migrations.Services/→StorageService(AWSSDK.S3 against SeaweedFS),AudioTranscoderService(ffmpeg →.m4a),PictureService(ImageSharp),StreamTicketService(RS256 signing).MassTransit/→ consumers, activities, and routing slips (see media-processing.md).Jobs/→UploadIntentExpirationJob,TemporalUploadsCleanUpJob.
Musify.StreamingGateway (:8081)
A reverse proxy (ASP.NET + YARP) that serves audio (.m4a) from SeaweedFS. Validates the stream ticket (RS256, public key) and, if the requested object falls under the authorized prefix, forwards it to the filer.
Why a separate project: it scales with byte traffic independently of the API, has a minimal surface (it only knows how to validate a JWT and proxy), and lets SeaweedFS stay on a private network. See streaming.md.
Musify.Worker
A background Worker Service that consumes MassTransit events and runs the heavy processing: audio transcoding to .m4a (ffmpeg), thumbnail generation (ImageSharp), file transfers within the bucket, and the upload-intent expiration/cleanup jobs.
Why separate: CPU/IO-heavy work shouldn't happen inside an HTTP request; it scales and restarts independently. (Previously named Musify.PictureWorker; renamed once it started doing more than just images.)
web-player (:5173 in dev, :3000 in a container)
The web client (SvelteKit 2 + Svelte 5 + Tailwind 4). The OIDC session lives on the server (an encrypted cookie); backend calls go out from the server with the access token, and uploads go straight to the presigned S3 URLs.
Tests
backend/Tests/ (the /Tests/ folder in the .slnx) has five xUnit projects:
Musify.Domain.Tests, Musify.Application.Tests (in-memory SQLite, no
Docker), Musify.Infrastructure.Tests and Musify.Api.Tests (Testcontainers:
real Postgres + SeaweedFS), and Musify.StreamingGateway.Tests. Details in
development.md.
Other folders
deploy/: self-contained Docker Compose stacks (dev and prod). See ../deploy/README.md.docs/: this documentation.