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

@nuskin/react-product-sdk

v1.2.0

Published

React bindings and connected components for Nu Skin product-domain capabilities.

Readme

@nuskin/react-product-sdk

React bindings and connected components that connect approved product-domain capabilities to presentational React components.

This package is the React-facing integration layer between consuming applications, @nuskin/product-lib, and @nuskin/react-product-components. It owns React providers, hooks, connected-component orchestration, and domain-to-view mapping. It does not own product GraphQL transport or reusable visual design.

Business rules remain in domain SDKs. Application composition remains in the consuming MFE or container. This package coordinates those capabilities without collapsing the boundaries between them.

Architecture contract

MFE / consuming application
        |
        | supplies session, configuration, routing, and SDK clients
        v
@nuskin/react-product-sdk
        |
        +--> @nuskin/product-lib --> product-domain services
        |
        +--> @nuskin/react-product-components --> foundation UI and theme

Dependencies must flow downward. Reverse dependencies are forbidden.

Non-negotiable boundaries

  • Experience components must consume product data through an approved product domain SDK rather than executing product GraphQL directly.
  • Experience-owned HTTP integrations are allowed when no domain SDK owns the capability. They must not duplicate product SDK responsibilities.
  • Domain models should be converted into explicit UI props through separately testable mapper functions.
  • Runtime session, configuration, routing, and domain clients are supplied by the consuming application or an approved integration mechanism.
  • Reusable visual design belongs in @nuskin/react-product-components.
  • Product components must remain usable with static props and callbacks. They must not access the network or depend on this package, a domain SDK, GraphQL, or application session state.
  • Local visual state may remain in the component library. Product, customer, cart, pricing, inventory, configuration, and session source-of-truth state may not.

See the architecture documentation for detailed ownership rules and CONTRIBUTING.md for the review checklist.

Current status

The initial connected product-card and product-carousel slices are implemented. They provide a typed client boundary over @nuskin/product-lib, client injection through ProductProvider, the useProductById async-state hook, ProductCard, and a windowed ProductCarousel.

@nuskin/product-lib is the initial product-data dependency.

ProductCard currently renders product content and images only. It does not map pricing or inventory, and it does not provide an add-to-cart callback, so the presentational component hides its CTA. Product clicks open the canonical PDP URL supplied by the product domain response in the same browser tab. Missing, malformed, and non-HTTP(S) canonical URLs do not trigger navigation.

ProductCarousel accepts the complete ordered product-ID collection. It reserves every position, preserves duplicates, loads the first six positions immediately, and uses the presentational carousel's internal demand signal to maintain one logical page of look-ahead. Product-data service requests contain at most five distinct IDs. Null, missing, not-found, failed, and invalid-PDP positions remain in place as error slots.

The demand window controls product-data requests. Separately, the presentational package mounts full ProductCard trees only near the visible carousel viewport while retaining lightweight slots elsewhere. Neither mechanism is a reusable product cache.

Usage

import {
    createProductClient,
    ProductCard,
    ProductCarousel,
    ProductProvider,
} from '@nuskin/react-product-sdk';

const productClient = createProductClient({
    environment: 'test',
    market: 'US',
    language: 'en',
});

export function Example() {
    return (
        <ProductProvider client={productClient}>
            <ProductCard productId="bltddf3c9598da66cbe" />
            <ProductCarousel
                ariaLabel="Featured products"
                productIds={[
                    'bltddf3c9598da66cbe',
                    'blt67368080ff19e808',
                    '01001647',
                ]}
            />
        </ProductProvider>
    );
}

Applications with authenticated product requests can supply getAccessToken. It is evaluated for each request so the client does not retain a stale session token:

const productClient = createProductClient({
    environment: runtime.environment,
    market: runtime.market,
    language: runtime.language,
    getAccessToken: () => session.getAccessToken(),
});

Provider lifecycle

Place ProductProvider above the product components and hooks that share the same environment, market, and language. It will commonly sit immediately below the consuming application's session, configuration, and locale providers.

The client captures environment, market, language, and useContentSource when it is created. Recreate it when one of those values changes. Passing a new client to ProductProvider causes active product hooks to request data using the new configuration:

import { useMemo } from 'react';

const productClient = useMemo(
    () =>
        createProductClient({
            environment: runtime.environment,
            market: locale.market,
            language: locale.language,
            useContentSource: runtime.contentSource,
            getAccessToken: () => session.getAccessToken(),
        }),
    [
        runtime.environment,
        runtime.contentSource,
        locale.market,
        locale.language,
    ],
);

return <ProductProvider client={productClient}>{children}</ProductProvider>;

Do not call createProductClient unconditionally during each render. A new client changes the context value and causes product hooks to request their data again. Session-token changes alone do not require a new client: getAccessToken is evaluated for every request.

ProductProvider shares the client instance, not request state or product results. Standalone cards requesting the same product issue independent product requests. A connected carousel deduplicates IDs within each of its own batches, but it is not a reusable product cache and does not deduplicate work with other cards or carousel instances.

Consumers that need custom rendering can use useProductById inside the provider and receive product, isLoading, and error directly.

Scripts

| Command | Purpose | | -------------------- | ------------------------------------------------- | | yarn build:package | Build CommonJS, ESM, and TypeScript declarations | | yarn lint | Check source architecture and code-quality rules | | yarn types:check | Type-check without emitting files | | yarn test | Run Jest and collect coverage | | yarn validate | Run formatting, lint, types, tests, and the build |

Storybook, a development host, browser automation, and GraphQL tooling are intentionally omitted. They should be introduced only when a concrete problem requires them.

License

MIT