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

@orbiocloud/site-widgets

v1.2.0

Published

Drop-in OrbioSite page widget for a customer's own website

Readme

@orbiocloud/site-widgets

Drop a published OrbioSite page into a customer's own website.

Phase 3.2 shipped the headless read API (GET /api/public/website/page/[slug]); this package is the drop-in half. The page is fetched as JSON and rendered with the same SitePageRenderer the editor live-preview and the server read path use, so the read-path isSafeHref gate travels with it.

Usage

Served from npm via unpkg, pinned to an exact version — never a floating tag like @latest, so a republish cannot change what already-embedded customer pages execute.

integrity is required, not decorative. Without it, anyone able to serve a different body at that URL — a CDN compromise, a cache poisoning, a hijacked npm account republishing the version — executes arbitrary JavaScript on every customer site that embeds this. SRI makes the browser refuse a body that does not match the hash.

Generate the real hashes from the published artifact and paste them in (they can only be produced after publish, which is why they are not committed here):

V=1.2.0
for f in orbio-site-widgets.umd.js orbio-site-widgets.css; do
  printf '%s  sha384-%s\n' "$f" \
    "$(curl -sL "https://unpkg.com/@orbiocloud/site-widgets@$V/dist/$f" \
       | openssl dgst -sha384 -binary | openssl base64 -A)"
done
<link rel="stylesheet"
      href="https://unpkg.com/@orbiocloud/[email protected]/dist/orbio-site-widgets.css"
      integrity="sha384-QVUTJmMFOz60YqOhH7IidcdQBOkJ5sWRcRBN5vr5p7j4o5OnyrKVIG6H4hRcga9P" crossorigin="anonymous">
<script src="https://unpkg.com/@orbiocloud/[email protected]/dist/orbio-site-widgets.umd.js"
        integrity="sha384-D575txNzxfeofUOdyznJEZctrz8wVbK6HJP3VpjDlVaBCBmb/mc0KlgZlKENtHNz" crossorigin="anonymous"></script>
<script>
  OrbioSiteWidgets.init({ apiKey: 'ws_live_...', subdomain: 'my-tenant' });
</script>

<div data-orbio-site-page data-slug="about"></div>
<div data-orbio-site-schedule data-slug="staff" data-days="7"></div>

Every [data-orbio-site-page] and [data-orbio-site-schedule] element with a data-slug is rendered. init() may be called before DOM ready. For markup injected later (SPA route change, lazy CMS section), call OrbioSiteWidgets.mountAll() — already-mounted containers are skipped.

Scheduled collections

[data-orbio-site-schedule] renders a published scheduled collection. data-days is optional and sets the window length (the server clamps it to 1–62, default 7); the window always begins on the collection's own current business day.

A mounted schedule keeps itself on the right day. Collections have their own timezone and rollover minute — a venue open until 2am still shows Friday's roster at 1am on Saturday — and a tab left open overnight would otherwise display the previous day indefinitely, because the fetch already happened and no cache header can reach it. The widget re-checks when the tab becomes visible and periodically while it is, and refetches when the business day has moved.

root.unmount() disposes everything the mount created, including that watcher.

Options

| Option | Required | Description | |---|---|---| | apiKey | yes | Publishable website key (ws_live_...) — read-only. | | subdomain | yes | The tenant's OrbioCloud subdomain. | | baseUrl | no | API origin. Defaults to https://app.orbiocloud.com. |

The key is publishable by design: it is read-only and reaches only published, tenant-scoped content, so it is safe in page source. Each key carries its own hourly rate limit, configured in the OrbioCloud website hub.

It is NOT origin-locked today. An earlier version of this document said it was, which was wrong and amounted to advice to embed a credential in public page source on a protection that did not exist.

The mechanism is now wired — validateWebsiteKey selects allowed_origins and the public-API wrapper enforces it, matching the showroom and shop validators — but every website key currently has an empty allowlist, and an empty allowlist means the check is skipped. So origin is not protecting anything for this key type until someone populates it per key, which is a deliberate per-consumer decision: setting it on a key whose site serves from an unexpected origin breaks that site.

Until then, treat a publishable website key as public: anyone who views source can read it and call the same read-only endpoints. That is the intended threat model — the protection is that the key grants nothing but published, tenant-scoped content — not that the origin is checked.

Distribution

npm → unpkg, version-pinned. We do not host. That is the operator decision on record (docs/ACTIVE-TODO-orbiosite.md: "headless JSON API + drop-in WIDGETS (we do NOT host)", and "Host npm→unpkg PINNED to an exact version (no CDN wired today)").

An earlier version of this section said "serve from our own origin" and documented app.orbiocloud.com/widgets/v1.0.0/…. That was wrong in two ways at once: it described a hosting model the plan excludes, and the URL it gave 404s — no such route was ever wired. Anyone following it reached a dead link and had no way to tell whether the package was broken or simply unreleased.

Self-hosting would buy control of cache headers and rollback, which matters more here than for @orbiocloud/shop-widgets (vanilla, dependency-free) because this bundle ships React + react-dom + @portabletext/react and runs a full render pipeline on the customer's page. SRI is what substitutes for that control: a pinned version plus an integrity hash means a mutated artifact fails closed in the browser rather than executing. That is why the integrity attribute above is mandatory rather than advisory.

Never document a floating @latest. Emit the hashes per release with:

openssl dgst -sha384 -binary dist/orbio-site-widgets.umd.js | openssl base64 -A
openssl dgst -sha384 -binary dist/orbio-site-widgets.css     | openssl base64 -A

Styling

The renderer emits Tailwind utility classes, which resolve to nothing on a non-Tailwind host page — so the widget ships its own precompiled stylesheet. Two properties make it safe to inject into a site we do not own, and both are enforced by src/scoped-stylesheet.test.ts:

  • Every rule is scoped to the .orbio-site-page container class.
  • No Preflight — Tailwind's base reset would restyle the host's own document. @tailwind components is omitted for the same reason: its container component is emitted unscoped, and .container is a common class on real sites.

The stylesheet's Tailwind content globs point at the renderer's sources, so editing a className in SitePageRenderer is picked up on the next build rather than silently drifting.

Global blocks (ref)

ref blocks resolve server-side in the public API. The payload reaching this bundle contains fully-resolved, already-sanitized blocks, so the widget never passes resolveRef and never fetches global-block content itself — a security control must not live in a bundle running on a host page we do not control. When M7 ships, this package is unchanged.

Development

pnpm --filter @orbiocloud/site-widgets build       # vite lib build -> dist/
pnpm --filter @orbiocloud/site-widgets test        # stylesheet + mount tests
pnpm --filter @orbiocloud/site-widgets type-check