> ## 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.

# Nuxt Integration

> Integrate PowerSync with Nuxt for offline-first Vue applications.

## Introduction

`@powersync/nuxt` is a Nuxt module that wraps [`@powersync/vue`](https://www.npmjs.com/package/@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.

<Card title="npm: @powersync/nuxt" icon="npm" href="https://www.npmjs.com/package/@powersync/nuxt" horizontal />

<Note>
  **Alpha:** The Nuxt PowerSync integration is currently in Alpha. APIs and behavior may change. We welcome feedback in [Discord](https://discord.com/invite/powersync) or on [GitHub](https://github.com/powersync-ja/powersync-js).
</Note>

<Note>
  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.
</Note>

For a complete working example, see the [Nuxt + Supabase Todo List demo](https://github.com/powersync-ja/powersync-js/tree/main/demos/nuxt-supabase-todolist).

## Setup

### Install PowerSync Dependencies

<CodeGroup>
  ```shell npm theme={null}
  npm install @powersync/nuxt
  ```

  ```shell pnpm theme={null}
  pnpm add @powersync/nuxt @powersync/vue @powersync/web
  ```
</CodeGroup>

<Note>
  With **npm** (v7+), peer dependencies are installed automatically. With **pnpm**, you must install peer dependencies explicitly, as shown above.
</Note>

### Add the Module

Add `@powersync/nuxt` to the `modules` array in `nuxt.config.ts` and include the required Vite configuration:

```typescript nuxt.config.ts theme={null}
export default defineNuxtConfig({
  modules: ['@powersync/nuxt'],
  vite: {
    optimizeDeps: {
      exclude: ['@powersync/web']
    },
    worker: {
      format: 'es'
    }
  }
});
```

<Warning>
  If you are using Tailwind CSS in your project, see the [Known Issues](#known-issues) section.
</Warning>

## Configure PowerSync in Your Project

### 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.

```typescript powersync/AppSchema.ts theme={null}
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'];
```

<Tip>
  Learn more about defining your schema in the [JavaScript Web SDK reference](/client-sdk-references/javascript-web#1-define-the-schema).
</Tip>

### Create your Connector

Create a file at `powersync/PowerSyncConnector.ts`. The connector handles authentication and uploading local changes to your backend.

```typescript powersync/PowerSyncConnector.ts theme={null}
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](https://nuxt.com/docs/guide/directory-structure/plugins) at `plugins/powersync.client.ts`. The `.client.ts` suffix ensures this only runs in the browser.

```typescript plugins/powersync.client.ts theme={null}
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

```vue components/TodoList.vue theme={null}
<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.

```typescript theme={null}
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:

<CodeGroup>
  ```shell npm theme={null}
  npm install @powersync/kysely-driver
  ```

  ```shell pnpm theme={null}
  pnpm add @powersync/kysely-driver
  ```
</CodeGroup>

Enable it in `nuxt.config.ts`:

```typescript nuxt.config.ts theme={null}
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:

```typescript theme={null}
import { usePowerSyncKysely } from '@powersync/nuxt';
import { type Database } from '~/powersync/AppSchema';

const db = usePowerSyncKysely<Database>();

const lists = await db.selectFrom('lists').selectAll().execute();
```

## DevTools

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](/tools/nuxt-inspector) for setup instructions and available views.
