Delivered remotely for a business based in Frankfurt, Germany. Names withheld by agreement.
Project Overview
Industry: Connected hardware / IoT — remote monitoring and control of installed equipment.
Type of solution: A native-quality iOS and Android mobile application, built from a single cross-platform codebase, that combines direct hardware communication over Bluetooth with cloud-based monitoring through a secure API.
Business context: Connected hardware is judged by its app. A manufacturer can build excellent equipment, but if the owner cannot get it onto their Wi-Fi in the first five minutes, the product is returned — and if the app cannot answer "is it running and is everything normal?" at a glance, the connectivity adds nothing. The commercial opportunity runs deeper still: once equipment reports remotely, the manufacturer's dealer and service network can diagnose and support customers without a site visit, which changes the economics of after-sales service.
General users: Equipment owners (residential or commercial), and service providers granted access to support the customers they serve. Platform administration is handled outside the app.
General purpose: To commission connected hardware reliably, to give owners continuous visibility of their equipment's condition, and to enable remote support by authorised service providers.
The Business Challenge
Getting a new device online is the hardest five minutes of product ownership. A device fresh out of the box has no network connection, so the app cannot reach it through the internet. Communication has to happen directly over Bluetooth, the device's own Wi-Fi scan has to be retrieved and displayed, credentials have to be transferred securely, and success or failure has to be reported clearly. Every step can fail for physical reasons — range, interference, a mistyped password, a device already provisioned. This flow determines whether the product succeeds.
No visibility without physical presence. Before the app, the owner learned about an out-of-range condition only by being there. Anything that happened while they were away was invisible until it became a problem.
A hierarchy, not a device list. Real installations do not consist of one device. Owners may have multiple locations, each with one or more systems, each containing several devices. A flat list would not survive contact with actual usage, so the model had to reflect the real structure and stay coherent as devices are added, renamed and moved.
Remote support was impossible. The dealer or service company had no route into a customer's equipment other than travelling to it. There was no controlled way to grant a third party visibility of a customer's installation, or to withdraw it later.
Security expectations of a connected product. Handling a customer's Wi-Fi credentials and remote control of physical equipment sets a high bar: strong account security, verified identity, and provisioning that never exposes credentials in transit.
Two platforms, one product. iOS and Android had to deliver identical capability, including the parts most exposed to platform differences — Bluetooth, runtime permissions and push notifications — on one team's budget.
Our Approach
Design the commissioning flow first. We treated first-run provisioning as the primary user journey rather than a setup detail. That meant designing for the failure cases up front: what the user sees when the device is out of range, when Bluetooth is off, when permissions are refused, when the Wi-Fi password is wrong, and when a device is already claimed. The happy path is short; the value is in the recoveries.
Establish a strict networking layer. We built the API integration as three separate layers — a configured HTTP client, a declarative registry of endpoints, and typed service functions — so screens never construct URLs or handle transport concerns. When the backend contract changes, one layer changes.
Model the hierarchy explicitly. Locations, systems and devices are modelled as a real hierarchy in both the API integration and client state, with data fetched by scope rather than in bulk, so a large installation does not degrade a screen that only needs one system.
Handle the platform layer properly. Bluetooth, location, camera and notification permissions were implemented per platform with correct sequencing and user-facing rationale, because a permission prompt at the wrong moment is a failed setup.
Separate environments at build level. Testing and production builds are distinct native variants with their own configuration and identifiers, so a test build can never be mistaken for or wired into the production platform.
Build in observability. Crash and error reporting was integrated from the start with source-map and debug-symbol handling, so real-world failures on real devices arrive as readable diagnostics rather than as one-star reviews.
Test the parts that can be tested. A unit test setup with mocked native modules covers logic, state and utilities; hardware-dependent flows are verified against physical devices, because Bluetooth and provisioning cannot be meaningfully simulated.
The Solution
Guided device commissioning. The app scans for nearby devices over Bluetooth Low Energy, establishes a secure session with the device, retrieves the Wi-Fi networks the device itself can see, accepts the network credentials, transfers them securely and confirms the outcome. Both Bluetooth and access-point based transports are supported, and QR-code identification is available to identify a specific unit quickly.
Location, system and device organisation. Owners create locations with address and time-zone context, group equipment into systems within a location, and manage devices inside those systems — renaming, moving or removing them as installations change.
Live status monitoring. Status views summarise condition at location and system level, with per-device readings including temperature in the owner's preferred unit. The owner can see at a glance whether everything is normal, without interpreting raw data.
Historical data. Past readings are available so trends and irregularities can be reviewed rather than only the current instant.
Alerts and push notifications. Conditions that need attention are delivered as push notifications, so the owner does not need to open the app to learn that something has changed. Notification delivery is subject to the user's own preferences.
Service-provider access. A service provider can be assigned to a location, modified, or removed by the owner — giving installers and service companies the remote visibility they need to support a customer, under the customer's control.
Account security. Registration is followed by email and SMS verification, and two-factor authentication is available with setup, challenge and verification flows. Sessions use access tokens with silent refresh, so security does not come at the cost of constant re-authentication.
Profile and preference management. Users manage their username, email address, phone number, password and profile photo, control notification and communication preferences, choose their temperature unit, and can delete their account entirely from within the app.
Key Features
Bluetooth device discovery and secure Wi-Fi provisioning Scans for nearby unprovisioned hardware, establishes a secure session with proof-of-possession, retrieves the device's own Wi-Fi scan, and transfers network credentials without exposing them in transit.
Multi-transport commissioning support Both Bluetooth Low Energy and access-point based provisioning paths are supported, with the transport and security mode selectable — so one app serves different hardware configurations.
QR-code device identification A physical unit can be identified by scanning its code, removing manual entry of identifiers during setup and support.
Location → system → device hierarchy Equipment is organised the way real installations are structured, with devices able to be renamed, moved between systems and locations, or removed as circumstances change.
Live status by location and system Condition summaries at each level of the hierarchy, with per-device readings presented in the user's chosen unit of measurement.
Historical data views Past readings are retained and viewable, so behaviour can be reviewed over time rather than only observed in the moment.
Push notifications for alerts Conditions requiring attention are pushed to the user's device, subject to their notification preferences, replacing the need to check the app.
Two-factor authentication with email and SMS verification Layered account security appropriate to an app that can remotely control physical equipment, implemented with setup, challenge and verification flows.
Service-provider access management Owners assign, modify and revoke a service provider's access to a location, enabling remote support without handing over account credentials.
Full self-service account management Username, email, phone, password and profile photo management, preference control, and complete in-app account deletion in line with app-store requirements.
Technical Architecture
Mobile client. A single React Native + TypeScript codebase targeting iOS and Android, organised by feature: screens, reusable components, feature-scoped navigators, global state slices, a networking layer, cross-cutting utilities and a theme layer.
State management. A predictable global store built with Redux Toolkit, split into typed slices for user session, preferences and profile media, with asynchronous thunks for operations that combine network calls and state transitions.
Navigation. Nested navigators separated by feature area — authentication, launch, main tabs, actions, status and history — so each area manages its own stack and the app's structure remains readable as it grows.
Networking layer. Three deliberate layers: a configured HTTP client handling base configuration and interceptors; a declarative endpoint registry defining every route in one place; and typed service functions exposing intent-level operations to screens. Screens call operations, never URLs.
Hardware communication layer. A separate Bluetooth pathway alongside the HTTP layer, handling device discovery, secure session establishment and the provisioning exchange with the hardware — a genuinely different transport with different failure modes, kept isolated from cloud API concerns.
Local persistence. On-device storage holds session state, user preferences and configuration so the app resumes correctly and respects user choices between launches.
Platform services. Runtime permission handling, push notification registration and handling, camera access for code scanning, and image selection with cropping for profile media.
Observability. Crash and error reporting integrated with release-build source maps and native debug symbols, so production failures are diagnosable.
Build and environment separation. Native build variants per environment on both platforms, each with its own configuration and identifiers.
Flow: Mobile app → (Bluetooth Low Energy) → Device provisioning session → Device joins Wi-Fi → Device reports to cloud platform → Mobile app → (HTTPS + token auth) → Cloud API → live status, history, alerts → Push notification service → Mobile app
Technology Stack
| Category | Technology |
|---|---|
| Mobile framework | React Native (current major version) |
| Language | TypeScript |
| UI runtime | React 19 |
| State management | Redux Toolkit, React Redux |
| Navigation | React Navigation (native stack + bottom tabs) |
| Networking | Axios with a layered API service architecture |
| Hardware connectivity | React Native BLE library |
| Device provisioning | Secure Wi-Fi provisioning protocol for embedded devices over BLE / SoftAP |
| Push notifications | Firebase Cloud Messaging |
| Error & crash monitoring | Sentry SDK with source maps and native debug symbols |
| Local storage | AsyncStorage |
| Permissions | React Native Permissions |
| Media & codes | Image picker with cropping, QR code rendering, SVG |
| Animation & gestures | Reanimated, Gesture Handler |
| Configuration | Environment-based config with per-environment native build variants |
| Testing & quality | Jest with native module mocks, ESLint, Prettier |
| Package management | Yarn (Berry) with dependency patch management |
Technical Challenges & Solutions
| Challenge | Our Approach |
|---|---|
| First-run device commissioning — the flow most likely to cause product returns | Designed the provisioning journey around its failure cases: explicit handling and clear messaging for out-of-range devices, disabled Bluetooth, refused permissions, incorrect network credentials and already-provisioned units, with a guided step-by-step path rather than a single opaque "connecting" state. |
| Transferring the customer's Wi-Fi credentials to hardware safely | A secure provisioning session with proof-of-possession is established before any credential is transmitted, so network credentials are never exposed in plain form over the air. |
| Bluetooth and permissions behaving differently across platforms and OS versions | Centralised runtime permission handling with correct sequencing and user-facing rationale, and platform-specific configuration for Bluetooth scanning and connection, so setup does not fail at a permission prompt. |
| Keeping a three-level hierarchy coherent as installations change | Location, system and device modelled explicitly across the API layer and client state, with scope-based fetching so screens load only the branch they display, and device moves and renames propagate consistently. |
| A backend contract that continues to evolve | A three-layer networking design — client, declarative endpoint registry, typed service functions — so contract changes are absorbed in one layer without touching screens. |
| Balancing strong account security with usability | Token-based sessions with silent refresh, layered on email and SMS verification and optional two-factor authentication, plus a centralised verification gate that routes partially-verified accounts correctly instead of leaving them stuck. |
| Presenting measurements consistently in the user's preferred unit | Unit preference stored per user and applied through a shared conversion and formatting utility used by every view, so live status, history and alerts never disagree. |
| Diagnosing failures on hardware we cannot reproduce in the office | Crash and error monitoring integrated with release source maps and native debug symbols, so production issues arrive as readable stack traces rather than unactionable reports. |
| Shipping test and production builds without cross-wiring | Separate native build variants per environment on both platforms, each with its own configuration and identifiers, so environments cannot be mixed accidentally. |
Security & Reliability
Authentication. Token-based authentication with refresh handling, so sessions remain valid without repeatedly prompting the user, and expire cleanly when they should.
Identity verification. Email and SMS verification flows confirm that the account belongs to a reachable, real contact before the account gains full capability.
Two-factor authentication. Optional second-factor authentication with setup, challenge and verification, appropriate for an application that can control physical equipment remotely.
Secure device provisioning. Provisioning uses an encrypted session with proof-of-possession before any credential exchange, protecting the customer's network credentials during commissioning.
Least-privilege permissions. Runtime permissions are requested only when the corresponding capability is used, with context explaining why they are needed.
Controlled third-party access. Service-provider access is granted per location by the owner and can be modified or revoked, rather than being implied by credential sharing.
Local data handling. Session and preference data are held in device storage; configuration values are supplied per build environment rather than embedded in source.
Production observability. Crash and error monitoring with symbolicated release builds gives visibility of real-world failures across a diverse device population.
Reliability of the hardware pathway. Bluetooth operations are treated as fallible by design, with explicit state handling and user-visible recovery paths rather than indefinite waiting.
Scalability & Performance
Scope-based data fetching. Status and device data are requested per location, per system or per device rather than as a single payload, so a customer with a large installation does not slow down every screen.
Push instead of polling. Alert delivery uses push notifications rather than continuous polling, reducing both network usage and battery consumption while improving the timeliness of alerts.
Efficient rendering. Virtualised lists for device and history views, animations executed on the UI thread through a modern animation runtime, and screen-level state kept minimal.
Fast, controlled startup. A native splash implementation covers cold-start work, and navigation stacks are separated by feature area so the app initialises only what the current area requires.
Media handling on device. Images are cropped and processed locally before upload, keeping payloads small and uploads quick on mobile connections.
Structured state. Feature-scoped state slices keep updates targeted, avoiding broad re-renders as data changes.
Business Outcomes
- Customers can commission equipment themselves, without a technician and without contacting support — the decisive factor in whether a connected product is kept or returned.
- Owners have continuous visibility of equipment condition from anywhere, instead of only when physically present.
- Problems surface as alerts rather than discoveries, giving owners the chance to act before a condition becomes damage.
- Service providers can support customers remotely, which reduces unnecessary site visits and changes the cost structure of after-sales service.
- Access stays under the owner's control, since provider access is granted and revoked per location rather than through shared credentials.
- One codebase serves both platforms, so features reach iOS and Android together at materially lower cost than two native builds.
- Production issues are visible and diagnosable, allowing problems to be fixed proactively rather than discovered through app-store reviews.
- The connected product is complete, giving the manufacturer the software layer that makes the hardware's connectivity worth something commercially.
Why it worked
Connected-product apps fail in a specific place: the first five minutes. Anyone can build a screen that displays a temperature. Reliably getting an unconfigured piece of hardware onto a stranger's home or business Wi-Fi — over Bluetooth, through a permissions system that changes with every OS release, on both platforms, with clear recovery when something physical goes wrong — is the part that decides whether the product succeeds.
Our team has built that layer repeatedly. We design commissioning flows around their failure modes, isolate the hardware transport from the cloud transport so each can be reasoned about independently, handle platform permission behaviour explicitly rather than hopefully, and instrument release builds so that failures on devices we will never hold are still diagnosable.
We pair that with disciplined application engineering: typed code throughout, a layered networking architecture that absorbs backend change, predictable state management, environment separation enforced at native build level, and an automated quality baseline. It is the combination — embedded connectivity experience plus solid application architecture — that makes a companion app something a hardware business can build a product line on.
Final Summary
A hardware manufacturer's connectivity is only as good as the app that exposes it. The equipment could report its condition, but owners had no way to see it, no way to be told when something needed attention, and no straightforward way to get a new unit onto their network in the first place. The manufacturer's service network, meanwhile, could not help a customer without travelling to them.
Our team built a cross-platform mobile application that closes all three gaps. It commissions new hardware over Bluetooth using a secure provisioning session so the customer's Wi-Fi credentials are never exposed, organises equipment into the location and system hierarchy that real installations actually have, and delivers live status, historical trends and push alerts from the cloud platform. Account security is layered — verified email and phone, optional two-factor authentication, token sessions with silent refresh — and owners can grant or revoke service-provider access per location, enabling remote support on their own terms.
The engineering emphasis was on the parts of a connected product that are genuinely hard: a commissioning flow designed around its failure cases, a hardware transport kept cleanly separate from the cloud API, explicit cross-platform permission handling, and production observability that makes real-world device failures diagnosable. For a hardware business, this is the layer that turns a connected device into a connected product.