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

@port-labs/plugins-sdk

v0.0.1

Published

Framework-agnostic SDK for Port embedded plugins (postMessage host bridge, page filter merge); optional React helpers under /react

Readme

@port-labs/plugins-sdk

TypeScript/JavaScript SDK for Port custom plugins running inside the Port web app (usually in an iframe). For React, use usePortPluginData from @port-labs/plugins-sdk/react. For other stacks, the same host context is available via a small subscribe / snapshot store and synchronous getters. The package also helps merge dashboard page filters into Port entity-search queries (mergePageFilters).

Install

npm install @port-labs/plugins-sdk
yarn add @port-labs/plugins-sdk
pnpm add @port-labs/plugins-sdk

Optional peer: react ≥ 18 — only required if you import @port-labs/plugins-sdk/react.

Node: use an LTS version compatible with your bundler; this package declares engines.node ≥ 22.

What it does

  1. Listens for messages from the Port host (PORT_TOKEN, PLUGIN_DATA).
  2. When embedded in an iframe, asks the parent once for a token (REQUEST_PORT_TOKEN).
  3. Exposes the latest host payload through usePortPluginData (React) or getters and subscribe + getSnapshot (Vue, Svelte, Solid, vanilla JS, etc.).
  4. Provides mergePageFilters to combine your widget’s entity-search body with the page’s filter rules.

Host protocol

Your plugin and the Port UI must agree on these messages:

| Direction | event.data.type | Payload / role | | ------------- | -------------------- | --------------------------------------- | | Plugin → host | REQUEST_PORT_TOKEN | Ask the host for a JWT for Port API calls. | | Host → plugin | PORT_TOKEN | { token: string } | | Host → plugin | PLUGIN_DATA | { params, page, user, entity, baseUrl, theme? } |

Getters expose: params, page, user, entity, theme (via getParams(), getPage(), …), plus getToken() and getPortApiBaseUrl() (same data as PLUGIN_DATA plus the token). Call applyThemeCss() to inject the host theme stylesheet (see Theming and CSS variables).

Usage

React

Install react ≥ 18, then import from @port-labs/plugins-sdk/react:

npm install react
import { usePortPluginData } from '@port-labs/plugins-sdk/react';

function MyPlugin() {
	const { portToken, portApiBaseUrl, page, user, entity, params } = usePortPluginData();

	if (!portToken) return <p>Waiting for host…</p>;

	return (
		<pre>{JSON.stringify({ page, user, entity, params }, null, 2)}</pre>
	);
}

To match the Port UI colors, opt in to host theme CSS with applyThemeCss from the same hook (see Theming and CSS variables).

Other frameworks (store + getters)

The same host data is available without React. Call initPortPluginMessaging() once early if you want (getters and subscribe call it automatically). Use subscribe(listener) to re-run when the host sends new data; read state with getSnapshot(). getServerSnapshot() is for SSR (empty static snapshot).

import {
	getSnapshot,
	getToken,
	subscribe,
	type PluginHostState,
} from '@port-labs/plugins-sdk';

function bindHostToView(update: (state: PluginHostState) => void) {
	const unsub = subscribe(() => update(getSnapshot()));
	update(getSnapshot());
	return unsub;
}

Synchronous reads anywhere (no extra listeners):

import { getToken, getPortApiBaseUrl } from '@port-labs/plugins-sdk';

async function callPortSearch(body: unknown) {
	const token = getToken();
	const base = getPortApiBaseUrl();
	if (!token || !base) throw new Error('Plugin not ready');
	// …
}

Merging page filters with a widget search query

Use mergePageFilters so results respect both the widget query and the dashboard page filters (page.pageFilters). Types such as EntitiesQuery, PageQuery, and Blueprint are exported from this package for typing your query and blueprint objects.

import { getPage, mergePageFilters, type Blueprint, type EntitiesQuery } from '@port-labs/plugins-sdk';

const widgetQuery: EntitiesQuery = {
	combinator: 'and',
	rules: [/* your rules */],
};

const merged = mergePageFilters(widgetQuery, getPage()?.pageFilters, blueprint as Blueprint);

mergeWidgetQueryWithPageQuery is an alias for mergePageFilters. The constant DASHBOARD_FILTERS_META_BLUEPRINT identifies dashboard-wide filter rules in page filter arrays.

Theming and CSS variables

The host can send a theme object on PLUGIN_DATA:

type Theme = {
	mode: string;
	css: string; // `:root { --background-primary: ...; --text-high: ...; }`
};

The SDK stores this on theme in the snapshot and from usePortPluginData(). To opt in to applying the host theme CSS, call applyThemeCss() (from the main package or via the hook):

import { useEffect } from 'react';
import { usePortPluginData } from '@port-labs/plugins-sdk/react';

function MyPlugin() {
	const { applyThemeCss } = usePortPluginData();

	useEffect(() => {
		applyThemeCss();
	}, [applyThemeCss]); // `applyThemeCss` identity updates when host `theme.css` changes

	// …
}

Vanilla / non-React:

import { applyThemeCss, subscribe } from '@port-labs/plugins-sdk';

subscribe(() => {
	applyThemeCss();
});
applyThemeCss();

This injects a <style id="port-plugin-theme"> tag with the theme’s css into document.head. If the host omits theme or css, that element is removed.

In your own CSS, consume variables with safe fallbacks, for example:

body {
	background: rgb(var(--primary, 245, 247, 250));
	color: var(--text-high, #1a1a2e);
}

.plugin-container {
	background: var(--background-primary, #fff);
}

.data-row {
	background: var(--background-contrast, #fff);
	border-color: var(--border-contrast-medium, #e2e8f0);
}

Common variables you can reuse include (non-exhaustive):

  • --background-primary: main surface/background color
  • --background-dim / --background-dim-transparent: softer backgrounds and cards
  • --background-contrast: high-contrast surface
  • --text-high / --text-medium / --text-low: primary, secondary, and subtle text
  • --border-medium / --border-contrast-medium: border colors
  • --primary: RGB triple for the primary color, used via rgb(var(--primary))

API overview

React entry (@port-labs/plugins-sdk/react)

| Export | Description | | ------ | ----------- | | usePortPluginData | Hook backed by useSyncExternalStore over the same store as the main entry. Includes theme and applyThemeCss (identity updates when theme.css changes so useEffect(..., [applyThemeCss]) reapplies styles). | | Types | Re-exported for convenience: Theme, PluginHostState, Page, User, Entity, Params (same as the main entry). |

Main entry (@port-labs/plugins-sdk)

| Export | Description | | ------ | ----------- | | getToken, getUser, getEntity, getPage, getParams, getPortApiBaseUrl, getTheme | Read the current snapshot. | | applyThemeCss | Apply or clear host theme CSS in document.head (#port-plugin-theme). | | initPortPluginMessaging | Ensures the listener is registered (also run automatically by getters and subscribe). | | subscribe, getSnapshot, getServerSnapshot | Framework-agnostic reactive core (subscribe notifies; getSnapshot reads). | | mergePageFilters | AND-merge widget EntitiesQuery with page filters and blueprint rules. | | mergeWidgetQueryWithPageQuery | Alias for mergePageFilters. | | Types | Host context: Page, User, Entity, Params, Theme, PluginHostState. Search/blueprint: EntitiesQuery, PageQuery, Blueprint, AnyEntitiesQueryRule, PluginParamType, PluginParamValue, … |

License

ISC