---
title: "useSkewProtection()"
description: "Composable for accessing skew protection state and methods."
canonical_url: "https://nuxtseo.com/docs/skew-protection/api/use-skew-protection"
last_updated: "2026-05-25T17:24:19.547Z"
---

The main composable for interacting with Nuxt Skew Protection.

## Usage

```ts
const skew = useSkewProtection()
```

## Options

### `lazy`

- Type: `boolean`
- Default: `false`

When `false` (default), the composable establishes the connection automatically when called in a mounted component. When `true`, you must call `connect()` manually.

```ts
// Auto-connect on mount (default)
const skew = useSkewProtection()

// Manual connection control
const skew = useSkewProtection({ lazy: true })
skew.connect() // Connect when ready
```

## Returns

### `manifest`

- Type: `Ref<NuxtAppManifestMeta | null>`

The current build manifest from `builds/latest.json`.

```ts
const { manifest } = useSkewProtection()

console.log(manifest.value?.id) // Current buildId
console.log(manifest.value?.timestamp) // Build timestamp
```

### `clientVersion`

- Type: `string`

The user's current version (from cookie or buildId).

```ts
const { clientVersion } = useSkewProtection()

console.log(clientVersion) // "abc123"
```

### `isAppOutdated`

- Type: `ComputedRef<boolean>`

Whether the user's version is outdated.

```ts
const { isAppOutdated } = useSkewProtection()

if (isAppOutdated.value) {
  console.log('User is on an old version')
}
```

### `isConnected`

- Type: `ComputedRef<boolean>`

Whether the SSE/WebSocket connection is currently active.

```ts
const { isConnected } = useSkewProtection()

if (isConnected.value) {
  console.log('Connected to update stream')
}
```

### `connect()`

- Type: `() => void`

Manually establish the connection. Only needed when using `lazy: true`.

```ts
const skew = useSkewProtection({ lazy: true })

// Connect when user clicks a button
function handleConnect() {
  skew.connect()
}
```

### `disconnect()`

- Type: `() => void`

Manually close the connection. Useful for cleanup or pausing updates.

```ts
const { disconnect } = useSkewProtection()

// Disconnect when leaving a section
onBeforeRouteLeave(() => {
  disconnect()
})
```

### `checkForUpdates()`

- Type: `() => Promise<void>`

Manually trigger an update check.

```ts
const { checkForUpdates } = useSkewProtection()

// Check for updates
await checkForUpdates()
```

### `onAppOutdated()`

- Type: `(callback: (manifest: NuxtAppManifestMeta | null) => void) => void`

Triggers when it detects a new version, 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).

```ts
const { onAppOutdated } = useSkewProtection()
onAppOutdated((manifest) => {
  console.log('New version available:', manifest?.id)
  // Show passive "Update available" badge
})
```

### `onCurrentChunksOutdated()`

- Type: `(callback: (payload: ChunksOutdatedPayload) => void) => void`

Triggers **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.

```ts
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')
})
```

## Type Definitions

```ts
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[]
}
```

## Examples

### Custom Invalidation Handler

```ts
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)`
  })
})
```

### Version Information Display

```vue
<script setup lang="ts">
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>
```

### Programmatic Update Check

Note: Only relevant if you're using `polling`.

```ts
const { checkForUpdates, isAppOutdated } = useSkewProtection()

async function handleUserAction() {
  // Check for updates before critical action
  await checkForUpdates()

  if (isAppOutdated.value) {
    const shouldReload = confirm('A new version is available. Reload now?')
    if (shouldReload) {
      window.location.reload()
    }
  }
  else {
    // Proceed with action
    await performCriticalAction()
  }
}
```
