MCPInstall

composables

Teaches Vue composables for reusable stateful logic with the Composition API. Use when extracting shared reactive state, side effects, or computed logic that multiple components need.

Installs
201
Last 24h
—
Trending rank
—
Security
Not audited

Install

Works with every agent the skills CLI supports.

npx skills add https://github.com/patternsdev/skills --skill composables
  1. 01

    Install

    Run the command in your project. The CLI asks which agents to install for.

  2. 02

    Describe the task

    Ask your agent for something this skill covers. It loads composables automatically when relevant.

  3. 03

    Review the result

    The agent follows the SKILL.md steps, scripts and references bundled with the skill.

SKILL.md

The instructions your agent reads when the skill is triggered.

Composables

Table of Contents

Composables are functions that encapsulate and reuse stateful logic using Vue's Composition API. They replace the Options API's fragmented code organization with clean, composable functions that can be shared across components.

When to Use

  • Use this when you need to share stateful logic across multiple components without duplication
  • This is helpful for extracting concerns like data fetching, event listeners, or timers into reusable functions

Instructions

  • Name composable functions with the use prefix by convention (e.g., useCounter, useWidth)
  • Use ref(), reactive(), and lifecycle hooks (onMounted, onBeforeUnmount) inside composables
  • Return reactive state and methods from composables for use in component templates
  • Prefer composables over the Options API for better code organization, reusability, and TypeScript support

Details

Options API

Before the introduction of the Composition API in Vue, developers relied on the Options API to organize component logic which include reactive data, lifecycle methods, computed properties, and more. The Options API allowed defining these aspects within specific options, as shown in the example below:

<!-- Template -->

<script>
  export default {
    name: "MyComponent",
    props: {
      // props
    },
    data() {
      // data
    },
    computed: {
      // computed properties
    },
    watch: {
      // properties to watch
    },
    methods: {
      // methods
    },
    created() {
      // lifecyle methods like created
    },
    // ...
  };
</script>

<!-- Styles -->

While this approach served its purpose and is still applicable in Vue v3, it can become challenging to manage and maintain as components grow larger and more complex. Defining component logic within specific options can make it harder to read and understand the code, especially when dealing with extensive components. Extracting and reusing common logic between components can also be difficult in this setup.

Let's take a look at a simple example of an App component that renders two individual child components — Count and Width.

<template>
  <div class="App">
    <Count :count="count" :increment="increment" :decrement="decrement" />
    <div id="divider" />
    <Width :width="width" />
  </div>
</template>

<script>
  import Count from "./components/Count.vue";
  import Width from "./components/Width.vue";

  export default {
    name: "App",
    data() {
      return {
        count: 0,
        width: 0,
      };
    },
    mounted() {
      this.handleResize();
      window.addEventListener("resize", this.handleResize);
    },
    beforeUnmount() {
      window.removeEventListener("resize", this.handleResize);
    },
    methods: {
      increment() {
        this.count++;
      },
      decrement() {
        this.count--;
      },
      handleResize() {
        this.width = window.innerWidth;
      },
    },
    components: {
      Count,
      Width,
    },
  };
</script>

The code snippet above represents a Vue single-file component (SFC) named App.

The <template> section defines the markup of the component. In this case, it contains a <div> element with the class "App" that wraps two child components: <Count> and <Width>. These child components are passed certain properties using Vue's attribute binding syntax (:count, :increment, :decrement, and :width).

The <script> section contains the JavaScript code for the component. Within the component definition, we have:

  • The data method which returns an object containing the initial data properties of the component, which are count and width initialized to 0.
  • The mounted() lifecycle hook is used to execute code after the component has been mounted in the DOM. In this case, it calls the handleResize() method and adds an event listener for the resize event.
  • The beforeUnmount() lifecycle hook is used to execute code before the component is unmounted and destroyed. Here, it removes the event listener for the resize event.
  • The methods object contains the component's methods. It defines increment(), decrement(), and handleResize() methods that manipulate the count and width data properties based on certain events or actions.

When the app is run, the current count and the window's inner width are displayed in real-time. The user can interact with the component by incrementing and decrementing the count using the buttons in the <Count> component. Similarly, the width is automatically updated whenever the window is resized.

Even though this component is small in size, the logic inside it is already intertwined. Some parts are dedicated to the functionality of the counter, while others pertain to the width logic. As the component grows, organizing and locating related logic within the component would become more challenging.

To address these challenges, the Vue team introduced the Composition API in Vue v3.

