npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@livo-tv/sdk

v1.13.0

Published

Embed the Livo player and studio in a third-party app

Readme

@livo-tv/sdk

Embed Livo in-DOM on your origin. Native React is the partner path: LivoPlayer, LivoHostStudio, and LivoGuestStudio. Do not iframe player.livo.tv.

import { LivoPlayer, applyEmbedTheme, type EmbedTheme } from "@livo-tv/sdk";
import {
	LivoHostStudio,
	LivoGuestStudio,
	StudioWindowGate,
	studioRoomLabels,
} from "@livo-tv/sdk/studio";
import "@livo-tv/sdk/styles.css";

const theme: EmbedTheme = {
	accent: "#0F6FF5",
	background: "#0b1220",
	foreground: "#f8fafc",
	radius: "8px",
	fontFamily: "Inter, sans-serif",
	mode: "dark",
};

<LivoPlayer
	streamId="s1"
	theme={theme}
	onPlaybackState={(state) => {
		/* loading | waiting | playing | paused | ended | error */
	}}
	onError={(error) => {
		/* not_found | playback */
	}}
/>;

@livo-tv/sdk, @livo-tv/sdk/studio, and @livo-tv/sdk/condo (LivoCommunity) are client entries (the published bundles start with "use client"). Import them from "use client" files in Next.js App Router — do not import those entries from a Server Component page. Do not install @livo-tv/blocks or add transpilePackages — the SDK bundles its UI internals. Tailwind hosts that restyle the embed can @source node_modules/@livo-tv/sdk/dist/*.{js,cjs,mjs}.

Root <LivoStudio> still iframes app.livo.tv and is not the partner contract. Native studio has no runtime dependency on player.livo.tv (no postMessage bridge, no hard-coded player origin). The hosted-player URL helpers (playerUrl) stay available for Livo's own player app.

Native studio (RealtimeKit)

Install:

pnpm add @livo-tv/sdk
# studio only:
pnpm add @cloudflare/realtimekit

Peers:

  • react / react-dom (required)
  • @cloudflare/realtimekit (optional, lazy-imported; studio only)
  • hls.js (optional, for <LivoPlayer> on browsers without native HLS)

Do not add @livo-tv/blocks as a host dependency. The published player and studio bundles inline it (and the UI kit). Next.js does not need transpilePackages.

Send this header on the route that mounts the studio (camera, mic, and screen share):

Permissions-Policy: camera=(self), microphone=(self), display-capture=(self)

Wrap the studio in StudioWindowGate with a stable lockKey (stream id or host token), not the partner pathname. The lock uses BroadcastChannel and is origin-scoped, so /dashboard/studio and /events/123/studio on the same origin still see each other.

<StudioWindowGate lockKey={`host:${streamId}`} labels={gateLabels}>
	<LivoHostStudio
		token={hostToken}
		apiUrl="https://api.livo.tv"
		labels={studioRoomLabels((key) => key)}
		embed
		theme={theme}
	/>
</StudioWindowGate>

theme is an EmbedTheme object (or a hosted encoded string). applyEmbedTheme writes CSS variables onto the studio container, not document.documentElement, so a partner shell keeps its own chrome.

Omit playerOrigin in native embeds. The watch-share control only appears when you pass a player origin; native partners should share their own watch URL.

Regression page: pnpm example:embed serves examples/partner-embed on http://localhost:3003.

Community (condo) — comments on every video, live Q&A only while a stream or webinar is preview / public. After the event, Q&A stays closed. Comments stay closed unless the organizer sets commentsAfterEnd.

Theater-only: native <LivoPlayer> does not show comments/Q&A unless you pass showCommunity. Hosted iframes show the panel by default; hide it with ?community=0 (or playerUrl(id, { community: false })).

Custom layout: mount <LivoCommunity> next to a theater-only player, or call createCommunityClient / the public HTTP API for a fully custom UI. Pass a public apiUrl for viewers (mode="viewer", polls). Pass JWT / X-Api-Key headers and mode="control" for settings, pin/hide/delete, and Q&A highlight/dismiss/answer. Unregistered posters send displayName, optional picture URL, and guestId. Supply displayName (and optional picture) to skip the name field; otherwise the composer asks once and stores livo-community-identity. Hosted iframes use ?name= / ?avatar= when the built-in panel is on.

import { LivoPlayer } from "@livo-tv/sdk";
import { LivoCommunity } from "@livo-tv/sdk/condo";
import "@livo-tv/sdk/styles.css";

<LivoPlayer streamId={stream.id} />

<LivoCommunity
	apiUrl="https://api.livo.tv"
	targetKind="stream"
	targetId={stream.id}
	flags={stream.community}
	mode="viewer"
	displayName="Ada"
	picture="https://cdn.example/ada.jpg"
	guestId="guest-ada"
/>;

Headless client (same public routes, your own UI):

import { createCommunityClient } from "@livo-tv/sdk/condo";

const client = createCommunityClient({
	apiUrl: "https://api.livo.tv",
	targetKind: "stream",
	targetId: stream.id,
	mode: "viewer",
});
await client.list({ type: "comment" });

Server (Node / Workers):

import { createLivoServerClient } from "@livo-tv/sdk/server";

const livo = createLivoServerClient({ apiKey: process.env.LIVO_API_KEY! });
const { vodId, uploadId, partSize } = await livo.createVod({
	filename: "talk.mp4",
	contentType: "video/mp4",
	byteSize: 12_000_000,
	sha256: "64-lowercase-hex",
});
await livo.completeVodUpload(vodId, {
	parts: [{ partNumber: 1, etag: '"etag-from-put"' }],
});
const { hostToken, guestToken } = await livo.mintHostSession(streamId, {
	displayName: "Host",
});

Browser part PUTs go to the presigned R2 URL. Bucket CORS is PUT * with ETag exposed; mint the URL with lk_ on your server.

GitHub livo-tv/sdk + npm OIDC publish are a human handoff (same as @livo-tv/blocks).