---
title: Movies Diary — Hexagonal Architecture
---
graph TB
subgraph Binaries["Binaries (Composition Root)"]
WEB["presentation
Axum web server
Routes, Handlers, Mappers"]
WORKER["worker
Event consumer
Concurrent dispatch, graceful shutdown"]
TUI["tui
Terminal UI"]
end
subgraph Application["Application Layer"]
direction TB
CTX["AppContext
Repositories + Services"]
subgraph UseCases["Use Cases"]
UC_AUTH["auth
login, register"]
UC_DIARY["diary
log_review, get_diary,
get_activity_feed, export"]
UC_MOVIES["movies
get_movies, get_movie_profile,
enrich_movie, request_enrichment,
sync_poster, reindex_search"]
UC_IMPORT["import
create_session, apply_mapping,
execute, profiles"]
UC_USERS["users
get_users, get_profile,
update_profile"]
UC_WATCHLIST["watchlist
add, remove, get"]
UC_WRAPUP["wrapup
generate, compute,
list, delete"]
UC_GOALS["goals
create, update, delete,
get, list"]
UC_INTEGRATIONS["integrations
webhooks, watch_queue,
confirm, dismiss"]
UC_SEARCH["search
execute"]
UC_PERSON["person
get, get_credits"]
end
subgraph EventHandlers["Event Handlers"]
EH_ENRICH["EnrichmentHandler"]
EH_DISCOVER["MovieDiscoveryIndexer"]
EH_CLEANUP["SearchCleanupHandler"]
EH_REINDEX["SearchReindexHandler"]
EH_WRAPUP["WrapUpEventHandler"]
end
subgraph Jobs["Periodic Jobs"]
JOB_IMPORT["ImportSessionCleanup"]
JOB_WATCH["WatchEventCleanup"]
JOB_STALE["EnrichmentStaleness"]
JOB_WRAPGEN["WrapUpAutoGenerate"]
end
WORKER_SVC["WorkerService
Semaphore(8), JoinSet,
shutdown signal"]
end
subgraph Domain["Domain Layer (0 dependencies)"]
direction TB
subgraph Models["Models"]
M_MOVIE["Movie, MovieSummary,
MovieProfile"]
M_REVIEW["Review, DiaryEntry,
FeedEntry"]
M_USER["User, UserSummary"]
M_PERSON["Person, PersonId,
PersonCredits"]
M_WATCHLIST["WatchlistEntry,
WatchEvent"]
M_GOAL["Goal, GoalWithProgress,
UserSettings, RemoteGoalEntry"]
M_WRAPUP["WrapUpReport,
MovieRef, PersonStat"]
M_SEARCH["SearchQuery,
SearchResults"]
end
subgraph Ports["Port Traits (Interfaces)"]
P_REPOS["MovieRepository
ReviewRepository
DiaryRepository
UserRepository
WatchlistRepository
WatchEventRepository
WebhookTokenRepository
ImportSessionRepository
MovieProfileRepository
WrapUpRepository
GoalRepository
UserSettingsRepository"]
P_SERVICES["AuthService
MetadataClient
PosterFetcherClient
ObjectStorage
EventPublisher
EventConsumer
PasswordHasher
DiaryExporter
DocumentParser"]
P_SEARCH["SearchPort
SearchCommand
PersonQuery
PersonCommand"]
P_FEDERATION["SocialQueryPort
LocalApContentQuery
RemoteWatchlistRepository
RemoteGoalRepository"]
end
EVENTS["DomainEvent enum
ReviewLogged, MovieDiscovered,
GoalCreated, GoalUpdated,
SearchReindexRequested, ..."]
VO["Value Objects
MovieId, UserId, Rating,
Email, Username, ..."]
end
subgraph ApiTypes["api-types (0 domain deps)"]
DTO["DTOs
MovieDto, ReviewDto,
FeedEntryDto, UserSummaryDto,
CastMemberDto, ..."]
end
subgraph Adapters["Adapters (implement Port Traits)"]
direction TB
subgraph Storage["Storage"]
A_SQLITE["sqlite
SQLite repos"]
A_PG["postgres
PostgreSQL repos"]
A_SQLITE_SEARCH["sqlite-search
FTS5"]
A_PG_SEARCH["postgres-search
tsvector/GIN"]
A_OBJ["object-storage
S3 / filesystem"]
end
subgraph Messaging["Messaging"]
A_NATS["nats
JetStream / Core"]
A_PG_QUEUE["postgres-event-queue
Polling, dead-letter"]
A_PAYLOAD["event-payload
Serde (de)serialization"]
end
subgraph External["External Services"]
A_METADATA["metadata
TMDB search/details"]
A_TMDB["tmdb-enrichment
Credits, keywords, cast"]
A_POSTER["poster-fetcher
TMDB image download"]
A_AUTH["auth
JWT tokens"]
end
subgraph Federation["Federation (feature-gated)"]
A_AP["activitypub
k_ap library"]
A_SQLITE_FED["sqlite-federation"]
A_PG_FED["postgres-federation"]
end
subgraph Media["Media Processing"]
A_IMG["image-converter
AVIF/WebP"]
A_POSTER_SYNC["poster-sync"]
end
subgraph Presentation["Presentation Helpers"]
A_TEMPLATE["template-askama
HTML templates"]
A_RSS["rss
Feed generation"]
A_EXPORT["export
CSV/JSON diary"]
A_IMPORT["importer
CSV/JSON/XLSX parser"]
end
subgraph Webhooks["Webhook Parsers"]
A_JELLYFIN["jellyfin"]
A_PLEX["plex"]
end
end
%% Dependency arrows
WEB -->|"uses"| Application
WEB -->|"maps to"| ApiTypes
WORKER -->|"uses"| Application
Application -->|"depends on"| Domain
Adapters -.->|"implements"| Ports
%% Key data flows
WEB ===|"HTTP"| DTO
WORKER ===|"Events"| EVENTS
classDef domain fill:#1a1a2e,stroke:#e94560,color:#fff
classDef app fill:#16213e,stroke:#0f3460,color:#fff
classDef adapter fill:#0f3460,stroke:#533483,color:#fff
classDef binary fill:#533483,stroke:#e94560,color:#fff
classDef api fill:#2a2a4a,stroke:#e94560,color:#fff
class Domain domain
class Application app
class Adapters adapter
class Binaries binary
class ApiTypes api