Skip to main content

Overview

FolderServerClient extends MediaClient to provide integration with EmbyTok’s folder-based streaming server. It supports local file browsing, orientation filtering, and localStorage-based favorites.

Constructor

import { FolderServerClient } from './services/FolderServerClient';

const client = new FolderServerClient(config);
config
ServerConfig
required
Server configuration with folder server details

Authentication

authenticate

Connects to the folder server and selects a streaming service.
authenticate(username: string, password: string): Promise<ServerConfig>
username
string
required
Username (used for display, defaults to ‘Folder User’)
password
string
required
Service ID or name to use (optional - will use current/first service if not provided)
url
string
Server URL
username
string
Username or ‘Folder User’ if not provided
userId
string
Selected service ID
token
string
Service ID (used for API requests)
serverType
'folder'
Always returns ‘folder’

Example

const config: ServerConfig = {
  url: 'http://localhost:3000',
  username: '',
  token: '',
  userId: '',
  serverType: 'folder'
};

const client = new FolderServerClient(config);

// Connect to server (auto-selects service)
const authConfig = await client.authenticate('User', '');

// Or specify a service
const authConfig = await client.authenticate('User', 'service-id-123');

Library Management

getLibraries

Fetches available folder libraries from the server.
getLibraries(): Promise<EmbyLibrary[]>
return
Promise<EmbyLibrary[]>
Array of library objects

Example

const libraries = await client.getLibraries();

libraries.forEach(lib => {
  console.log(`${lib.Name} (${lib.Id})`);
});

Video Retrieval

getVideos

Fetches videos from the folder server with server-side filtering.
getVideos(
  parentId: string | undefined,
  libraryName: string,
  feedType: FeedType,
  skip: number,
  limit: number,
  orientationMode: OrientationMode
): Promise<VideoResponse>
parentId
string | undefined
Library ID to fetch from (optional for favorites)
libraryName
string
required
Library name (not used, included for interface compatibility)
feedType
FeedType
required
  • 'latest': Server-side latest sort
  • 'random': Server-side random shuffle
  • 'favorites': Client-side filtering from localStorage
skip
number
required
Starting index for pagination
limit
number
required
Number of items to return
orientationMode
OrientationMode
required
Server-side orientation filter: ‘vertical’, ‘horizontal’, or ‘both’
items
EmbyItem[]
Array of video items
totalCount
number
Total number of items available
nextStartIndex
number
Index for the next page

Example

const response = await client.getVideos(
  'library-123',
  '',
  'latest',
  0,
  15,
  'vertical'
);

console.log(`Loaded ${response.items.length} of ${response.totalCount} videos`);
For favorites feed, the client fetches up to 5000 items and filters client-side using localStorage favorites.

Media URLs

getVideoUrl

Generates streaming URL for a video file.
getVideoUrl(item: EmbyItem): string
item
EmbyItem
required
Video item to stream
return
string
Streaming endpoint URL with service ID

getImageUrl

Not supported for folder server (returns empty string).
getImageUrl(
  itemId: string,
  tag?: string,
  type?: 'Primary' | 'Backdrop'
): string
return
string
Always returns empty string

Example

const videoUrl = client.getVideoUrl(video);
// http://localhost:3000/api/folder/stream/video-id-123?serviceId=service-id

const thumbnailUrl = client.getImageUrl(video.Id);
// '' (empty - no thumbnails for folder server)

Favorites Management

FolderServerClient stores favorites in localStorage instead of server-side playlists.

getFavorites

Retrieves favorited item IDs from localStorage.
getFavorites(libraryName: string): Promise<Set<string>>
libraryName
string
required
Library name (not used, included for interface compatibility)
return
Promise<Set<string>>
Set of item IDs stored in localStorage

toggleFavorite

Toggles favorite status in localStorage.
toggleFavorite(
  itemId: string,
  isFavorite: boolean,
  libraryName: string
): Promise<void>
itemId
string
required
Video item ID
isFavorite
boolean
required
Current status: true = remove from favorites, false = add to favorites
libraryName
string
required
Library name (not used, included for interface compatibility)

Example

// Load favorites
const favoriteIds = await client.getFavorites('');
console.log(`${favoriteIds.size} favorites`);

// Toggle favorite
const isFavorite = favoriteIds.has(video.Id);
await client.toggleFavorite(video.Id, isFavorite, '');

Storage Key Format

embytokFolderFavorites:{serverUrl}:{serviceId}
This allows different favorite lists per server and service.

Complete Usage Example

import { ClientFactory } from './services/clientFactory';

// Authenticate with folder server
const config = await ClientFactory.authenticate(
  'folder',
  'http://localhost:3000',
  'User',
  '' // Auto-select service
);

const client = ClientFactory.create(config);

// Get libraries
const libraries = await client.getLibraries();
const firstLib = libraries[0];

// Load latest vertical videos
const { items, totalCount } = await client.getVideos(
  firstLib.Id,
  '',
  'latest',
  0,
  15,
  'vertical'
);

// Check favorites
const favoriteIds = await client.getFavorites('');

items.forEach(video => {
  const url = client.getVideoUrl(video);
  const isFav = favoriteIds.has(video.Id);
  
  console.log(`${video.Name} - Favorite: ${isFav}`);
  console.log(`Stream: ${url}`);
});

// Add first video to favorites
await client.toggleFavorite(items[0].Id, false, '');

API Endpoints

The client communicates with these folder server endpoints:

Ping

GET /api/folder/ping
Response: { ok: boolean }

Services

GET /api/folder/services
Response: {
  items: Array<{ id: string, name: string, isActive?: boolean }>,
  currentServiceId?: string
}

Libraries

GET /api/folder/libraries?serviceId={serviceId}
Response: { items: EmbyLibrary[] }

Videos

GET /api/folder/videos?serviceId={serviceId}&libraryId={libraryId}&feedType={feedType}&skip={skip}&limit={limit}&orientationMode={orientationMode}
Response: {
  items: EmbyItem[],
  totalCount: number,
  nextStartIndex: number
}

Stream

GET /api/folder/stream/{itemId}?serviceId={serviceId}
Response: Video file stream

Implementation Details

Service ID

The service ID is stored in both token and userId fields of ServerConfig and appended to all API requests as a query parameter.

Favorites Storage

Favorites are stored in localStorage as JSON arrays:
["video-id-1", "video-id-2", "video-id-3"]

Favorites Feed

When feedType === 'favorites', the client:
  1. Fetches up to 5000 items from the ‘latest’ feed
  2. Filters client-side using localStorage favorites
  3. Paginates the filtered results
This approach works well for moderate-sized libraries.

See Also

Build docs developers (and LLMs) love