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

@mattebox/cast-playground

v0.1.2

Published

A Cast receiver page under Google's real receiver framework in a desktop browser, with the device's platform and a sender played by the page around it. No device, no registration.

Readme

@mattebox/cast-playground

The playground runs a Cast receiver page in a desktop browser, under Google's real receiver framework. The page around the receiver acts as the device's platform and as one sender. You need no device and no registration, and you do not change the receiver page.

npx @mattebox/cast-playground http://localhost:5173/

The command prints an address. Open it in a browser. You see the receiver page in a frame of 1280 by 720, the size of a Chromecast screen, next to the controls of a sender.

| Part | What you do with it | | ------------ | ------------------------------------------------------------------------------------------------------------ | | Load content | You send a LOAD. You pick a listed stream, a resource of an SRG SSR media, or you type a URL | | Load | You set autoplay and a start time for the next LOAD. The LOAD names a start time only when you set one | | Transport | You send PLAY, PAUSE, STOP, SEEK and SET_PLAYBACK_RATE, and you go to the live edge with "Go live" | | Tracks | You send EDIT_TRACKS_INFO. You choose among the tracks that the last status reported | | Receiver | You add a query to the receiver page's URL, and you restart the receiver. This part sends no message | | Messages | You read every message sent and answered, with its JSON. This part sends no message |

When you type a URL, you can also give a license URL, the sender's subtitles, and customData as JSON. Use customData when your receiver has conventions of its own.

Options

| Option | What it sets | | ---------------- | -------------------------------------------------------------------------------------------------------------------- | | <receiver url> | The URL of the receiver page, as you would open it in a browser. The page can be local or hosted, over http or https | | --port | The port of the playground. The default is 8010. The receiver's proxy uses the next port | | --host | The address the playground listens on. The default is localhost, which only this machine reaches | | --lan | The playground listens on every interface, so the local network reaches it. This is the same as --host 0.0.0.0 |

On the local network

npx @mattebox/cast-playground http://localhost:5173/ --lan

With --lan, the command prints one address of the playground for each network this machine is on. You can open that address on a phone, a tablet or another computer. You do not move the receiver page. The proxy reaches the page from this machine, so a dev server on localhost needs no change.

The two pages refer to each other with the address the browser asked for. One run therefore serves localhost and the network at the same time. You can play a protected stream from localhost, because a browser treats localhost as a secure context and only offers its DRM in a secure context.

The server

The playground uses Node's own http module and has no dependency. It starts two servers:

| Server | Port | What it serves | | --------- | ------------------- | --------------------------------------------------------------------------------------------------------------------- | | The page | --port, 8010 | The playground's page, built to static files, and config.json, which gives the URL of the receiver's frame | | The proxy | The next port, 8011 | The whole origin of the receiver page. The proxy adds platform.js as the first script in the head of every document |

The proxy changes only the HTML documents. It does these things:

  • It passes every other response through unchanged.
  • It follows the receiver's own paths.
  • It keeps a redirect inside the receiver's origin on the proxy.
  • It pipes a WebSocket through, so the hot reload of a dev server works in the frame.
  • It removes Content-Security-Policy and X-Frame-Options from the documents it serves. The page can then load in a frame, with the added script.
  • It answers with a 502 and a message when the receiver page does not answer.

How it works

On a device, the framework talks to the platform over a WebSocket at ws://localhost:8008/v2/ipc. On a desktop, that socket never opens, so the receiver context never becomes ready.

The playground serves the receiver page through a local proxy. The proxy changes one thing: it adds platform.js as the first script in the head of every HTML document, before the framework's script. platform.js replaces that one socket with messages to the playground's window. Every other socket is the real one and goes through the proxy. This includes the hot reload of a dev server.

The playground answers as the platform does. It sends the platform's ready message, with the capabilities of a registered device, and it connects one sender. The framework, the receiver's library and the receiver page are the same code that a device runs.

In this repository

npm run playground                          # over the repository's app, with hot reload
npm run playground -- <receiver url>        # over any receiver page
npm run playground -- <receiver url> --lan  # and on the local network

You run the playground from the sources with one command. The command builds the package when a source file is newer than the last build.

From code

You can start the playground from a script:

import { startPlayground } from "@mattebox/cast-playground";

const playground = await startPlayground({
  receiver: "http://localhost:5173/",
});
console.log(playground.url);
await playground.close();

License

MIT