From 22c894326efca8498690d7198aa7e461128be9fb Mon Sep 17 00:00:00 2001 From: benitav Date: Tue, 13 Jan 2026 13:00:58 +0200 Subject: [PATCH 1/8] Update tutorials/client/sdks/web/next-js.mdx Co-Authored-By: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com> --- tutorials/client/sdks/web/next-js.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tutorials/client/sdks/web/next-js.mdx b/tutorials/client/sdks/web/next-js.mdx index f4018f22..0310fdf4 100644 --- a/tutorials/client/sdks/web/next-js.mdx +++ b/tutorials/client/sdks/web/next-js.mdx @@ -7,7 +7,7 @@ keywords: ["next.js", "web"] ## Introduction In this tutorial, we’ll explore how to enhance a Next.js application with offline-first capabilities using PowerSync. In the following sections, we’ll walk through the process of integrating PowerSync into a Next.js application, setting up local-first storage, and handling synchronization efficiently. -At present PowerSync will not work with SSR enabled with Next.js and in this guide we disable SSR across the entire app. However, it is possible to have other pages, which do not require authentication for example, to still be rendered server-side. This can be done by only using the DynamicSystemProvider (covered further down in the guide) for specific pages. This means you can still have full SSR on other page which do not require PowerSync. +PowerSync now supports SSR environments. Importing PowerSync packages no longer throws errors during server-side rendering. The SDK automatically detects SSR environments and returns empty results for queries executed server-side, allowing your pages to render without errors. ## Setup From b366bd8c4c22ad31675cb6aa4b110bb8b50d290b Mon Sep 17 00:00:00 2001 From: benitav Date: Tue, 13 Jan 2026 13:02:54 +0200 Subject: [PATCH 2/8] Update tutorials/client/sdks/web/next-js.mdx Co-Authored-By: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com> --- tutorials/client/sdks/web/next-js.mdx | 132 +++++++++++++++----------- 1 file changed, 78 insertions(+), 54 deletions(-) diff --git a/tutorials/client/sdks/web/next-js.mdx b/tutorials/client/sdks/web/next-js.mdx index 0310fdf4..7818ab19 100644 --- a/tutorials/client/sdks/web/next-js.mdx +++ b/tutorials/client/sdks/web/next-js.mdx @@ -5,7 +5,7 @@ keywords: ["next.js", "web"] --- ## Introduction -In this tutorial, we’ll explore how to enhance a Next.js application with offline-first capabilities using PowerSync. In the following sections, we’ll walk through the process of integrating PowerSync into a Next.js application, setting up local-first storage, and handling synchronization efficiently. +In this tutorial, we'll explore how to enhance a Next.js application with offline-first capabilities using PowerSync. In the following sections, we'll walk through the process of integrating PowerSync into a Next.js application, setting up local-first storage, and handling synchronization efficiently. PowerSync now supports SSR environments. Importing PowerSync packages no longer throws errors during server-side rendering. The SDK automatically detects SSR environments and returns empty results for queries executed server-side, allowing your pages to render without errors. @@ -36,15 +36,13 @@ Would you like to use ESLint? Yes Would you like to use Tailwind CSS? Yes Would you like your code inside a `src/` directory? Yes Would you like to use App Router? (recommended) Yes -Would you like to use Turbopack for `next dev`? No +Would you like to use Turbopack for `next dev`? Yes Would you like to customize the import alias (`@/*` by default)? Yes ``` - - Do not use Turbopack when setting up a new Next.js project as we’ll be updating the `next.config.ts` to use Webpack. This is done because we need to enable: - 1. asyncWebAssembly - 2. topLevelWait - + + Turbopack is supported in Next.js 16+. If you're using an older version of Next.js, see the [Webpack configuration (legacy)](#webpack-configuration-legacy) section below. + ### Install PowerSync Dependencies @@ -70,27 +68,72 @@ pnpm install @powersync/web @journeyapps/wa-sqlite @powersync/react This SDK currently requires [@journeyapps/wa-sqlite](https://www.npmjs.com/package/@journeyapps/wa-sqlite) as a peer dependency. +### Copy Worker Assets + +When using Turbopack, you need to copy the PowerSync worker files to your public directory. Add a `postinstall` script to your `package.json`: + +```json package.json +{ + "scripts": { + "postinstall": "powersync-web copy-assets -o public" + } +} +``` + +Then run the script to copy the assets: + + + +```shell npm +npm run postinstall +``` + +```shell yarn +yarn postinstall +``` + +```shell pnpm +pnpm postinstall +``` + + + +This copies the pre-bundled worker files to `public/@powersync/`, which are required since Turbopack doesn't support dynamic imports of workers yet. + +Add `public/@powersync/*` to your `.gitignore` file since these are generated assets. + ## Next.js Config Setup -In order for PowerSync to work with the Next.js we'll need to modify the default `next.config.ts` to support PowerSync. +For Next.js 16+ with Turbopack, the configuration is minimal: ```typescript next.config.ts module.exports = { - experimental: { - turbo: false, - }, - webpack: (config: any, isServer: any) => { + images: { + disableStaticImages: true + }, + turbopack: {} +}; +``` + +Run `pnpm dev` to start the development server and check that everything compiles correctly, before moving onto the next section. + +### Webpack configuration (legacy) + +If you're using an older version of Next.js (before 16) or prefer to use Webpack, use this configuration instead: + +```typescript next.config.ts +module.exports = { + webpack: (config: any, { isServer }: any) => { config.experiments = { ...config.experiments, - asyncWebAssembly: true, // Enable WebAssembly in Webpack + asyncWebAssembly: true, topLevelAwait: true, }; - // For Web Workers, ensure proper file handling if (!isServer) { config.module.rules.push({ test: /\.wasm$/, - type: "asset/resource", // Adds WebAssembly files to the static assets + type: "asset/resource", }); } @@ -99,11 +142,6 @@ module.exports = { } ``` -Some important notes here, we have to enable `asyncWebAssemply` in Webpack, `topLevelAwait` is required and for Web Workers, ensure proper file handling. -It's also important to add web assembly files to static assets for the site. We will not be using SSR because PowerSync does not support it. - -Run `pnpm dev` to start the development server and check that everything compiles correctly, before moving onto the next section. - ## Configure a PowerSync Instance Now that we've got our project setup, let's create a new PowerSync Cloud instance and connect our client to it. For the purposes of this demo, we'll be using Supabase as the source backend database that PowerSync will connect to. @@ -235,25 +273,29 @@ Add a new file in the newly created `providers` directory called `SystemProvider import { AppSchema } from '@/lib/powersync/AppSchema'; import { BackendConnector } from '@/lib/powersync/BackendConnector'; import { PowerSyncContext } from '@powersync/react'; -import { PowerSyncDatabase, WASQLiteOpenFactory, WASQLiteVFS, createBaseLogger, LogLevel } from '@powersync/web'; +import { PowerSyncDatabase, WASQLiteOpenFactory, createBaseLogger, LogLevel } from '@powersync/web'; import React, { Suspense } from 'react'; const logger = createBaseLogger(); logger.useDefaults(); logger.setLevel(LogLevel.DEBUG); +const factory = new WASQLiteOpenFactory({ + dbFilename: 'powersync.db', + // Use the pre-bundled worker from public/@powersync/ + // This is required since Turbopack doesn't support dynamic imports of workers yet + worker: '/@powersync/worker/WASQLiteDB.umd.js' +}); + export const db = new PowerSyncDatabase({ + database: factory, schema: AppSchema, - database: new WASQLiteOpenFactory({ - dbFilename: 'exampleVFS.db', - vfs: WASQLiteVFS.OPFSCoopSyncVFS, - flags: { - enableMultiTabs: typeof SharedWorker !== 'undefined', - ssrMode: false - } - }), flags: { - enableMultiTabs: typeof SharedWorker !== 'undefined', + disableSSRWarning: true + }, + sync: { + // Use the pre-bundled sync worker from public/@powersync/ + worker: '/@powersync/worker/SharedSyncImplementation.umd.js' } }); @@ -261,7 +303,6 @@ const connector = new BackendConnector(); db.connect(connector); export const SystemProvider = ({ children }: { children: React.ReactNode }) => { - return ( {children} @@ -270,38 +311,22 @@ export const SystemProvider = ({ children }: { children: React.ReactNode }) => { }; export default SystemProvider; - ``` -The `SystemProvider` will be responsible for initializing the `PowerSyncDatabase`. Here we supply a few arguments, such as the AppSchema we defined earlier along with very important properties such as `ssrMode: false`. -PowerSync will not work when rendered server side, so we need to explicitly disable SSR. +The `SystemProvider` is responsible for initializing the `PowerSyncDatabase`. The worker paths point to the pre-bundled workers copied to the public directory by the `powersync-web copy-assets` command. We also instantiate our `BackendConnector` and pass an instance of that to `db.connect()`. This will connect to the PowerSync instance, validate the token supplied in the `fetchCredentials` function and then start syncing with the PowerSync service. -#### DynamicSystemProvider.tsx - -Add a new file in the newly created `providers` directory called `DynamicSystemProvider.tsx`. - -```typescript components/providers/DynamicSystemProvider.tsx -'use client'; - -import dynamic from 'next/dynamic'; - -export const DynamicSystemProvider = dynamic(() => import('./SystemProvider'), { - ssr: false -}); - -``` -We can only use PowerSync in client side rendering, so here we're setting `ssr:false` - #### Update `layout.tsx` -In our main `layout.tsx` we'll update the `RootLayout` function to use the `DynamicSystemProvider` created in the last step. +In our main `layout.tsx` we'll update the `RootLayout` function to use the `SystemProvider`. ```typescript app/layout.tsx +'use client'; + +import { SystemProvider } from '@/app/components/providers/SystemProvider'; import { Geist, Geist_Mono } from "next/font/google"; import "./globals.css"; -import { DynamicSystemProvider } from '@/app/components/providers/DynamicSystemProvider'; const geistSans = Geist({ variable: "--font-geist-sans", @@ -322,12 +347,11 @@ export default function RootLayout({ - {children} + {children} ); } - ``` #### Use PowerSync From cef0a18a0236fa929d0379f108959abb2eda2b13 Mon Sep 17 00:00:00 2001 From: benitav Date: Tue, 13 Jan 2026 13:03:12 +0200 Subject: [PATCH 3/8] Update client-sdk-references/javascript-web.mdx Co-Authored-By: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com> --- client-sdk-references/javascript-web.mdx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client-sdk-references/javascript-web.mdx b/client-sdk-references/javascript-web.mdx index 5547fe64..ddf7cdfa 100644 --- a/client-sdk-references/javascript-web.mdx +++ b/client-sdk-references/javascript-web.mdx @@ -48,6 +48,12 @@ import LocalOnly from '/snippets/local-only-escape.mdx'; +### SSR Compatibility + +The PowerSync Web SDK supports server-side rendering (SSR) environments. Importing PowerSync packages no longer throws errors during server-side rendering — the SDK automatically detects SSR environments and returns empty results for any queries executed server-side. This allows your pages to render without errors while the actual database operations occur client-side. + +For Next.js integration with Turbopack support, see the [Next.js tutorial](/tutorials/client/sdks/web/next-js). + ## Installation From 633fee2588c52b18f6dcb2136ffdc34953f72d11 Mon Sep 17 00:00:00 2001 From: benitav Date: Tue, 13 Jan 2026 13:03:28 +0200 Subject: [PATCH 4/8] Update client-sdk-references/capacitor.mdx Co-Authored-By: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com> --- client-sdk-references/capacitor.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client-sdk-references/capacitor.mdx b/client-sdk-references/capacitor.mdx index 353ba2dd..11c6d2ec 100644 --- a/client-sdk-references/capacitor.mdx +++ b/client-sdk-references/capacitor.mdx @@ -46,6 +46,8 @@ import LocalOnly from '/snippets/local-only-escape.mdx'; - Certain features are not supported on native Android and iOS platforms, see [limitations](#limitations) below for details All code examples from the Web SDK apply to Capacitor — use `@powersync/web` for imports instead of `@powersync/capacitor`. See the [JavaScript Web SDK reference](/client-sdk-references/javascript-web) for ORM support, SPA framework integration, and developer notes. + + **SSR Compatibility**: The Capacitor SDK supports SSR environments. Importing the package no longer throws errors during server-side rendering. ### SDK Features From 9a6a81990c79528e90b76157df19148a0b677e9e Mon Sep 17 00:00:00 2001 From: benitav Date: Wed, 14 Jan 2026 14:08:41 +0200 Subject: [PATCH 5/8] Update tutorials/client/sdks/web/next-js.mdx Co-Authored-By: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com> --- tutorials/client/sdks/web/next-js.mdx | 2 -- 1 file changed, 2 deletions(-) diff --git a/tutorials/client/sdks/web/next-js.mdx b/tutorials/client/sdks/web/next-js.mdx index 7818ab19..b5504dd9 100644 --- a/tutorials/client/sdks/web/next-js.mdx +++ b/tutorials/client/sdks/web/next-js.mdx @@ -7,8 +7,6 @@ keywords: ["next.js", "web"] ## Introduction In this tutorial, we'll explore how to enhance a Next.js application with offline-first capabilities using PowerSync. In the following sections, we'll walk through the process of integrating PowerSync into a Next.js application, setting up local-first storage, and handling synchronization efficiently. -PowerSync now supports SSR environments. Importing PowerSync packages no longer throws errors during server-side rendering. The SDK automatically detects SSR environments and returns empty results for queries executed server-side, allowing your pages to render without errors. - ## Setup ### Next.js Project Setup From 11a1ca2fbfdfffb4abff0163c8b7e5426e1acb22 Mon Sep 17 00:00:00 2001 From: benitav Date: Wed, 14 Jan 2026 14:09:25 +0200 Subject: [PATCH 6/8] Update client-sdk-references/javascript-web.mdx Co-Authored-By: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com> --- client-sdk-references/javascript-web.mdx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/client-sdk-references/javascript-web.mdx b/client-sdk-references/javascript-web.mdx index ddf7cdfa..5547fe64 100644 --- a/client-sdk-references/javascript-web.mdx +++ b/client-sdk-references/javascript-web.mdx @@ -48,12 +48,6 @@ import LocalOnly from '/snippets/local-only-escape.mdx'; -### SSR Compatibility - -The PowerSync Web SDK supports server-side rendering (SSR) environments. Importing PowerSync packages no longer throws errors during server-side rendering — the SDK automatically detects SSR environments and returns empty results for any queries executed server-side. This allows your pages to render without errors while the actual database operations occur client-side. - -For Next.js integration with Turbopack support, see the [Next.js tutorial](/tutorials/client/sdks/web/next-js). - ## Installation From a63d33251799f5f2aaae4af5f87937e905d6d7da Mon Sep 17 00:00:00 2001 From: benitav Date: Wed, 14 Jan 2026 14:10:12 +0200 Subject: [PATCH 7/8] Update client-sdk-references/capacitor.mdx Co-Authored-By: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com> --- client-sdk-references/capacitor.mdx | 2 -- 1 file changed, 2 deletions(-) diff --git a/client-sdk-references/capacitor.mdx b/client-sdk-references/capacitor.mdx index 11c6d2ec..353ba2dd 100644 --- a/client-sdk-references/capacitor.mdx +++ b/client-sdk-references/capacitor.mdx @@ -46,8 +46,6 @@ import LocalOnly from '/snippets/local-only-escape.mdx'; - Certain features are not supported on native Android and iOS platforms, see [limitations](#limitations) below for details All code examples from the Web SDK apply to Capacitor — use `@powersync/web` for imports instead of `@powersync/capacitor`. See the [JavaScript Web SDK reference](/client-sdk-references/javascript-web) for ORM support, SPA framework integration, and developer notes. - - **SSR Compatibility**: The Capacitor SDK supports SSR environments. Importing the package no longer throws errors during server-side rendering. ### SDK Features From 2efa8736728b89eb667c11abf4c03d70efd7f6b1 Mon Sep 17 00:00:00 2001 From: benitav Date: Wed, 14 Jan 2026 17:36:32 +0200 Subject: [PATCH 8/8] Update tutorials/client/sdks/web/next-js.mdx Co-Authored-By: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com> --- tutorials/client/sdks/web/next-js.mdx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tutorials/client/sdks/web/next-js.mdx b/tutorials/client/sdks/web/next-js.mdx index b5504dd9..ca0ad257 100644 --- a/tutorials/client/sdks/web/next-js.mdx +++ b/tutorials/client/sdks/web/next-js.mdx @@ -7,6 +7,10 @@ keywords: ["next.js", "web"] ## Introduction In this tutorial, we'll explore how to enhance a Next.js application with offline-first capabilities using PowerSync. In the following sections, we'll walk through the process of integrating PowerSync into a Next.js application, setting up local-first storage, and handling synchronization efficiently. + +PowerSync is tailored for client-side applications — there isn't much benefit to using SSR with PowerSync. Some frameworks like Next.js push towards enabling SSR by default, which means code is evaluated in a Node.js runtime. The PowerSync Web SDK requires browser APIs which are not available in Node.js. For ergonomics, the SDK performs no-ops if used in Node.js (rather than throwing errors), but you should not expect any data from PowerSync during server-side rendering. If you are using SSR in your application, we recommend explicitly isolating PowerSync to client-side code. + + ## Setup ### Next.js Project Setup