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

@chiahq/react

v0.2.0

Published

React hooks and components for customer-facing Chia subscription management

Readme

@chiahq/react

React hooks and components for customer-facing Chia subscription management.

Drop this into your own app to let subscribers see their subscription, pay an outstanding balance over mobile money, and cancel when you allow it. No dashboard, no iframe, no redirect hijacking.

Install

npm install @chiahq/react

react is the only peer dependency. The package ships no HTTP client, no data-fetching library and no toast library: it talks to the Chia embed API with fetch and returns errors to you.

A Chia publishable key is required

This package will not function without a Chia publishable key. Create one in the Chia dashboard and pass it to ChiaProvider as publishableKey. The key (a pk_... value) is sent as Authorization: Bearer <publishableKey> on every request, and the organization is derived from it: there is no orgSlug any more. Publishable keys may be origin-restricted, so a key only works from the domains you allow in the dashboard.

Quick start

import { ChiaProvider, SubscriptionManager } from "@chiahq/react";
import "@chiahq/react/styles.css"; // optional

export function BillingPage({ subscriberId }: { subscriberId: string }) {
	return (
		<ChiaProvider publishableKey="pk_live_...">
			<SubscriptionManager
				subscriberId={subscriberId}
				onNextAction={(nextAction) => {
					// You own navigation. Chia never calls window.location for you.
					if (nextAction.type === "redirect" && nextAction.redirectUrl) {
						router.push(nextAction.redirectUrl);
					}
				}}
			/>
		</ChiaProvider>
	);
}

apiBaseUrl defaults to https://api.usechia.com. Point it elsewhere for local work:

<ChiaProvider publishableKey="pk_test_..." apiBaseUrl="http://localhost:3001">

Caching

ChiaProvider creates its own cache, scoped to that provider. Queries are keyed by publishable key. Components sharing a key share one request rather than each issuing their own, and a mutation invalidates the queries it affects. Nothing to configure and no query client to wire in.

Two providers on one page keep separate caches, so a test or a preview pane never shares state with the live tree.

What it does not do: there is no retry, no request cancellation on unmount, and no background refetch on window focus. If you need those, run the hooks' mutateAsync and the returned state inside your own layer, or keep using a full data-fetching library alongside this package.

Hooks

Use these directly if you want your own markup.

import { usePlans, useSubscription, useCancelSubscription, usePayOutstanding } from "@chiahq/react";

function Billing({ subscriberId }: { subscriberId: string }) {
	const pay = usePayOutstanding(subscriberId, {
		onNextAction: (action) => setPrompt(action.message),
	});

	// Poll only while a payment is settling. TanStack Query handles the timer.
	const settling = pay.data?.paymentStatus === "processing";
	const { data } = useSubscription(subscriberId, { refetchInterval: settling ? 3000 : false });

	const cancel = useCancelSubscription(subscriberId);

	if (!data) return null;

	return (
		<>
			<p>{data.plan?.name}</p>
			<p>{data.subscriber.status}</p>
			{data.subscriber.status === "past_due" && (
				<button onClick={() => pay.mutate()} disabled={pay.isPending}>
					Pay now
				</button>
			)}
			{data.allowSelfCancel && <button onClick={() => cancel.mutate()}>Cancel</button>}
		</>
	);
}

| Hook | Endpoint | | --- | --- | | usePlans() | GET /embed/v1/plans | | useSubscription(subscriberId, options?) | GET /embed/v1/subscription/:subscriberId | | useCancelSubscription(subscriberId) | POST /embed/v1/subscription/:subscriberId/cancel | | usePayOutstanding(subscriberId, options?) | POST /embed/v1/subscription/:subscriberId/pay |

Every request carries the publishable key as Authorization: Bearer <publishableKey>. Subscriber-scoped calls also carry the portal session token in a separate X-Chia-Subscriber-Token header. Mutations invalidate ["chia-subscription", publishableKey, subscriberId] on success.

Cancellation is server-gated

useSubscription returns allowSelfCancel from the organization's settings. SubscriptionManager renders no cancel affordance when it is false, and the API returns 403 regardless, so a hand-rolled UI cannot bypass it. Check the flag before rendering your own cancel button.

Cancellation sets cancelAtPeriodEnd -- the subscription stays active until the current period ends.

nextAction is surfaced, never acted on

POST .../pay returns a nextAction describing what the customer must do: redirect, tan_prompt, ussd_prompt, pin_prompt, wait_for_webhook, or none.

This package hands it to you and stops. It does not call window.location.href, does not open windows, and does not swallow redirectUrl. SubscriptionManager renders a plain link for redirect actions and calls onNextAction for everything else; your app decides whether that means a router push, a modal, or a full navigation.

Money is never a number

Amounts arrive as decimal strings from numeric(12,2) and stay strings all the way to the DOM. formatAmount groups digits with string operations only -- no parseFloat, no precision loss. Do the same in your own components: never parse an amount to a float for storage or comparison.

Styling

Components ship with semantic markup and chia-* class names, unstyled by default. Two ways to theme:

  1. Import the optional stylesheet: import "@chiahq/react/styles.css".
  2. Style the class names yourself, or override the CSS custom properties the stylesheet reads. Every property has a fallback, so setting none of them still looks reasonable.
:root {
	--chia-accent: #1d4ed8;
	--chia-text: #17191c;
	--chia-text-muted: #878e96;
	--chia-radius: 0.5rem;
}

usableBrand() is exported for brand-color work: it returns ink instead of the brand when the brand is too light for white text to be readable on it.

Subscription statuses

incomplete, awaiting_customer_action, trialing, active, renewal_pending, paused, cancelled, past_due.

License

Business Source License 1.1 (BUSL-1.1). You may use this package in production only when it connects to the official Chia platform. Non-production use is otherwise permitted, and the license converts to MIT on the Change Date. See LICENSE for the full terms, including the Additional Use Grant.