---
title: App Wake Lock Plugin
related:
  - title: App Fullscreen Plugin
    path: app-fullscreen.md
  - title: App Visibility Plugin
    path: app-visibility.md
---
Recipe pages, boarding passes, presentations, navigation views: some screens must stay on while the user is not touching the device. The AppWakeLock plugin wraps the [Screen Wake Lock API](https://developer.mozilla.org/en-US/docs/Web/API/Screen_Wake_Lock_API) so that a single `request()` keeps the screen awake for as long as you want it to, and `release()` lets the device go back to its normal timeout.

## AppWakeLock API

### Props

- `isCapable` (boolean, optional, reactive)
  Does the browser support the Screen Wake Lock API? Always 'false' on the server and, on SSR/SSG, until hydration completes
- `isActive` (boolean, optional, reactive)
  Is a screen wake lock currently held? Becomes 'false' when the browser releases the lock on its own (page hidden, battery saver) and 'true' again once the plugin re-acquires it

### Methods

- `request(): Promise<void>`
  Keep the screen awake; the plugin re-acquires the lock whenever the browser drops it (page hidden) until release() is called
  Returns: `Promise<void>`
    A Promise which is resolved when the wake lock is held. It gets rejected with 'Not capable' if the browser is not capable, and with the browser's DOMException (usually 'NotAllowedError': page hidden, battery saver, permissions policy) if the lock could not be acquired.
    Examples: `request().then(() => { ... }).catch(err => { ... })`
- `release(): Promise<void>`
  Let the screen turn off again
  Returns: `Promise<void>`
    A Promise which is resolved when the wake lock is released. It gets rejected with 'Not capable' if the browser is not capable.
    Examples: `release().then(() => { ... }).catch(err => { ... })`
- `toggle(): Promise<void>`
  Request or release the wake lock, depending on whether one is currently held
  Returns: `Promise<void>`
    A Promise which is resolved when the wake lock is acquired / released. It gets rejected with 'Not capable' if the browser is not capable, and with the browser's DOMException if the lock could not be acquired.
    Examples: `toggle().then(() => { ... }).catch(err => { ... })`

### Vue Injection

Accessible via `$q.wakeLock` (e.g., `this.$q.wakeLock` in Options API or `useQuasar().wakeLock` in Composition API).

## Installation

Add to `quasar.config.js`:

```js
framework: {
    plugins: [
      'AppWakeLock'
    ]
}
```

## Usage

Example "Outside of a Vue file":

```js
import { AppWakeLock } from 'quasar'

// Keep the screen awake:
AppWakeLock.request()
  .then(() => {
    // success!
  })
  .catch(err => {
    // page hidden, battery saver, or not capable
  })

// Let the screen turn off again:
AppWakeLock.release()
```

Example "Inside of a Vue file":

```js
import { useQuasar } from 'quasar'

setup () {
  const $q = useQuasar()

  $q.wakeLock.request()
    .then(() => {
      // success!
    })
    .catch(err => {
      // page hidden, battery saver, or not capable
    })

  // ...later
  $q.wakeLock.release()
}
```

Example "Basic":

```vue
<template>
  <div v-if="$q.wakeLock.isCapable">
    <q-toggle
      v-model="keepAwake"
      label="Keep the screen awake"
      @update:model-value="onToggle"
    />

    <div class="q-mt-sm"> Lock held: {{ $q.wakeLock.isActive }} </div>

    <div class="q-mt-sm text-caption">
      Switch to another tab or app and come back: the browser drops the lock
      while the page is hidden and the plugin re-acquires it.
    </div>
  </div>

  <div v-else> This browser does not support the Screen Wake Lock API. </div>
</template>

<script setup>
import { useQuasar } from 'quasar'
import { ref, watch } from 'vue'

const $q = useQuasar()
const keepAwake = ref(false)

function onToggle(val) {
  const promise = val ? $q.wakeLock.request() : $q.wakeLock.release()

  promise.catch(err => {
    keepAwake.value = false
    $q.notify({
      type: 'negative',
      message: `Wake lock ${val ? 'request' : 'release'} failed: ${err.message}`
    })
  })
}

// the plugin keeps re-acquiring the lock until release() is called,
// so this is only a mirror of what the toggle asked for
watch(
  () => $q.wakeLock.isActive,
  val => {
    if (val) keepAwake.value = true
  }
)
</script>
```

## The browser releases the lock on its own

A wake lock only lives while the page is visible. As soon as the user switches tabs, minimizes the browser or locks the phone, the browser releases the lock, and `isActive` drops to `false`. The plugin remembers that you asked for the lock and requests it again the moment the page becomes visible, until you call `release()`. There is nothing to wire up on your side: one `request()` on mount and one `release()` on unmount is all a component needs.

```html
<template>...</template>

<script setup>
  import { useQuasar } from 'quasar'
  import { onBeforeUnmount } from 'vue'

  const $q = useQuasar()

  $q.wakeLock.request().catch(() => {
    // not available; the page still works, the screen just times out
  })

  onBeforeUnmount(() => {
    $q.wakeLock.release()
  })
</script>
```

`isActive` always reflects the actual state: `true` only while a lock is really held. Watch it if your UI shows the current status.

> [!WARNING]
> **When the request is refused**
>
> The browser rejects `request()` with a `NotAllowedError` when the page is hidden, when the device is in a battery saver mode, or when a `screen-wake-lock` [Permissions Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Permissions-Policy/screen-wake-lock) forbids it (relevant when your app runs inside an iframe). Treat the rejection as a soft failure: the screen behaves as it always did.

## Browser support

The Screen Wake Lock API needs a secure context (HTTPS or localhost) and is available in Chromium-based browsers, Safari 16.4+ and Firefox 126+. Check `$q.wakeLock.isCapable` before showing a "keep screen on" control; where it is `false`, the methods reject with a `Not capable` error.

> [!TIP]
> **Hybrid apps**
>
> The API works inside the WebViews used by Capacitor and Cordova on current platforms, so the plugin stays the single answer for web, PWA and hybrid builds. If you need the screen on regardless of the WebView's support, the native keep-awake plugins of those platforms are the fallback.

## SSR and SSG

There is no screen on the server, so `isCapable` and `isActive` are both `false` there and the methods resolve without doing anything. On the client, `isCapable` gets its real value only after hydration completes, which keeps markup that depends on it (a `v-if` around your toggle) from mismatching the server render.
