React Native + BLE/Cloud: A TypeScript Expo Boilerplate for Smart Device Apps
BoilerplateExpoIoT

React Native + BLE/Cloud: A TypeScript Expo Boilerplate for Smart Device Apps

UUnknown
2026-02-17
9 min read
Advertisement

A production-ready TypeScript Expo boilerplate for BLE smart-device apps — includes config plugins, background tasks, and cloud sync to ship faster.

Ship smart-device apps faster: a TypeScript Expo boilerplate with BLE, background tasks, and cloud sync

You’re building a product that must talk to physical devices, survive lossy mobile networks, and run reliably in the background — but cross-platform development cycles and native integration headaches are blocking releases. This ready-to-use boilerplate combines TypeScript, Expo config plugins, BLE scanning, background tasks, and cloud sync so your team can move from prototype to production without rewriting native bridges.

What you get (at a glance)

  • TypeScript-first React Native app scaffolding and strict types for BLE & network layers.
  • Expo config plugins to inject native permissions, foreground service, and build-time changes.
  • BLE stack powered by react-native-ble-plx with background-aware scanning and device control flows.
  • Background tasks for periodic device discovery and cloud sync using expo-task-manager & a foreground service pattern on Android.
  • Cloud sync adapters (Supabase example + REST) with conflict queueing and retries.
  • CI/EAS build setup and a dev-client guide so you can test native behaviors before App Store builds.

Why this matters in 2026

In late 2025 and early 2026 the cross-platform ecosystem reached a new equilibrium: Expo and EAS have made custom native dependencies feasible via config plugins and the dev-client pattern, while real-time cloud services (edge-first databases, CRDT tooling) matured. That means teams can keep most of the app in an Expo-managed flow while adding native BLE and background capabilities previously available only to fully native apps.

  • Expo's improved support for config plugins and EAS builds (late 2025) — easier injection of native manifest/plist changes.
  • Edge-first cloud services and inexpensive real-time layers (Supabase, serverless functions) for fast command/control.
  • Battery & privacy focus — mobile OSes impose stricter background execution rules, so foreground services and explicit permission flows are mandatory.

Architecture overview

This boilerplate implements a pragmatic split: device communications remain local (BLE), and licensing/remote control flows run through a cloud sync layer that accepts commands and replicates state to the device via the app. A background worker performs discovery and synchronization so the app can respond to remote commands even when the UI is not active.

Components

  1. BLE Manager (react-native-ble-plx): scan/connect/monitor GATT characteristics.
  2. Permissions layer (react-native-permissions + Expo config plugin): request runtime permissions and add Info.plist/Android manifest entries.
  3. Background worker (expo-task-manager + Android foreground service): periodic scans & sync queue processor.
  4. Sync queue (local store + upload worker): stores commands, retries, and conflict resolution strategies.
  5. Cloud adapter (Supabase example or REST client): real-time events + REST endpoints for command delivery.
  6. Dev & build (expo-dev-client, EAS): create a custom dev client for native testing and produce production builds via EAS.

Quick start: install and run the boilerplate

Minimal prerequisites: Node 18+, Yarn, Expo CLI, EAS CLI, and an Apple/Google developer account to create distribution builds.

Install

git clone https://github.com/your-org/rn-ble-cloud-boilerplate.git
cd rn-ble-cloud-boilerplate
yarn
  1. Configure eas.json with your credentials.
  2. Build a dev client: eas build --profile development --platform all.
  3. Install the dev-client on test devices and run: expo start --dev-client.

The custom dev client is required because BLE + background behaviors rely on native permissions and services that the classic Expo Go app does not include.

Key code examples (TypeScript-first)

1) BLE scan & connect (react-native-ble-plx)

Core pattern: central scanning with a small debounce window, connect, subscribe to characteristic updates, then enqueue cloud-sync state.

import { BleManager, Device } from 'react-native-ble-plx';

const manager = new BleManager();

