v1.0.0
Introduction
Nuxt Skew Protection v1 is the module's first stable release. Choose when outdated clients reload and read version state on the client and server.
Several hooks and options have shorter names. Check the breaking changes before upgrading.
Run the codemod below to migrate your project. For a guided migration, use the LLM upgrade prompt with Claude or ChatGPT.
npx nuxt-skew-protection migrate🔍 Server Version Awareness
Every incoming request now carries event.context.skewVersion populated from the client's cookie. Use the new getClientVersion(event) server utility to read it explicitly, or isClientOutdated(event) to check staleness in API handlers.
export default defineEventHandler((event) => {
if (isClientOutdated(event)) {
// return stale-safe response or set cache headers
}
})⏪ Rollback Detection
The isRollback computed ref is true when the server version is older than the client version. Use it to detect rollbacks.
🛠️ DevTools Panel
Inspect skew protection state in the new Nuxt DevTools panel. It has four tabs:
- Overview shows your resolved module configuration and, when connected to a production URL, displays real time health status and active connection stats.
- Versions lists all stored deployment versions with build timestamps, asset counts, and expiration status.
- Connections shows version distribution and route distribution across active users (requires
connectionTracking: true). - Docs links directly to the module documentation.
The panel is available at /__nuxt-skew-protection in dev mode and can proxy production endpoints for live debugging.
⚡ Multi-Tab Coordination
Tabs share detected deployments through BroadcastChannel, reducing duplicate polling. The module enables this behavior by default. Set multiTab: false to disable it.
🔄 Reload Strategies
Previously the module always showed a notification and waited for the user to click reload. Now you choose the behavior that fits your app with a single config option.
export default defineNuxtConfig({
skewProtection: {
// 'prompt' (default) | 'immediate' | 'idle' | false
reloadStrategy: 'idle',
},
})immediate reloads the moment chunks are invalidated. idle waits until the user switches tabs or the browser is idle, avoiding mid-interaction disruption. Set false to disable built-in handling and drive your own logic through hooks.
⚠️ Breaking Changes
Dependency Version Bumps
The minimum version changed for this dependency. Check its release notes before upgrading:
- nuxt-site-config v4: breaking changes
Hook Renamed: skew:chunks-outdated
The Nuxt hook skew-protection:chunks-outdated has been shortened to skew:chunks-outdated.
// Before
nuxtApp.hooks.hook('skew-protection:chunks-outdated', (payload) => {
// ...
})
// After
nuxtApp.hooks.hook('skew:chunks-outdated', (payload) => {
// ...
})Composable Return: isAppOutdated
isOutdated was renamed to isAppOutdated to distinguish it from chunk-level staleness.
// Before
const { isOutdated } = useSkewProtection()
// After
const { isAppOutdated } = useSkewProtection()Config: bundleAssets
bundlePreviousDeploymentChunks was renamed to bundleAssets for brevity.
// Before
const before = { skewProtection: { bundlePreviousDeploymentChunks: true } }
// After
const after = { skewProtection: { bundleAssets: true } }Route Prefix: /__skew/
Internal API routes moved from /_skew/ to /__skew/ (double underscore) to follow the Nuxt convention for internal routes. Update any custom proxy rules or firewall allowlists.
Cookie Defaults
sameSite changed from strict to lax so the cookie survives cross-origin navigations (e.g. OAuth redirects). maxAge shortened from 60 days to 7 days to reduce stale version drift.
Standalone checkForUpdates Removed
We removed the standalone export. Use the composable method instead:
// Before
import { checkForUpdates } from '#skew-protection'
// After
const { checkForUpdates } = useSkewProtection()Legacy _generate Compat Removed
We removed the internal _generate compatibility check from early pre-releases. If you were on v0.4 or earlier, upgrade to v0.7.6 first, then to v1.
🤖 LLM Upgrade Prompt
Paste this into Claude, ChatGPT, or any LLM to migrate your codebase automatically.
# Upgrade Guide: nuxt-skew-protection v0.x to v1.0.0
You are helping me upgrade nuxt-skew-protection from v0.x to v1.0.0 in my Nuxt project.
## Breaking Changes
### 1. Hook Renamed
**What changed:** `skew-protection:chunks-outdated` → `skew:chunks-outdated`
**Search my codebase for:** `skew-protection:chunks-outdated`
**Regex pattern:** `skew-protection:chunks-outdated`
**Before:**
```ts
nuxtApp.hooks.hook('skew-protection:chunks-outdated', callback)
```
**After:**
```ts
nuxtApp.hooks.hook('skew:chunks-outdated', callback)
```
### 2. Composable Return Renamed
**What changed:** `isOutdated` → `isAppOutdated` on the `useSkewProtection()`{lang="ts"} return.
**Search my codebase for:** `isOutdated`
**Regex pattern:** `isOutdated(?!Payload|\.)`{lang="ts"}
**Before:**
```ts
const { isOutdated } = useSkewProtection()
```
**After:**
```ts
const { isAppOutdated } = useSkewProtection()
```
### 3. Config Renamed
**What changed:** `bundlePreviousDeploymentChunks` → `bundleAssets`
**Search my codebase for:** `bundlePreviousDeploymentChunks`
**Regex pattern:** `bundlePreviousDeploymentChunks`
**Before:**
```ts
skewProtection: { bundlePreviousDeploymentChunks: true }
```
**After:**
```ts
skewProtection: { bundleAssets: true }
```
### 4. Route Prefix Changed
**What changed:** `/_skew/` → `/__skew/` (double underscore)
**Search my codebase for:** `/_skew/`
**Regex pattern:** `/_skew/`
**Before:**
```ts
$fetch('/_skew/sse')
```
**After:**
```ts
$fetch('/__skew/sse')
```
### 5. Standalone checkForUpdates Removed
**What changed:** The standalone `checkForUpdates` export no longer exists. Use the composable.
**Search my codebase for:** `import { checkForUpdates }`
**Regex pattern:** `checkForUpdates.*from.*#skew`
**Before:**
```ts
import { checkForUpdates } from '#skew-protection'
checkForUpdates()
```
**After:**
```ts
const { checkForUpdates } = useSkewProtection()
checkForUpdates()
```
### 6. Cookie Defaults Changed
**What changed:** `sameSite` is now `lax` (was `strict`), `maxAge` is now 7 days (was 60 days).
**Action:** No code changes needed unless you explicitly rely on the old defaults. If you need the old behavior, set them in config:
```ts
skewProtection: {
cookie: { sameSite: 'strict', maxAge: 60 * 60 * 24 * 60 }
}
```
## Verification Checklist
1. `pnpm install` (update lockfile)
2. `npx nuxi typecheck` (catch type errors)
3. `pnpm build` (catch build-time issues)
4. `pnpm test` (catch runtime regressions)
5. Test SSR page load, verify no hydration mismatch warnings
---
Please scan my codebase for all affected patterns listed above and generate a complete migration plan. For each file that needs changes, show me the exact diff.✅ Upgrading
# pnpm
pnpm add nuxt-skew-protection@^1
# npm
npm install nuxt-skew-protection@^1
# yarn
yarn add nuxt-skew-protection@^1📋 Changelog
Compare changes
🚀 Enhancements
reloadStrategyoption:prompt,immediate,idle, orfalse(4b6a9fe)- Multi-tab coordination via
BroadcastChannel(4b6a9fe) /__skew/healthmonitoring endpoint (4b6a9fe)event.context.skewVersionon all server requests (4b6a9fe)getClientVersion(event)server utility (4b6a9fe)isRollbackdetection on composable (4b6a9fe)serverVersionreactive ref on composable (4b6a9fe)isOpenslot prop onSkewNotification(4b6a9fe)- SSR hydration via
useStateforisConnected,serverVersion,manifest(4b6a9fe) - DevTools panel with overview, version history, connection monitoring, and production debug endpoints (
8dc6d1e)
🩹 Fixes
- Handle possibly undefined manifest in multi-tab plugin (
d19bfcf)