@syncraft-labs/vue
| Install | |
|---|---|
npm install @syncraft-labs/vue |
|
| Latest Version: | 0.7.1 |
| Vue: | 3 |
| License: | MIT |
| Last Updated: | Oct 21, 2026 |
| Links: | GitHub · npm |
@syncraft-labs/vue
The official Vue 3 bindings for Syncraft Labs - local-first state synchronization.
Purpose
@syncraft-labs/vue provides the useSync composable for Vue 3. It gives your Vue components instant optimistic writes, durable IndexedDB persistence, automatic background outbox sync, and cross-tab synchronization.
Built with Vue 3's shallowRef to safely integrate with proxy draft objects, preventing unnecessary deep reactivity proxying overhead while keeping your UI instantly synced. It relies on createSyncraft() plugin registration via provide/inject for complete store isolation in Nuxt 3 and SSR environments.
Installation
# npm
npm install @syncraft-labs/core @syncraft-labs/vue
# yarn
yarn add @syncraft-labs/core @syncraft-labs/vue
# pnpm
pnpm add @syncraft-labs/core @syncraft-labs/vue
Peer dependencies: Vue ≥ 3.3.0
Documentation
The Syncraft Labs documentation is available at syncraft-labs.web.id.
Basic Usage
Mount the createSyncraft() plugin in your root application (crucial for Nuxt 3 SSR request isolation), then consume state anywhere using useSync.
// main.ts - Install plugin for app-level store isolation
import { createApp } from "vue";
import { createSyncraft } from "@syncraft-labs/vue";
import App from "./App.vue";
const app = createApp(App);
app.use(createSyncraft());
app.mount("#app");
<!-- App.vue -->
<script setup lang="ts">
import { useSync } from "@syncraft-labs/vue";
interface TodoState {
todos: Array<{ id: string; text: string; done: boolean }>;
}
const { data, update, isHydrating, isOffline, error } = useSync<TodoState>(
"todos",
{ initialState: { todos: [] } }
);
function addTodo() {
update((draft) => {
draft.todos.push({
id: crypto.randomUUID(),
text: "New todo",
done: false,
});
});
}
</script>
<template>
<p v-if="isHydrating">Loading from cache...</p>
<div v-else>
<p v-if="isOffline">You're offline - changes saved locally</p>
<p v-if="error">Error: {{ error.message }}</p>
<button @click="addTodo">Add Todo</button>
<ul>
<li v-for="t in data?.todos" :key="t.id">
{{ t.text }}
</li>
</ul>
</div>
</template>
Remote Sync (Background Pushing)
Inject your API calls into the useSync options. Syncraft automatically queues mutations offline and drains the outbox using exponential backoff when connectivity is available.
<script setup lang="ts">
import { useSync } from "@syncraft-labs/vue";
const { data, update, refetch, isSyncing } = useSync<TodoState>("todos", {
initialState: { todos: [] },
// Fetch initial data (called once if DB is empty)
fetcher: () => fetch("/api/todos").then((r) => r.json()),
// Push pending mutations to your backend
pusher: async (entries) => {
await fetch("/api/sync", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(entries),
});
},
// Polling interval in ms (default: 5000)
syncInterval: 3000,
});
</script>
<template>
<button @click="refetch" :disabled="isSyncing">
{{ isSyncing ? "Syncing..." : "Refresh" }}
</button>
</template>
Performance & Optimization
Selector-based Reactivity: Prevent over-rendering by passing a selector function. The composable will only trigger reactivity if the selected slice of data changes (using shallowRef internally).
const { data: doneTodos } = useSync("todos", {
selector: (state) => state?.todos.filter((t) => t.done),
});
Developer Tools
Syncraft Labs exposes a global object window.__SYNCRAFT_DEVTOOLS__ in the browser. You can inspect all active local stores via window.__SYNCRAFT_DEVTOOLS__.stores.
API Reference
| Export | Type | Description |
|---|---|---|
createSyncraft() |
Plugin | Vue plugin guaranteeing app-level store registry isolation across SSR requests |
useSync<T>(key, options) |
Composable | Primary Vue 3 composable returning reactive shallowRef state and updater |
destroyStore(key) |
Function | Destroys an active store instance by storage key |
UseSyncOptions<T> |
Interface | Configuration options (initialState?, fetcher?, pusher?, syncInterval?, selector?, onSyncStart?, onSyncSuccess?, onSyncError?, onRollback?, maxOutboxSize?, overflowStrategy?, onOverflow?, storageMode?, idField?) |
UseSyncReturn<T> |
Interface | Return values (data, update, refetch, isHydrating, isSyncing, isOffline, error) |
License
MIT © Denis Listiadi
Related Packages
Write-behind cache for Vue 3 — local state stays authoritative, the server's rep...
Tiny reactive Vue 3 client for db-state: typed tables, listRef / idsRef / countR...
Reactive state synchronization library bridging an in-memory store, IndexedDB pe...
Version History
| Version | Released | License |
|---|---|---|
| 0.7.1 | MIT | |
| 0.7.0 | MIT | |
| 0.6.0 | MIT | |
| 0.5.0 | MIT | |
| 0.4.2 | MIT | |
| 0.4.0 | MIT | |
| 0.3.0 | MIT | |
| 0.2.1 | MIT | |
| 0.2.0 | MIT | |
| 0.1.1 | MIT | |
| 0.1.0 | MIT |