@nivo-sdk/player-react
v0.1.1
Published
A drop-in React video player for Nivo-hosted videos. It wraps [Vidstack](https://vidstack.io) with the Nivo default control layout, resolves the HLS stream + metadata for a `videoId`, bundles `hls.js` (no runtime CDN fetch), and wires viewer analytics thr
Readme
@nivo-sdk/player-react
A drop-in React video player for Nivo-hosted videos. It wraps
Vidstack with the Nivo default control layout, resolves
the HLS stream + metadata for a videoId, bundles hls.js (no runtime CDN
fetch), and wires viewer analytics through @nivo-sdk/analytics automatically.
Install
bun add @nivo-sdk/player-react
# or: npm install @nivo-sdk/player-reactreact and react-dom (v19) are peer dependencies. @vidstack/react and
hls.js are bundled in — you do not install them separately.
Import the stylesheet once, near your app root:
import '@nivo-sdk/player-react/styles.css'This is a single self-contained file (Vidstack base + default theme + video layout, inlined) — no other Vidstack CSS import is required.
'use client' — client component only
NivoPlayer and NivoProvider render browser-only APIs (hls.js, Vidstack
custom elements) and are marked 'use client'. They cannot render on the
server.
Next.js App Router
Load the player with dynamic(..., { ssr: false }) so it never runs during SSR:
'use client'
import dynamic from 'next/dynamic'
import { NivoProvider } from '@nivo-sdk/player-react'
const NivoPlayer = dynamic(
() => import('@nivo-sdk/player-react').then(m => m.NivoPlayer),
{ ssr: false }
)
export function Watch({ videoId }: { videoId: string }) {
return (
<NivoProvider writeKey="nvo_pub_xxx">
<NivoPlayer videoId={videoId} />
</NivoProvider>
)
}Quickstart
Wrap your app (or a subtree) in NivoProvider to supply the analytics
writeKey and any host overrides, then render a NivoPlayer per video:
'use client'
import { NivoProvider, NivoPlayer } from '@nivo-sdk/player-react'
export function Player() {
return (
<NivoProvider writeKey="nvo_pub_xxx">
<NivoPlayer videoId="kT9aFp2xQ7mB" accentColor="#6d28d9" />
</NivoProvider>
)
}The player fetches the video's metadata (title, poster, aspect ratio, timeline
sprite thumbnails) and stream URL from the Nivo watch service, so you only pass
a videoId. writeKey may be set on the provider (shared by every player) or
per-player via the writeKey prop.
If a consumer swaps
videoIdon a mounted player, give the player akey={videoId}so it remounts cleanly — analytics attaches on provider setup, and remounting guarantees a fresh monitor for the new video.
Props
NivoPlayer takes a single videoId at minimum; everything else is optional.
It also forwards a ref to the Vidstack
MediaPlayerInstance for
imperative control.
| Prop | Type | Default | Description |
|---|---|---|---|
| videoId | string | — (required) | Nivo video id to resolve, load, and play. |
| autoPlay | boolean | false | Start playback on load. Browsers require muted for autoplay to succeed. |
| muted | boolean | false | Start muted. |
| loop | boolean | false | Loop playback. |
| startTime | string \| number | 0 | Start offset — seconds as a number, or a string like 90 or 1h2m3s. |
| poster | string | video metadata poster | Override the poster image URL. |
| aspectRatio | string | video metadata, else 16/9 | CSS aspect ratio, e.g. 16/9. |
| accentColor | string | Vidstack default | Control accent color — mapped to the --media-brand CSS variable. |
| defaultQuality | 'auto' \| number | auto | Reserved. Not yet wired — see Roadmap. |
| writeKey | string | NivoProvider writeKey | Analytics publishable key. Presence enables analytics. |
| metadata | Record<string, unknown> | — | Custom key/values forwarded to the analytics monitor. |
| analytics | boolean | true when a writeKey is present | Set false to disable analytics for this player. |
| onPlay / onPause / onEnded / onTimeUpdate / onError | Vidstack event handlers | — | Forwarded to the underlying MediaPlayer. |
| onQualityChange | (quality: VideoQuality \| null) => void | — | Fires on a quality switch, after the analytics bridge reports it. |
| ref | Ref<MediaPlayerInstance> | — | Imperative Vidstack player handle. |
The exported types NivoPlayerProps, MediaPlayerInstance, and VideoQuality
are available for typing refs and handlers without importing @vidstack/react
directly.
Analytics
When a writeKey is present and analytics is not false, the player attaches
a @nivo-sdk/analytics monitor to the underlying <video> element once the
provider is ready. It reports the standard view lifecycle plus quality_change
events (bridged from Vidstack's HLS quality switches). The monitor is destroyed
on unmount and on videoId change.
Pass extra context with the metadata prop — it is forwarded verbatim into the
monitor options and attached to every beacon.
Theming
Set accentColor for the quickest customization — it maps to Vidstack's
--media-brand custom property on the layout root, coloring sliders, buttons,
and focus rings:
<NivoPlayer videoId="..." accentColor="#6d28d9" />For deeper control, target any of
Vidstack's CSS variables (e.g.
--media-brand, --media-controls-color, --video-border-radius) in your own
stylesheet, scoped to a wrapper around the player.
Staging / self-host overrides
The player defaults to Nivo production hosts (stream.nivo.video for
playback, analytics.nivo.video for ingest). Override per environment on the
provider:
<NivoProvider
writeKey="nvo_pub_xxx"
watchBaseUrl="https://watch.getomni.dev"
ingestUrl="https://analytics.getomni.dev"
>
<NivoPlayer videoId="kT9aFp2xQ7mB" />
</NivoProvider>watchBaseUrl— origin of the Nivo watch service (stream + metadata). The player appends/v1/v/<id>(stream) and/v1/videos/<id>(metadata).ingestUrl— origin of the analytics ingest service. The monitor appends/v1/collect.
Roadmap
defaultQuality— Vidstack exposes quality selection only afterhls.jsreports levels, so seeding an initial cap requires post-load interaction with the player's quality list. The prop is accepted but not yet wired; it is a follow-up.
