Skip to main content

Codebase Flow Map

This page is for a new developer who needs to understand how Prismedia moves from screen to API to domain behavior to database and back again. It is a codebase map, not an exhaustive component catalog.

Snapshot date: June 16, 2026.

Read This First

Prismedia has three big rules that explain most of the repo:

  1. The .NET backend owns server behavior, persistence, HTTP contracts, migrations, jobs, playback preparation, and integration adapters.
  2. The Svelte app is a static frontend client. It calls the backend through generated OpenAPI clients and local presentation helpers.
  3. Long-running media work is durable job work. It moves through PostgreSQL job rows and the .NET worker, not a TypeScript worker or browser process.

Runtime Shape

The API process also applies EF Core migrations on startup. The worker waits for the database to be reachable and migrated before it begins claiming work.

Code Layout At A Glance

AreaPathWhat it owns
Web appapps/web-svelteSvelte routes, app chrome, stores, generated API client, entity grids/details, media players, readers.
API hostapps/backend/src/Prismedia.ApiMinimal API endpoint composition, auth, OpenAPI, static frontend hosting, codegen manifest, HTTP result mapping.
Contractsapps/backend/src/Prismedia.ContractsPublic .NET request/response DTOs consumed by OpenAPI generation.
Applicationapps/backend/src/Prismedia.ApplicationUse-case services, job handlers, ports, settings, security, playback policy, Jellyfin catalog projection.
Domainapps/backend/src/Prismedia.DomainEntity kinds, behavior-bearing entities, capabilities, coded enums, taxonomy concepts.
Infrastructureapps/backend/src/Prismedia.InfrastructureEF Core, row models, migrations, repositories/read services, media tools, plugins, requests, queue storage.
Workerapps/backend/src/Prismedia.WorkerHosted process that registers worker services and runs queue/scheduler hosted services.
Shared UIpackages/ui-svelteDomain-free Svelte primitives, composed UI pieces, tokens, motion helpers.
Shared mediapackages/media-coreFile classification, filename parsing, discovery, fingerprint and media helper primitives.
Plugin toolingpackages/pluginsPlugin manifest parsing, execution helpers, Stash adapter helpers, normalized result helpers.
Documentation sitedocumentation-siteDocusaurus docs published separately from the app shell.

Current repository scale from rg --files: apps/web-svelte has about 889 files, backend source has about 611 files, backend tests have about 110 files, and the repo has about 261 test files across C# and TypeScript.

Dependency Direction

The most important practical habit: when a feature touches a user action, start at the route or endpoint, then follow the dependency direction inward. Do not skip directly from a Svelte component into database-shaped assumptions.

Request To Render Flow

Read-only endpoints often project EF rows directly into contract DTOs. Writes should flow through a command or use-case service, call domain behavior where there is a business invariant, and save once per use case whenever possible.

Frontend Flow

The frontend is route-driven, but the reusable entity scaffolds carry a lot of the product surface:

  • EntityIndexPage owns the common library page shell.
  • EntityGrid, EntityGridToolbar, EntityGridFilterDrawer, and pagination modules own browsing, filtering, selection, and view modes.
  • EntityDetail owns the shared detail surface for descriptions, metadata, images, relationships, children, progress, and edit actions.
  • EntityThumbnail owns grid card rendering, artwork fallbacks, preview hover, badges, progress, and reference chips.
  • Route pages usually choose kind-specific configuration and delegate to shared scaffolds instead of rebuilding layouts from scratch.

API Surface Flow

Endpoint files should stay thin. They decode HTTP-shaped input, call application services, and return explicit contract DTOs or ApiProblem responses.

Important groups currently mapped:

