🎯

create-agnostic-composable

🎯Skill

from serkodev/vue-skills

VibeIndex|
What it does

Generates agnostic Vue composables that flexibly handle reactive and non-reactive inputs using Vue's reactivity utilities like toValue() and toRef().

πŸ“¦

Part of

serkodev/vue-skills(2 items)

create-agnostic-composable

Installation

Quick InstallInstall with npx
npx skills add serkodev/vue-skills
πŸ“– Extracted from docs: serkodev/vue-skills
1Installs
-
AddedFeb 4, 2026

Skill Details

SKILL.md

Create a library-grade Vue composable that accepts maybe-reactive inputs (MaybeRef / MaybeRefOrGetter) so callers can pass a plain value, ref, or getter. Normalize inputs with toValue()/toRef() inside reactive effects (watch/watchEffect) to keep behavior predictable and reactive. Use this skill when user asks for creating agnostic or reusable composables.

Overview

# Create Agnostic Composable

Agnostic composables are reusable functions that can accept both reactive and non-reactive inputs. This allows developers to use the composable in a variety of contexts without worrying about the reactivity of the inputs.

Steps to design an agnostic composable in Vue.js:

  1. Confirm the composable's purpose and API design and expected inputs/outputs.
  2. Identify inputs params that should be reactive (MaybeRef / MaybeRefOrGetter).
  3. Use toValue() or toRef() to normalize inputs inside reactive effects.
  4. Implement the core logic of the composable using Vue's reactivity APIs.

Core Type Concepts

Type Utilities

```ts

/**

* value or writable ref (value/ref/shallowRef/writable computed)

*/

export type MaybeRef = T | Ref | ShallowRef | WritableComputedRef;

/**

* MaybeRef + ComputedRef + () => T

*/

export type MaybeRefOrGetter = MaybeRef | ComputedRef | (() => T);

```

Policy and Rules

  • Read-only, computed-friendly input: use MaybeRefOrGetter
  • Needs to be writable / two-way input: use MaybeRef
  • Parameter might be a function value (callback/predicate/comparator): do not use MaybeRefOrGetter, or you may accidentally invoke it as a getter.
  • DOM/Element targets: if you want computed/derived targets, use MaybeRefOrGetter.

When MaybeRefOrGetter or MaybeRef is used:

  • resolve reactive value using toRef() (e.g. watcher source)
  • resolve non-reactive value using toValue()

Examples

Agnostic useDocumentTitle Composable: read-only title parameter

```ts

import { watch, toRef } from 'vue'

import type { MaybeRefOrGetter } from 'vue'

export function useDocumentTitle(title: MaybeRefOrGetter) {

watch(toRef(title), (t) => {

document.title = t

}, { immediate: true })

}

```

Agnostic useCounter Composable: two-way writable count parameter

```ts

import { watch, toRef } from 'vue'

import type { MaybeRef } from 'vue'

function useCounter(count: MaybeRef) {

const countRef = toRef(count)

function add() {

countRef.value++

}

return { add }

}

```