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

@cside.dev/device-intelligence

v1.1.0

Published

cside Device Intelligence: collect client telemetry and exchange it for a device token

Readme

@cside.dev/device-intelligence

Collect client telemetry and exchange it for a cside device token, with types. The collection code is bundled into the package, so there is no remote script to load.

Installation

# npm
npm i @cside.dev/device-intelligence

# yarn
yarn add @cside.dev/device-intelligence

# pnpm
pnpm i @cside.dev/device-intelligence

Usage

import { initDeviceIntelligence } from "@cside.dev/device-intelligence";

const { sendClientTelemetry } = await initDeviceIntelligence({
  teamID: "your-team-id",
});

const { token, errors } = await sendClientTelemetry({ userId: "u_123" });

initDeviceIntelligence starts passive signal collection and behavior tracking, so a later sendClientTelemetry() call only has the per-call probes left to run. Send the returned token to your backend to look up the device. Telemetry is posted to the cside edge, which attributes it by the page origin.

sendClientTelemetry never rejects: when telemetry could not be collected it resolves with { token: null, errors }. Collection needs a browser; see Server-side rendering for what happens elsewhere.

React

Calling it from an effect is fine, including under StrictMode, where the effect runs twice: collection only starts once per page, and both calls resolve with the same function.

import {
  initDeviceIntelligence,
  type SendClientTelemetry,
} from "@cside.dev/device-intelligence";
import { useEffect, useState } from "react";

export function useDeviceIntelligence(teamID: string) {
  const [send, setSend] = useState<SendClientTelemetry>();

  useEffect(() => {
    let active = true;

    initDeviceIntelligence({ teamID }).then(({ sendClientTelemetry }) => {
      // Wrapped in a callback so React stores the function itself.
      if (active) setSend(() => sendClientTelemetry);
    });

    return () => {
      active = false;
    };
  }, [teamID]);

  return send;
}

Options

| Option | Type | Default | Description | | -------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------ | | teamID | string | required | Your cside team ID. Collection does not use it yet; a later release will use it to fetch the team's dynamic configuration. |

API

initDeviceIntelligence(options)

Returns a Promise<{ sendClientTelemetry }>.

  • Starts passive signal collection and behavior tracking. Calling it again is safe: collection only starts once per page, and every call resolves with the same sendClientTelemetry.
  • Rejects with a TypeError when teamID is missing or empty.
  • It returns a promise even though nothing is awaited today, so the dynamic configuration fetch planned for teamID can land without a breaking change.

Also available as the default export.

sendClientTelemetry(externalIds?)

Collects device signals and exchanges them for a device token.

const { token, errors } = await sendClientTelemetry({ userId: "u_123" });

externalIds is an optional map of your own identifiers to attach to the collected signals. Resolves with { token } on success and { token: null, errors } on failure.

Server-side rendering

The package can be imported anywhere a server renderer or edge runtime evaluates client code. Its exports map points the react-server, edge-light, workerd, worker and node conditions at a small server entry with the same API, so no environment checks are needed in your code and none exist in the browser bundle. On the server, initDeviceIntelligence resolves with a sendClientTelemetry that returns { token: null, errors } instead of collecting anything. Browser builds (the browser and default conditions) get the real bundle.

Content-Security-Policy

The package posts telemetry to the cside edge. No script is loaded from a team subdomain:

Every telemetry request also carries the package version as the x-v-di request header; the edge allows it in its CORS preflight.

connect-src https://edge.csidefd.com;

Build artifacts

This package produces two outputs from one codebase:

  • dist/index.js and dist/index.cjs: the npm library documented above (obfuscated, no readable source).
  • dist-cdn/fingerprint.js: the CDN artifact deployed to the edge and served to browsers. Same collection pipeline, exposed as a global instead of an npm export.

Both run the same seeded orchestration bytecode. The readable source of truth is src/bytecode/operations.ts and spec.ts; add handlers and readable steps there rather than editing numeric output. Each step declares whether it runs when the script loads or when the page asks for a token, and the specification emits one program per phase over a shared slot space. Rollup generates a seeded physical layout for each release; the seed, source commit, bytecode version, and program hash are written to the ignored dist-cdn/.device-intelligence-bytecode.metadata.json build record. Release CI should set DEVICE_INTELLIGENCE_BYTECODE_SEED once per artifact; local development and unit tests use fixed defaults.

This provides reverse-engineering resistance, not secrecy. The browser still receives the handlers and generated program. The direct implementation in bytecode/reference.ts is test-only and is never a production fallback.

Development

pnpm dev at the repo root rebuilds on change and serves the html folder under localhost:8069/di/ (the web-script pages sit at the root of the same server); pnpm test runs the vitest and Playwright suites against a server on port 1993. The Playwright suite covers both artifacts: device-intelligence.spec.ts loads the CDN script, and library.spec.ts imports the npm bundle (served as /lib/index.js) through html/library.html. The local dev/test server lives in packages/core/dev, shared with web-script.

Documentation

See the cside docs for more.

Minimum release age

We recommend configuring a minimum release age so your package manager only installs versions that have been published for at least 7 days. Compromised package versions are typically detected and unpublished within days of publication, so a cooldown protects you from npm supply chain attacks. This applies to all your dependencies, not just this package.

# npm (.npmrc, in days)
min-release-age=7
# yarn (.yarnrc.yml, as a duration string)
npmMinimalAgeGate: "7d"
# pnpm (pnpm-workspace.yaml, in minutes)
minimumReleaseAge: 10080