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

which-nuxt

v0.4.2

Published

Detect Nuxt, Vue and Nuxt-related package versions from public Nuxt sites.

Readme

npm version npm downloads license

🔍 Point it at a URL. Get back the Nuxt and Vue versions, the Nuxt modules, the host, and any GitHub advisories that match.

[!TIP] Using an AI agent? Get the which-nuxt Skill on skilld.dev/gh/harlan-zw/which-nuxt.

Features

  • 🔍 Versions from a URL: See the exact Nuxt version a site runs, and the Vue version when a bundled chunk exposes it, with no access to its code.
  • 🛡️ Advisory check: Find out which GitHub security advisories affect those versions. An inferred version range gives a possible match, not a confirmed one.
  • 🧩 20 Nuxt modules: Spot Nuxt UI, Nuxt Content, i18n, the Nuxt SEO modules and more. Each match says how sure it is.
  • 🌐 Hosting and domain age: Learn which platform serves the site and, if you ask, how old its domain is.
  • 🕷️ Built for crawlers: Already have the HTML? Scan it with no extra requests, and load only the module presets you use.

CLI

# Scan a site
npx which-nuxt https://nuxt.com

A bare hostname such as nuxt.com is scanned as https://nuxt.com.

The whichnuxt alias runs the same command.

# Print the full result as JSON
which-nuxt https://nuxt.com --json

# Skip the GitHub advisory check
which-nuxt https://nuxt.com --no-advisories

# Read the page only: no JavaScript chunks, no endpoint probes
which-nuxt https://nuxt.com --no-js --no-endpoints

# Add the domain age, and use a token for a higher GitHub rate limit
which-nuxt https://nuxt.com --age --github-token "$GITHUB_TOKEN"

| Flag | Description | | --- | --- | | --json | Print the full detection and advisory result as JSON. | | --no-advisories | Skip GitHub advisory checks. | | --no-js | Skip fetching and scanning Nuxt JavaScript chunks. | | --no-endpoints | Skip probing Nuxt public endpoints. | | --no-hosting | Skip hosting provider detection from response headers. | | --age | Fetch RDAP domain age metadata. | | --timeout <ms> | Network timeout. Defaults to 8000. | | --max-js-requests <count> | Most Nuxt JavaScript chunks to fetch. Defaults to 4. Stops early once it has both the Nuxt and Vue versions. | | --github-token <token> | GitHub token for advisory API requests. Defaults to GITHUB_TOKEN. | | --user-agent <agent> | User-Agent for requests to the target site. |

Exit codes

| Code | Meaning | | --- | --- | | 0 | The scan completed and no advisory matched, or the advisory check was skipped. | | 1 | Usage error, such as a bad --timeout value. | | 2 | The scan is incomplete: one or more scan steps failed. | | 3 | One or more advisories match the detected versions. |

What it requests

One scan fetches the page, up to 4 JavaScript chunks, and a set of public endpoints such as /_payload.json, /_nuxt/builds/latest.json and module debug routes. The advisory check calls the GitHub API. --age adds one RDAP lookup. Each --no-* flag turns its step off.

