@beacio/detect
v1.0.0
Published
Detect WebBLE Safari extension on iOS. Auto-show install banner when extension not found
Maintainers
Readme
@beacio/detect
Detect the WebBLE Safari Web Extension on iOS and guide users through install — extension state checks, an install banner, and a React provider.
Requires iOS 26.0+ Safari with the WebBLE app for the extension path. On browsers with native Web Bluetooth (Chrome, Edge) detection is a no-op.
Install
npm install @beacio/detectZero-config auto mode
Import once in your browser entry file. It detects the extension and, when missing on iOS Safari, shows a guided install prompt:
import '@beacio/detect/auto';The auto entry reads an optional API key from <meta name="ioswebble-key" content="wbl_xxxxx"> or window.__IOSWEBBLE_KEY__.
Manual detection
import {
getExtensionInstallState,
isExtensionInstalled,
isIOSSafari,
} from '@beacio/detect';
if (isIOSSafari()) {
const state = await getExtensionInstallState();
// 'not-installed' | 'installed-inactive' | 'active'
if (state !== 'active') {
// show your own UI, or use showInstallBanner() below
}
}Install banner
import { showInstallBanner, removeInstallBanner } from '@beacio/detect';
showInstallBanner({
mode: 'sheet', // 'sheet' (iOS bottom sheet, default) or 'banner'
operatorName: 'FitTracker', // your app name shown in the prompt
dismissDays: 14, // suppress after dismiss
});The banner's default CTA opens the guided setup flow at https://ioswebble.com/setup (install → enable the Safari extension → return to your page). Override with startOnboardingUrl or appStoreUrl.
Full init
import { initBeacio } from '@beacio/detect';
await initBeacio({
operatorName: 'FitTracker',
banner: { mode: 'sheet' }, // or false to disable
onReady: () => console.log('extension active'),
onInstalledInactive: () => console.log('installed, needs Safari activation'),
onNotInstalled: () => console.log('not installed'),
});State changes also dispatch a ioswebble:statechange CustomEvent on window.
React
import { BeacioProvider, useBeacio } from '@beacio/detect/react';
export default function Layout({ children }) {
return <BeacioProvider>{children}</BeacioProvider>;
}
function Status() {
const { state } = useBeacio();
return <span>{state}</span>;
}Related packages
@beacio/core— thenavigator.bluetoothpolyfill itself@beacio/profiles— typed GATT profiles (heart rate, battery, …)@beacio/testing— mock Bluetooth API for tests
Docs: https://ioswebble.com/docs.md · Setup guide: https://ioswebble.com/setup
License
MIT
