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

@full-self-browsing/concierge-react

v0.4.0

Published

React bindings and optional action visuals for @full-self-browsing/concierge

Readme

@full-self-browsing/concierge-react

React lifecycle bindings and optional action-state chrome for an existing @full-self-browsing/concierge instance and bridge registry.

Version 0.4 is a public preview of contract 4. It supports React 18 and 19, requires Node 22.12 or newer for server rendering, and does not support Edge runtimes in the 0.4 line. useConciergeActivity now returns the last observer event, and useConciergeBridge accepts null to unregister.

Entry points

The package root is server-safe and type-only. It forwards the public core Bridge, BridgeRegistry, and Concierge types without importing React runtime code:

import type {
  Bridge,
  BridgeRegistry,
  Concierge,
} from "@full-self-browsing/concierge-react";

Import runtime bindings only from the client entry:

import {
  ConciergeActivityOverlay,
  ConciergeProvider,
  useConcierge,
  useConciergeActivity,
  useConciergeBridge,
  useConciergeValue,
} from "@full-self-browsing/concierge-react/client";

The client entry carries the "use client" directive. The package root and the framework-neutral core do not.

Construct core in application setup

The React package does not call or wrap createConcierge. Build the core objects in application code with the public createBridge and createConcierge exports, then inject those exact objects into React.

// concierge.ts
import {
  createBridge,
  createConcierge,
} from "@full-self-browsing/concierge";
import type { Bridge } from "@full-self-browsing/concierge";

import { resultsActions } from "./actions.js";

export type ResultsBridge = Bridge<
  {
    readonly applyFilter: (
      key: string,
      values: readonly string[],
    ) => void;
  },
  {
    readonly selectedBrands: () => readonly string[];
  }
>;

export const resultsRegistry =
  createBridge<ResultsBridge>("results");

export const concierge = createConcierge({
  stages: [
    {
      id: "results",
      match: (context) => context.pathname === "/results",
      actions: resultsActions,
      bridge: resultsRegistry,
    },
  ],
});

resultsActions above is the application's existing set of core action declarations. The adapter neither declares those actions nor assembles their catalog.

Provide, read, and register

Pass a plain current value to useConciergeValue. The hook owns the ref and returns a stable getter, so application code does not maintain a parallel ref. Construct an ordinary core Bridge, then give that bridge and the existing registry to useConciergeBridge.

// ResultsRoute.tsx
import { useMemo } from "react";

import {
  ConciergeProvider,
  useConcierge,
  useConciergeBridge,
  useConciergeValue,
} from "@full-self-browsing/concierge-react/client";

import {
  concierge,
  resultsRegistry,
} from "./concierge.js";
import type { ResultsBridge } from "./concierge.js";

type ResultsBindingProps = {
  readonly selectedBrands: readonly string[];
  readonly applyFilter: (
    key: string,
    values: readonly string[],
  ) => void;
};

function ResultsBinding({
  selectedBrands,
  applyFilter,
}: ResultsBindingProps) {
  const currentConcierge = useConcierge();
  const readSelectedBrands = useConciergeValue(selectedBrands);

  const bridge = useMemo<ResultsBridge>(
    () => ({
      actions: { applyFilter },
      snapshot: { selectedBrands: readSelectedBrands },
    }),
    [applyFilter, readSelectedBrands],
  );

  useConciergeBridge(resultsRegistry, bridge);

  // `useConcierge` returns the exact object supplied to the provider.
  if (currentConcierge !== concierge) {
    throw new Error("Unexpected Concierge provider.");
  }

  return null;
}

export function ResultsRoute(props: ResultsBindingProps) {
  return (
    <ConciergeProvider concierge={concierge}>
      <ResultsBinding {...props} />
    </ConciergeProvider>
  );
}

ConciergeProvider carries the supplied reference through React context and, by default, mounts the browser-only anonymous telemetry runtime. Pass telemetry={false} to leave this provider's runtime uninstrumented. Multiple providers for the same Concierge object in one document share one runtime, so React StrictMode does not inflate the active-instance count. See the telemetry privacy contract for the exact payload and origin-wide opt-out API.

Optional action visuals

ConciergeActivityOverlay is opt-in, pointer-transparent UI chrome driven only by onDispatch. It keeps overlapping parent and child dispatches active independently, removes itself after the final terminal event, and never enters dispatch control flow.

<ConciergeProvider concierge={concierge}>
  <ConciergeActivityOverlay
    glow={{
      color: "#ff6b35",
      secondaryColor: "#635bff",
      intensity: 0.72,
    }}
    poweredByFSB
  />
  <App />
</ConciergeProvider>

Rendering the component enables the glow by default. Set glow={false} to disable it. The poweredByFSB badge defaults to false and appears only while an action is active. When enabled, its position defaults to bottom-left; pass an object with position, color, backgroundColor, and borderColor to override its presentation. Both layers use fixed positioning, ignore pointer input, and accept a shared zIndex.

For application-owned visuals, useConciergeActivity() exposes the same concurrency-safe { active, lastEvent } store without rendering anything. lastEvent is the redacted observer event; it is never unredacted args.

Lifecycle guarantees

  • ConciergeProvider subscribes once through onDispatch before descendant layout effects and shares its activity state with every useConciergeActivity consumer. Activity is keyed by dispatchId, so repeated lifecycle phases do not inflate activity and one terminal child cannot hide an active parent.
  • useConciergeBridge calls registry.register(bridge) only from useEffect and returns that exact registration unsubscriber as cleanup. Passing null unregisters and does not install a dummy bridge.
  • React StrictMode's development sequence—setup, cleanup, setup—therefore leaves the current registration live. The core registry's monotonic token makes a retained stale cleanup an idempotent no-op, while final unmount removes the live registration.
  • useConciergeValue mirrors the plain value after commit and returns one stable getter. Reads through a registered bridge observe the latest committed render, not the value captured when the bridge was first created.
  • Passive effects do not execute during server rendering. Importing the server-safe root or rendering the client binding on the server performs zero bridge registrations and needs no window or document branch.

Ownership and security boundary

Before client registration, the hook invokes core's singleton guard and checks the adapter's embedded contract-version literal. Those checks are client compatibility and integrity defenses: they catch a duplicate core module graph or an adapter/core contract mismatch before registration can split bridge, deduplication, or consent state.

They are not identity checks and do not provide server authorization. Treat every client-originated action, consent assertion, receipt, and result as untrusted at the server boundary. A relying server must independently authenticate the current principal and authorize the exact action and payload under current server policy immediately before any protected effect.

The React adapter owns context propagation, committed-value mirroring, effect-scoped bridge registration, and optional observer-driven action chrome. Application and core code continue to own action declarations, catalogs, dispatch, sessions, consent, transports, scheduling, and results.

License

MIT © Full Self Browsing