# zamelane/lophius architecture

> Architecture diagram of the GitHub repository zamelane/lophius, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-08-06). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/zamelane/lophius
- Repository: https://github.com/zamelane/lophius

## Overview

#### Purpose and topology
Lophius is a Bun/TypeScript monorepo for collecting, curating, searching, and tracking media. It has three deployable surfaces: the user-facing Next.js application, a separate plugin-driven metadata worker, and a Next.js documentation site. Shared persistence is a database package.
- `apps/web/app/layout.tsx`
- `apps/worker/src/index.ts`
- `packages/database/src/index.ts`

#### Web application entry and routing
The primary runtime is a localized Next.js App Router application. Language-scoped routes divide authentication/configuration from the authenticated media workspace, including media-type pages, calendars, lists, profiles, settings, and administration. Middleware, instrumentation, and a custom server form the HTTP/runtime boundary.
- `apps/web/app/[lang]/(home)/layout.tsx`
- `apps/web/app/[lang]/(home)/[mediaType]/page.tsx`
- `apps/web/middleware.ts`
- `apps/web/server.ts`

#### Identity, startup, and configuration
Authentication is implemented as feature services with validation schemas and session/shared auth state. A configuration wizard provisions an administrator, database connection/schema, environment, and reload flow; startup code seeds/initializes application state. This is the operational boundary before normal user workflows are available.
- `apps/web/src/features/auth/services/login.tsx`
- `apps/web/src/processes/configuration/view.tsx`
- `apps/web/src/features/configuration/services/database-push.ts`
- `apps/web/src/shared/lib/startup/index.ts`

#### Media domain and persistence
`packages/database` centralizes Drizzle configuration, schemas, model repositories, and services. Its core model is media linked to types, status, votes, budgets/revenue, contributors, taxonomy, translations, release dates, sources, and external artwork. Web features and worker plugins should use this package rather than define independent persistence mappings.
- `packages/database/src/schemas/medias.ts`
- `packages/database/src/models/Media/repository.ts`
- `packages/database/src/services/UnitOfWorks.ts`
- `packages/database/drizzle.config.ts`

#### Media interaction flows
The web app reads media details and lists from local storage, lets users organize items into lists, and presents calendar/activity views. Search has offline and online modes, with language prioritization; online work crosses to the worker through a WebSocket-oriented client hook. Route handlers expose selected user, asset, and Open Graph endpoints.
- `apps/web/src/features/media/search/search/index.tsx`
- `apps/web/src/features/online-search/hooks/useSearchWebSocket.tsx`
- `apps/web/src/features/media-list-button/services/addToList.ts`
- `apps/web/app/api/assets/route.ts`

#### Worker and metadata-ingestion pipeline
The worker is an independent server that loads/manages plugins, queues searches, stores plugin state, and publishes parse status over WebSocket. Its TMDB plugin calls the TMDB API, runs staged pipelines to obtain details, images, people, translations, and recommendations, persists normalized data, and emits incremental status/data events. Rate limiting and DNS-agent utilities protect outbound integration calls.
- `apps/worker/src/server-app.ts`
- `apps/worker/src/plugin-loader.ts`
- `apps/worker/src/search/search-queue.ts`
- `apps/worker/plugins/tmdb/plugin.ts`
- `apps/worker/plugins/tmdb/steps/details/index.ts`

#### Presentation, localization, and documentation
The web client is organized around feature/widget/shared layers, with SWR, theme, and auth providers; locale messages support eight languages. `apps/docs` is a separate Next.js/MDX documentation application, not part of the production media workflow.
- `apps/web/src/shared/providers/SWRProvider.tsx`
- `apps/web/src/shared/i18n/config.ts`
- `apps/web/src/widgets/media/page-info/view.tsx`
- `apps/docs/app/[[...mdxPath]]/page.jsx`

