Architecture Guide

Bounded Context Layer Structure

Bånder follows Domain-Driven Design with strict bounded contexts. Each context contains up to four layers:

ContextLayersClasses
ActivityInterface, Application, Infrastructure, Domain12
AuthInterface, Application, Infrastructure, Domain153
CatalogInterface, Application, Infrastructure, Domain64
CommandExportOpenApiSpecCommand.php1
FilesystemWatcher, Mime, Application, Command5
LibraryInterface, Application, Infrastructure, Domain29
LyricsInfrastructure, Domain3
MediaInterface, Application, Infrastructure, Domain17
MetadataInterface, Application, Infrastructure, Domain51
NotificationInterface, Application, Infrastructure, Domain, Console37
PartyInterface, Application, Infrastructure, Domain46
PlaylistInterface, Application, Infrastructure, Domain23
RecommendationInterface, Application, Infrastructure, Domain24
SharedInterface, Application, Infrastructure, Domain95
TranscodeInterface, Application, Infrastructure, Domain73
UserPreferenceInterface, Application, Infrastructure, Domain16

CQRS Flow

Commands and queries are dispatched via Symfony Messenger. Each command has a dedicated handler marked with #[AsMessageHandler].

Activity

CommandHandler
RecordPlayCommandRecordPlayHandler
ToggleLoveCommandToggleLoveHandler

Auth

CommandHandler
LoginUserCommandLoginUserHandler
RequestPasswordResetCommandRequestPasswordResetHandler
ApproveDeviceCodeCommandApproveDeviceCodeHandler
EnableTotpCommandEnableTotpHandler
CreateUserCommandCreateUserHandler
RevokeTokenCommandRevokeTokenHandler
IssueTokenCommandIssueTokenHandler
DisableTotpCommandDisableTotpHandler
RegisterUserCommandRegisterUserHandler
RefreshTokenCommandRefreshTokenHandler
RegisterPasskeyCommandRegisterPasskeyHandler
AuthenticatePasskeyCommandAuthenticatePasskeyHandler

Catalog

CommandHandler
BatchExtractCoversCommandBatchExtractCoversHandler

Library

CommandHandler
ScanLibraryCommandScanLibraryHandler
CreateLibraryCommandCreateLibraryHandler

Metadata

CommandHandler
ExtractAlbumCoverCommandExtractAlbumCoverHandler
SyncSongMessageSyncSongHandler
SyncAlbumMessageSyncAlbumHandler
SyncArtistMessageSyncArtistHandler
SyncLibraryMessageSyncLibraryHandler

Notification

CommandHandler
SendWebhookCommandSendWebhookHandler
SendEmailCommandSendEmailHandler
SendPushCommandSendPushHandler
SeedDefaultPreferencesCommandSeedDefaultPreferencesHandler
CreateNotificationCommandCreateNotificationHandler

Party

CommandHandler
LeavePartySessionCommandLeavePartySessionHandler
CreatePartySessionCommandCreatePartySessionHandler
StartPlaybackCommandStartPlaybackHandler
EndPartySessionCommandEndPartySessionHandler
SyncPlaybackCommandSyncPlaybackHandler
TransferHostCommandTransferHostHandler
PausePlaybackCommandPausePlaybackHandler
SeekPlaybackCommandSeekPlaybackHandler
JoinPartySessionCommandJoinPartySessionHandler

Playlist

CommandHandler
RemoveSongCommandRemoveSongHandler
UpdatePlaylistCommandUpdatePlaylistHandler
CreatePlaylistCommandCreatePlaylistHandler
AddSongCommandAddSongHandler

Recommendation

CommandHandler
GetRecommendationsForUserQueryGetRecommendationsForUserHandler
GetRecommendationQueryGetRecommendationHandler
GetRecommendationsBySourceQueryGetRecommendationsBySourceHandler
GetTargetingRecommendationsQueryGetTargetingRecommendationsHandler
DeleteRecommendationCommandDeleteRecommendationHandler
SaveRecommendationCommandSaveRecommendationHandler
DeleteRecommendationsBySourceCommandDeleteRecommendationsBySourceHandler

Transcode

CommandHandler
CleanupOrphanedJobsCommandCleanupOrphanedJobsHandler
CreateTranscodeSessionCommandCreateTranscodeSessionHandler
CancelTranscodeSessionCommandCancelTranscodeSessionHandler
PauseTranscodeSessionCommandPauseTranscodeSessionHandler
ResumeTranscodeSessionCommandResumeTranscodeSessionHandler

Port Pattern

Controllers depend on port interfaces defined in Application/Port/, not on repositories directly. This keeps the Interface layer decoupled from Infrastructure.