Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.elata.bio/llms.txt

Use this file to discover all available pages before exploring further.

Use this page if you already have a browser app and need the recommended existing-app BLE transport path. If you want the scaffold path instead, use Quickstart. If you only need the transport model first, use Web Bluetooth With Supported Devices. This tutorial builds on the browser EEG package and adds live Web Bluetooth transport with @elata-biosciences/eeg-web-ble. Use this when your app needs real headset data in Chrome or Edge. This step turns on Web Bluetooth for a Muse-compatible headset on top of the EEG stack. It comes after you are committed to EEG (and usually after rPPG if your product also uses camera biosignals).

Before You Start

You need:
  • Chrome or Edge
  • https:// or localhost
  • Bluetooth enabled on the machine
  • a supported Muse-compatible device
  • @elata-biosciences/eeg-web installed alongside @elata-biosciences/eeg-web-ble
Safari and iOS are not supported for this browser BLE workflow.

What You Will Build

You will:
  1. install the BLE transport package
  2. create a BleTransport
  3. subscribe to frame and status events
  4. connect and start streaming

Step 1: Install The Packages

pnpm add @elata-biosciences/eeg-web @elata-biosciences/eeg-web-ble

Step 2: Transport module + connect (single paste)

Use one module so imports, handlers, and lifecycle stay together (for example src/headbandBle.ts). Call connectHeadband() from a button click (browser BLE requires a user gesture).
headbandBle.ts
import { AthenaWasmDecoder } from "@elata-biosciences/eeg-web";
import { BleTransport } from "@elata-biosciences/eeg-web-ble";

let transport: BleTransport | null = null;

export function createHeadbandTransport() {
  const next = new BleTransport({
    deviceOptions: {
      athenaDecoderFactory: () => new AthenaWasmDecoder(),
    },
  });

  next.onStatus = (status) => {
    console.log("status", status.state, status.reason);
  };

  next.onFrame = (frame) => {
    console.log("eeg samples", frame.eeg.samples.length);
  };

  return next;
}

export async function connectHeadband() {
  transport = createHeadbandTransport();
  try {
    await transport.startStreaming();
  } catch (error) {
    console.error("BLE start failed", error);
  }
}
Why include athenaDecoderFactory up front:
  • it keeps Athena-compatible devices working
  • it uses the supported decoder path from @elata-biosciences/eeg-web
  • it avoids a common failure mode later when testing across device variants
startStreaming() is the recommended default because it handles the common connect() plus start() sequence in one call and avoids a frequent mistake where apps connect successfully but never actually begin streaming.

Step 3: Turn Frames Into App State

Once onFrame starts firing, move the data into your own app state instead of leaving it only in console.log. The usual pattern is:
  1. receive HeadbandFrameV1 frames
  2. extract EEG samples or metadata
  3. compute or forward the values your app cares about
  4. render charts, scores, or adaptation logic

Step 4: Clean Up On Route Or Component Exit

When the current view is leaving, stop streaming so later reconnect attempts start from a clean state. Add this next to the helpers above (same module as transport). Append to headbandBle.ts:
export async function stopHeadband() {
  if (!transport) return;
  await transport.stop();
  transport = null;
}
If you prefer finer-grained lifecycle control, you can still call connect() and start() separately. The tutorial uses startStreaming() because it is the safest default for most app integrations.

Step 5: Handle Browser And Platform Constraints

If the chooser never appears or navigator.bluetooth is missing, check these first:
  • the page is running on https:// or localhost
  • you are using Chrome or Edge
  • Bluetooth is enabled
  • the target device is powered on and available

Athena And Classic Devices

This repo supports:
  • Muse 2 and Muse S classic BLE devices
  • Muse S Athena protocol v2 devices
Including athenaDecoderFactory is the simplest supported way to keep both flows covered.

Common Problems

  • navigator.bluetooth is undefined: unsupported browser or insecure context
  • No device chooser appears: Bluetooth disabled or page not running on a secure origin
  • Athena decoding fails: make sure you passed athenaDecoderFactory
  • You need Safari or iOS support: this browser package is not the right path; use a native or bridge strategy

Next

eeg-web-ble Reference

Transport API and options

eeg-web Reference

EEG runtime and models

Web Bluetooth Guide

Transport model overview