Main entry points: [`apps/web/app/[lang]/(home)/layout.tsx`](https://github.com/zamelane/lophius/blob/master/apps/web/app/%5Blang%5D/(home)/layout.tsx) (Localized workspace routes), [`packages/database/src/index.ts`](https://github.com/zamelane/lophius/blob/master/packages/database/src/index.ts) (Database package), [`apps/web/app/[lang]/(home)/[mediaType]/page.tsx`](https://github.com/zamelane/lophius/blob/master/apps/web/app/%5Blang%5D/(home)/%5BmediaType%5D/page.tsx) (Media-type pages), [`apps/worker/src/server-app.ts`](https://github.com/zamelane/lophius/blob/master/apps/worker/src/server-app.ts) (Worker server)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_web["Web application"]
  node_web_runtime{{"HTTP runtime<br/>Next.js server<br/>[server.ts]"}}
  node_web_routes["Localized workspace routes<br/>App Router<br/>[layout.tsx]"]
  node_media_page["Media-type pages<br/>route page<br/>[page.tsx]"]
  node_auth["Authentication<br/>feature services<br/>[login.tsx]"]
  node_configuration["Configuration wizard<br/>startup process<br/>[view.tsx]"]
  node_startup["Startup initialization<br/>startup library<br/>[index.ts]"]
  node_search["Media search<br/>feature UI<br/>[index.tsx]"]
  node_online_search["Worker search client<br/>WebSocket hook"]
  node_list_management["List management<br/>feature service<br/>[addToList.ts]"]
  node_asset_api["Asset API<br/>route handler<br/>[route.ts]"]
  node_providers_i18n["Client providers and i18n<br/>presentation layer<br/>[SWRProvider.tsx]"]
end

subgraph group_worker["Metadata worker"]
  node_worker_server{{"Worker server<br/>independent server<br/>[server-app.ts]"}}
  node_plugin_loader["Plugin loader<br/>plugin manager<br/>[plugin-loader.ts]"]
  node_search_queue["Search queue<br/>job queue<br/>[search-queue.ts]"]
  node_tmdb_plugin["TMDB plugin<br/>metadata integration<br/>[plugin.ts]"]
  node_tmdb_details["TMDB detail pipeline<br/>ingestion stage<br/>[index.ts]"]
end

subgraph group_data["Shared persistence"]
  node_database[("Database package<br/>Drizzle data layer<br/>[index.ts]")]
  node_media_schema[("Media schema and repository<br/>domain persistence<br/>[medias.ts]")]
end

subgraph group_docs["Documentation"]
  node_docs_site["Documentation site<br/>Next.js MDX app<br/>[page.jsx]"]
end

node_web_runtime -->|"serves"| node_web_routes
node_web_routes -->|"renders"| node_media_page
node_web_routes -->|"requires session"| node_auth
node_web_runtime -->|"exposes setup flow"| node_configuration
node_configuration -->|"triggers reload"| node_startup
node_startup -->|"initializes"| node_database
node_media_page -->|"uses"| node_search
node_media_page -->|"organizes media"| node_list_management
node_search -->|"uses for online mode"| node_online_search
node_online_search -->|"WebSocket search"| node_worker_server
node_web_routes -->|"uses assets"| node_asset_api
node_web_routes -->|"wraps with"| node_providers_i18n
node_web_routes -->|"reads and writes"| node_database
node_worker_server -->|"loads"| node_plugin_loader
node_worker_server -->|"manages"| node_search_queue
node_search_queue -->|"dispatches search"| node_tmdb_plugin
node_plugin_loader -->|"registers"| node_tmdb_plugin
node_tmdb_plugin -->|"runs"| node_tmdb_details
node_tmdb_details -->|"persists normalized data"| node_database
node_database -->|"defines media model"| node_media_schema

click node_web_runtime "https://github.com/zamelane/lophius/blob/master/apps/web/server.ts"
click node_web_routes "https://github.com/zamelane/lophius/blob/master/apps/web/app/%5Blang%5D/(home)/layout.tsx"
click node_media_page "https://github.com/zamelane/lophius/blob/master/apps/web/app/%5Blang%5D/(home)/%5BmediaType%5D/page.tsx"
click node_auth "https://github.com/zamelane/lophius/blob/master/apps/web/src/features/auth/services/login.tsx"
click node_configuration "https://github.com/zamelane/lophius/blob/master/apps/web/src/processes/configuration/view.tsx"
click node_startup "https://github.com/zamelane/lophius/blob/master/apps/web/src/shared/lib/startup/index.ts"
click node_search "https://github.com/zamelane/lophius/blob/master/apps/web/src/features/media/search/search/index.tsx"
click node_online_search "https://github.com/zamelane/lophius/blob/master/apps/web/src/features/online-search/hooks/useSearchWebSocket.tsx"
click node_list_management "https://github.com/zamelane/lophius/blob/master/apps/web/src/features/media-list-button/services/addToList.ts"
click node_asset_api "https://github.com/zamelane/lophius/blob/master/apps/web/app/api/assets/route.ts"
click node_providers_i18n "https://github.com/zamelane/lophius/blob/master/apps/web/src/shared/providers/SWRProvider.tsx"
click node_worker_server "https://github.com/zamelane/lophius/blob/master/apps/worker/src/server-app.ts"
click node_plugin_loader "https://github.com/zamelane/lophius/blob/master/apps/worker/src/plugin-loader.ts"
click node_search_queue "https://github.com/zamelane/lophius/blob/master/apps/worker/src/search/search-queue.ts"
click node_tmdb_plugin "https://github.com/zamelane/lophius/blob/master/apps/worker/plugins/tmdb/plugin.ts"
click node_tmdb_details "https://github.com/zamelane/lophius/blob/master/apps/worker/plugins/tmdb/steps/details/index.ts"
click node_database "https://github.com/zamelane/lophius/blob/master/packages/database/src/index.ts"
click node_media_schema "https://github.com/zamelane/lophius/blob/master/packages/database/src/schemas/medias.ts"
click node_docs_site "https://github.com/zamelane/lophius/blob/master/apps/docs/app/%5B%5B...mdxPath%5D%5D/page.jsx"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_web_runtime,node_web_routes,node_media_page,node_auth,node_configuration,node_startup,node_search,node_online_search,node_list_management,node_asset_api,node_providers_i18n toneBlue
class node_worker_server,node_plugin_loader,node_search_queue,node_tmdb_plugin,node_tmdb_details toneAmber
class node_database,node_media_schema toneMint
class node_docs_site toneRose
```

## Components

### Web application

Localized Next.js media workspace.

- [HTTP runtime](https://github.com/zamelane/lophius/blob/master/apps/web/server.ts): Next.js server · Custom server and middleware form the request boundary. · `apps/web/server.ts`
- [Localized workspace routes](https://github.com/zamelane/lophius/blob/master/apps/web/app/%5Blang%5D/(home)/layout.tsx): App Router · Authenticated media, calendar, list, profile, settings, and admin routes. · `apps/web/app/[lang]/(home)/layout.tsx`
- [Media-type pages](https://github.com/zamelane/lophius/blob/master/apps/web/app/%5Blang%5D/(home)/%5BmediaType%5D/page.tsx): route page · `apps/web/app/[lang]/(home)/[mediaType]/page.tsx`
- [Authentication](https://github.com/zamelane/lophius/blob/master/apps/web/src/features/auth/services/login.tsx): feature services · Login validation and shared session state. · `apps/web/src/features/auth/services/login.tsx`
- [Configuration wizard](https://github.com/zamelane/lophius/blob/master/apps/web/src/processes/configuration/view.tsx): startup process · Provisions admin, database, schema, environment, and reload. · `apps/web/src/processes/configuration/view.tsx`
- [Startup initialization](https://github.com/zamelane/lophius/blob/master/apps/web/src/shared/lib/startup/index.ts): startup library · Seeds and initializes application state. · `apps/web/src/shared/lib/startup/index.ts`
- [Media search](https://github.com/zamelane/lophius/blob/master/apps/web/src/features/media/search/search/index.tsx): feature UI · Provides offline and online search with language prioritization. · `apps/web/src/features/media/search/search/index.tsx`
- [Worker search client](https://github.com/zamelane/lophius/blob/master/apps/web/src/features/online-search/hooks/useSearchWebSocket.tsx): WebSocket hook · Streams online search work from the worker. · `apps/web/src/features/online-search/hooks/useSearchWebSocket.tsx`
- [List management](https://github.com/zamelane/lophius/blob/master/apps/web/src/features/media-list-button/services/addToList.ts): feature service · `apps/web/src/features/media-list-button/services/addToList.ts`
- [Asset API](https://github.com/zamelane/lophius/blob/master/apps/web/app/api/assets/route.ts): route handler · Serves selected user and media assets. · `apps/web/app/api/assets/route.ts`
- [Client providers and i18n](https://github.com/zamelane/lophius/blob/master/apps/web/src/shared/providers/SWRProvider.tsx): presentation layer · SWR, theme, auth providers, and eight-language locale configuration. · `apps/web/src/shared/providers/SWRProvider.tsx`

### Metadata worker

Plugin-driven ingestion and search runtime.

- [Worker server](https://github.com/zamelane/lophius/blob/master/apps/worker/src/server-app.ts): independent server · Hosts plugin management and WebSocket status publishing. · `apps/worker/src/server-app.ts`
- [Plugin loader](https://github.com/zamelane/lophius/blob/master/apps/worker/src/plugin-loader.ts): plugin manager · `apps/worker/src/plugin-loader.ts`
- [Search queue](https://github.com/zamelane/lophius/blob/master/apps/worker/src/search/search-queue.ts): job queue · Queues metadata searches and tracks plugin state. · `apps/worker/src/search/search-queue.ts`
- [TMDB plugin](https://github.com/zamelane/lophius/blob/master/apps/worker/plugins/tmdb/plugin.ts): metadata integration · Calls TMDB and emits incremental status and data events. · `apps/worker/plugins/tmdb/plugin.ts`
- [TMDB detail pipeline](https://github.com/zamelane/lophius/blob/master/apps/worker/plugins/tmdb/steps/details/index.ts): ingestion stage · Obtains details, images, people, translations, and recommendations. · `apps/worker/plugins/tmdb/steps/details/index.ts`

### Shared persistence

Database package used by both runtimes.

- [Database package](https://github.com/zamelane/lophius/blob/master/packages/database/src/index.ts): Drizzle data layer · Central schemas, repositories, services, and unit-of-work boundary. · `packages/database/src/index.ts`
- [Media schema and repository](https://github.com/zamelane/lophius/blob/master/packages/database/src/schemas/medias.ts): domain persistence · Normalizes media, taxonomy, contributors, translations, releases, sources, and artwork. · `packages/database/src/schemas/medias.ts`

### Documentation

Separate Next.js and MDX site.

- [Documentation site](https://github.com/zamelane/lophius/blob/master/apps/docs/app/%5B%5B...mdxPath%5D%5D/page.jsx): Next.js MDX app · Standalone documentation surface outside production media workflows. · `apps/docs/app/[[...mdxPath]]/page.jsx`

## Connections

- HTTP runtime → Localized workspace routes: serves
- Localized workspace routes → Media-type pages: renders
- Localized workspace routes → Authentication: requires session
- HTTP runtime → Configuration wizard: exposes setup flow
- Configuration wizard → Startup initialization: triggers reload
- Startup initialization → Database package: initializes
- Media-type pages → Media search: uses
- Media-type pages → List management: organizes media
- Media search → Worker search client: uses for online mode
- Worker search client → Worker server: WebSocket search
- Localized workspace routes → Asset API: uses assets
- Localized workspace routes → Client providers and i18n: wraps with
- Localized workspace routes → Database package: reads and writes
- Worker server → Plugin loader: loads
- Worker server → Search queue: manages
- Search queue → TMDB plugin: dispatches search
- Plugin loader → TMDB plugin: registers
- TMDB plugin → TMDB detail pipeline: runs
- TMDB detail pipeline → Database package: persists normalized data
- Database package → Media schema and repository: defines media model
