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

@patientos/website-kit

v0.2.19

Published

PatientOS clinic website components and patient-facing interactive islands.

Readme

@patientos/website-kit

React components and client-side patient surfaces for PatientOS clinic websites.

Install

npm install @patientos/website-kit @patientos/public-sdk react react-dom

Certificate funnel

import { CertificateFunnelClient } from '@patientos/website-kit/islands-impl'
import '@patientos/website-kit/website-kit.css'

export function CertificateFunnel() {
  return (
    <CertificateFunnelClient
      publicApi={{ publishableKey: 'rcp_pk_…', apiBase: 'https://clinic.example.com' }}
      services={[{ key: 'medical-certificate', label: 'Medical certificate' }]}
      clinicName="Example Clinic"
      clinicPhone="02 9000 0000"
    />
  )
}

clinicPhone is shown to the patient exactly as you pass it and dialled in E.164 — pass 1300 362 555 and every escape link renders tel:+611300362555.

publicApi.publishableKey is public by design and is validated against the consuming site's origin by PatientOS. Never put server credentials or patient data in these props.

For a PatientOS clinic that explicitly registers http://localhost:*, the kit can carry a verified patient session back to a dynamically allocated localhost dev server. The one-time return credential is scrubbed from the URL and exchanged for a tab-scoped bearer; deployed sites continue to use host-only patient cookies.

Store, cart and checkout

Use the runtime implementations in an ordinary hydrated React site. Import each surface from its OWN subpath — the islands-impl barrel pulls the payment stack (BPOINT, the address picker, Medicare) into every page that touches it:

import { StoreClient } from '@patientos/website-kit/islands-impl/store'
import { CartClient } from '@patientos/website-kit/islands-impl/cart'
import { CartButtonClient } from '@patientos/website-kit/islands-impl/cart-button'
import { CheckoutClient } from '@patientos/website-kit/islands-impl/checkout'
import '@patientos/website-kit/website-kit.css'

const storeApiOrigin = 'https://my.example-clinic.com'

<StoreClient storeApiOrigin={storeApiOrigin} productHandle="vitamin-d" />
<CartClient storeApiOrigin={storeApiOrigin} />
<CheckoutClient
  storeApiOrigin={storeApiOrigin}
  ordersHref="/account/orders"
  completionHref="/checkout/complete"
/>

Use productHandle for one exact product or categoryHandle for a category-filtered catalogue; an exact product takes precedence when both are supplied.

Server-rendering the shop

Fetch the catalogue in your own per-request route loader and pass it as initialCatalog. The grid then renders on the server — real product markup for a crawler and no loading swap — and the island still refreshes in the background, so prices stay honest. Never bake a catalogue into a statically built artifact.

import { createStoreClient, fetchStoreCatalog } from '@patientos/website-kit'
import type { StoreCatalog } from '@patientos/website-kit'

// in the route loader (runs per request, on the server)
const catalog = await fetchStoreCatalog(createStoreClient({ apiOrigin: storeApiOrigin }))

// in the component
<StoreClient storeApiOrigin={storeApiOrigin} initialCatalog={catalog} hideCartLink />

fetchStoreCatalog returns null on any failure, and StoreClient then falls back to its own client fetch. Pass hideCartLink when your site has its own header cart.

The header cart

<CartButtonClient/> is a count badge that opens a cart drawer. It costs no requests: the count comes from the cart already in the shopper's browser, and the drawer quotes POST /api/store/quote only when opened. The badge is absent (never 0) until the client effect runs, so it adds nothing to server-rendered HTML and your header stays cacheable.

<CartButtonClient
  storeApiOrigin={storeApiOrigin}
  label="Cart"
  cartHref="/cart"
  checkoutHref="/checkout"
/>

To build your own affordance instead, import the cart module directly:

import { cartItemCount, readCart, subscribeToCart } from '@patientos/website-kit/cart-storage'

It is browser-only by design (readCart() answers empty on the server) and is shared by every surface in one page, so a store block adding an item updates your badge with no shared React tree.

Omit storeApiOrigin when PatientOS serves the clinic website and store on one origin. For a separately deployed site it must be the clinic's verified patient/API origin, and the site Origin must be registered on that clinic's active web-form channel. The client always sends credentials: 'include' and cache: 'no-store'; checkout remains patient sign-in-required.

The hosting clinic site owns completionHref. It defaults to /checkout/complete, must resolve on that same origin, and receives the paid order ID as its order query parameter. Cross-origin or malformed destinations safely fall back to the default. Cart lines carry package-owned opaque IDs so paid reconciliation removes only the exact line generation captured by that checkout attempt.

Document verification

DocumentVerifier is the marker for the document-verifier island. React sites can import DocumentVerifierClient from @patientos/website-kit/islands-impl/document-verifier and mount it client-side with { apiBase: 'https://patientos.com.au', publishableKey: 'your-site-public-key', token?: string }. Include the kit stylesheet. A /verify page offers camera scanning and link entry; a /verify/$token page can pass the path token for an automatic check. Verification calls the existing anonymous API directly from the browser; camera frames stay local. The component never follows scanned links. It checks the issued record, not altered PDF bytes or the presenter's identity. Existing printed QR destinations remain valid.

Patient account overview (PAT-971)

The new runtime export PortalDashboardClient (./islands-impl/dashboard) combines appointment and document metadata using the existing portal client. Import ./portal-dashboard.css for its scoped patient-facing styles. Pass the verified portalApiOrigin, optional portalUrl, and site-owned appointmentsHref, documentsHref and bookHref; never pass patient data or a patient identifier. Mount client-only inside the site's account shell. No request runs during SSR.

This is a source addition awaiting a new package release; the published 0.2.11 does not include it. See docs/patient-dashboard-integration.md in the repository for behaviour, local pairing, test evidence and release gates.