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

web-platform-kit

v0.0.4

Published

TypeScript user-agent & platform detection — OS, browser, engine, and device parsing with User-Agent Client Hints (high-entropy) merging, version comparison, WebView/PWA/Node detection.

Readme

npm bundle size types

web-platform-kit

A tiny TypeScript user-agent & platform detector — resolves OS, browser, engine, and device from the UA string, then refines the result with User-Agent Client Hints (high-entropy) when available.

npm install web-platform-kit

API at a glance

PlatformKit is a singleton. All detection fields are getters.

| Member | Type | Description | |------------------------------------| --- | --- | | PlatformKit.version | string | The installed package version | | PlatformKit.ready | Promise<void> | Resolves once async UA Client Hints have merged in | | PlatformKit.userAgent | string (get/set) | Read the active UA string, or set one to parse a custom UA | | PlatformKit.os | { name, version } | name: unknown \| windows \| macos \| android \| ios | | PlatformKit.browser | { name, version } | name: unknown \| chrome \| safari \| edge \| firefox \| opera \| ie \| samsung | | PlatformKit.engine | { name, version } | name: blink \| webKit \| gecko \| presto \| trident \| … | | PlatformKit.device | string | unknown \| mobile \| desktop | | PlatformKit.webview | boolean | Whether running inside a WebView | | PlatformKit.node | boolean | Whether running under Node.js | | PlatformKit.standalone | boolean | Whether launched as an installed PWA | | PlatformKit.compareVersion(a, b) | -1 \| 0 \| 1 | Numeric dotted-version comparison (named export) |

About ready: on Chromium, the most accurate OS/browser version comes from User-Agent Client Hints, which resolve asynchronously. Read fields after await PlatformKit.ready for best accuracy; before it resolves you still get a synchronous result parsed from the UA string.


ESM

import PlatformKit from 'web-platform-kit'

// Synchronous (UA-string based) — available immediately
console.log(PlatformKit.os)      // { name: 'ios', version: '17.4' }
console.log(PlatformKit.browser) // { name: 'safari', version: '17.4' }
console.log(PlatformKit.device)  // 'mobile'

// Refined with Client Hints (Chromium) — await first
await PlatformKit.ready
console.log(PlatformKit.os.version) // full platform version on Chromium

// Version gate
if (PlatformKit.compareVersion(PlatformKit.os.version, '15.0') >= 0) {
  // iOS 15+
}

CommonJS

The bundle is built with exports: "named", so the singleton lives under .default:

const { default: PlatformKit } = require('web-platform-kit')

console.log(PlatformKit.browser.name, PlatformKit.browser.version)

UMD (browser <script>)

The global PlatformKit is a namespace object. The singleton is PlatformKit.default; the helper is PlatformKit.compareVersion.


<script src="https://unpkg.com/web-platform-kit/dist/platform-kit.umd.min.js"></script>
<script>
    var p = window.PlatformKit.default

    document.body.dataset.os = p.os.name
    document.body.dataset.browser = p.browser.name

    if (p.webview) {
        console.log('running inside a WebView')
    }
</script>

TypeScript

The { name, version } shape is exported as NameVersionPair<T>; the singleton shape is PlatformKitInstance. The os / browser / engine / device name unions are exported too (OS, Browsers, Engines, Devices).

import PlatformKit, {
  type OS,
  type NameVersionPair,
} from 'web-platform-kit'

const os: NameVersionPair<OS> = PlatformKit.os

function isModernSafari(): boolean {
  return PlatformKit.browser.name === 'safari'
    && PlatformKit.compareVersion(PlatformKit.browser.version, '16.0') >= 0
}

Parsing a custom UA string

Set userAgent to parse an arbitrary string — useful server-side or in tests. Setting a custom UA parses purely from that string (no Client Hints merge).

import PlatformKit from 'web-platform-kit'

PlatformKit.userAgent = 'Mozilla/5.0 (Linux; Android 14; Pixel 8) ' +
  'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0 Mobile Safari/537.36'

console.log(PlatformKit.os)      // { name: 'android', version: '14' }
console.log(PlatformKit.browser) // { name: 'chrome', version: '124.0' }

Note: userAgent is shared singleton state — setting it changes detection globally for every reader. Restore PlatformKit.userAgent if other code relies on the real environment.


Notes

  • Detection is best-effort. User agents are spoofable and inconsistent across vendors; treat the result as a strong hint, not ground truth. Prefer feature detection for capability decisions where possible.
  • Client Hints are Chromium-only and async. Non-Chromium browsers resolve ready immediately with UA-string parsing; os.version granularity is limited to what the UA string exposes there.
  • iPadOS reports as desktop. iPadOS Safari sends a macOS UA; this library re-classifies it as ios when navigator.standalone is present and maxTouchPoints > 2, but edge cases remain.
  • .default in CJS/UMD is a consequence of keeping both a default and named exports. To drop it, switch the entry to fully-named exports and rebuild.