Architecture Guide
Bounded Context Layer Structure
Bånder follows Domain-Driven Design with strict bounded contexts. Each context contains up to four layers:
- Domain — Business rules, entities, value objects, repository interfaces
- Application — Use cases, command/query handlers, port interfaces
- Infrastructure — Doctrine repositories, external adapters, storage
- Interface — Controllers, request DTOs, API resources
| Context | Layers | Classes |
|---|---|---|
| Activity | Interface, Application, Infrastructure, Domain | 12 |
| Auth | Interface, Application, Infrastructure, Domain | 153 |
| Catalog | Interface, Application, Infrastructure, Domain | 64 |
| Command | ExportOpenApiSpecCommand.php | 1 |
| Filesystem | Watcher, Mime, Application, Command | 5 |
| Library | Interface, Application, Infrastructure, Domain | 29 |
| Lyrics | Infrastructure, Domain | 3 |
| Media | Interface, Application, Infrastructure, Domain | 17 |
| Metadata | Interface, Application, Infrastructure, Domain | 51 |
| Notification | Interface, Application, Infrastructure, Domain, Console | 37 |
| Party | Interface, Application, Infrastructure, Domain | 46 |
| Playlist | Interface, Application, Infrastructure, Domain | 23 |
| Recommendation | Interface, Application, Infrastructure, Domain | 24 |
| Shared | Interface, Application, Infrastructure, Domain | 95 |
| Transcode | Interface, Application, Infrastructure, Domain | 73 |
| UserPreference | Interface, Application, Infrastructure, Domain | 16 |
CQRS Flow
Commands and queries are dispatched via Symfony Messenger. Each command has a dedicated handler marked with #[AsMessageHandler].
Activity
| Command | Handler |
|---|---|
RecordPlayCommand | RecordPlayHandler |
ToggleLoveCommand | ToggleLoveHandler |
Auth
| Command | Handler |
|---|---|
LoginUserCommand | LoginUserHandler |
RequestPasswordResetCommand | RequestPasswordResetHandler |
ApproveDeviceCodeCommand | ApproveDeviceCodeHandler |
EnableTotpCommand | EnableTotpHandler |
CreateUserCommand | CreateUserHandler |
RevokeTokenCommand | RevokeTokenHandler |
IssueTokenCommand | IssueTokenHandler |
DisableTotpCommand | DisableTotpHandler |
RegisterUserCommand | RegisterUserHandler |
RefreshTokenCommand | RefreshTokenHandler |
RegisterPasskeyCommand | RegisterPasskeyHandler |
AuthenticatePasskeyCommand | AuthenticatePasskeyHandler |
Catalog
| Command | Handler |
|---|---|
BatchExtractCoversCommand | BatchExtractCoversHandler |
Library
| Command | Handler |
|---|---|
ScanLibraryCommand | ScanLibraryHandler |
CreateLibraryCommand | CreateLibraryHandler |
Metadata
| Command | Handler |
|---|---|
ExtractAlbumCoverCommand | ExtractAlbumCoverHandler |
SyncSongMessage | SyncSongHandler |
SyncAlbumMessage | SyncAlbumHandler |
SyncArtistMessage | SyncArtistHandler |
SyncLibraryMessage | SyncLibraryHandler |
Notification
| Command | Handler |
|---|---|
SendWebhookCommand | SendWebhookHandler |
SendEmailCommand | SendEmailHandler |
SendPushCommand | SendPushHandler |
SeedDefaultPreferencesCommand | SeedDefaultPreferencesHandler |
CreateNotificationCommand | CreateNotificationHandler |
Party
| Command | Handler |
|---|---|
LeavePartySessionCommand | LeavePartySessionHandler |
CreatePartySessionCommand | CreatePartySessionHandler |
StartPlaybackCommand | StartPlaybackHandler |
EndPartySessionCommand | EndPartySessionHandler |
SyncPlaybackCommand | SyncPlaybackHandler |
TransferHostCommand | TransferHostHandler |
PausePlaybackCommand | PausePlaybackHandler |
SeekPlaybackCommand | SeekPlaybackHandler |
JoinPartySessionCommand | JoinPartySessionHandler |
Playlist
| Command | Handler |
|---|---|
RemoveSongCommand | RemoveSongHandler |
UpdatePlaylistCommand | UpdatePlaylistHandler |
CreatePlaylistCommand | CreatePlaylistHandler |
AddSongCommand | AddSongHandler |
Recommendation
| Command | Handler |
|---|---|
GetRecommendationsForUserQuery | GetRecommendationsForUserHandler |
GetRecommendationQuery | GetRecommendationHandler |
GetRecommendationsBySourceQuery | GetRecommendationsBySourceHandler |
GetTargetingRecommendationsQuery | GetTargetingRecommendationsHandler |
DeleteRecommendationCommand | DeleteRecommendationHandler |
SaveRecommendationCommand | SaveRecommendationHandler |
DeleteRecommendationsBySourceCommand | DeleteRecommendationsBySourceHandler |
Transcode
| Command | Handler |
|---|---|
CleanupOrphanedJobsCommand | CleanupOrphanedJobsHandler |
CreateTranscodeSessionCommand | CreateTranscodeSessionHandler |
CancelTranscodeSessionCommand | CancelTranscodeSessionHandler |
PauseTranscodeSessionCommand | PauseTranscodeSessionHandler |
ResumeTranscodeSessionCommand | ResumeTranscodeSessionHandler |
Port Pattern
Controllers depend on port interfaces defined in Application/Port/, not on repositories directly. This keeps the Interface layer decoupled from Infrastructure.