React Native IoT App Architecture With Feature-First Folders That Scale

React Native IoT App Architecture With Feature-First Folders That Scale

Dec 12, 2025
8 minute read

In mobile app development, most React Native IoT apps start small during IoT app development: one device type, a simple dashboard, a few toggles. Then product asks for scenes, schedules, OTA updates, multiple device families, and your src folder slowly turns into a junk drawer.

A clear React Native IoT Architecture with a feature-first folder structure keeps that chaos under control. You group code around real product capabilities, not around technical layers, so onboarding, refactors, and new device support all stay manageable.

This guide walks through a concrete structure you can lift into your own app, with examples for BLE, MQTT, and HTTP, and how to plug in new features without rewriting half the codebase.

Why Feature-First Fits IoT Apps

IoT apps are naturally feature oriented: device provisioning, live telemetry, control (including real-time data handling), automation rules, user access, and so on. Each of these features touches UI, networking, storage, and sometimes background tasks.

In mobile app development, a layer-first layout like components/, services/, screens/ scatters the mental model. To debug a provisioning bug, you open files in four different folders before you even understand the flow.

A feature-first structure keeps everything related to a capability in one place:

  • Screens and UI components
  • Hooks for local state
  • Device communication services (BLE, MQTT, HTTP)
  • Types and mappers for that domain

If you want more background, this idea is described well in this guide to feature-first architecture in React and React Native.

High-Level React Native IoT Architecture

!Clean technical diagram of scalable React Native IoT app architecture with feature-first folder structure, showing mobile app layers, feature modules, data flows via BLE MQTT HTTP to IoT devices and Firebase cloud._High-level React Native IoT architecture with feature modules and device/cloud data flows. Image generated by AI._

At a high level, a solid React Native IoT setup based on the New Architecture has:

  • Mobile app layer (React Native + navigation + state)
  • Feature modules (devices, automation, auth, settings)
  • Device communication layer (communication protocols like BLE, MQTT, HTTP/REST, Matter and Thread)
  • Cloud layer (Firebase, Supabase, or custom backend for secure device communication)

For a practical overview of how React Native fits IoT use cases, this summary of React Native for IoT app development is a useful reference.

The point of the architecture is to make each feature own the flows that matter:

  • Provisioning: scanning, pairing, claiming devices
  • Telemetry: subscribing to live values and history
  • Control: sending commands and actions
  • Automation: rules, scenes, and schedules

The folder structure is how you encode this model in the codebase.

A Feature-First Folder Structure For React Native IoT

!Clean technical diagram of a feature-first folder structure tree for a React Native IoT application, featuring directories like device-management, automation-rules, user-auth, settings, shared utilities, and app navigation with folder icons and subtle import connections._Example of a feature-first folder tree for a React Native IoT app. Image created with AI._

Here is a concrete folder layout that scales well for IoT app development:

src/
app/
navigation/
RootNavigator.tsx
providers/
AuthProvider.tsx
QueryClientProvider.tsx
features/
devices/
screens/
DeviceListScreen.tsx
DeviceDetailScreen.tsx
ProvisionDeviceScreen.tsx
components/
DeviceCard.tsx
TelemetryChart.tsx
hooks/
useDevices.ts
useProvisionDevice.ts
services/
bleClient.ts
deviceApi.ts (HTTP to backend)
deviceMappers.ts
types/
Device.ts
Telemetry.ts
automation/
screens/
AutomationListScreen.tsx
AutomationEditScreen.tsx
components/
RuleSummary.tsx
hooks/
useAutomationRules.ts
services/
automationApi.ts
ruleEngine.ts
types/
AutomationRule.ts
auth/
screens/
LoginScreen.tsx
SignupScreen.tsx
hooks/
useAuth.ts
services/
authApi.ts
types/
User.ts
settings/
screens/
SettingsScreen.tsx
hooks/
useThemePreference.ts
shared/
components/
Button.tsx
ScreenContainer.tsx
TextField.tsx
hooks/
useTypedNavigation.ts
useAppStateEffect.ts
utils/
dateTime.ts
validation.ts
types/
api.ts
common.ts

A few key points:

  • features/ holds product features, not technical layers.
  • Each feature has screens, components, hooks, services, types. For example, the devices/ folder manages practical use cases like smart home sensors.
  • Device communication code that is feature specific, like BLE for devices, lives inside that feature in services/.
  • shared/ holds cross-feature utilities, and should be curated, not a trash bin.
  • This feature-first structure supports cross-platform performance by keeping related code together, which helps maintain app speed as it grows.

For more ideas on structuring React Native apps at scale in mobile app development, this guide to the best folder structure in React Native is helpful background, even though it is not IoT focused.

How new features slot in

Say product wants:

  • A new wearables device family for wearable technology with custom UI
  • A new automation rule type: “If temp > X for Y minutes, send alert”

You add:

