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

@arythmatic/connect-sdk

v0.1.5

Published

Embed Arythmatic Connect community workspaces into third-party platforms (LMS, CRM, portals) via a sandboxed iframe.

Readme

@arythmatic/connect-sdk

Thin JavaScript SDK for embedding Arythmatic Connect community workspaces into third-party platforms (LMS, CRM, portals, etc.) via a sandboxed <iframe>.

How it works

  1. Host platform (e.g. your Next.js LMS) includes the SDK and creates an ArythmaticEmbed instance.
  2. The SDK injects an <iframe> pointing to /embed/:workspace/:path on the Arythmatic Community domain.
  3. The iframe redirects to the canonical workspace route (/w/:workspace/:path?embed=1).
  4. The host sends the user's JWT to the iframe via postMessage.
  5. The iframe stores the token in localStorage — the existing API client picks it up automatically.
  6. No Auth0 redirect is triggered; the user is silently authenticated.

Tenant & workspace identification

| Resource | How it's identified | |----------|---------------------| | Workspace | URL slug (/w/:workspaceSlug) — passed explicitly in SDK options | | Tenant | Preferred: iframe subdomain (acme.connect.arythmatic.cloud) — resolved by backend from hostname | | Tenant (fallback) | tenant SDK option → cached in iframe → sent as X-Embed-Tenant header on every API call | | User | Bearer <token> — validated by backend; LMS must issue JWTs the backend can verify |

Subdomain mode (recommended)

Set tenant and point baseUrl at your apex domain:

const embed = new ArythmaticEmbed({
  container: '#community-root',
  workspace: 'acme-corp',
  tenant: 'acme',                       // iframe loads from acme.connect.arythmatic.cloud
  baseUrl: 'https://connect.arythmatic.cloud',
  token: lmsJwt,
});

The iframe loads from https://acme.connect.arythmatic.cloud/embed/acme-corp. The backend resolves the tenant from the hostname exactly like the standalone app.

Central-domain mode (fallback)

If you must load from a single domain:

const embed = new ArythmaticEmbed({
  container: '#community-root',
  workspace: 'acme-corp',
  tenant: 'acme',                       // forwarded to backend via X-Embed-Tenant header
  baseUrl: 'https://connect.arythmatic.cloud',
  token: lmsJwt,
});

The iframe loads from https://connect.arythmatic.cloud/embed/acme-corp. The SDK passes tenant: 'acme' via postMessage; the iframe caches it in localStorage and the API client sends X-Embed-Tenant: acme on every authenticated request.

Backend contract

For the embed auth flow to work, the backend must:

  1. Validate LMS tokens — accept Authorization: Bearer <lms-jwt> and verify the issuer/signature/audience.
  2. Extract user identity from the LMS JWT claims (sub, email, or a custom claim like arythmatic_user_id).
  3. Map to a CommunityUser — auto-provision or look up the user in the tenant's user pool.
  4. Support X-Embed-Tenant (for central-domain mode) — read the header when org_id isn't available from the JWT or hostname.

Install

Looking for framework-specific recipes (React, Next.js, Vue, Angular)? See NPM_INTEGRATION.md — focused step-by-step guide for integrators using the npm package.

Option A: npm (ES modules)

npm install @arythmatic/connect-sdk
import { ArythmaticEmbed } from '@arythmatic/connect-sdk';

const embed = new ArythmaticEmbed({
  container: '#community-root',
  workspace: 'acme-corp',
  path: 'feed',
  tenant: 'acme',
  token: lmsJwt,
});

embed.mount();

Option B: CDN (UMD via jsDelivr)

Any npm-published package is automatically mirrored by jsDelivr, so no separate CDN deploy is needed. Pin to a specific version for production to avoid surprise updates:

<script src="https://cdn.jsdelivr.net/npm/@arythmatic/[email protected]/dist/arythmatic-connect.umd.js"></script>
<script>
  const embed = new ArythmaticConnectSDK.ArythmaticEmbed({
    container: '#community-root',
    workspace: 'acme-corp',
    tenant: 'acme',
    token: userJwt,
  });
  embed.mount();
</script>

