Releases: IbbyLabs/XRDB
v1.22.0
Tip
Changelog: read the matching entry or browse the full compare.
Added
-
support original language artwork selection (FR-85)
• add original as a first class language option in the configurator and supported language defaults
• keep request state cache identity distinct for lang=original without breaking fixed locale callers
• resolve TMDB artwork bundles, certification lookups, and localized badge data through the title's original language
• document lang=original usage and cover it with request state, prepared media, and configurator regression tests
Fixed
-
resolve BUG-111 badge border scaling
Replace fixed badge border stroke widths with height relative stroke calculations so rating and genre badges keep proportional borders at large poster scales.
Scale outer and inner badge strokes from badge height with clamps to preserve current normal size rendering while fixing thin borders on 4K and oversized poster outputs.
Add direct SVG regression tests for rating badge glass borders and genre badge glass borders so future changes cannot silently reintroduce under scaled outlines.
-
resolve BUG-110 logo quality badge flow
Remove the duplicated logo quality controls from the configurator and wire logo quality badges through the full image route pipeline.
Parse logo quality badge params, enable the media feature pipeline for logo requests, preserve logo quality settings in the render seed, size the logo badge band for rating and quality rows, and render logo quality rows in the final output.
Add regression coverage for logo request state parsing, logo quality only layout, renderer output in the logo badge band, and render cache busting for logo quality changes.
Documentation
- refresh static doc assets
v1.21.2
Tip
Changelog: read the matching entry or browse the full compare.
Fixed
-
invalidate proxied manifests when source config changes
Make proxy manifest identity depend on the effective source manifest payload and proxy seed so stable source URLs do not keep a stale addon identity after configuration changes.
Add explicit no store cache headers to proxy manifest and proxy ref responses and cover the behavior with focused proxy regression tests.
-
BUG-101 BUG-105 preserve proxy age rating placement and clean genre sizing
Keep the genre badge size slider available when the clean text genre style is active so the configurator still exposes badge scaling in that mode.
Forward ageRatingBadgePosition through shared proxy image query keys and cover the rewrite with a regression test so poster proxy manifests preserve custom age rating placement.
Documentation
-
refresh static doc assets
-
align freshness guidance and refresh doc assets
Clarify that the Generated manifest flow uses a stable UUID backed install URL that refreshes when the source addon manifest changes instead of implying a rotated install link is required.
Update proxy page and reference copy to describe server managed TMDB and MDBList coverage, record the recent proxy and configurator fixes in the unreleased changelog, and refresh the tracked README preview metadata plus static documentation captures.
v1.21.1
Tip
Changelog: read the matching entry or browse the full compare.
Fixed
-
keep personal provider keys server side
Move personal provider credentials into an opaque server held session and resolve them through session aware configurator routes instead of browser visible params.
Add server fallback behavior for TMDB, Fanart, and Simkl requests, strip provider keys from previews and saved workspace exports, and show masked previews for saved personal keys in the advanced access keys modal.
-
harden server managed credential handling
Prefer server side TMDB bearer auth when a read access token is configured while keeping explicit per request overrides intact.
Redact sensitive credential query params from observer URLs and replay storage, hash MDBList cache keys, and omit xrdbKey from masked exports.
Update docs, templates, and tests for the new credential handling and masked export behavior.
-
BUG-109 restore full language options
Move configurator language loading behind a server route so provider keys stay out of the browser while TMDB backed language options still load. Also keep the language dropdown aligned inside the viewport and cover both regressions with focused tests.
-
prefer IMDb reverse mapping for anime episode fallback
Use season aware reverse mapping for AniList episode thumbnail fallback instead of always routing through the TMDB show id.
The previous fallback path could resolve sequel anime entries to the wrong AniList work and reuse the same episode thumbnail across seasons, which is what caused the JJK S02E01 and S03E01 collision.
Prefer explicit anime mapping ids and resolved IMDb ids before falling back to TMDB, and keep the regression covered with a focused artwork selection test for the season 3 episode fallback path.
-
sanitize poster warm replay requests
Default poster warm renders to a lean imdb,tmdb profile and strip replay only params, provider credentials, config ids, and MDBList backed providers before replay.
Share the MDBList backed provider set and add focused regressions for sanitized replay storage and warm request parameter normalization.
-
BUG-108 shorten cache for transient MDBList failures
Detect transient MDBList failures during provider resolution and carry a short lived TTL through prepared media into final image cache control.
Add focused regressions for MDBList failure handling, provider resolution propagation, prepared media state, and final image TTL calculation.
Documentation
- refresh static doc assets
v1.21.0
Tip
Changelog: read the matching entry or browse the full compare.
Added
-
harden stream cache
Implement stream cache hardening controls for Torrentio with feature gated behavior and a global hardening kill switch.
Add negative caching, stale while revalidate serving, circuit breaker thresholds and cooldowns, provider request budgets, prewarm popularity ranking with snapshot restore, and observe only auto tune telemetry paths.
Document activation and rollback controls in README and env template, extend config and metadata plumbing for hardening controls, and add targeted hardening tests that validate gating, rollback behavior, SWR, circuit, budgets, and prewarm recovery flows.
-
add adaptive stream cache ttl policy
Introduce adaptive Torrentio stream cache TTL selection using recency buckets (fresh, warm, stable) instead of relying only on a fixed TTL.
Add operator configurable adaptive window and TTL environment variables, document them in README and env template, and wire prepared media cache TTL calls through the adaptive helper.
Add targeted tests for recency classification boundaries, fallback behavior for missing or invalid dates, and deterministic TTL jitter behavior.
Fixed
-
BUG-106 restore full provider resolution
• switch MDBList fetch from legacy mdblist.com/api query format to api.mdblist.com path format
• pass resolved media type through provider rating fetch so movie/show endpoints are targeted correctly
• map MDBList popcorn source aliases to tomatoesaudience so RT audience ratings render
• update MDB fetch tests to assert exact endpoint URLs and add popcorn alias coverage
-
replace s<=30 season cap with TMDB number_of_seasons bound
Fetch the show detail endpoint to read number_of_seasons and use that
as the upper bound for the consolidated remap season walk. Falls back
to 100 if the endpoint fails. Eliminates the hard coded 30 season cap
that would silently return null for long running consolidated series.Updated resolveTmdbConsolidatedSeasonEpisode tests to mock the
tmdb:tv:{id} show detail key in all three test cases. -
BUG-102 BUG-103 TMDB episode ID mode and anime S2 consolidated remap
BUG-103: add tmdb episode ID mode with tmdb:{tmdb_id} URL pattern.
Wired tmdb to EpisodeIdMode union, EPISODE_ID_MODE_SET,
buildEpisodePatternBaseId, and applyEpisodeIdModeToXrdbId.
Added TMDB selector to export view and configuratorPageOptions.
export view now imports EPISODE_ID_MODE_OPTIONS from
configuratorPageOptions so option descriptions render inline
below the selector pills.BUG-102: anime S2+ thumbnails now resolve unique stills via
resolveTmdbConsolidatedSeasonEpisode. Applied in the generic
IMDb else path and as TVDB fallback when thetvdb.com scrape
returns null (no hard 404).README: document tmdb:{tmdb_id} in episode base ID formats.
Verified: lint clean, 841/841 tests pass, production build
clean. Manual checks: tmdb:1399/S01E01 200, anime S1/S2 stills
differ, tvdb:81189/S99E99 200 fallback, tt0468569 poster 200,
TVDB description visible in export options. -
constrain Tailwind source scanning to app and components (#3)
Co authored by: IbbyLabs 40578997+IbbyLabs@users.noreply.github.com
Documentation
- refresh static doc assets
- add minimal self host template
Other Changes
-
reuse known TMDB season counts in remap helper
Reuse TMDB show season counts that are already loaded in image route
resolution when calling resolveTmdbConsolidatedSeasonEpisode. This
avoids an extra /tv/{id} fetch in thumbnail remap paths while keeping
the existing fallback fetch when the season count is not already known.Verified with focused thumbnail tests, full lint + test, and a fresh
manual pass of the export and thumbnail checks on a clean dev server. -
consolidate season fetch loop into single pass
Replace the separate targetSeason early check fetch and priorCount loop
with a single pass from s=1 to targetSeason. Tracks priorCount and
targetSeasonEpisodeCount in one loop, eliminating the duplicate fetch
of targetSeason that previously occurred when episodes exceeded the
season count. All fetches after the first are still cache hits.Updated test mocks to reflect the new fetch sequence.
-
add color scheme dark meta tag (#2)
v1.20.1
Tip
Changelog: read the matching entry or browse the full compare.
Fixed
-
BUG-100 stabilize saved profile revert and sync diffs
Route saved profile revert through the canonical snapshot apply path so imported workspace changes clear dirty state correctly after revert.
Compare saved profile and cross type sync params with allow missing server managed provider key options so dirty checks and sync diffs still work when TMDB and MDBList keys are only configured on the server.
Add regression coverage for provider keyless dirty detection and sync to all diffs.
Documentation
- refresh static doc assets
v1.20.0
Tip
Changelog: read the matching entry or browse the full compare.
Added
-
expand poster warm sources with TMDB multi endpoint, IMDb baseline, recent ring
• TMDB: fetch 6 endpoints per pass (movie/popular p1+p2, movie/now_playing p1,
tv/popular p1+p2, tv/on_the_air p1) instead of 2; up to ~120 raw ids before cap
• MDBList: raise default limit from 100 to 200
• IMDb: new optional source reads local title.ratings.tsv.gz, sorts by vote count,
merges top N ids; no network required, falls back cleanly when file is absent
• Recent ring: bounded in memory ring buffer (default 500) records each inbound
poster request with its full search params (auth stripped); scheduler replays
exact request signatures so warm hits land in per config cache slots
• Wire recordRecentPosterRequest into imageRouteHandler for poster requests
• New env vars: XRDB_POSTER_WARM_IMDB_ENABLED/LIMIT, XRDB_POSTER_WARM_RECENT_ENABLED/LIMIT
• Update XRDB_POSTER_WARM_MDBLIST_LIMIT default in docs and env.template to 200
• 9 new tests covering TMDB 6 endpoint mapping, IMDb sort/cap/missing file,
ring dedup/eviction/auth strip/limit; all existing tests updated for new fields
• 834/834 tests pass, lint clean, build clean -
FR-80 FR-55 speed up poster cold loads
• default poster stream badges to off for new configs
• add non blocking posterStreamBadges=auto behavior with deferred warming
• add Torrentio timeout, fallback host, and proxy bypass controls
• add scheduled poster cache warming with source parsing and overlap protection
• enforce metadata cache pruning bounds and add stream warm observability
• update docs, env template, and tests for new behavior
Fixed
- track poster warm target seed file
- include poster warm targets in docker build context
Documentation
- refresh static doc assets
Other Changes
- bake poster warm targets.txt into image
v1.19.1
Tip
Changelog: read the matching entry or browse the full compare.
Fixed
-
BUG-97 apply stored episode config profile when thumbnail URL has no explicit badge params
The /thumbnail//S01E01.jpg route is a thin wrapper that parses the
episode token into season and episode numbers, then constructs an internal
backdrop URL (/backdrop/::.jpg?thumbnail=1) and
delegates rendering to the shared image handler.XRDB_EPISODE_CONFIG_PROFILE_ID is a server side env var intended to apply
a default config profile to all episode thumbnail requests, so Plex,
Jellyfin, and similar callers that send bare URLs with no query params
receive the operator configured badge and rating settings. The feature was
completely inert due to two separate gaps in the route:-
configId was read only from the ?config= search param of the incoming
URL. The env var was never consulted, so bare thumbnail URLs always
rendered with no profile applied. -
The route constructs a fresh internal URL for the backdrop handler. The
original search params are copied over but ?config= was never explicitly
set on the internal URL. Even if configId had been populated, the
backdrop renderer would have received no config param and skipped the
profile lookup entirely.
Fix reads XRDB_EPISODE_CONFIG_PROFILE_ID as a fallback when no ?config=
is present on the incoming request. When configId resolves from the env
var rather than the caller URL, it is injected into the internal backdrop
URL as ?config= before forwarding. The guard on !requestUrl.searchParams
.has('config') ensures the env var is strictly a fallback: an explicit
?config= from the caller always takes precedence. -
-
BUG-98 fix quality badge column centering when clean genre badge reserves bottom space
When a poster renders Pill Glass quality badges alongside a clean style
genre badge, the renderer reserves a block of space at the bottom of the
poster for the genre badge via cleanPosterReservedBottomHeight. That value
is folded into effectiveBadgeBottomOffset so layout bounds are correct
throughout the renderer.The quality badge column centering step did not use effectiveBadgeBottomOffset
as the lower boundary. Instead it divided the full output height by two,
treating the center of the entire image as the target midpoint. The result
was that the quality column drifted into the space reserved for the genre
badge and appeared off center relative to the usable area above it.The fix computes availableCenter as:
(badgeTopOffset + outputHeight, effectiveBadgeBottomOffset) / 2This bounds the center calculation to the region between the top badge
offset and the effective bottom offset, so the column centers correctly
within the available space regardless of how much bottom space the clean
genre badge reserves. -
BUG-99 apply configured value color to ring score text across all accent modes
aggregateValueColor was fully resolved in the display state pipeline but
was never passed to buildPosterCompactRingOverlay. The ring builder had
the score text fill hardcoded to #f8fafc regardless of what color was
configured. As a result, any value set via aggregateValueColor was silently
ignored whenever the compact ring presentation was active.The fix adds an optional valueColor param to buildPosterCompactRingOverlay
and threads it through to the SVG fill attribute using valueColor ?? '#f8fafc'
so the hardcoded default is preserved when no color is configured.On the display state side, compactRingValueColor is derived before the
ring builder call: when the primary badge is an aggregate kind, the color
follows the aggregate value color resolver; for provider badges, it falls
back to the aggregateValueColor input. This keeps behavior consistent
across all four accent modes (source, genre, custom, dynamic).Tests added for all four accent modes to confirm the configured color
appears in the rendered SVG and that the default white is preserved when
no color is set.
Documentation
- refresh static doc assets
v1.19.0
Tip
Changelog: read the matching entry or browse the full compare.
Added
-
shift to server managed provider keys
Remove provider key entry fields from configurator access keys and surface server credential status in the UI.
Use server TMDB and MDBList fallbacks across search, preview, proxy, and export payload generation while keeping optional per request overrides.
Update docs and env template for XRDB_TMDB_API_KEY support and add regression coverage for credential omission and server key detection.
Fixed
-
BUG-96 fallback to server MDBList keys
Retry provider rating resolution with the server MDBList key pool when a manual MDBList key returns no data.
Add regression coverage for manual key failure so preview badges keep rendering from fallback data.
-
BUG-95 genre badge respects selected position in blockbuster mode
In blockbuster poster mode, the collision avoidance loop was pushing the
genre badge away from all blockbuster overlay elements (score tiles,
callout tiles, rating badges, strip), ignoring the user's chosen position
entirely. The badge could end up halfway down the poster regardless of
what genreBadgePosition was set to.Fix: pass empty collisionRects for blockbuster poster mode in
imageRouteRenderer so the collision loop exits immediately and the badge
renders at the user selected offset. Non blockbuster posters and
backdrops continue to use full collision avoidance as before.Also refreshed doc static assets and README capture date.
-
BUG-92 accept all config profile ID formats in link import
Configurator link import validated config IDs with a UUID only pattern, which caused encrypted xrc_ IDs and legacy xr_ IDs to be rejected during parse. When those URLs were imported, configProfileId was dropped and the saved profile binding was silently lost.
This commit replaces the UUID only matcher with a unified CONFIG_PROFILE_ID_RE that accepts all supported profile ID families: UUID v4, xrc_<16 hex>, and xr_<8 hex>. The parsing path now preserves profile IDs consistently across import flows without changing merge precedence behavior.
Regression coverage includes explicit xrc_ and xr_ parser tests plus request state tests validating UUID profile resolution, explicit URL parameter precedence over saved profile parameters, and parity between generated inline URLs and ?config URLs across poster, backdrop, logo, and thumbnail routes.
-
BUG-89 skip clean style scrim when background opacity is 0
Clean genre badge rendering still produced the clean style scrim when background opacity was explicitly set to 0, which made fully transparent clean badges impossible and caused a mismatch between requested opacity and rendered output.
This commit updates the clean style rendering path so the scrim/background layer is skipped when effective clean background opacity resolves to zero, while preserving existing clean text treatment, shadow behavior, and non zero opacity rendering.
The change keeps clean style visuals deterministic across inline URLs and saved profile URLs where genreBadgeBackgroundOpacity is set to 0.
-
BUG-88 enforce clean text only constraints
Clean style behavior drifted across configurator state, URL generation, and runtime normalization. Icon and both modes could leak into clean style and non bottom center positions could persist, which produced inconsistent output between saved settings, generated links, and rendered images.
This commit centralizes clean style coercion through shared helpers so clean style resolves to text mode and bottom center placement unless genre badge mode is explicitly off. The coercion is applied across configurator props normalization, output query generation, runtime request state parsing, and renderer badge building to keep behavior consistent on poster, backdrop, thumbnail, and logo routes.
Regression coverage was expanded in genre badge, request state, image route badge, and ui config suites to lock clean style mode and placement coercion and ensure clean output remains text only across parsing and rendering paths.
-
BUG-87 prevent clean genre title overlap
Clean genre badges could overlap the poster title area on some output sizes because clean mode placement short circuited before collision avoidance and because the renderer did not reserve space using the actual clean badge footprint.
This commit removes the clean mode early return in genre placement so collision rect solving always runs, clamps placement using dynamic min inset, computes clean poster reserved bottom height from the rendered clean badge SVG height, and tracks the clean overlay collision rectangle so later overlays cannot collide into it.
Coverage was added with a multi size poster placement regression test to verify clean genre badges do not overlap the title region across normal, large, and 4k poster outputs.
-
BUG-86 keep poster genre and clean logo scaling proportional
Adjust poster genre badge auto scaling to keep normalized visual proportions more stable across normal, large, and 4K outputs while preserving user scale compounding behavior.
Update poster clean overlay logo sizing so small source logos can upscale proportionally for higher resolution poster renders, preventing undersized 4K logo output.
Add focused regression coverage for poster genre normalized ratio consistency and 4K clean logo upscale behavior across rendering paths.
-
BUG-80 harden AIOMetadata TV poster target resolution
Harden AIOMetadata TV export target resolution so poster URLs consistently resolve the correct media target and avoid ambiguous poster selection behavior.
Align export view and config profile client state handling with the normalized media target path so generated patterns and saved state stay consistent.
Add targeted regression tests for config profile client state, media target normalization, and UI config serialization to lock the BUG-80 behavior in place.
-
stabilize side placement and grouped age rating behavior
Allow grouped age rating placement to participate correctly on supported poster side layouts while preserving the intended quality badge side behavior.
Update poster display preference resolution and quality badge placement controls so grouped certification output does not overlap or drift when side positions are selected.
Refresh supporting docs and visual reference assets, and add regression coverage for display preference resolution, age rating extraction behavior, quality badge control normalization, and UI config payload handling.
Documentation
- refresh static doc assets
v1.18.2
Tip
Changelog: read the matching entry or browse the full compare.
Fixed
-
BUG-91 prevent server key exposure and allow tmdb only profile save with server mdb fallback
Hide server side Fanart, MDBList, and Simkl credential values from configurator env access responses while keeping non sensitive availability flags.
Decouple profile save gating from config string generation so profile create/update/migrate only require TMDB when server MDBList is configured.
Add legacy MDBLIST_KEY alias support for server availability checks and update regression tests.
Documentation
- refresh static doc assets
v1.18.1
Tip
Changelog: read the matching entry or browse the full compare.
Fixed
-
BUG-90 prevent login overwrite of unsaved config
Add login conflict handling so profile reveal does not silently replace active local configurator edits.
Introduce explicit conflict resolution actions for loading profile values or keeping web changes.
Add and update config profile client state tests for conflict detection behavior.
Verification: pnpm run lint && pnpm run test && pnpm run build
Documentation
- refresh static doc assets