Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.discovr.media/llms.txt

Use this file to discover all available pages before exploring further.

A page is the personalized browse screen your user sees after selecting a profile. It has two main parts: a hero carousel at the top (featured titles), and recommendation rows below (each row is a horizontal “rail” of media). After your user selects a profile, you fetch a page with createPage() and getPage(). Discovr fills the page’s rows with personalized recommendations based on that profile’s viewing history. Rows come in four types—media (movie/TV thumbnails), top_n (ranked lists), navigation (drill-down destinations), and provider (filter by streaming service). See Rows overview for details and pagination.
Pages APIs require an active profile session. Start with selectProfile(), then fetch pages. See Sessions, Profiles & Sign Out for setup. Code snippets use TypeScript, Kotlin, and Swift tabs.
Illustrative UI only—hero from getPage(), stacked rails from getRows().
Light theme full-page browse screenshot: wide hero carousel at top with spotlight title art and synopsis, stacked vertical layout below showing the first recommendation row heading and horizontal poster thumbnails (media-style rail); models Discovr page = hero strip plus vertically stacked rows.

Hero vs rows

  • getPage() returns the page envelope, including hero (the large carousel at the top—ten spotlight-style items).
  • getRows() returns rows on that page, created on demand and paginated. Your UI stacks them vertically and scrolls; each row can be tapped for items or destinations as the row type implies.
Repeated createPage() calls with the same pageFilters in the same session reuse the same page id (deterministic snapshot for that browse context).
If getPage() returns 401 SESSION_EXPIRED against an old pageId (after selecting a new profile), recreate the page with the echoed filters rather than pinning ids forever—see Error handling.

Typical “tabs”: Home, Movies, Series

Apps often expose top-level browsing as tabs or modes. Discovr does not ship tab UI—you map each tab to a page created with filters:
IdeaApprox. createPage bodyPurpose
Home / mixed{} — omit pageFilters or send empty filtersBroad, default browse
Movies{ "pageFilters": { "media_type": "movie" } }Movie-first rail mix
Series{ "pageFilters": { "media_type": "tv" } }TV-first rail mix
Add an optional name ("Movies", "Series", etc.) when you store or debug tabs—responses can surface it depending on origin.

Stack-like navigation from rows

Some navigation-style rows don’t stop at scrolling: choosing an item pushes the user onto another page (a new pageId and its own hero + rows). Treat that like a navigation stack: opening a drill-in pushes a page on your stack; system back pops it. Today, deepest reachable depth is three levels counting the root—think root, then one drilled page, then one more leaf page. Going further purely via row-based navigation isn’t supported; design your UX accordingly.

Build the first surfaces

Use this flow once the SDK has a session for the chosen profile (selectProfile()).
1

Create pages for each top-level tab

Call createPage() for Home (no filters), Movies (media_type: "movie"), and Series (media_type: "tv"). Persist each returned id for that tab.
import { DiscovrClient } from "discovr";

const discovr = new DiscovrClient("your-client-id", {
	basePath: "https://api.discovr.media",
});

const home = await discovr.createPage({ name: "Home" });
const movies = await discovr.createPage({
	pageFilters: { media_type: "movie" },
	name: "Movies",
});
const series = await discovr.createPage({
	pageFilters: { media_type: "tv" },
	name: "Series",
});
2

Fetch hero metadata and rows

Render the carousel from getPage(tabPageId) and list rails from getRows(tabPageId) (optionally getRow() / getRowItems() once you drill into one row).
const page = await discovr.getPage(home.id);
const { rows, hasMore, nextPageToken } = await discovr.getRows(home.id, { limit: 10 });
console.log(page.hero.length, rows.length, hasMore, nextPageToken);
3

Handle push navigation from rows

When a navigation item resolves to another destination, you usually receive a distinct pageId: push that screen and load it with the same layering—getPage for the hero, getRows (then getRow() / getRowItems() when you open a rail). Pop back to the previous browse surface when the user navigates backward. Respect the three-level cap above when designing nested browse.

What’s next