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

@monetize.software/sdk-extension

v3.0.0-alpha.5

Published

Monetize SDK for Chrome extensions — single source of truth via offscreen document, drop-in compatible with @monetize.software/sdk public API

Readme

@monetize.software/sdk-extension

SDK for Chrome extensions. A single offscreen document holds the BillingClient, AuthClient and EventTracker — the single source of truth for all tabs, popups, side panels, and extension pages.

The content-script public API is drop-in compatible with @monetize.software/sdk — the host writes import { PaywallUI } from '@monetize.software/sdk-extension' and gets the same class with the same method set.

⚠️ Bundle as an npm dependency. Do not load from a CDN. Chrome Web Store MV3 policy forbids remote code execution — every line of JS your extension runs must be reviewable at submission time and ship inside the extension package. pnpm add @monetize.software/sdk-extension and bundle it with Vite/Rollup/webpack like any other npm dep. Loading this package (or @monetize.software/sdk, or @monetize.software/sdk-react) from esm.sh/unpkg/jsDelivr from a content script, popup, or service worker will get the extension rejected by review, or removed retroactively if the policy violation is spotted later. This is also why we publish sdk-extension as a separate package — its content-script bundle has all dependencies inlined, no runtime fetch of code.

Architecture

content script (per tab) ──port──▶ service worker ──port──▶ offscreen
        │                              (forwarder)              │
   Shadow DOM modal                                  BillingClient
   RemoteBillingClient                               AuthClient
                                                     EventTracker
                                                     UserWatcher
  • content-script: UI + RemoteBillingClient (proxy over a port into offscreen).
  • service worker: content↔offscreen router; OAuth flow via chrome.identity (offscreen can't access it directly).
  • offscreen: the real SDK state, survives tab closes, the sole coordination point for auth refresh / trial counter / analytics batching.

Status

Phase 0 — skeleton: package.json, vite multi-entry, wire-protocol types, stubs for content/offscreen/sw and a demo-extension manifest. Actual routing and RemoteBillingClient come in the next phases.

See TODO in the repo and src/shared/protocol.ts for the message contract.

Usage (target shape, when complete)

In the extension:

// service-worker.ts
import { installRouter } from '@monetize.software/sdk-extension/sw';
installRouter({ offscreenUrl: chrome.runtime.getURL('offscreen.html') });
// offscreen.html → offscreen.ts
import { startOffscreenServer } from '@monetize.software/sdk-extension/offscreen';
startOffscreenServer({ paywallId: '...', apiOrigin: 'https://...' });
// content-script.ts (in every tab)
import { PaywallUI } from '@monetize.software/sdk-extension';
const paywall = new PaywallUI({ paywallId: '...', apiOrigin: '...' });
paywall.open();  // exactly like @monetize.software/sdk

On websites — keep using @monetize.software/sdk, nothing changes.

Manifest: what to declare in the host extension

The SDK itself does not add anything to the manifest — the host extension picks permissions to match its own UX. Minimum for the SDK to work:

{
  "permissions": ["offscreen", "storage"],
  "host_permissions": ["https://api.monetize.software/*"],
  "background": { "service_worker": "sw.js", "type": "module" }
}

Optional:

  • "permissions": ["identity"] — if you enable OAuth flows (auth: true + Google/etc.).
  • web_accessible_resources for offscreen.html is not required — the document is created by the service worker via chrome.offscreen.createDocument, that's a Chrome API and doesn't need WAR. Listing it adds attack surface (any site could <iframe> your offscreen, plus it fingerprints your extension ID).

host_permissions — what to pick

host_permissions control two things: where the extension can fetch (from offscreen / SW / content-script) and which origins the content-script can be injected into (together with content_scripts.matches).

| Scenario | Recommendation | |---|---| | Host extension already needs <all_urls> (recorder, all-sites tool, assistant) | Keep <all_urls>. SDK works as-is. Risk: Chrome Web Store review for <all_urls> is a manual audit and takes longer; AV vendors (Avast/Kaspersky/etc.) are more likely to flag such extensions as PUA. That's the price of broad injection — it's a property of your use case, not an SDK risk. | | Host extension only talks to your backend and gates its own features (popup tool, side-panel app) | Do NOT request <all_urls>. Your apiOrigin is enough: ["https://api.your-domain.com/*"]. No content-script injection on every site needed. | | Hybrid — popup tool, but content-script needed on a narrow list of domains | Constrain both host_permissions and content_scripts.matches to those domains: ["https://*.your-target.com/*", "https://api.your-domain.com/*"]. |

The main signal to CWS/AV: the narrower host_permissions, the less suspicion. Keep <all_urls> only when it's genuinely required for your UX, and be ready to justify it in CWS review (the "Permission justification" field).

Demo extension: build modes

For self-testing and e2e there's demo-extension/ — a reference implementation. Two builds are available:

pnpm build:demo       # production build (= the template clients can copy)
pnpm build:demo:e2e   # debug build — exposes window.__paywall for Playwright

build:demo does NOT put window.__paywall into the bundle (dead-code-eliminated via import.meta.env.MODE !== 'e2e'). The template clients copy stays clean: any script on the page could otherwise call paywall.open() / paywall.track() and abuse someone else's extension.

pnpm dev:demo builds in e2e mode (handy for live debugging from the DevTools console).