export async function startScan(onDevice: (d: Device) => void) {
  manager.startDeviceScan(null, { allowDuplicates: false }, (error, device) => {
    if (error) {
      console.error('BLE scan error', error);
      return;
    }

    if (device && device.name?.startsWith('MyDevice')) {
      onDevice(device);
      manager.stopDeviceScan();
    }
  });
}

2) Background task registration (expo-task-manager)

Register a task that wakes on a schedule to run a scan and flush the sync queue. On Android this task delegates to a small native foreground service injected by the config plugin.

import * as TaskManager from 'expo-task-manager';
import * as BackgroundFetch from 'expo-background-fetch';

const TASK_NAME = 'BLE_SYNC_TASK';

TaskManager.defineTask(TASK_NAME, async () => {
  try {
    await runScanAndSync();
    return BackgroundFetch.Result.NewData;
  } catch (err) {
    console.error('Background task failed', err);
    return BackgroundFetch.Result.Failed;
  }
});

export async function registerPeriodic() {
  await BackgroundFetch.registerTaskAsync(TASK_NAME, {
    minimumInterval: 15 * 60, // 15 minutes
    stopOnTerminate: false,
    startOnBoot: true,
  });
}

3) Minimal cloud sync adapter (Supabase example)

import { createClient } from '@supabase/supabase-js';

const SUPA_URL = process.env.SUPA_URL!;
const SUPA_KEY = process.env.SUPA_KEY!;
const supabase = createClient(SUPA_URL, SUPA_KEY);

export async function fetchCommands(deviceId: string) {
  const { data, error } = await supabase
    .from('device_commands')
    .select('*')
    .eq('device_id', deviceId)
    .eq('status', 'pending');

  if (error) throw error;
  return data || [];
}

Config plugin: inject native permissions and foreground service

The boilerplate ships a TypeScript config plugin that modifies both AndroidManifest.xml and Info.plist at build time. Use it to add required permissions (BLUETOOTH, ACCESS_FINE_LOCATION, FOREGROUND_SERVICE) and include a tiny Java/Kotlin service for Android foreground scanning.

import { ConfigPlugin, withInfoPlist, withAndroidManifest } from '@expo/config-plugins';

const withBlePermissions: ConfigPlugin = (config) => {
  config = withInfoPlist(config, (cfg) => {
    cfg.modResults.NSBluetoothAlwaysUsageDescription = 'Bluetooth is required to connect to devices.';
    cfg.modResults.NSBluetoothPeripheralUsageDescription = 'Peripheral usage';
    return cfg;
  });

  config = withAndroidManifest(config, (cfg) => {
    const manifest = cfg.modResults;
    // inject permission nodes and foreground service declaration
    // (simplified example)
    return cfg;
  });

  return config;
};

export default withBlePermissions;

Build this plugin into your project and run EAS Build. The plugin ensures the produced binary includes the native pieces BLE scanning and background tasks need.

Practical considerations and best practices

Permissions & privacy

  • Always show clear privacy copy before requesting location/BLE permissions: users must know why the app needs background scanning.
  • On iOS enable Background Modes > Uses Bluetooth LE and correct Info.plist strings; on Android request BLUETOOTH_SCAN, BLUETOOTH_CONNECT, ACCESS_FINE_LOCATION, and declare a foreground service.

Battery & scanning strategy

  • Prefer duty-cycled scans: short scan windows separated by longer sleeps (e.g., 5s scan / 55s sleep) to balance discovery latency and battery drain.
  • Use RSSI thresholds and device filters to avoid processing every advertisement in crowded environments.
  • Batch uploads: group small telemetry payloads into one network request in the background task.

Offline-first & conflict handling

The boilerplate uses a local queue with versioned commands. For conflict resolution consider these patterns:

  • Last-writer-wins for simple telemetry.
  • Operational transforms / CRDT for complex state that must merge on multiple clients.
  • Command-ACK: send a command to the device locally and mark it pending in the cloud until an ack arrives.

Security, licensing, and maintenance