GroupPrimary route areaTypical owner
Entity browse/detail/api/entities, kind aliases like /api/videosIEntityReadService, entity projectors, generated DTOs.
Library roots/api/librariesSettings and scan-root persistence.
Files/api/filesFilesService, managed storage, file persistence.
Jobs/api/jobsJobService, IJobQueueService, job_runs.
Identify/api/identifyPlugin services, identify queues, cascade runners.
Requests/api/requestsRadarr, Sonarr, Lidarr clients and history stores.
Playback/api/playback, /api/music-player, Jellyfin routesPlayback services, HLS assets, stream sources.
Settings/security/api/settings, /api/securitySettings registry, API key and Jellyfin profile services.

Background Job Flow

Registered handler families:

FamilyExamplesWhat they do
ScanningScanLibraryJobHandler, ScanGalleryJobHandler, ScanBookJobHandler, ScanAudioJobHandlerWalk roots, classify folders/files, upsert entities, enqueue downstream work.
ProbeProbeVideoJobHandler, ProbeAudioJobHandlerRun media probes and persist technical metadata.
FingerprintFingerprintJobHandler for video, image, audioCompute MD5/oshash-style fingerprints where enabled and needed.
Asset generationGrid thumbnails, image thumbnails, book covers/pages, audio waveforms, video previews, subtitlesProduce generated assets and capability state.
IdentifySearch, bulk identify, auto identify, cascade identifyCall providers/plugins, store review state, apply metadata and structure.
MaintenanceRefresh entity, refresh collection, library maintenanceKeep derived views and stale records tidy.

Entity And Capability Flow

Conceptually, an Entity is the canonical library object. Its kind, files, relationships, children, image assets, source ids, progress, classification, technical metadata, and playback state are attached through bounded domain capabilities and EF row structures.

Two capability patterns matter:

  • Domain capabilities are real domain state, persisted and projected where appropriate.
  • Contract pseudo-capabilities project universal entity properties into the API so the frontend sees a uniform capability surface.

Do not introduce a global entity graph runtime. Structural children and relationship links are persistence structures and read projections, not a cross-app object graph to hydrate everywhere.

Generated Client And Code Constants

Any backend contract, OpenAPI operation, or [Code] enum change must be followed by regenerating the frontend client with the dev API running. pnpm api:check guards this by regenerating and failing if committed generated files are stale.

Main User Journey Maps

Browse To Playback

New Media Scan

Identify Review

Request Workflow

Where To Start For Common Changes

ChangeStart hereThen inspect
New library page or grid behaviorapps/web-svelte/src/lib/components/entities/EntityIndexPage.svelteEntityGrid.svelte, entity-grid.ts, route page for the kind.
Detail page layout or metadata editingEntityDetail.svelteentity-detail.ts, entity-detail-edit.ts, kind detail route, update endpoints.
New API routePrismedia.Api/Endpoints/EndpointRouteBuilderExtensions.csMatching endpoint group, Prismedia.Contracts, generated client.
New backend settingAppSettingKeys.cs and AppSettingsRegistry.csSettings endpoints, generated codes, settings UI.
New closed-set codeDomain [Code] enum or constants manifestCodesManifest.cs, scripts/gen-codes.mjs, codes.ts.
New media scan behaviorScan handler for that familyLibraryScanPersistenceService.*, file classifier/parsing helpers, downstream job needs.
New worker jobPrismedia.Application/Jobs/DependencyInjection.csJobType, handler, queue tests, Jobs UI if surfaced.
Playback negotiation changePlaybackInfoService.csVideoDirectPlayPolicy, HlsAssetService*, VideoPlayer.svelte, Jellyfin endpoints.
Plugin/identify behaviorIdentifyPluginService* or identify job handlersQueue store, proposal traversal, apply service, identify UI store.
Request integrationRequestEndpoints.cs and request servicesArr clients, request contracts, settings UI, history tests.

Quality Snapshot

Strong Signals

  • The backend has an explicit architecture contract and a mechanical architecture audit script.
  • Domain, Application, Infrastructure, API, Worker, and Contracts are split into separate projects with mostly inward dependencies.
  • The Svelte client has a generated OpenAPI layer and a generated closed-code manifest layer.
  • Tests exist across domain, infrastructure, API endpoints, frontend view-model helpers, Svelte components, and shared packages.
  • pnpm validate ties together version/changelog checks, generated-client drift, Svelte checks, unit tests, docs build, and backend tests.
  • Generated migrations and generated API files are isolated enough that large file size does not automatically imply hand-maintained complexity.

