Web Bluetooth IoT Provisioning for ESP32 with Tiny Beacon
Provisioning credentials onto a brand-new IoT device is historically painful.
The standard captive portal approach works like this:
- The ESP32 spins up an SoftAP Wi-Fi network like
ESP32_SETUP_9A3F. - The user disconnects their phone or laptop from their home network.
- The user connects to the ESP32 Wi-Fi.
- Mobile OS captive portal detection kicks in, opens a restricted mini-browser that often fails to render or drops the connection.
- You type the SSID/password and hope it connects. If the password was wrong, the device drops the AP and you have to factory reset.
I built Tiny Beacon to eliminate this friction entirely using Web Bluetooth.
How Web Bluetooth Changes the Flow
With Web Bluetooth, the user stays connected to their normal internet network. They visit a web page in Chrome or Edge, click "Connect Device", select their ESP32 from the browser's native BLE pairing prompt, and transmit Wi-Fi credentials directly over GATT characteristics.
No Wi-Fi switching, no captive portal popups, and no native iOS/Android mobile apps to publish or maintain.
Integration
I made it super easy to use with esp-idf or arduino-esp32. You only need to declare the connector, register a success callback, and initialize it.
#include "TinyBeacon.h"
void app_main() {
// Initialize NVS & network stack as usual...
static TinyBeacon connector;
// 1. Define provisioning callback
connector.onProvisioned([](const char* ssid, const char* password, const char* customFieldsJson) {
printf("Connected to %s! Config: %s\n", ssid, customFieldsJson);
});
// 2. Start advertising or connect using custom IDs from the backend dashboard
connector.begin("YOUR_PUBLISHER_ID", "YOUR_APP_ID");
}
or for arduino-esp32
#include <TinyBeacon.h>
TinyBeacon connector;
void setup() {
// 1. Define what happens when provisioning completes
connector.onProvisioned([](const char* ssid, const char* password, const char* customFieldsJson) {
Serial.printf("Connected to %s! Custom config: %s\n", ssid, customFieldsJson);
});
// 2. Start provisioning with your Publisher ID & App ID (generated in the backend dashboard)
connector.begin("YOUR_PUBLISHER_ID", "YOUR_APP_ID");
}
Live Feedback Loop
Because BLE remains active while the ESP32 attempts connection to the 2.4GHz Wi-Fi AP, the device can instantly notify the browser if authentication failed (e.g. invalid WPA2 key) without crashing or dropping connection. Once successful, the device reports its assigned local IP, registers itself with the backend API, and turns off BLE advertising.
It makes the entire onboarding experience take roughly 10 seconds.