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

@playpilot/tpi

v8.34.1

Published

Link Injections (also called TPI (Text Playlink Injection)) adds links to any page content. These links open a popover or modal with relevant information for any given movie or show. Alternatively, they link directly to the related PlayPilot page. This al

Readme

💉 PlayPilot Link Injections

Link Injections (also called TPI (Text Playlink Injection)) adds links to any page content. These links open a popover or modal with relevant information for any given movie or show. Alternatively, they link directly to the related PlayPilot page. This also contains the Streaming Guide all under one script. TPI and the Streaming Guide are tightly linked as they share many components.

Development

Start development server using:

npm run dev

The dev environment will be available at:

localhost:3000

The root page contains a test article with various real-world scenarios that are tricky to inject in to. The primary +layout.svelte file confusingly contains the actual content for this page. This is because the +page.svelte file is what is eventually build into the final script, ignoring anything in the +layout file. /elements Contains various elements to help during debugging such as modals, popovers, and some streaming guide components, as well as some other individual components for titles. /explore Contains the streaming guide.

The final script is build including the main.ts or mount.ts entry files. These do not run when running npm run dev. To work on these files you can instead run:

npm run dev-build

and visit the dev environment at:

localhost:3000/build.html

This does currently not feature any HMR or other fancy-ness. It's just an HTML file.

Build

To build the final script simply run npm run build.

The final build differs largely from the development environment. The development environment uses SvelteKit, but the final build only uses Svelte which is build to distrinct files:

  • dist/link-injections.js. This is the primary entry point and should be as light as possible. Svelte is not used here. This fetches the domain config file, and if that is in order it will fetch injections along side the next script.
  • dist/mount.js. This contains everything needed for both TPI and the Streaming Guide. All Svelte components including their CSS are bundled in this one file.
  • dist/editorial.mount.js. This contains the same as dist/mount.js plus everything needed for the editorial mode, which are the editorial components themselves. Whether this file or mount.js are loaded are determined by dist/link-injections.js based on the existence of a URL param or an auth cookie.

Publishing

The project is published on NPM as a package, but only the final dist file is relevant. This file is included in the repo so that it can be picked up by jsdelivr.net, which we use as a CDN for the script. The url that is presented to clients is a redirect from https://scripts.playpilot.com/link-injection.js to https://cdn.jsdelivr.net/npm/@playpilot/tpi@[version]/dist/link-injections.js. We use a direct version rather than @latest to have better control over caching, as @latest is cached both on jsdelivr and the end user's browser.

The build and publish a new version simply run:

npm run release major|minor|patch

Before doing this you might want to make sure you are logged in to NPM by running npm login.

To publish the script manually follow these steps (this is often done for beta versions):

  1. Build the script using `npm run build, optionally commit the new file as a separate commit
  2. Bump the package.json version, optionally commit this change
  3. Publish the script using npm publish --access public (or npm publish --access public --tag next for beta versions)
  4. Update redirect rules on Cloudflare to match the new version, which can be found under the "TPI: Latest script version (jsdelivr)" rule (or "TPI: Beta script version (jsdelivr)" for beta versions).

Notes

The script inserts elements right on the page it is used, because of that all elements relevant to the script automatically inherit styling from the page. Because of this it's very important to adhere to some rules:

  • Avoid semantics tags. Tags such as h1, header, p, and more, are convenient but are very likely to be styled quite specifically. Instead, stick to general elements such as div and span, but with proper attributes. A heading might use div role=heading level=2, a dialog might use div role=dialog. While this doesn't do anything visually, it keeps accessibility features intact.
  • Do not use global styling.. Styling from the page leaks into element from our script, but the opposit is also true. Any global styling we apply will apply to the page itself. Stick to scoped styling either via styling in Svelte components, or stick to very specific class names either on the elements themselves or as parents. src/lib/scss/global.scss holds such elements. Some other global css in included in src/routes/+page.svelte`
  • Use css variables for styling. All elements that are displayed on the page might need to be styled to match the page. This is done through css variables rather than just overwriting style via selectors. This makes it easier for us to change styling without having to worry about updating partner specific styling. These css variables often have other css variables as fallbacks, and are always prefixed with --playpilot. For instance var(--playpilot-dialog-background, var(--playpilot-light)). This can be further expanded to var(--playpilot-title-background, var(--playpilot-dialog-background, var(--playpilot-light))). In this case all default styling is still handled through our own styling --playpilot-light, but can be overwritten on all relevant elements with --playpilot-dialog-background, and more specifically with --playpilot-title-background. To make this process easier, use the theme SCSS helper function. This will output a css variable with a default. The --playpilot- prefix is automatically added. theme(title-background, #ff0000);
  • Avoid external libraries. The script is meant to be as lean as possible, it needs to load quickly. External libraries by nature contain things we don't need and add unnecessary bloat. That's not always true, so use your best judgement. This only includes libraries that would be included in the final build of course.
  • Do not use non-vector images within the script. The script is compiled to a single file. Including non-vector images will lead to a much larger file size as these images will need to be inlined and this is not compressable. Stick to SVGs and make sure these SVGs are inlined.