# Quickstart — HTML / plain JavaScript

Minimal integration: one `<script>` tag, one `<button>`, a working heart-rate reader. No build step, no framework, no bundler.

## Prerequisites

- WebBLE Safari Web Extension installed from the App Store and enabled on this origin. See [the base quickstart](quickstart.md) for extension setup.
- A Bluetooth Low Energy peripheral that advertises the standard Heart Rate service (`0x180D`).

## 1. Drop in the polyfill

```html
<!doctype html>
<html>
  <body>
    <button id="connect">Connect heart-rate monitor</button>
    <pre id="out"></pre>
    <script src="https://cdn.ioswebble.com/v1.js"></script>
    <script>
      const out = document.getElementById('out');
      document.getElementById('connect').onclick = async () => {
        const device = await navigator.bluetooth.requestDevice({
          filters: [{ services: ['heart_rate'] }]
        });
        const server = await device.gatt.connect();
        const service = await server.getPrimaryService('heart_rate');
        const char = await service.getCharacteristic('heart_rate_measurement');
        await char.startNotifications();
        char.addEventListener('characteristicvaluechanged', (ev) => {
          const v = ev.target.value;
          const bpm = v.getUint8(0) & 0x01 ? v.getUint16(1, true) : v.getUint8(1);
          out.textContent = `${bpm} bpm`;
        });
      };
    </script>
  </body>
</html>
```

Open the page over HTTPS on iPhone, tap the button, pick the monitor in the chooser sheet, and values stream into the `<pre>` block.

## 2. npm install alternative

Prefer a real module graph? Install the core package:

```bash
npm install @ios-web-bluetooth/core
```

```js
import '@ios-web-bluetooth/core/auto';

const device = await navigator.bluetooth.requestDevice({
  filters: [{ services: ['heart_rate'] }]
});
```

Importing the package side-effect mounts `navigator.bluetooth` and `window.webbleIOS`.

## What just happened

- `@ios-web-bluetooth/core` detected the WebBLE Safari Web Extension and installed the W3C polyfill at `navigator.bluetooth`.
- `requestDevice` opened the system chooser sheet — the extension is the only code allowed to drive it.
- GATT read/write/notify traffic flows through the extension to CoreBluetooth and back, fully off the main thread.

## Next

- [API reference](api-reference.md)
- [Recipes](recipes.md)
- [Troubleshooting: extension not detected](troubleshooting/extension-not-detected.md)