Every request identifies itself as which-nuxt/<version> (+https://github.com/harlan-zw/which-nuxt). Pass --user-agent to change it for the target site.

API

import { checkAdvisories, detectNuxt } from 'which-nuxt'

const detected = await detectNuxt('https://nuxt.com')
const advisories = await checkAdvisories(detected)

detectNuxt() returns, among other fields:

  • packages: detected dependency versions. checkAdvisories() reads these.
  • modules: Nuxt module fingerprints, each with a certainty of confirmed, inferred or possible.
  • hosting.provider: the edge, CDN or platform named by the response headers.
  • hosting.domainAge: registrar, creation date and age from RDAP, when you pass domainAge: true.

Every result carries a confidence score. checkAdvisories() reports an exact match for a detected version and a possible match for an inferred range.

Module presets

By default detectNuxt() runs every bundled module mapping. Pass one preset and the others never load at runtime:

import { detectNuxt } from 'which-nuxt'
import { officialNuxtModuleDetectors } from 'which-nuxt/modules/official'

const detected = await detectNuxt('https://nuxt.com', {
  moduleDetectors: officialNuxtModuleDetectors,
})

This trims runtime work, not bundle size: detectNuxt() keeps a lazy import of the default presets, so a bundler still emits every preset as a lazy chunk. For a smaller bundle, scan the HTML and JavaScript yourself with which-nuxt/scanners.

| Preset | Import | Covers | | --- | --- | --- | | officialNuxtModuleDetectors | which-nuxt/modules/official | @nuxt/* modules | | communityNuxtModuleDetectors | which-nuxt/modules/community | @nuxtjs/*, nuxt-* and third-party modules | | nuxtModuleDetectors | which-nuxt/modules | both |

Pass moduleDetectors: false to skip module fingerprinting and keep core Nuxt detection.

Scanners

A crawler already has each page's HTML and its /_nuxt/ assets. Hand them to the scanners and skip the requests detectNuxt() would make:

import { officialNuxtModuleDetectors } from 'which-nuxt/modules/official'
import { scanHtml, scanJs } from 'which-nuxt/scanners'

const page = scanHtml(html, url, { moduleDetectors: officialNuxtModuleDetectors })
const entry = scanJs(entryChunk, { moduleDetectors: officialNuxtModuleDetectors })

Cache

Pass an unstorage instance to cache the full detection result. Install unstorage in your project first: pnpm add unstorage.

import type { DetectCacheArtifact } from 'which-nuxt'
import { createStorage } from 'unstorage'
import memoryDriver from 'unstorage/drivers/memory'
import { detectNuxt } from 'which-nuxt'

const cache = createStorage<DetectCacheArtifact>({ driver: memoryDriver() })

const first = await detectNuxt('https://nuxt.com', { cache })
const cached = await detectNuxt('https://nuxt.com', { cache })
const fresh = await detectNuxt('https://nuxt.com', { cache, cacheBust: true })

cacheMaxAge expires entries after this many milliseconds. cacheNamespace and cacheKey control the storage keys. An incomplete scan is not cached, so the next call retries the failed steps.

Supported Module Mappings

Every mapping reads public fingerprints, so a site can hide or fake any of them. The certainty on each result tells you how much weight the signal carries.

| Module | Package | Public mappings | Version mapping | | --- | --- | --- | --- | | Nuxt SEO | @nuxtjs/seo | Inferred when at least three supported SEO child modules are detected. | None. | | Nuxt Robots | @nuxtjs/robots | robots.txt Nuxt Robots credits, /__robots__/debug.json, JS fingerprints such as nuxt-robots, @nuxtjs/robots, robots:bot-context and useRobotsRule. | /__robots__/debug.json. | | Nuxt Sitemap | @nuxtjs/sitemap | sitemap.xml, sitemap_index.xml, /__sitemap__/style.xsl, /__sitemap__/debug.json, JS fingerprints such as __sitemap__, @nuxtjs/sitemap and sitemap:urls. | /__sitemap__/debug.json. | | Nuxt Schema.org | nuxt-schema-org | data-nuxt-schema-org, <script id="schema-org-graph">, /__schema-org__/debug.json, JS fingerprints such as nuxt-schema-org, #schema-org and schema-org:meta. Generic schema.org JSON-LD is not treated as a module signal. | /__schema-org__/debug.json. | | Nuxt OG Image | nuxt-og-image | OG/Twitter image URLs under /_og/ or /__og-image__/, nuxt-og-image-options, nuxt-og-image-overrides, /_og/debug.json, JS fingerprints such as nuxt-og-image and defineOgImage. | /_og/debug.json. | | Nuxt SEO Utils | nuxt-seo-utils | /__nuxt-seo-utils/debug.json, JS fingerprints such as nuxt-seo-utils, seo-utils, useSeoMeta, useBreadcrumbItems and useShareLinks. | /__nuxt-seo-utils/debug.json or JS nuxt-seo-utils-version. | | Nuxt Site Config | nuxt-site-config | /__site-config__/debug.json, JS fingerprints such as nuxt-site-config, #site-config, useSiteConfig and site-config-stack. | /__site-config__/debug.json. | | Nuxt Link Checker | nuxt-link-checker | JS fingerprints such as nuxt-link-checker, __link-checker__ and link-checker:links. | None. | | Nuxt AI Ready | nuxt-ai-ready | /__ai-ready__/debug.json, llms.txt containing a Canonical Origin: header line, <link rel="alternate" type="text/markdown" href="*.md">, JS fingerprints nuxt-ai-ready and __ai-ready. A bare llmstxt.org-format llms.txt is not treated as a module signal. | /__ai-ready__/debug.json. | | Nuxt Scripts | @nuxt/scripts | Proxied/bundled script src under /_scripts/, JS fingerprints such as /_scripts/, @nuxt/scripts, useScript and script-registry. | None. | | Nuxt Image | @nuxt/image | IPX provider URLs under /_ipx/ in img/source src/srcset, JS fingerprint /_ipx/. | None. | | Nuxt Fonts | @nuxt/fonts | Self-hosted font assets under /_fonts/ in link[rel=preload] and @font-face src. | None. | | Nuxt Icon | @nuxt/icon | Rendered class="iconify i-<collection>-<name>" spans (inferred; the @iconify/vue iconify-- form is excluded), JS fingerprints /api/_nuxt_icon and @nuxt/icon. | None. | | Nuxt UI | @nuxt/ui | <style id="nuxt-ui-colors"> (or data-nuxt-ui-colors) injected by the colors plugin, JS fingerprint nuxt-ui-colors. | None. | | Vuetify | vuetify-nuxt-module | <style id="vuetify-theme-stylesheet"> injected by Vuetify (inferred). | None. | | Nuxt Color Mode | @nuxtjs/color-mode | Inline window.__NUXT_COLOR_MODE__ script, JS fingerprint __NUXT_COLOR_MODE__. | None. | | Nuxt Content | @nuxt/content | /__nuxt_content/content/sql_dump.txt (v3), /api/_content/cache.json (v2), JS fingerprints such as /__nuxt_content/, queryCollection and /api/_content/. | None. | | Nuxt i18n | @nuxtjs/i18n | i18n_redirected cookie (inferred). Generic hreflang alternates are not treated as a module signal. | None. | | Nuxt Security | nuxt-security | Default security header set such as X-XSS-Protection: 0, Origin-Agent-Cluster: ?1 and X-Permitted-Cross-Domain-Policies: none (inferred), SRI sha384 hashes on /_nuxt/ assets. | None. | | Pinia | @pinia/nuxt | pinia key in the __NUXT_DATA__ payload (possible; only when a store has SSR state). | None. |

License

Licensed under the MIT license.