Current Architecture Audit

The mechanical .NET architecture audit currently reports two medium findings:

SeverityLocationMeaning
Mediumapps/backend/src/Prismedia.Api/Endpoints/Requests/RequestEndpoints.csThe endpoint imports Prismedia.Domain.Entities to decode request provider/media code enums.
Mediumapps/backend/tests/Prismedia.Api.Tests/RequestEndpointTests.csTests use the same domain-coded request enums.

This is a bounded issue rather than a broad layering collapse. Before release, either document it as an intentional code-decoding boundary or move the request decode surface behind API/contract-owned helpers so endpoint contracts do not directly depend on domain namespaces.

Hand-Maintained Hotspots

These files are not automatically bad; they are places where changes require careful reading, focused tests, and a preference for extracting proven patterns instead of adding one-off branches.

AreaHotspotWhy it matters
Frontend detail surfaceEntityDetail.svelteLarge shared page surface for many entity kinds. Small changes can affect movies, shows, books, images, audio, and taxonomy pages.
Frontend playbackVideoPlayer.svelteCoordinates browser media events, HLS, fallback, progress, controls, and recovery.
Frontend gridsEntityGrid.svelte, EntityGridToolbar.svelte, EntityThumbnail.svelteShared browsing behavior, filtering, selection, thumbnails, previews, and mobile ergonomics.
Identify UIidentify-store.svelte.ts, identify review componentsLong-running async state, provider selection, review/apply progress, and refresh survival.
API wrapperapps/web-svelte/src/lib/api/prismedia.tsTransitional wrapper around generated clients; useful but should not become a second contract layer.
Backend JellyfinJellyfinCatalogService*, Jellyfin endpointsCompatibility surface with many legacy route shapes and client expectations.
Backend identifyIdentifyQueueService, IdentifyPluginService*Async matching, provider behavior, queue state, cascade and apply paths.
Backend playbackHlsAssetService*, playback policy servicesDirect play, direct stream, transcode, cache, seek, and process lifecycle all interact.
Backend scanningLibraryScanPersistenceService.*, scan handlersConverts files into canonical entities and downstream job work.
Backend queueJobQueueService, QueueWorkerDurable work, visibility, retries, cancellation, concurrency, foreground lane behavior.

Low-Noise Findings

  • TODO/FIXME comments are mostly inside vendored foliate-js reader code.
  • One application job handler logs that provider metadata import has not yet been migrated; that appears to be an explicit placeholder, not hidden dead code.
  • Generated files dominate the largest-file list only because EF migrations and generated API clients are necessarily verbose.

Release Readiness Checklist

Before a release branch or release image, run the checks from the repo root:

pnpm validate
dotnet build apps/backend/Prismedia.slnx
pnpm docs:check

When backend contracts or [Code] enums changed, run the app at http://localhost:8008, regenerate with:

pnpm --filter @prismedia/web-svelte api:generate
pnpm api:check

When runtime behavior changed, smoke the app through the .NET API at http://localhost:8008, not Vite directly.

Practical Mental Model

Use this path when you are lost:

Route or user action
-> shared frontend scaffold or page-local component
-> src/lib/api wrapper
-> generated OpenAPI operation
-> Prismedia.Api endpoint group
-> Application service, handler, or job handler
-> Domain behavior if a business rule is involved
-> Infrastructure EF/media/plugin adapter
-> PostgreSQL rows or generated assets
-> projected contract DTO
-> generated TypeScript model
-> screen state

If a proposed change skips a layer, ask why. Some read paths are intentionally projection-first for speed, and some compatibility paths have external route constraints, but those exceptions should be visible in code and tests.