npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

convex-vue-query

v0.1.2

Published

Integrate convex-vue + Tanstack Query.

Readme

convex-vue-query

A seamless integration between convex-vue and Vue Query (TanStack Query) for Vue applications. This package provides a powerful and type-safe way to manage server state and real time updates with Convex while leveraging Vue Query's powerful caching and control over the query lifecycle.

Features

  • 🚀 Type-safe: Full TypeScript support with Convex's generated types
  • 🔄 Real-time: Automatic real-time updates with Convex subscriptions
  • 💾 Configurable caching: Vue Query's powerful control of query data, placeholders and stale time.
  • 🔗 Reactive: Pass reactive references and objects to query params.

Installation

# npm
npm install convex-vue-query

# pnpm
pnpm add convex-vue-query

Quick Start

1. Setup the Plugin

Setup the plugin after configuring convex-vue and Vue Query.

import { createApp } from 'vue'
import { convexVue } from 'convex-vue'
import { VueQueryPlugin } from '@tanstack/vue-query'
import { ConvexVueQuery } from 'convex-vue-query'

const app = createApp(App)

// Default setup for convex-vue. See their repo for more details and options.
app.use(convexVue, { url: import.meta.env.VITE_CONVEX_URL })

// Setup Vue Query.
app.use(VueQueryPlugin)

// Setup this plugin at the end.
app.use(ConvexVueQuery)

app.mount('#app')

2. Basic Query Example

We have a helper convexQuery to generate a query configuration object that can be used with Vue Query's useQuery. It has the same name and usage as the official React wrapper that Convex provides.

<template>
  <div>
    <ul>
      <li v-for="message in messages" :key="message._id">
        {{ message.text }}
      </li>
    </ul>
  </div>
</template>

<script lang="ts" setup>
import { convexQuery } from 'convex-vue-query'
import { api } from '~convex/_generated/api'

const { data: messages } = useQuery(convexQuery(api.messages.list, {}))
</script>

3. Simple Mutation Example

Use useConvexMutation that is directly exported from convex-vue.

<template>
  <div>
    <input v-model="text" @keyup.enter="send" />
    <button @click="send">Send Message</button>
  </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import { useConvexMutation } from 'convex-vue-query'
import { api } from '~convex/_generated/api'

const text = ref('')
const { mutate } = useConvexMutation(api.messages.create)

async function send() {
  await mutate({ text: text.value })
  text.value = ''
}
</script>

4. Advanced Example with Placeholder Data

Expand the convexQuery options to further configure the query as needed. For example you can use the placeholderData option to provide placeholder data for the query reading a previous query from the list if present.

You can override any option like enabled or initialData as needed. Some options do not make sense to use with Convex like refetchInterval or staleTime so please do not configure them.

<template>
  <div>
    <ul>
      <li v-for="message in messages" :key="message._id">
        {{ message.text }}
        <button @click="selected = message._id">Select</button>
      </li>
    </ul>

    <div v-if="selectedMessage" class="selected">
      {{ selectedMessage }}
      <button @click="selected = undefined">Unselect</button>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref, computed } from 'vue'
import { useQuery, useQueryClient } from '@tanstack/vue-query'
import { convexQuery, convexQueryKey, useConvexMutation } from 'convex-vue-query'
import { api } from '~convex/_generated/api'
import type { Doc, Id } from '~convex/_generated/dataModel'

const { data: messages } = useQuery(convexQuery(api.messages.list, {}))

const selected = ref<Id<'messages'> | undefined>()
const client = useQueryClient()
type Message = Doc<'messages'>

const { data: selectedMessage } = useQuery({
  ...convexQuery(api.messages.get, { id: computed(() => selected.value!) }),
  placeholderData: () => {
    // Try to read a previous query if it exists to fill up the placeholder
    // data while the query is loading.
    const messages = client.getQueryData<Message[]>(convexQueryKey(api.messages.list, {}))
    return messages?.find((m) => m._id === selected.value)
  },
})
</script>

API Reference

convexQuery(apiFunction, args)

Creates a query configuration object that can be used with Vue Query's useQuery.

const { data, isLoading, error } = useQuery(convexQuery(api.messages.list, {}))

useConvexMutation(apiFunction)

Returns a mutation object with a mutate method and some helpful properties.

const { mutate, isPending, error } = useConvexMutation(api.messages.create)

convexQueryKey(apiFunction, args)

Generates a consistent query key for manual cache manipulation.

const queryKey = convexQueryKey(api.messages.list, {})
client.setQueryData(queryKey, newData)

const queryKeyWithArgs = convexQueryKey(api.messages.get, { id: '123' })
client.setQueryData(queryKeyWithArgs, newData)

Real-time Updates

Convex queries automatically stay in sync with your database. When data changes on the server, your Vue components will automatically re-render with the latest data.

Differences from using TanStack Query with fetch

Stale Time

New query results are pushed from the server, so a staleTime of Infinity should be used and is enforced by convexQuery. Queries will be always up to date without the need to manually refetch and won't refetch when switching tabs or any other default behavior of TanStack Query.

Subscription time

A difference from the official React+Tanstack Query library is that the subscription time is tied to the query lifecycle. When a query is unmounted, the subscription is cancelled inmediately instead of waiting for the gcTime to kick in. When the query is mounted again, the subscription is re-established like a normal fetch-based query would do.

This is nicer as it avoids uncontrolled background usage when the query is unmounted racking up unnecessary costs.

Refetching

Do not configure refetchInterval or any kind of refetching as this will be handled by Convex. Any data updates will be pushed to the client automatically.

Contributing

We welcome contributions! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

License

This project is licensed under the MIT License - see the LICENSE file for details.