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

@kaidn/nuxt

v2.0.0

Published

Kaidn for Nuxt. A composable that collects a device id in the browser, and a server helper that scores it with the IP and device-token cookie read straight off the h3 event.

Readme

@kaidn/nuxt

Kaidn for Nuxt. A composable that collects a device id in the browser, and a server helper that scores it with the IP and the device-token cookie read straight off the h3 event.

npm install @kaidn/nuxt

Full guide: kaidn.io/docs/quickstart/nuxt

Why this exists

You can do all of this with @kaidn/fp and @kaidn/sdk directly. This package removes the two things a hand-written server route gets subtly wrong.

The IP. getRequestIP(event) returns an address the server already resolved. Written by hand this is the field people either forget — the event goes out with no ip and every IP signal quietly dies — or get wrong by trusting x-forwarded-for when nothing overwrites it.

The device token. Read from the cookie on the way in, written back on the way out. That is what turns a fingerprint which collides across people into a browser you actually recognise.

Client

The publishable key is an argument, not something this package reaches into Nuxt to find. Importing useRuntimeConfig from Nuxt's virtual imports would save you one line and tie this package to an internal that moves between versions. This works on Nuxt 3, Nuxt 4, plain Vue, and in a test.

// app/composables/useKaidn.ts
import { useDeviceId } from "@kaidn/nuxt";

export function useKaidn() {
  return useDeviceId(useRuntimeConfig().public.kaidnPk);
}
<script setup lang="ts">
const { getDeviceId } = useKaidn();
const deviceId = await getDeviceId(); // never throws; null on the server or when blocked
</script>

Collection is deduplicated for the life of the page: a double-clicked submit button does not fingerprint twice, and each beacon is a billable event.

Server

// server/api/signup.post.ts
import { createKaidn } from "@kaidn/nuxt/server";

const kaidn = createKaidn({ apiKey: process.env.NUXT_KAIDN_API_KEY! });

export default defineEventHandler(async (event) => {
  const { email, deviceId } = await readBody(event);

  const result = await kaidn.score(event, {
    event: "signup",
    email,
    device_id: deviceId ?? undefined,
  });

  if (result.verdict === "block") {
    throw createError({ statusCode: 403, statusMessage: "Signup refused" });
  }
  return { ok: true };
});

No ip, no device_token: both come from the event. Anything you pass wins over what is inferred.

A server route is a public endpoint. Anyone can POST it without loading your form, so enforce the verdict inside the handler.

Options

| option | default | | |---|---|---| | apiKey | — | required, and every other @kaidn/sdk option is accepted too | | cookieName | __kdn | the first-party device-token cookie | | cookieMaxAge | one year, in seconds | | | persistToken | true | set false to stop refreshing the cookie |

There is deliberately no option to trust x-forwarded-for. h3 can be told to read it, and h3's own docs say to make sure the header can be trusted first — its first entry is client-supplied, so unless something you control overwrites it on every request, a caller can choose their own address. A fraud library offering that as a switch is offering a footgun. If you genuinely need it, pass ip yourself and it wins.

Versions

h3 is a peer dependency on the 1.x line, which is what Nuxt ships. It is a peer rather than a dependency so there is exactly one h3 in the process: yours.

License

MIT