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

# React Native Web Support

> Configure PowerSync for React Native Web projects.

[React Native for Web](https://necolas.github.io/react-native-web/) enables developers to use the same React Native codebase for both mobile and web platforms.

<Note>
  **Availability**

  Support for React Native Web is available since versions 1.12.1 of the PowerSync [React Native SDK](/client-sdks/reference/react-native-and-expo) and 1.8.0 if the [JavaScript Web SDK](/client-sdks/reference/javascript-web), and is currently in a **beta** release.
</Note>

A demo app showcasing this functionality is available here:

<Card title="powersync-js/demos/react-native-web-supabase-todolist" icon="github" href="https://github.com/powersync-ja/powersync-js/tree/main/demos/react-native-web-supabase-todolist" horizontal />

## Configuring PowerSync in Your React Native for Web Project

To ensure that PowerSync features are fully supported in your React Native Web project, follow the below steps. This documentation covers necessary web worker configurations, database instantiation, and multi-platform implementations.

### 1. Install Web SDK

The [PowerSync Web SDK](/client-sdks/reference/javascript-web), alongside the [PowerSync React Native SDK](/client-sdks/reference/react-native-and-expo), is required for Web support.

See installation instructions [here](https://www.npmjs.com/package/@powersync/web).

### 2. Configure Web Workers

For React Native for Web, workers need to be configured when instantiating `PowerSyncDatabase`. An example of this is available [here](https://github.com/powersync-ja/powersync-js/blob/main/demos/react-native-web-supabase-todolist/library/powersync/system.ts).

To do this, copy the contents of `node_modules/@powersync/web/dist` to the root of your project (typically in the `public `directory). To make it easier to manage these files in the `public` directory, it is recommended to place the contents in a nested directory like `@powersync`.

The [`@powersync/web`](https://github.com/powersync-ja/powersync-js/tree/main/packages/web) package includes a CLI utility which can copy the required assets to the `public` directory (configurable with the `--output` option).

```bash theme={null}
# Places assets into public/@powersync by default. Override with `--output path/from_current_working_dir`.
npx @powersync/web copy-assets
# or pnpm @powersync/web copy-assets
```

### 3. Instantiate Web Workers

The example below demonstrates how to instantiate the workers (PowerSync requires a database and a sync worker) when instantiating `PowerSyncDatabase`. You can either specify a path to the worker (they are available in the `worker` directory of the `dist` contents), or provide a factory function to create the worker.

```js theme={null}
const factory = new WASQLiteOpenFactory({
  dbFilename: 'sqlite.db',

  // Option 1: Specify a path to the database worker
  worker: '/@powersync/worker/WASQLiteDB.umd.js'

  // Option 2: Or provide a factory function to create the worker.
  // The worker name should be unique for the database filename to avoid conflicts if multiple clients with different databases are present.
  // worker: (options) => {
  //   if (options?.flags?.enableMultiTabs) {
  //     return new SharedWorker(`/@powersync/worker/WASQLiteDB.umd.js`, {
  //       name: `shared-DB-worker-${options?.dbFilename}`
  //     });
  //   } else {
  //     return new Worker(`/@powersync/worker/WASQLiteDB.umd.js`, {
  //       name: `DB-worker-${options?.dbFilename}`
  //     });
  //   }
  // }
});

this.powersync = new PowerSyncDatabaseWeb({
  schema: AppSchema,
  database: factory,
  sync: {
    // Option 1: You can specify a path to the sync worker
    worker: '/@powersync/worker/SharedSyncImplementation.umd.js'

    //Option 2: Or provide a factory function to create the worker.
    // The worker name should be unique for the database filename to avoid conflicts if multiple clients with different databases are present.
    // worker: (options) => {
    //   return new SharedWorker(`/@powersync/worker/SharedSyncImplementation.umd.js`, {
    //     name: `shared-sync-${options?.dbFilename}`
    //   });
    // }
  }
});
```

This `PowerSyncDatabaseWeb` database will be used alongside the native `PowerSyncDatabase` to support platform-specific implementations. See the [Instantiating PowerSync](#implementations) section below for more details.

### 4. Enable multiple platforms

To target both mobile and web platforms, you need to adjust the Metro configuration and handle platform-specific libraries accordingly.

#### Metro config

Refer to the example [here](https://github.com/powersync-ja/powersync-js/blob/main/demos/react-native-web-supabase-todolist/metro.config.js). Setting `config.resolver.resolveRequest` allows Metro to behave differently based on the platform.

```js theme={null}
config.resolver.resolveRequest = (context, moduleName, platform) => {
  if (platform === 'web') {
    // Depending on `@powersync/web` for functionality, ignore mobile specific dependencies.
    if (['react-native-prompt-android', '@powersync/react-native'].includes(moduleName)) {
      return {
        type: 'empty'
      };
    }
    const mapping = { 'react-native': 'react-native-web', '@powersync/web': '@powersync/web/dist/index.umd.js' };
    if (mapping[moduleName]) {
      console.log('remapping', moduleName);
      return context.resolveRequest(context, mapping[moduleName], platform);
    }
  } else {
    // Depending on `@powersync/react-native` for functionality, ignore `@powersync/web` dependencies.
    if (['@powersync/web'].includes(moduleName)) {
      return {
        type: 'empty'
      };
    }
  }

  // Ensure you call the default resolver.
  return context.resolveRequest(context, moduleName, platform);
};
```

#### Implementations

Many `react-native` and `web` packages are implemented with only their specific platform in mind, as such there may be times where you will need to evaluate the platform and provide alternative implementations.

**Instantiating PowerSync**

The following snippet constructs the correct `PowerSyncDatabase` depending on the platform that the code is executing on.

```js theme={null}
import React from 'react';
import { PowerSyncDatabase as PowerSyncDatabaseNative } from '@powersync/react-native';
import { PowerSyncDatabase as PowerSyncDatabaseWeb } from '@powersync/web';

if (PowerSyncDatabaseNative) {
  this.powersync = new PowerSyncDatabaseNative({
    schema: AppSchema,
    database: {
      dbFilename: 'sqlite.db'
    }
  });
} else {
  const factory = new WASQLiteOpenFactory({
    dbFilename: 'sqlite.db',
    worker: '/@powersync/worker/WASQLiteDB.umd.js'
  });
  this.powersync = new PowerSyncDatabaseWeb({
    schema: AppSchema,
    database: factory,
    sync: {
      worker: '/@powersync/worker/SharedSyncImplementation.umd.js'
    }
  });
}
```

**Implementations that don't support both mobile and web**

```js theme={null}
import { Platform } from 'react-native';

import { Platform } from 'react-native';
import rnPrompt from 'react-native-prompt-android';

// Example conditional implementation
export async function prompt(
    title = '',
  description = '',
  onInput = (_input: string | null): void | Promise<void> => {},
  options: { placeholder: string | undefined } = { placeholder: undefined }
) {
  const isWeb = Platform.OS === 'web';
  let name: string | null = null;

  if (isWeb) {
    name = window.prompt(`${title}\n${description}`, options.placeholder);
  } else {
    name = await new Promise((resolve) => {
      rnPrompt(
        title,
        description,
        (input) => {
          resolve(input);
        },
        { placeholder: options.placeholder, style: 'shimo' }
      );
    });
  }

  await onInput(name);
}

```

Which can then be used agnostically in a component.

```js theme={null}
import { Button } from 'react-native';
import { prompt } from 'util/prompt';

<Button
  title="Add"
  onPress={() => {
    prompt(
      'Add a new Todo',
      '',
      (text) => {
        if (!text) {
          return;
        }

        return createNewTodo(text);
      },
      { placeholder: 'Todo description' }
    );
  }}
/>;
```

### 5. Configure UMD target

React Native Web requires the UMD target of `@powersync/web` (available at `@powersync/web/umd`). To fully support this target version, configure the following in your project:

1. Add `config.resolver.unstable_enablePackageExports = true;` to your `metro.config.js` file.

2. TypeScript projects: In the `tsconfig.json` file specify the `moduleResolution` to be `Bundler`.

```json theme={null}
 "compilerOptions": {
    "moduleResolution": "Bundler"
  }
```
