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

uxaura

v0.3.0

Published

A silent, trigger-driven UX watcher and rule engine — lets your users personalize your app by asking, without touching your source code.

Readme

uxaura

A silent, trigger-driven watcher for React apps. It stays invisible until it detects real friction — a rage click, a dead click, a form abandoned — then drops a small prompt right where it happened, instead of a chat bubble nobody opens.

No AI runs in the browser. Detection is plain JS reading DOM events; the only network call happens if the user actually replies.

Install

npm install uxaura

Quick start

import { UXauraProvider, UXauraWatcher } from 'uxaura'
import 'uxaura/styles.css'

function App() {
  return (
    <UXauraProvider
      projectKey="your-project-key"
      userId={currentUser.id}
      route={pathname}
      apiBaseUrl="https://your-server.example.com"
    >
      <YourApp />
      <UXauraWatcher />
    </UXauraProvider>
  )
}

projectKey identifies which tenant's Map/Rules/Boundaries this app talks to — generate one from the dashboard's project screen. UXauraProvider fetches and applies rules to elements by name — an id, a data-testid, or a data-uxa-id if you want a dedicated hook; whichever you already have. UXauraWatcher is invisible until a trigger fires, a change was just made, or there's something active on the page to review.

UXauraProvider and UXauraWatcher are the client half of a larger system — they expect a multi-tenant server implementing /api/map, /api/rules, /api/chat, and the /api/admin/* dashboard endpoints, authenticated via the x-uxaura-project-key header this SDK sends on every request. See the full project for the reference server and the owner dashboard.

Finding what's on your page

uxaura installs a CLI too — no second package. It reads your app's own JSX for elements that already have an id, data-testid, or data-uxa-id, and uploads them as your project's Map. Nothing to add to your components.

Add a uxaura.config.js next to your package.json, mapping each file you want scanned to the route it's rendered on:

export default {
  routes: {
    'src/pages/Home.jsx': '/',
    'src/pages/Product.jsx': '/product',
  },
}

Then run:

UXAURA_API_URL=https://your-server.example.com \
UXAURA_PROJECT_KEY=your-project-key \
npx uxaura scan

Without the env vars it just prints what it found — safe to run locally to check first. A re-scan only adds or refreshes names; it never deletes an anchor and never touches a lock an owner has already set in the dashboard.

Built-in triggers

Eight ready to use, matching the frustration-signal taxonomy FullStory and Hotjar already track in session recordings — no AI in any of them:

import {
  rageClickTrigger,
  deadClickTrigger,
  errorClickTrigger,
  thrashedCursorTrigger,
  exitIntentTrigger,
  rageScrollTrigger,
  uTurnTrigger,
  formAbandonTrigger,
} from 'uxaura'

<UXauraWatcher triggers={[rageClickTrigger(), deadClickTrigger(), exitIntentTrigger()]} />

Omit triggers and you get rageClickTrigger() + deadClickTrigger() by default.

Writing your own trigger

A trigger is a plain object — no special API, nothing to register beyond passing it in the array:

function myTrigger({ id = 'my-trigger', prompt = 'Need help?' } = {}) {
  return {
    id,
    events: ['click'], // any DOM event name
    handleEvent(e, { fire, now, isOwnUI }) {
      // your own logic, using ordinary closures for state
      if (/* condition */ false) fire({ prompt })
    },
  }
}

Styling

Every default component takes a classNames prop that merges over its internal defaults:

<UXauraWatcher
  classNames={{
    trigger: { root: 'my-trigger-card', input: 'my-input' },
    toast: { root: 'my-toast' },
    pill: { pill: 'my-pill' },
  }}
/>

For full control, replace a component outright:

<UXauraWatcher components={{ TriggerLabel: MyTriggerLabel }} />

A replacement receives { trigger, onDone } and can call the exported useUXaura() hook itself for sendMessage / toggleRule — nothing about the defaults is required to build your own.

License

MIT