@guebbit/vue-toolkit

Vue 3 composables and Pinia stores for CRUD screens: a normalized record store, a REST layer built on TanStack Query, Zod-backed form validation, and toast/loading stores.
2,654
Install
npm install @guebbit/vue-toolkit
Latest Version:5.2.0
Vue:3
License:AGPL-3.0-only
Last Updated:Oct 9, 2026
Links: GitHub  ·  npm
Maintainer: shinseiten

@guebbit/vue-toolkit

npm version license

Vue 3 composables and Pinia stores for CRUD screens: a normalized record store, a REST layer built directly on TanStack Query — one shared cache, optimistic updates rolled back automatically on failure — Zod-backed form validation, and toast/loading stores.

Documentation: guebbit.github.io/vue-toolkit

Install

npm install @guebbit/vue-toolkit @tanstack/vue-query pinia
npm install zod # optional: only useStructureFormValidation needs it
Peer Version
vue ^3.4
pinia ^2.1 || ^3 || ^4
@tanstack/vue-query ^5.103
zod (optional) ^4.4.3

Install @tanstack/vue-query, never @tanstack/query-core next to it. The package ships ES2023: Chrome/Edge 110+, Firefox 115+, Safari 16+, Node 22+.

Setup

import { createApp } from 'vue';
import { createPinia } from 'pinia';
import { QueryClient, VueQueryPlugin } from '@tanstack/vue-query';

const app = createApp(App);
app.use(createPinia());
// one client per app: every resource shares it, which is what lets them invalidate each other
app.use(VueQueryPlugin, { queryClient: new QueryClient() });

What to use

You want… Use
A whole resource: list, filtered search, read, create, update, delete useStructureCrudApi (start here)
Filtered, server-paginated search, wiring the calls yourself useStructureSearchApi
One fetch, watcher or optimistic write at a time useStructureRestApi
A normalized record store for data you already have useStructureDataManagement
Form state, Zod validation, errors the server found useStructureFormValidation
A progress bar for one upload useUploadProgress
data / error / loading for one call that is not a resource useAsyncAction
A "the API is unreachable" banner useLivenessProbe
"Is anything loading?" across the app useIsLoading, useCoreStore
Toasts, and messages that stay until the user deletes them useNotificationsStore

A CRUD resource in one store

import { defineStore, storeToRefs } from 'pinia';
import { useStructureCrudApi } from '@guebbit/vue-toolkit';

export const useProductsStore = defineStore('products', () => ({
    // <record, id, filters>
    ...useStructureCrudApi<IProduct, string, IProductFilters>(
        {
            list: () => listProducts(),
            search: (filters, page, pageSize) =>
                searchProducts(filters, page, pageSize).then((r) => ({
                    items: r.items,
                    totalItems: r.total
                })),
            get: (id) => getProduct(id),
            create: (data) => createProduct(data),
            update: (id, data) => updateProduct(id, data),
            remove: (id) => deleteProduct(id)
        },
        // resourceKey: the first segment of every cache key this resource makes
        { resourceKey: 'products', initialFilters: { text: '' } }
    )
}));

// In a component: state through storeToRefs, methods from the store itself.
const store = useProductsStore();
const { filters, pageItemList, pageCurrent, pageTotal, totalItems } = storeToRefs(store);
const { error } = store.watchList(); // the active search; never rejects
store.updateOne('42', { title: 'New title' }).catch(showError); // optimistic, rolled back on failure

Every operation is optional (a read-only resource supplies list and get). Everything the lower layers offer stays reachable on the same object.

Learn more

License

AGPL-3.0 — see LICENSE.

Related Packages

@qualisero/openapi-endpoint

Type-safe OpenAPI integration for Vue Query

6,354 0
@risklight/models

Framework-agnostic Model/Collection with Proxy-based reactivity and Zod validati...

1,845 0
@vuehookform/core

TypeScript-first form library for Vue 3, inspired by React Hook Form. Form-level...

8,370 8
@maroonedog/waypoint

A field's address exists before the component that draws it: typed paths the com...

308 1
@formkit/core

The framework agnostic core of FormKit

6,311,049 4,779

Version History

Version Released Vue License
5.2.0 ^3.4 AGPL-3.0-only
5.0.0 ^3.4 AGPL-3.0-only
4.0.0 >=3.0.0 AGPLv3.0
3.1.0 >=3.0.0 AGPLv3.0
3.0.0 >=3.0.0 AGPLv3.0