src/
features/
devices/
screens/
WearableDetailScreen.tsx
components/
WearableCard.tsx
WearableControls.tsx
services/
wearableMappers.ts
automation/
components/
TemperatureRuleEditor.tsx
services/
ruleEngine.ts (extend existing rule handlers)

The key is that you do not touch app/ or unrelated features. Each new concept lives where users will see it in the product.

If you like reading other engineers’ takes on scalable layouts, this article on a scalable React Native project structure is another solid reference.

Where Device Communication Logic Lives (BLE, MQTT, HTTP)

!Technical diagram of device communication logic in a React Native IoT app, featuring BLE services, MQTT client, phone connections to devices and cloud, with UI and domain separation._Device communication flows (BLE, MQTT, HTTP) connected to feature modules. Image generated by AI._

Device communication should be treated as domain services, not as UI helpers. This approach leverages modern native-to-JS flows, contrasting legacy asynchronous bridges.

A simple pattern:

  • BLE: src/features/devices/services/bleClient.ts

Wraps libraries like react-native-ble-plx for Bluetooth Low Energy. Exposes stable methods like scanForDevices, connect, readCharacteristic, writeCommand.

  • MQTT: src/shared/utils/mqttClient.ts or src/features/devices/services/mqttClient.ts

If MQTT protocol is only for device telemetry and real-time updates (alternative to WebSockets), keep it inside devices. If multiple features use MQTT protocol, place a small client in shared/utils and feature-specific topics and handlers in each feature’s services.

  • HTTP/REST: per feature *Api.ts inside services/

Example: deviceApi.ts, automationApi.ts, authApi.ts. Each exposes typed calls and maps raw responses to feature types.

Screens and hooks never talk to raw BLE or MQTT clients. They call feature services instead, which handle raw data to minimize data serialization costs. That way, if you move from direct BLE to a gateway later, you change services/ and keep UI intact.

Separating UI, Domain, And Shared Code

In React Native's New Architecture, you want clear, boring boundaries to align with its technical evolution:

  • screens/ handle navigation and wire up hooks.
  • components/ are mostly presentational, driven by props and handled efficiently by the Fabric renderer.
  • hooks/ orchestrate data fetching, subscriptions, and local state.
  • services/ talk to BLE, MQTT, HTTP via the JavaScript Interface, encode the domain, and use TurboModules for communication logic with hardware.
  • types/ define the feature’s contract.

Shared code needs similar discipline, benefiting from synchronous layout updates and concurrent rendering in the modern engine powered by the Hermes engine:

  • shared/components: buttons, layout wrappers, form inputs.
  • shared/hooks: generic hooks like useDebounce, useAppStateEffect.
  • shared/utils: cross-cutting helpers such as date formatting and validation.
  • shared/types: primitives like ApiError, Pagination.

If a piece of code mentions “device”, “automation”, or “auth”, it probably belongs in a feature, not shared. That rule alone keeps shared from turning into a dumping ground.

Adding New Devices And Automation Rules Safely

Imagine your app for hardware-intensive applications already manages smart plugs over BLE and MQTT. You want to add:

  • A Zigbee bridge managed purely over HTTP, such as in an ESP32 project
  • A new automation rule “If device is offline for 10 minutes, notify user” with offline functionality

You would:

  1. Extend devices feature through SDK integration
  2. Add new types, for example ZigbeeBridge.ts.
  3. Extend deviceApi.ts with getBridges, updateBridge.
  4. Add new screens and components for bridge detail and setup, including native module calls for custom protocol support.
  5. Extend automation, not devices, for rules
  6. In automation/types/AutomationRule.ts, add OfflineRule.
  7. Update automation/services/ruleEngine.ts to evaluate connectivity rules with low energy consumption.
  8. Add OfflineRuleEditor.tsx in automation/components.
  9. Reuse shared pieces
  10. Use shared ScreenContainer and Button so UI stays consistent.
  11. Use shared/hooks/useAppStateEffect to handle background/foreground events for connectivity and cloud synchronization.

Nothing here requires touching BLE or MQTT code if the bridge is pure HTTP. The app remains responsive during complex hardware interactions via JavaScript Interface, synchronous layout updates, and concurrent rendering. If later you get a requirement to support MQTT direct to devices through additional SDK integration, you extend devices/services/mqttClient.ts and the rule engine, not the whole app.

If you prefer not to build all of this from scratch, a boilerplate such as IoTfast gives you a similar structure with BLE, MQTT, authentication, dashboards, and device firmware wired in for the full IoT stack, so you can focus on your specific devices and automations.

Conclusion: Make Your React Native IoT Architecture Boring To Grow

A clean feature-first structure makes your React Native IoT Architecture boring in the best way. Features sit in clear folders, communication protocols stay behind service boundaries, and shared code is small and predictable.

Start by grouping around devices, automation, auth, and settings, then let new requirements plug into those modules instead of inventing new ones every sprint. Over time, your mobile app development grows in scope, not in mess.

Take a look at your current tree, pick one feature, and restructure it along these lines to align with the New Architecture. After shipping a couple of changes in the new layout, you will not want to go back.