For demos / staging you can use a major-range pointer like @arythmatic/connect-sdk@0 instead of @0.1.3, but production should always pin to an exact version (and ideally use an integrity="sha384-…" SRI hash — jsDelivr exposes one in the file's <details> panel).

API

new ArythmaticEmbed(options)

| Option | Type | Required | Default | Description | |--------|------|----------|---------|-------------| | container | string \| HTMLElement | Yes | — | DOM element or selector where the iframe is injected. | | workspace | string | Yes | — | Workspace slug to open. | | path | string | No | — | Initial route inside the workspace (e.g. "channels/general"). | | baseUrl | string | No | https://connect.arythmatic.cloud | Arythmatic Community base URL. | | tenant | string | No | — | Tenant slug. Used for subdomain routing and X-Embed-Tenant header. | | token | string | No | — | JWT access token from the host platform. | | width | string | No | "100%" | Iframe width. | | height | string | No | "600px" | Iframe height. | | className | string | No | — | CSS class(es) for the iframe element. | | style | object | No | — | Additional inline styles for the iframe. | | onReady | () => void | No | — | Called when the iframe signals it is ready. | | onAuthError | (err) => void | No | — | Called on auth failures inside the iframe. | | onNavigate | (path) => void | No | — | Called when the user navigates inside the embed. | | theme | ArythmaticEmbedTheme | No | — | Theme overrides — see Theming below. |

Instance methods

  • embed.setToken(token) — Update the auth token (e.g. after LMS refresh).
  • embed.setTheme(theme) — Update the theme at runtime (field-by-field merge).
  • embed.navigate(path) — Programmatically navigate the embed.
  • embed.resize(width?, height?) — Adjust iframe dimensions.
  • embed.destroy() — Remove the iframe and clean up listeners.

Theming

The embed exposes every colour the standalone app uses, plus a light/dark mode toggle.

const embed = new ArythmaticEmbed({
  container: '#community-root',
  workspace: 'acme-corp',
  tenant: 'acme',
  token: lmsJwt,
  theme: {
    mode: 'light',                  // 'light' | 'dark' | 'auto' (follow OS)
    colors: {
      accent: '#FF6600',            // primary brand colour
      bgSurface: '#ffffff',
      textPrimary: '#111111',
    },
    // Per-mode overrides applied on top of `colors`. Use these when your
    // brand needs different tones in light vs. dark mode.
    dark: {
      accent: '#FF8833',            // brighter accent for legibility on dark
      bgBase: '#0e0e10',
    },
    light: {
      accent: '#CC4400',            // deeper accent for contrast on light
    },
  },
});

What you can override

theme.colors, theme.light, and theme.dark all accept the same shape (ArythmaticThemeColors):

| Group | Fields | Maps to | |-------|--------|---------| | Brand | accent, accentHover, accentSoft, accentRing, accentDeep | --color-accent, --color-accent-hover, --color-accent-soft, --color-accent-ring, --color-accent-deep | | Surfaces | bgBase, bgSurface, bgElevated, bgHover | --color-bg-base, --color-bg-surface, --color-bg-elevated, --color-bg-hover | | Text | textPrimary, textSecondary, textMuted | --color-text-primary, --color-text-secondary, --color-text-muted | | Borders | borderSubtle, borderStrong | --color-border-subtle, --color-border-strong | | Status | danger, success | --color-danger, --color-success |

Pass only the fields you want to change — everything else falls back to the embed's built-in palette for the current mode.

Smart defaults for accent

If you set only accent, the embed auto-derives the related variants so the UI stays coherent:

  • accentHover → ~12% lighter
  • accentSoft → 15% alpha
  • accentRing → 35% alpha
  • accentDeep → ~15% darker

Override any of these explicitly to pin them.

Merge order

Highest priority last:

  1. The embed's built-in palette for mode
  2. theme.colors
  3. theme.light (when mode is light) or theme.dark (when mode is dark)

Runtime updates

embed.setTheme({ dark: { accent: '#ff6600' } }) merges field-by-field on top of the current theme. You can drop or change any single field without resending the rest.

Security

Every colour value must be a hex (#rgb / #rrggbb / #rrggbbaa), a CSS named colour, or rgb() / rgba() / hsl() / hsla() functional notation. Values containing ;, {, }, or HTML are rejected so the host can't inject arbitrary CSS through this prop. Unknown field names are silently dropped.

Build

cd sdk
npm install
npm run build

Outputs:

  • dist/arythmatic-connect.mjs — ES module
  • dist/arythmatic-connect.umd.js — UMD bundle (browser <script> tag)
  • dist/index.d.ts — TypeScript declarations

Publishing

From the sdk/ directory:

npm login                       # one-time, npm credentials with publish rights on @arythmatic
npm version patch               # or minor / major — bumps package.json + creates a git tag
npm publish                     # `prepublishOnly` rebuilds dist/ first; `publishConfig.access` makes it public
git push --follow-tags          # push the version-bump commit + tag

Pre-publish dry-run to inspect what will go up:

npm pack --dry-run

Security notes

  • The SDK validates postMessage origins against the configured baseUrl (or tenant subdomain).
  • The iframe uses sandbox="allow-same-origin allow-scripts allow-popups allow-forms".
  • The token is never exposed in the iframe URL; it travels exclusively via postMessage.
  • Host platforms should issue short-lived JWTs scoped to the Arythmatic Community audience.
  • The X-Embed-Tenant header is only sent when a tenant option was provided, preventing cross-tenant leakage.