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

nuxt-live-version

v1.1.0

Published

Detect when a new build of your Nuxt app has been deployed while a user still has an old version open in their browser.

Readme

nuxt-live-version

npm version npm downloads License Nuxt

Detect when a new build of your Nuxt app has been deployed while a user still has an old version open in their browser — and let your app decide what to do about it.

The problem

A user opens your app at version 1.0.0 and leaves the tab open. Two hours later you deploy 1.0.1. The user is still running the old JavaScript bundle against a backend/API that has since moved on — a classic source of confusing runtime errors in long-lived sessions (dashboards, back-office tools, anything left open all day).

nuxt-live-version answers one question, reliably: "is the version running in this browser tab still the version published on the server?" It does not decide what to do about it — that's your app's call (toast, banner, silent reload, whatever fits).

Features

  • 🪶 Tiny, zero UI, zero opinions on how you notify the user
  • 🔒 TypeScript-first, fully typed public API
  • 🧩 SSR-safe — never performs the check on the server, never touches window during SSR
  • ⚙️ Configurable polling interval, fully disableable
  • 🌐 Ships its own /__nuxt_version endpoint — no external backend required
  • 🧵 Network errors are swallowed — a failed check never breaks your app
  • 🚫 Never reloads the page for you — no reload loops, ever

Quick Setup

Install the module:

npx nuxi module add nuxt-live-version
# or manually:
npm install nuxt-live-version

Add it to nuxt.config.ts:

export default defineNuxtConfig({
  modules: ['nuxt-live-version'],

  versionCheck: {
    enabled: true,
    interval: 60000, // ms
  },
})

Use it anywhere in your app:

<script setup lang="ts">
const { currentVersion, latestVersion, updateAvailable, checkForUpdate, reload } = useNuxtVersionCheck()
</script>

<template>
  <div v-if="updateAvailable">
    A new version is available.
    <button @click="reload">Reload</button>
  </div>
</template>

That's it. ✨

How it works

The version identifier

The module never reads package.json in the browser. Instead, a version string is stamped once, server-side, at build/start time:

  1. If the NUXT_VERSION_CHECK_VERSION environment variable is set at build/start time, it is used as-is. This is the recommended approach for CI/CD: set it to your git commit SHA, release tag, or build number.
  2. Otherwise it falls back to the server start timestamp (Date.now()), which still changes on every deploy without any configuration.

That value is written once into Nuxt's runtimeConfig.public.versionCheck.currentVersion during the module's setup(). From there it flows to two places that are guaranteed to be in sync because they share the same source:

  • The client bundle reads it as the initial currentVersion (baked into the JS your browser downloaded).
  • The /__nuxt_version server endpoint reads the same value from useRuntimeConfig() on every request and returns { "version": "..." }.

Because both sides read from the same build-time value, a browser tab always sees currentVersion === latestVersion until the app is redeployed — at which point the server process (and its baked-in version) changes, and the endpoint starts returning something new while the open tab still holds the old one.

Caching and CDNs

The /__nuxt_version response is sent with Cache-Control: no-store, no-cache, must-revalidate, and the client additionally appends a cache-busting query parameter to every request. This is what makes the check reliable behind CDNs/proxies that might otherwise serve a stale cached response and mask a real deployment.

SSR safety

The polling logic lives in a .client-suffixed Nuxt plugin, which Nuxt guarantees never runs on the server. The composable's checkForUpdate() additionally no-ops if called during SSR (import.meta.server), and reload() only touches window on the client. The module never makes a network request from the Nitro server process to check its own version — it only tells the browser what version it is.

Configuration

versionCheck: {
  enabled: true,   // default: true
  interval: 60000, // default: 60000ms — set to 0 to disable automatic polling only
}

| Option | Type | Default | Description | | ---------- | --------- | ------- | ----------------------------------------------------------------------------------------------- | | enabled | boolean | true | Turns automatic polling on/off. When false, useNuxtVersionCheck() and manual checkForUpdate() calls still work — only the automatic interval is skipped. | | interval | number | 60000 | Milliseconds between automatic checks. 0 or negative disables automatic polling (same effect as enabled: false, kept separate so you can toggle either independently). |

API

const {
  currentVersion,   // Ref<string>            — version baked into the currently loaded bundle
  latestVersion,    // Ref<string | null>      — version last seen on the server (null before first check)
  updateAvailable,  // ComputedRef<boolean>    — true once latestVersion is known and differs from currentVersion
  checkForUpdate,   // () => Promise<void>     — manually trigger a check; never throws
  reload,           // () => void              — window.location.reload(), client-only
} = useNuxtVersionCheck()
  • checkForUpdate() swallows all errors (offline, 5xx, CDN hiccups, ...): on failure the state is simply left as it was, so a flaky network never crashes your app.
  • reload() is entirely opt-in — the module never calls it for you, so there is no risk of a reload loop.

