Concepts
The key ideas behind Limeplay's architecture.
Feature Model
Limeplay is built from features. A feature owns one capability, such as playback, volume, timeline, playlist, player setup, or asset loading.
Each feature can provide:
- A namespaced store slice, such as
playback.pausedorvolume.level. - A setup component that syncs native media or Shaka Player state.
- Typed events for state changes, such as
play,seek, orassetloaded.
You compose the features you need with createMediaKit.
"use client"
import { createMediaKit } from "@/components/limeplay/media-provider"
import { mediaFeature } from "@/hooks/limeplay/use-media"
import { playbackFeature } from "@/hooks/limeplay/use-playback"
import { volumeFeature } from "@/hooks/limeplay/use-volume"
export const media = createMediaKit({
features: [mediaFeature(), playbackFeature(), volumeFeature()] as const,
})
export const { MediaProvider, useMediaApi, useMediaEvents, useMediaStore } =
mediaUse this page to understand the model. Use the Hooks section when you need exact APIs.
Store
Each MediaProvider creates an isolated Zustand store. Multiple players on the same page do not share state unless you explicitly wire them together.
Read state with selectors so components only re-render for the fields they use.
const paused = usePlaybackStore((state) => state.paused)
const volume = useVolumeStore((state) => state.level)For imperative code, use the media API returned by your kit.
const api = useMediaApi()
api.setState(({ volume }) => {
volume.level = 0.5
})Event And Action Bridge
Limeplay keeps events and actions separate.
- UI components call actions, such as
playback.togglePaused()ortimeline.seek(). - Actions update the native media element or Shaka Player.
- Native events flow back into feature setup components.
- Feature setup components update the store and emit typed events.
Subscribe to events with useMediaEvents.
const events = useMediaEvents()
React.useEffect(() => {
return events.on("play", () => {
console.log("playing")
})
}, [events])For exact event names and payloads, use the relevant hook docs. Each feature exports its own event type.
Component Hierarchy
Most Limeplay players follow this shape. Blocks package this structure for you; custom players can compose the pieces directly.
Source Loading
For blocks, pass content through source and loading behavior through loading. Blocks use use-playback-source, which calls use-asset internally.
Use useAsset directly when you need lower-level source orchestration. Use usePlayer directly only when you intentionally want to bypass asset, playlist, preload, and recovery behavior.
See Usage for the full loading model.
Core Dependencies
- Shaka Player for HLS, DASH, adaptive bitrate, and DRM-capable playback.
- Zustand and Immer for isolated player state.