The main composable for interacting with Nuxt Skew Protection.
const skew = useSkewProtection()
lazybooleanfalseWhen false (default), the connection is established automatically when the composable is called in a mounted component. When true, you must call connect() manually.
// Auto-connect on mount (default)
const skew = useSkewProtection()
// Manual connection control
const skew = useSkewProtection({ lazy: true })
skew.connect() // Connect when ready
manifestRef<NuxtAppManifestMeta | null>The current build manifest from builds/latest.json.
const { manifest } = useSkewProtection()
console.log(manifest.value?.id) // Current buildId
console.log(manifest.value?.timestamp) // Build timestamp
clientVersionstringThe user's current version (from cookie or buildId).
const { clientVersion } = useSkewProtection()
console.log(clientVersion) // "abc123"
isOutdatedComputedRef<boolean>Whether the user's version is outdated.
const { isOutdated } = useSkewProtection()
if (isOutdated.value) {
console.log('User is on an old version')
}
isConnectedComputedRef<boolean>Whether the SSE/WebSocket connection is currently active.
const { isConnected } = useSkewProtection()
if (isConnected.value) {
console.log('Connected to update stream')
}
connect()() => voidManually establish the connection. Only needed when using lazy: true.
const skew = useSkewProtection({ lazy: true })
// Connect when user clicks a button
function handleConnect() {
skew.connect()
}
disconnect()() => voidManually close the connection. Useful for cleanup or pausing updates.
const { disconnect } = useSkewProtection()
// Disconnect when leaving a section
onBeforeRouteLeave(() => {
disconnect()
})
checkForUpdates()() => Promise<void>Manually trigger an update check.
const { checkForUpdates } = useSkewProtection()
// Check for updates
await checkForUpdates()
onAppOutdated()(callback: (manifest: NuxtAppManifestMeta | null) => void) => voidTriggers when a new version is detected, regardless of whether it affects the current session. Uses Nuxt's built-in app:manifest:update hook.
Use case: Make next page load a hard navigation (forces HTML reload).
const { onAppOutdated } = useSkewProtection()
onAppOutdated((manifest) => {
console.log('New version available:', manifest?.id)
// Show passive "Update available" badge
})
onCurrentChunksOutdated()(callback: (payload: ChunksOutdatedPayload) => void) => voidTriggers only when the user's loaded JavaScript modules have been changed in a new deployment.
Consider the case of a user on a blog post when you deploy a new version that only changes the homepage. The user's session is unaffected
and they can continue browsing without interruption. In this case, onCurrentChunksOutdated will not trigger.
Under the hood this tracks modules using a service worker.
const { onCurrentChunksOutdated } = useSkewProtection()
onCurrentChunksOutdated((payload) => {
console.log('Deleted chunks:', payload.deletedChunks)
console.log('Invalidated modules:', payload.invalidatedModules)
console.log('Passed releases:', payload.passedReleases)
// Show notification
alert('Please reload to get the latest version')
})
interface NuxtAppManifestMeta {
id: string
timestamp: number
skewProtection?: {
current: string
versions: Record<string, VersionInfo>
}
}
interface VersionInfo {
timestamp: string
expires: string
assets: string[]
deletedChunks?: string[]
}
interface ChunksOutdatedPayload {
deletedChunks: string[]
invalidatedModules: string[]
passedReleases: string[]
}
const { onCurrentChunksOutdated } = useSkewProtection()
onCurrentChunksOutdated(({ invalidatedModules, passedReleases }) => {
// Track in analytics
analytics.track('chunks_outdated', {
count: invalidatedModules.length,
modules: invalidatedModules,
releases: passedReleases
})
// Show custom UI
showUpdateDialog({
title: 'Update Required',
message: `${invalidatedModules.length} modules need updating (${passedReleases.length} releases passed)`
})
})
<script setup>
const { clientVersion, manifest } = useSkewProtection()
const buildDate = computed(() => {
if (!manifest.value?.timestamp)
return null
return new Date(manifest.value.timestamp).toLocaleString()
})
</script>
<template>
<div class="version-info">
<p>Your version: {{ clientVersion }}</p>
<p>Latest version: {{ manifest?.id }}</p>
<p>Build date: {{ buildDate }}</p>
</div>
</template>
Note: Only relevant if you're using polling.
const { checkForUpdates, isOutdated } = useSkewProtection()
async function handleUserAction() {
// Check for updates before critical action
await checkForUpdates()
if (isOutdated.value) {
const shouldReload = confirm('A new version is available. Reload now?')
if (shouldReload) {
window.location.reload()
}
}
else {
// Proceed with action
await performCriticalAction()
}
}