Composition API

The Composition API can be seen as an API that provides standalone functions representing Vue's core capabilities. These functions are primarily used within a single setup() option which serves as the entry point for utilizing the Composition API.

<!-- Template -->

<script>
  export default {
    name: "MyComponent",
    setup() {
      // the setup function
    },
  };
</script>

<!-- Styles -->

The setup() function is executed before a component is created and when the props of the component are available.

With the Composition API, we can import standalone functions to help us access Vue's core capabilities within our component. Let's rewrite the counter and width example we've seen above while relying on the Composition API syntax.

<template>
  <div class="App">
    <Count :count="count" :increment="increment" :decrement="decrement" />
    <div id="divider" />
    <Width :width="width" />
  </div>
</template>

<script>
  import { ref, onMounted, onBeforeUnmount } from "vue";
  import Count from "./components/Count.vue";
  import Width from "./components/Width.vue";

  export default {
    name: "App",
    setup() {
      const count = ref(0);
      const width = ref(0);

      const increment = () => {
        count.value++;
      };

      const decrement = () => {
        count.value--;
      };

      const handleResize = () => {
        width.value = window.innerWidth;
      };

      onMounted(() => {
        handleResize();
        window.addEventListener("resize", handleResize);
      });

      onBeforeUnmount(() => {
        window.removeEventListener("resize", handleResize);
      });

      return {
        count,
        width,
        increment,
        decrement,
      };
    },
    components: {
      Count,
      Width,
    },
  };
</script>

The <template> of our component remains the same but in the <script> section of our component, we now utilize the Composition API with the setup() function.

Inside the setup() function, we:

  • Define the count and width reactive variables using the ref() function — the function that accepts a single primitive value (e.g. string, number, etc.) and returns a reactive/mutable object.
  • We also define the custom functions increment(), decrement(), and handleResize(). These functions are similar to the methods we defined in our previous Options API example.
  • We use the onMounted() lifecycle function to call the custom handleResize() function and add an event listener for the resize event when the component is mounted. Similarly, we use the onBeforeUnmount() lifecycle function to remove the event listener for the resize event before the component is unmounted.
  • The reactive variables and functions defined in the setup() function are then returned, making them accessible in the component template.

Composables

With our previous code example, one might still wonder how the setup() function offers any advantage to development since it appears that it just requires us to declare component options within a single function.

One of the fantastic benefits of adopting the composition API is the capability to extract and reuse shared logic between components. This is driven by the fact that we can simply declare functions of our own that use Vue's globally available composition functions and have our functions be easily used in multiple components to achieve the same outcome.

Let's take our previous counter and width example further by creating composable functions that encapsulates shared logic that can be reused across components.

First, let's create a composable function called useCounter, a composable that encapsulates the counter functionality and returns the current value of count, an increment() method, and a decrement() method.

By convention, composable function names start with the "use" keyword.

import { ref } from "vue";

export function useCounter(initialCount = 0) {
  const count = ref(initialCount);

  function increment() {
    count.value++;
  }

  function decrement() {
    count.value--;
  }

  return {
    count,
    increment,
    decrement,
  };
}

Similarly, we can create a composable called useWidth() that encapsulates the width functionality of our app.

import { ref, onMounted, onBeforeUnmount } from "vue";

export function useWidth() {
  const width = ref(0);

  function handleResize() {
    width.value = window.innerWidth;
  }

  onMounted(() => {
    handleResize();
    window.addEventListener("resize", handleResize);
  });

  onBeforeUnmount(() => {
    window.removeEventListener("resize", handleResize);
  });

  return {
    width,
  };
}

In our App component, we can now use the composable functions to achieve the same outcome:

<template>
  <div class="App">
    <Count :count="count" :increment="increment" :decrement="decrement" />
    <div id="divider" />
    <Width :width="width" />
  </div>
</template>

<script>
  import Count from "./components/Count.vue";
  import Width from "./components/Width.vue";
  import { useCounter } from "./composables/useCounter";
  import { useWidth } from "./composables/useWidth";

  export default {
    name: "App",
    components: {
      Count,
      Width,
    },
    setup() {
      const { count, increment, decrement } = useCounter(0);
      const { width } = useWidth();

      return {
        count,
        increment,
        decrement,
        width,
      };
    },
  };
</script>

With these changes, our app will function the same as it did before but in a more composable setting.

By using composable functions in the Composition API setting, we were able to break the context of our app down into smaller, reusable pieces that separated the logic.

