# react-native-ble-plx vs. WebBLE

`react-native-ble-plx` is the standard Bluetooth Low Energy library for React Native apps on iOS and Android. WebBLE solves a related but different problem: giving a regular web page access to BLE on iOS Safari through a Safari Web Extension. This page compares them honestly so you can pick the right tool.

## TL;DR

- **react-native-ble-plx** is for teams shipping a **React Native app** to the App Store. It wraps CoreBluetooth / Android BluetoothGatt behind a Promise / Observable API.
- **WebBLE** is for teams shipping a **web page** (PWA, SPA, static site, React/Vue/Svelte app on the open web). The user installs the WebBLE Safari Web Extension once, and the page gets the standard W3C `navigator.bluetooth` API.

If your product is already a native iOS app, stay with `react-native-ble-plx`. If your product is already — or should be — a web page, WebBLE lets you keep it a web page and still talk to BLE devices on iPhone.

## Comparison

| Axis | react-native-ble-plx | WebBLE |
|------|----------------------|--------|
| **Runtime** | React Native bridge → native module | Safari Web Extension → CoreBluetooth |
| **API surface** | Library-specific (`BleManager`, `device.connect()`, observables) | Standard W3C `navigator.bluetooth` |
| **Target platforms** | iOS + Android native apps | Any browser on any OS; iOS Safari via extension |
| **Language** | TypeScript / JavaScript in React Native | TypeScript / JavaScript in a plain web page |
| **Distribution** | App Store / Play Store per release | Web deploy; one-time user install of the extension |
| **Update cadence** | Blocked by App Review | Same-day deploy |
| **PWA / web SEO** | None — it is a native app | Native — your site remains indexable and linkable |
| **Code reuse with Chrome/Edge web app** | Fork required | 100 % — same `navigator.bluetooth` |
| **Background BLE** | Full iOS background modes | Premium `window.webbleIOS.backgroundSync` via companion app |
| **GATT primitives** | Read / write / notify / indicate / descriptors | Read / write / notify / indicate / descriptors |
| **Peripheral (advertise) role** | No on iOS via this library | Premium `window.webbleIOS.peripheral` |
| **Beacon scanning** | Possible via native modules | Premium `window.webbleIOS.backgroundSync` beacons |
| **Licence** | Apache-2.0 | Polyfill free; iOS premium via companion app |
| **Scan UI** | Custom in-app list | iOS system chooser (enforced by the extension, per W3C) |

## When react-native-ble-plx is the right answer

- You are already building a React Native app, or the product category requires a native iOS app (deep HealthKit, CarPlay, widgets as first-class UI, etc.).
- You need programmatic scan control with custom UI — `requestDevice` on W3C mandates a system chooser on iOS.
- You ship to both iOS and Android from one RN codebase and don't want a web tier at all.

## When WebBLE is the right answer

- Your product is a web page (PWA, dashboard, SaaS console, marketing site with a "try it" button).
- You want one `navigator.bluetooth` codebase that runs on Chrome desktop *and* iOS Safari.
- You want same-day updates without App Review.
- You already have a web app and want iOS BLE without porting to React Native.
- You want your content to stay indexable, shareable, and deep-linkable on the open web.

## API mapping

```js
// react-native-ble-plx
const manager = new BleManager();
manager.startDeviceScan(null, null, (error, device) => { /* ... */ });
await device.connect();
const char = await device.readCharacteristicForService(svcUuid, chrUuid);

// WebBLE (standard navigator.bluetooth)
const device = await navigator.bluetooth.requestDevice({
  filters: [{ services: ['heart_rate'] }]
});
const server = await device.gatt.connect();
const svc = await server.getPrimaryService('heart_rate');
const chr = await svc.getCharacteristic('heart_rate_measurement');
const val = await chr.readValue();
```

See the [quickstart](../quickstart.md) and the [API reference](../api-reference.md) for the complete surface.
