Documentation Index
Fetch the complete documentation index at: https://docs.powersync.com/llms.txt
Use this file to discover all available pages before exploring further.
Introduction
@powersync/nuxt is a Nuxt module that wraps @powersync/vue and provides everything you need to build offline-first Nuxt applications. It re-exports all @powersync/vue composables so this is the only PowerSync dependency you need, and it adds a Nuxt Devtools integration with a PowerSync diagnostics panel for inspecting sync status, local data, config, and logs.
Alpha: The Nuxt PowerSync integration is currently in Alpha. APIs and behavior may change. We welcome feedback in Discord or on GitHub.
PowerSync is tailored for client-side applications — there isn’t much benefit to using SSR with PowerSync. Nuxt evaluates plugins server-side unless you use the .client.ts suffix. The PowerSync Web SDK requires browser APIs that are not available in Node.js; it performs no-ops in a Node.js runtime rather than throwing errors, but you should not expect any data from PowerSync during server-side rendering. Always create your PowerSync plugin as plugins/powersync.client.ts to ensure it runs only in the browser.
For a complete working example, see the Nuxt + Supabase Todo List demo.
Setup
Install PowerSync Dependencies
npm install @powersync/nuxt
With npm (v7+), peer dependencies are installed automatically. With pnpm, you must install peer dependencies explicitly, as shown above.
Add the Module
Add @powersync/nuxt to the modules array in nuxt.config.ts and include the required Vite configuration:
export default defineNuxtConfig({
modules: ['@powersync/nuxt'],
vite: {
optimizeDeps: {
exclude: ['@powersync/web']
},
worker: {
format: 'es'
}
}
});
If you are using Tailwind CSS in your project, see the Known Issues section.
Define your Schema
Create a file at powersync/AppSchema.ts and define your local SQLite schema. PowerSync will hydrate these tables once the SDK connects to your PowerSync instance.
import { column, Schema, Table } from '@powersync/web';
const lists = new Table({
created_at: column.text,
name: column.text,
owner_id: column.text
});
const todos = new Table(
{
list_id: column.text,
created_at: column.text,
completed_at: column.text,
description: column.text,
created_by: column.text,
completed_by: column.text,
completed: column.integer
},
{ indexes: { list: ['list_id'] } }
);
export const AppSchema = new Schema({
todos,
lists
});
// For types
export type Database = (typeof AppSchema)['types'];
export type TodoRecord = Database['todos'];
export type ListRecord = Database['lists'];
Create your Connector
Create a file at powersync/PowerSyncConnector.ts. The connector handles authentication and uploading local changes to your backend.
powersync/PowerSyncConnector.ts
import { UpdateType, type PowerSyncBackendConnector } from '@powersync/web';
export class PowerSyncConnector implements PowerSyncBackendConnector {
async fetchCredentials() {
// Return a JWT for the PowerSync Service to authenticate the client.
// See https://docs.powersync.com/installation/authentication-setup
// For quick local testing, use a development token:
// https://docs.powersync.com/installation/authentication-setup/development-tokens
return {
endpoint: '[Your PowerSync instance URL]',
token: '[Your auth token]'
};
}
async uploadData(db: any) {
// Send local changes to your backend.
// See https://docs.powersync.com/client-sdk-references/javascript-web#3-integrate-with-your-backend
const transaction = await db.getNextCrudTransaction();
if (!transaction) return;
try {
for (const op of transaction.crud) {
const record = { ...op.opData, id: op.id };
switch (op.op) {
case UpdateType.PUT:
// TODO: send CREATE to your backend API
break;
case UpdateType.PATCH:
// TODO: send PATCH to your backend API
break;
case UpdateType.DELETE:
// TODO: send DELETE to your backend API
break;
}
}
await transaction.complete();
} catch (error: any) {
console.error('Data upload error - discarding', error);
await transaction.complete();
}
}
}
Create the Plugin
Create a Nuxt plugin at plugins/powersync.client.ts. The .client.ts suffix ensures this only runs in the browser.
plugins/powersync.client.ts
import { NuxtPowerSyncDatabase, createPowerSyncPlugin } from '@powersync/nuxt';
import { AppSchema } from '~/powersync/AppSchema';
import { PowerSyncConnector } from '~/powersync/PowerSyncConnector';
export default defineNuxtPlugin({
async setup(nuxtApp) {
const db = new NuxtPowerSyncDatabase({
database: {
dbFilename: 'my-app.sqlite'
},
schema: AppSchema
});
const connector = new PowerSyncConnector();
await db.init();
await db.connect(connector);
const plugin = createPowerSyncPlugin({ database: db });
nuxtApp.vueApp.use(plugin);
}
});
Using PowerSync
The module automatically exposes all @powersync/vue composables. You can import and use them directly in any component or composable.
Reading Data
<script setup lang="ts">
import { usePowerSync, useQuery, useStatus } from '@powersync/nuxt';
// Access the PowerSync database instance
const powersync = usePowerSync();
// Reactive query — re-renders automatically when data changes
const { data: lists, isLoading } = useQuery('SELECT * FROM lists ORDER BY created_at DESC');
// Connection status
const status = useStatus();
</script>
<template>
<div>
<p>Status: {{ status.connected ? 'Connected' : 'Offline' }}</p>
<p v-if="isLoading">Loading...</p>
<ul v-else>
<li v-for="list in lists" :key="list.id">{{ list.name }}</li>
</ul>
</div>
</template>
Writing Data
Use execute to write to the local SQLite database. Changes are queued and uploaded to your backend via uploadData in the connector.
import { usePowerSync } from '@powersync/nuxt';
import { v4 as uuid } from 'uuid';
const powersync = usePowerSync();
await powersync.execute(
'INSERT INTO lists (id, created_at, name, owner_id) VALUES (?, ?, ?, ?)',
[uuid(), new Date().toISOString(), 'My List', currentUserId]
);
Kysely ORM (Optional)
The module optionally exposes a usePowerSyncKysely() composable for type-safe query building. You must install the driver and opt in via config.
Install the driver:
npm install @powersync/kysely-driver
Enable it in nuxt.config.ts:
export default defineNuxtConfig({
modules: ['@powersync/nuxt'],
powersync: {
kysely: true
},
vite: {
optimizeDeps: {
exclude: ['@powersync/web']
},
worker: {
format: 'es'
}
}
});
Then use usePowerSyncKysely with your schema’s Database type for full type safety:
import { usePowerSyncKysely } from '@powersync/nuxt';
import { type Database } from '~/powersync/AppSchema';
const db = usePowerSyncKysely<Database>();
const lists = await db.selectFrom('lists').selectAll().execute();
The @powersync/nuxt module includes a PowerSync diagnostics panel that integrates with Nuxt DevTools. It shows sync status, local data, config, and logs. See Nuxt DevTools Integration for setup instructions and available views.