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

@undefineds.co/extension-sdk

v0.1.1-rc.0

Published

`@undefineds.co/extension-sdk` defines the boundary between an applet and the host that runs it. An applet declares its identity, layout structure, and content slots. The host owns authentication, Pod initialization, application navigation, native capabil

Readme

Applet SDK

@undefineds.co/extension-sdk defines the boundary between an applet and the host that runs it. An applet declares its identity, layout structure, and content slots. The host owns authentication, Pod initialization, application navigation, native capabilities, and final composition.

The first planned product consumer is Xpod. Xpod can use the same layout language as Linx while exposing a settings-first entry such as Models, Pod, Network, and Services. Linx production layout remains on its current composition until a later migration.

Layout responsibilities

The SDK has two layout layers:

  • AppLayout is host-owned. It renders the outer application frame, including product navigation, host header, and the active applet surface.
  • SinglePaneLayout, TwoPaneLayout, and ThreePaneLayout render applet workspaces inside the host frame. They own pane geometry, responsive list-to-detail navigation, separators, and scroll containment.

Applets do not render product navigation, inspect viewport width, or branch on whether they run in Linx, Xpod, or a standalone host.

Define an applet

New applets should use a descriptor-based layout module. The manifest keeps the legacy layout field for extension discovery, and the layout.descriptor gives hosts a portable workspace contract.

import {
  defineApplet,
  defineAppletLayout,
  type WebExtensionHost,
} from '@undefineds.co/extension-sdk/web'

type NotesController = {
  host: WebExtensionHost
}

export const notesApplet = defineApplet({
  manifest: {
    appId: 'https://example.com/applets/notes',
    name: 'Notes',
    entry: '.',
    commands: [],
    layout: 'two-pane',
  },
  layout: {
    descriptor: defineAppletLayout({ type: 'two-pane' }),
    slots: {
      listHeader: () => <input aria-label="Search notes" />,
      list: () => <nav aria-label="Notes">Notes list</nav>,
      mainHeader: () => <h1>Notes</h1>,
      main: ({ controller }) => {
        const { pod } = controller.host.solid
        return pod.status === 'ready'
          ? <main>{pod.current.podUrl}</main>
          : <main>Pod unavailable</main>
      },
    },
  },
  createController: (host): NotesController => ({ host }),
})

Single-pane modules provide layout.render. Three-pane modules provide layout.slots.listHeader, list, mainHeader, main, and context, plus optional descriptor context:

defineAppletLayout({
  type: 'three-pane',
  context: { collapsible: true, initiallyCollapsed: false },
})

Compose from a host

The host creates one WebExtensionHost, calls useApplet, and resolves the mounted layout variant to SDK workspace layouts. The surrounding AppLayout belongs to the host, so Xpod and Linx can share geometry while keeping different navigation models.

import {
  AppLayout,
  SinglePaneLayout,
  ThreePaneLayout,
  TwoPaneLayout,
  useApplet,
} from '@undefineds.co/extension-sdk/react'
import type {
  AppletModule,
  WebExtensionHost,
} from '@undefineds.co/extension-sdk/web'

function AppletSurface({
  applet,
  host,
}: {
  applet: AppletModule
  host: WebExtensionHost
}) {
  const mounted = useApplet(applet, host)

  if (!mounted) return null

  if (mounted.layout === 'single-pane') {
    return <SinglePaneLayout main={mounted.element} />
  }

  if (mounted.layout === 'three-pane') {
    return (
      <ThreePaneLayout
        listHeader={mounted.slots.listHeader}
        list={mounted.slots.list}
        mainHeader={mounted.slots.mainHeader}
        main={mounted.slots.main}
        context={mounted.slots.context}
        contextConfig={mounted.contextConfig}
      />
    )
  }

  return (
    <TwoPaneLayout
      listHeader={mounted.slots.listHeader}
      list={mounted.slots.list}
      mainHeader={mounted.slots.mainHeader}
      main={mounted.slots.main}
    />
  )
}

export function XpodSettingsHost({
  applet,
  host,
}: {
  applet: AppletModule
  host: WebExtensionHost
}) {
  return (
    <AppLayout
      navigation={<nav aria-label="Xpod settings">Models / Pod / Network</nav>}
    >
      <AppletSurface applet={applet} host={host} />
    </AppLayout>
  )
}

useApplet creates one controller for a stable applet/host pair, calls activate after mounting, and balances cleanup when disabled, replaced, or unmounted. mountTwoPaneApplet remains as a low-level compatibility helper; new hosts should prefer useApplet and the mounted layout union.

