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

vue-qs

v0.1.18

Published

Type‑safe, reactive URL query parameters for Vue 3 with full TypeScript support

Downloads

479

Readme

vue-qs

vue-qs social

CI npm version license

Note: This library is currently in active development. APIs may change significantly between versions. Please use with caution and expect breaking changes.

📖 Documentation: https://iamsomraj.github.io/vue-qs/
🌏 中文文档: https://iamsomraj.github.io/vue-qs/zh/

Type‑safe, reactive URL query parameters for Vue 3. Inspired by nuqs (React) but built for the Vue Composition API.

✨ Features

  • 🔄 Bidirectional Sync: URL parameters stay in sync with your reactive state
  • 🎯 Type Safety: Full TypeScript support with type inference
  • 🚀 Vue 3 Ready: Built for Vue 3 Composition API
  • 🔧 Flexible: Works with or without Vue Router
  • 🛡️ SSR Safe: Server-side rendering compatible
  • 📦 Tree Shakeable: Only import what you need
  • 🎨 Customizable: Built-in codecs + custom serialization support

🎯 Why vue-qs?

Keep UI state (page, filters, search text, sort, tabs) in the URL so users can:

  • 🔄 Refresh and keep state
  • 🔗 Share links with specific state
  • ⬅️➡️ Use browser back/forward buttons

vue-qs gives you composables that feel like normal refs/reactive objects, but they automatically stay in sync with the URL query string.

📦 Installation

npm install vue-qs
# or
pnpm add vue-qs
# or
bun add vue-qs

Peer Dependencies:

  • vue ^3.3.0 (required)
  • vue-router ^4.2.0 (optional, for router integration)

🚀 Quick Start

Basic Usage (No Router)

<script setup lang="ts">
import { queryRef } from 'vue-qs';

// Create a ref bound to ?name=...
// Falls back to default value if param is missing
const name = queryRef('name', {
  defaultValue: '',
});
</script>

<template>
  <input v-model="name" placeholder="Your name" />
</template>

Multiple Parameters

<script setup lang="ts">
import { queryReactive } from 'vue-qs';

// Each field config controls parsing, defaults, and omission rules
const queryState = queryReactive({
  q: { defaultValue: '' },
  page: { defaultValue: 1, codec: numberCodec },
  showDetails: { defaultValue: false, codec: booleanCodec },
});
</script>

<template>
  <input v-model="queryState.q" placeholder="Search..." />
  <button @click="queryState.page++">Next Page</button>
  <button @click="queryState.showDetails = !queryState.showDetails">Toggle Details</button>
</template>

🔗 Vue Router Integration

Option 1: Global Plugin (Recommended)

// main.ts
import { createApp } from 'vue';
import { createVueQsPlugin, createVueRouterAdapter } from 'vue-qs';
import { router } from './router';
import App from './App.vue';

const app = createApp(App);

app.use(
  createVueQsPlugin({
    queryAdapter: createVueRouterAdapter(router),
  })
);
app.use(router);
app.mount('#app');

Option 2: Per-Component Adapter

<script setup lang="ts">
import { queryRef, createVueRouterAdapter } from 'vue-qs';
import { useRouter } from 'vue-router';

const router = useRouter();
const adapter = createVueRouterAdapter(router);

const page = queryRef('page', {
  defaultValue: 1,
  codec: numberCodec,
  queryAdapter: adapter,
});
</script>

🔧 Codecs (Type Conversion)

Import ready‑made codecs for common types:

import {
  stringCodec,
  numberCodec,
  booleanCodec,
  dateISOCodec,
  createArrayCodec,
  createJsonCodec,
} from 'vue-qs';

// Basic types
const name = queryRef('name', {
  defaultValue: '',
  codec: stringCodec,
});

const page = queryRef('page', {
  defaultValue: 1,
  codec: numberCodec,
});

const isActive = queryRef('active', {
  defaultValue: false,
  codec: booleanCodec,
});

// Complex types
const tags = queryRef('tags', {
  defaultValue: [] as string[],
  codec: createArrayCodec(stringCodec),
});

const filters = queryRef('filters', {
  defaultValue: { category: 'all', sort: 'name' },
  codec: createJsonCodec<{ category: string; sort: string }>(),
});

⚙️ Configuration Options

Shared Options

| Option | Type | Default | Description | | ------------------- | ------------------------- | ------------- | -------------------------------------------- | | defaultValue | T | - | Initial value if parameter is missing | | codec | QueryCodec<T> | stringCodec | Parser and serializer for the type | | parse | QueryParser<T> | - | Custom parser function (overrides codec) | | serializeFunction | QuerySerializer<T> | - | Custom serializer function (overrides codec) | | shouldOmitDefault | boolean | true | Remove from URL when equal to default | | isEqual | (a: T, b: T) => boolean | Object.is | Custom equality function | | historyStrategy | 'replace' \| 'push' | 'replace' | Browser history update strategy | | queryAdapter | QueryAdapter | - | Override default query adapter |

Custom Equality Example

const filters = queryRef('filters', {
  defaultValue: { category: 'all', sort: 'name' },
  codec: createJsonCodec<{ category: string; sort: string }>(),
  isEqual: (a, b) => a.category === b.category && a.sort === b.sort,
});

🛡️ SSR Safety

vue-qs is SSR-safe. On the server, the composables use an internal cache until hydration, so you can render initial HTML safely without touching window.

📚 API Reference

queryRef(name, options)

Creates a reactive ref that syncs with a URL query parameter.

function queryRef<T>(parameterName: string, options?: QueryRefOptions<T>): Ref<T>;

queryReactive(schema, options)

Creates a reactive object that syncs multiple URL query parameters.

function queryReactive<TSchema extends QueryParameterSchema>(
  parameterSchema: TSchema,
  options?: QueryReactiveOptions
): ReactiveQueryState<TSchema>;

createHistoryAdapter()

Creates an adapter for browser History API (default).

function createHistoryAdapter(): QueryAdapter;

createVueRouterAdapter(router)

Creates an adapter for Vue Router integration.

function createVueRouterAdapter(router: Router): QueryAdapter;

Development Setup

# Clone and install
git clone https://github.com/iamsomraj/vue-qs.git
cd vue-qs
bun install

# Development
bun run dev          # Watch mode
bun run test         # Run tests
bun run typecheck    # Type checking
bun run lint         # Linting
bun run docs:dev     # Documentation dev server

📄 License

MIT License - see LICENSE for details.

🙏 Acknowledgments

  • Inspired by nuqs for React
  • Built with Vue 3 Composition API
  • TypeScript support powered by TypeScript