Environment variables

| Variable | Effect | | ------------------------------ | --------------------------------------------------------------------------------------------- | | NUXT_VERSION_CHECK_VERSION | Overrides the stamped version at build/start time. Set this in CI/CD to a commit SHA or release tag for a precise, human-meaningful version identifier. | | NUXT_PUBLIC_VERSION_CHECK_ENABLED / NUXT_PUBLIC_VERSION_CHECK_INTERVAL | Standard Nuxt runtime config env overrides — let you flip enabled/interval without rebuilding, since both are exposed as public runtime config. |

Requirements / infrastructure

  • Nuxt 4 (tested against nuxt@^4.5.2) with SSR or a Nitro server preset that can serve dynamic routes (Node server, Vercel, Netlify, Cloudflare, etc.). No external backend, database, or third-party service is needed — the module adds its own Nitro route handler at build time.
  • Static/prerendered-only deployments (nuxt generate with no server, e.g. plain static hosting) will bake /__nuxt_version into a static file at generate time — it will only change on the next generate+redeploy, which is fine, but no server-side freshness beyond redeploying is possible. Redeploying a static site is enough to invalidate it as long as the host doesn't cache that path indefinitely (the module sends no-store, but static hosts vary in how strictly they honor per-file cache headers — check your host's docs if you rely on this).
  • No extra runtime dependency beyond ofetch (already bundled with every Nuxt app) — nothing new for consumers to install.

Local development

# Install dependencies (pnpm workspace: root module + playground)
pnpm install

# Generate type stubs (.nuxt/ for both the module and the playground)
pnpm run dev:prepare

# Run the playground with the module linked live
pnpm run dev

# Build the playground for production
pnpm run dev:build

# Lint
pnpm run lint

# Run the test suite
pnpm run test
pnpm run test:watch

# Type-check the module and the playground
pnpm run test:types

# Build the publishable module (dist/)
pnpm run prepack

Running the playground

pnpm install
pnpm run dev:prepare
pnpm run dev

This starts the playground app (playground/) at http://localhost:3000 with nuxt-live-version loaded from src/ via a pnpm workspace link (playground/package.json depends on nuxt-live-version: workspace:*) — any change to src/ is picked up on the next reload, no publish/link step needed. The playground is configured with a 10s interval (see playground/nuxt.config.ts) so automatic polling is easy to observe.

Simulating a version bump (1.0.0 → 1.0.1)

The version is stamped once, when the Nitro server process starts — a running dev/production server keeps serving the same version until it restarts. To simulate a real deploy:

# Terminal 1: start "1.0.0"
NUXT_VERSION_CHECK_VERSION=1.0.0 pnpm run dev

Open http://localhost:3000 in a browser and leave the tab open. Then, without closing that tab:

# Terminal 1: stop the server (Ctrl+C) and restart it as "1.0.1"
NUXT_VERSION_CHECK_VERSION=1.0.1 pnpm run dev

Within one polling interval (10s in the playground), the still-open tab's checkForUpdate() call will hit the now-restarted server, see { "version": "1.0.1" }, and updateAvailable will flip to true — without ever reloading the page for you. You can also trigger it immediately with the playground's "Check for update" button instead of waiting for the interval.

On PowerShell, set the variable for a single command with:

$env:NUXT_VERSION_CHECK_VERSION = "1.0.1"; pnpm run dev

In a real deployment this happens naturally: your CI/CD pipeline sets NUXT_VERSION_CHECK_VERSION (typically to the git commit SHA) before starting the new server process, and every open tab picks up the change on its next automatic or manual check — no special orchestration required.

Running the tests

pnpm run test

This runs three kinds of tests (see test/):

  • test/basic.test.ts — end-to-end, spins up the real fixture app (test/fixtures/basic) and checks: the page renders under SSR (proving the client-only plugin never runs server-side), /__nuxt_version returns a valid { version } payload, and the response is never cacheable.
  • test/composable.nuxt.test.ts — runs inside a real (in-process) Nuxt app instance via @nuxt/test-utils's nuxt environment, and covers useNuxtVersionCheck() directly: same version → updateAvailable === false, different version → updateAvailable === true, a failing request leaves state untouched instead of throwing, and reload() calls window.location.reload().
  • test/plugin.test.ts — a fast, dependency-free unit test of the automatic-polling plugin (mocked Nuxt runtime + fake timers): verifies it polls at the configured interval, and verifies it never polls when enabled: false or interval: 0.

Release

pnpm run release

Runs lint + tests, builds dist/, bumps the version and changelog, publishes to npm, and pushes tags. Requires npm publish access to the package.