For stack-mode navigation, hosts may pass a history adapter to TwoPaneLayout or ThreePaneLayout. The SDK moves focus to the active pane and calls the adapter on user navigation, but it does not write to window.history directly. Browser hosts can map the adapter to their router or to popstate handling; embedded hosts can omit it.

Authentication boundary

AuthBoundary and LoginView standardize presentation only. They do not own a Solid session, create an Inrupt session, start a second OIDC flow, persist tokens, or decide return-path behavior. The host maps its existing session runtime into a typed boundary state and passes the login callback.

import {
  AuthBoundary,
  type AuthBoundaryState,
} from '@undefineds.co/extension-sdk/react'

function SolidGate({
  state,
  login,
  children,
}: {
  state: AuthBoundaryState
  login: (issuer: string) => Promise<void>
  children: React.ReactNode
}) {
  return (
    <AuthBoundary
      state={state}
      login={login}
      loginView={{
        title: 'Connect Solid Pod',
        description: '登录后即可访问当前 Pod 的 applet 数据。',
        defaultIssuer: 'https://solidcommunity.net',
      }}
    >
      {children}
    </AuthBoundary>
  )
}

The host remains responsible for Solid OIDC operations, session restoration, logout, token refresh, and return-path handling. This is the same contract when the applet runs in Linx, Xpod, or an isolated test host.

Solid and data rules

An applet receives Solid through host.solid:

  • Use host.solid.session.fetch for authenticated network requests.
  • Read the already-opened database and collection state from host.solid.pod; do not initialize Inrupt OIDC, drizzle-solid, or collections inside the applet.
  • Call host.solid.requireLogin() when an anonymous standalone host needs login. The host supplies the shared login UI and OIDC flow.
  • Import RDF schemas from @undefineds.co/models.
  • Perform Pod CRUD with drizzle-solid. Collections own hydration and reactive query setup.
  • Never accept or persist bearer tokens, DPoP material, API keys, or refresh tokens in browser storage. User AI credentials remain encrypted in the Pod through the Xpod service boundary.

Applet code must not branch on deployment shape such as local or cloud. Data and capabilities should be self-describing through the host contract.

Legacy compatibility

The previous applet shape is still supported:

defineApplet({
  manifest: {
    appId: 'https://example.com/applets/legacy',
    name: 'Legacy',
    entry: '.',
    commands: [],
    layout: 'two-pane',
  },
  createController: (host) => ({ host }),
  slots: {
    listHeader: () => <input aria-label="Search legacy items" />,
    list: () => <nav>Items</nav>,
    mainHeader: () => <h1>Legacy</h1>,
    main: () => <main>Detail</main>,
  },
})

Keep this path for existing applets and tests. Prefer descriptors for new applets so hosts can resolve layout structure consistently across products.

Test independently

Use the SDK mock host to test applet behavior without launching Linx or implementing OIDC. Tests can provide anonymous, ready, or failed Solid capabilities.

import { render, screen } from '@testing-library/react'
import { TwoPaneLayout, useApplet } from '@undefineds.co/extension-sdk/react'
import { createMockWebExtensionHost } from '@undefineds.co/extension-sdk/testing'

const host = createMockWebExtensionHost({ solid: readySolidCapability })

function Harness() {
  const mounted = useApplet(notesApplet, host)
  return mounted?.layout === 'two-pane'
    ? (
      <TwoPaneLayout
        mode="stack"
        listHeader={mounted.slots.listHeader}
        list={mounted.slots.list}
        mainHeader={mounted.slots.mainHeader}
        main={mounted.slots.main}
      />
    )
    : null
}

render(<Harness />)
screen.getByRole('heading', { name: 'Notes' })

See examples/extension-test-host for a running isolated host that composes AppLayout, AuthBoundary, SDK workspace layouts, and the AI Connection applet.

Public entry points

  • @undefineds.co/extension-sdk: framework-neutral manifest, layout, lifecycle, testing, and React exports for package-internal consumers.
  • @undefineds.co/extension-sdk/manifest: manifest contracts.
  • @undefineds.co/extension-sdk/web: applet definitions, layout descriptors, mounting, and host capabilities.
  • @undefineds.co/extension-sdk/react: AppLayout, workspace layouts, AuthBoundary, LoginView, and useApplet.
  • @undefineds.co/extension-sdk/testing: deterministic host test doubles.