Example Catalog Source
The Example Catalog Source is the maintained reference for the public source
contract. It combines Blender Foundation open movies carrying TMDB identifiers
with a deterministic fictional series hierarchy and a generic-video record. The
addon performs no network request and depends only on the published addon
contract.
Manifest
{
"id": "com.tootiapps.streamshare.catalog-example",
"name": "Example Catalog Source",
"version": "1.0.0",
"compatibleVersion": "^3.13.0",
"type": "source",
"main": "dist/index.js",
"author": "TootiApps",
"description": "A deterministic catalog demonstrating the public source-addon contract.",
"permissions": {
"network": []
}
}
An empty network allowlist is intentional: the example never calls api.http.
StreamShare enriches movie records through its own TMDB integration and opens the
Blender media URL only after playback resolution. The fictional episode URLs under
example.com remain non-working placeholders.
Source identity
getSourceInfo() advertises exactly the implemented behavior. In particular, the
example supports local type/year filtering and direct TMDB lookup, but does not
claim genre filtering.
getSourceInfo(): SourceInfo {
return {
id: 'example-catalog',
name: 'Example Catalog',
isAvailable: true,
capabilities: {
supportsSearch: true,
supportsBrowse: true,
supportsTypeFilter: true,
supportsGenreFilter: false,
supportsYearFilter: true,
supportsTmdbLookup: true,
supportedSorts: ['relevance', 'date', 'rating', 'title'],
supportedTypes: ['movie', 'series', 'season', 'episode', 'folder', 'video'],
},
};
}
TMDB enrichment and direct lookup
The movie records intentionally omit artwork, overview, genres and rating. Their stable TMDB IDs let StreamShare provide those fields in the current application language:
{
id: 'movie:big-buck-bunny',
type: 'movie',
title: 'Big Buck Bunny',
isContainer: false,
tmdbId: 10378,
productionYear: 2008,
}
The source also advertises supportsTmdbLookup: true because it applies
targetTmdbId and parentTmdbId criteria before pagination. Merely returning a
tmdbId for host enrichment would not be enough to advertise this capability.
See TMDB metadata and source addons for the complete
distinction.
The generic-video record intentionally has no TMDB identity. It demonstrates
that video is a first-class playable type when a source advertises it:
{
id: 'video:cosmos-livestream',
type: 'video',
title: 'Cosmos Livestream',
isContainer: false,
qualityLabel: '1080p live',
language: 'VO',
}
Source-selection metadata
Every playable demonstration item provides structured technical metadata. These labels are illustrative and show how the source-selection interface presents each field independently:
{
id: 'episode:orbit:1:1',
type: 'episode',
title: 'Arrival',
isContainer: false,
seasonNumber: 1,
episodeNumber: 1,
resolution: '2160p',
source: 'WEB-DL',
encoding: 'HEVC',
language: 'MULTI',
}
The reference catalog exposes one playable representation per item, so it does not
advertise supportsPlaybackVariants. A provider with several encodes should return
one logical item during discovery and expand it into stable variant IDs only when
isSourceSelection is requested. See Describe playback quality.
Search and pagination
The reference catalog filters and sorts the complete result before applying a bounded page. Its next-page token is a string offset, but consumers must treat it as opaque.
async search(criteria: SourceSearchCriteria, pageToken?: string | number) {
const matchingItems = filterItems(criteria);
const result = paginate(matchingItems, pageToken, criteria.limit);
result.facets = {
years: [...new Set(matchingItems
.map((item) => item.productionYear)
.filter((year): year is number => year !== undefined))]
.sort((left, right) => right - left),
};
return result;
}
Browse hierarchy
The root contains Movies, Series and Videos folders. Selecting the example
series navigates through a season to two playable episodes. Unknown parents
return an empty page rather than leaking an implementation error.
Playback resolution
Only known, playable logical IDs resolve. Containers and unknown IDs fail clearly.
async resolvePlayback(sourceItemId: string): Promise<SourcePlaybackInfo> {
const url = PLAYBACK_URLS[sourceItemId];
if (!url) throw new Error(`No playable media exists for '${sourceItemId}'.`);
return {url};
}
The movie map uses openly distributed Blender Foundation resources. Replace every URL with media you own or are authorized to distribute when adapting the example. The fictional episode URLs are placeholders and are not expected to play.
Validate locally
From the example project directory:
pnpm validate
pnpm test
pnpm dev
The tests cover capabilities, hierarchy, filtering, sorting, pagination, recents and playback resolution. Follow Build a source addon for the design rules behind each method.