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

@bota-apps/extension-sdk

v0.2.9

Published

The runtime contract for embeddable @bota-apps extension apps: the host↔iframe bridge (isEmbedded/notifyHost, install-context parsing), the standalone ExtensionShell chrome, and createExtensionApp — the bootstrap factory that renders an extension bare whe

Readme

@bota-apps/extension-sdk

The runtime contract for embeddable @bota-apps extension apps. An extension runs either embedded in a host (inside an iframe) or standalone (its own tab, for local dev); this package owns that duality so each extension only writes its pages.

Install

pnpm add @bota-apps/extension-sdk
# peers: react, react-dom

Usage

createExtensionApp returns an App that renders the current page bare when embedded in a host and wraps it in the standalone ExtensionShell (sidebar + history-based nav) when run on its own:

import { createExtensionApp } from "@bota-apps/extension-sdk";
import { Gift } from "lucide-react";
import { MilestonesRoute } from "./routes/milestonesRoute";

const { App } = createExtensionApp({
  appName: "Project Milestones",
  appIcon: Gift,
  appVersion: "0.1.0",
  pages: [{ path: "/", label: "Milestones", icon: Gift }],
  readyMessage: { kind: "milestones.ready", appId: "milestones" },
  renderPage: (path) => (path === "/" ? <MilestonesRoute /> : null),
});

Custom install context

The host passes an AppInstallationContext (tenantId, tenantName, appToken) on the URL. Extensions needing extra fields pass their own readContext, layering on top of the base readContextFromUrlcreateExtensionApp is generic over the resulting context type:

readContext: (search) => {
  const base = readContextFromUrl(search);
  const params = new URLSearchParams(search);
  return { ...base, projectId: params.get("projectId") ?? undefined };
},

Talking to the host

The bridge helpers are the entire host↔iframe contract. isEmbedded() reports the mode; notifyHost(message) posts a message up to the host window (a no-op when standalone, so the same code runs in both modes). Each extension owns its own message union:

import { isEmbedded, notifyHost } from "@bota-apps/extension-sdk";

if (isEmbedded()) {
  notifyHost({ kind: "milestones.submitted", taskId });
}

API

| Export | Kind | What | | -------------------------- | --------- | ---------------------------------------------------------------------------- | | createExtensionApp | function | Bootstrap factory returning { App } — bare when embedded, shell standalone | | ExtensionShell | component | Standalone sidebar chrome (app name/icon/version + page nav) | | isEmbedded | function | true when running inside a host iframe | | notifyHost | function | Post a message up to the host window (no-op standalone) | | readContextFromUrl | function | Parse the base install context from a URL search string | | standaloneContext | constant | Fallback install context used when standalone | | AppInstallationContext | type | Base install-context shape (tenantId, tenantName, appToken) | | ExtensionPage | type | One navigable page (path, label, icon) | | ExtensionShellProps | type | Props for ExtensionShell | | CreateExtensionAppConfig | type | Config accepted by createExtensionApp |

Part of the @bota-apps packages monorepo.