Using composable functions in Vue made it easier to separate the logic of our component into several smaller pieces. Reusing the same stateful logic now becomes easy since we are no longer confined to organizing our code within specific options in the Options API.

With composable functions, we have the flexibility to extract and reuse shared logic across components. This separation of concerns allows us to focus on specific functionality within each composable function making our code more modular and maintainable.

By breaking down the logic into smaller, reusable pieces, we can compose our components using these composable functions, bringing together the necessary functionality without duplicating code. This approach promotes code reusability and reduces the risk of code duplication and inconsistencies.

Additionally, using the Composition API provides better readability and understandability of the component's logic. Each composable function encapsulates a specific aspect of the component's behavior, making it easier to reason about and test. It also allows for easier collaboration among team members, as the code becomes more structured and organized.

Lastly, building Vue apps with the Composition API allows for better type inference. Since the Composition API helps us handle our component logic with variables and standard JavaScript functions, it becomes a lot easier to build large-scale Vue applications with a static type system like TypeScript!

Source

References

FAQ

What does the composables skill do?

Teaches Vue composables for reusable stateful logic with the Composition API. Use when extracting shared reactive state, side effects, or computed logic that multiple components need.

How do I install composables?

Run npx skills add https://github.com/patternsdev/skills --skill composables in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/composables/ (personal) or .claude/skills/composables/ (project).

Which AI agents can use composables?

Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.

Is composables safe to install?

No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.

Who maintains composables?

It is published by patternsdev in patternsdev/skills. It has 201 recorded installs.

More from patternsdev/skills

View all →

ai-ui-patterns

patternsdev/skills

Teaches design patterns for building AI-powered React interfaces. Use when creating chatbots, intelligent assistants, streaming UIs, or any AI-driven user experience in React.

react-2026

patternsdev/skills

Provides a comprehensive guide to the modern React 2026 stack. Use when starting a new React project or modernizing an existing one with current frameworks, build tools, routing, state management, or AI integration.

dynamic-import

patternsdev/skills

Teaches dynamic import() for on-demand code loading. Use when you need to reduce initial bundle size by lazily loading modules that aren't required at startup.

Business & Finance1.5K installs

bundle-splitting

patternsdev/skills

Teaches bundle splitting techniques for web performance. Use when your application has a large JavaScript bundle that affects load times or when you need to reduce FCP/LCP.

compression

patternsdev/skills

Teaches JavaScript compression techniques including Gzip and Brotli. Use when optimizing network transfer times or configuring server-side compression for production builds.

Backend & APIs1.5K installs

loading-sequence

patternsdev/skills

Teaches resource loading sequence optimization for Core Web Vitals. Use when you need to improve FCP, LCP, or FID by reordering how critical resources are discovered and loaded.

1.5K installs

Popular frontend & design skills

View category →

setup-matt-pocock-skills

mattpocock/skills

Configure this repo for the engineering skills: set up its issue tracker, triage label vocabulary, and domain doc layout. Run once before first use of the other engineering skills.

Frontend & Design1.1M installs

frontend-design

anthropics/skills

Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one. Helps with aesthetic direction, typography, and making choices that don't read as templated defaults.

OfficialFrontend & Design1M installs

hyperframes-animation

heygen-com/hyperframes

All animation knowledge for HyperFrames — atomic motion rules, multi-phase scene blueprints, scene transitions, broader motion-design techniques, AND the seven runtime adapters (GSAP default, plus Lottie, Three.js, Anime.js, CSS keyframes, Web Animations API, TypeGPU). Use for any motion or animation task: pick 2-4 rules and compose, or load a blueprint, or look up runtime-specific API (e.g. GSAP eases / Lottie player / Three.js mixer). Also covers auditing an existing composition's choreography (animation map) and 24 named text-animation effects. HyperFrames-native: single paused timeline, seek-safe, deterministic.

prototype

mattpocock/skills

Build a throwaway prototype to answer a design question. Use when the user wants to sanity-check whether a state model or logic feels right, or explore what a UI should look like.

Frontend & Design999.2K installs

hyperframes-core

heygen-com/hyperframes

The HyperFrames composition contract — build one renderable project. Use for composition structure, the data- timing attributes, class="clip", tracks, sub-compositions, variables, framework-owned media playback, deterministic-render rules, and validation. Read before writing composition HTML.

Frontend & Design930.5K installs

vercel-react-best-practices

vercel-labs/agent-skills

React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.

OfficialFrontend & Design843.1K installs