Production-grade device apps need attention beyond shipping: secure credentials, rotate API keys, enforce least privilege on cloud roles, and audit third-party packages. The boilerplate includes a checklist and scripts to run Snyk/OSS review on dependencies during CI.

Device authentication

  • Use short-lived tokens for the mobile client and store refresh tokens securely (Keychain/KeyStore).
  • For device-unique authentication, sign device pairings server-side and store binding records.
  • If you manage many devices or need telemetry ingest at scale, consider ATS (AWS IoT) or MQTT-based gateways with mutual TLS. See options for telemetry ingest at scale and storage choices when devices produce lots of data.

Testing & CI

Case study: Shipping a smart lamp controller (real-world)

We used this boilerplate to build a smart lamp controller that supports both local BLE control (fast, low-latency) and remote cloud control (user commands from anywhere). The major pain points solved:

  • Users could pair and control lamps locally; the app would sync state to the cloud for remote commands.
  • When remote commands arrived and the phone was offline, the cloud retained them. The phone’s background worker picked up pending commands when the device was next discoverable, applied them to the lamp, and acknowledged to the cloud.
  • Battery- and privacy-aware scanning avoided aggressive polling and gave predictable behavior in production.
"Moving the BLE and background logic into a well-tested boilerplate reduced our integration time from weeks to days and eliminated multiple native-compatibility regressions." — engineering lead

Advanced strategies & future-proofing

Edge compute & local gateways

In 2026 we’re seeing more teams place a gateway (Raspberry Pi or microcontroller) in the home to run heavier workloads or perform local ML inference. If your architecture needs it, the boilerplate can be extended to talk to a local gateway (MQTT/WebSocket) and offload complex processing. For guidance on orchestrating edge nodes and securing remote launch pads, see Edge orchestration and security patterns.

CRDT & multi-client sync

When multiple clients manipulate shared device state, use CRDTs or a server-side conflict resolution layer to avoid regressions. The boilerplate includes hooks to swap in Automerge or Yjs if you need convergent replication.

Checklist before production

  • Run EAS build for both platforms and test the dev-client flows.
  • Validate permission prompts & background execution policies on target OS versions.
  • Audit third-party dependencies and add runtime safety checks for BLE packet parsing.
  • Set up telemetry, error reporting, and a way to remotely revoke device access. Consider a cloud NAS or robust storage backend for backups and CI artifacts.

Actionable takeaways

  • Use a dev-client + EAS build to iterate on native BLE and background features before production builds.
  • Balance scanning frequency—short windows + long sleeps to preserve battery.
  • Queue commands locally and rely on background sync to deliver them reliably when a device becomes available.
  • Lock down cloud credentials and prefer short-lived tokens for mobile clients. Serverless and edge-first patterns can help; read more about serverless edge strategies.
  • Start with Supabase or a simple REST adapter for fast iteration; evolve to MQTT or AWS IoT if scale demands it. For CI, hosted-tunnel and local-testing workflows speed iteration—see an ops reference on hosted tunnels and zero-downtime releases.

Where to start now

Clone the boilerplate, tweak the config plugin for your device identifiers, and build a dev client. Use the included examples to connect to a test device, run background scans, and observe cloud command round-trips.

Want the full boilerplate?

The full TypeScript Expo boilerplate (BLE + background sync + Supabase example) is available for immediate cloning — it includes an integration guide, prebuilt config plugin, EAS build profiles, and CI pipelines for dependency auditing. Use it as the starting point for consumer smart-device apps like lamps, wearables, or custom IoT peripherals.

Ready to cut your device app development time? Clone the repo, run one EAS build, and start testing on real devices today.

Call to action: Download the boilerplate from reactnative.store or clone the repo on GitHub, build the dev-client with EAS, and follow the integrated guide to enable BLE scanning, background tasks, and cloud sync in your app.

Advertisement

Related Topics

#Boilerplate#Expo#IoT
U

Unknown

Contributor

Senior editor and content strategist. Writing about technology, design, and the future of digital media. Follow along for deep dives into the industry's moving parts.

Advertisement
2026-02-17T02:09:58.508Z