Skip to main content

Introduction

Embedded React is React Native for embedded MCUs. You write a React app, build it, and flash it onto a microcontroller. The UI runs on the device: no browser, no phone, and no operating system required.

App.jsx
import {useState} from 'react';
import {View, Text, Pressable} from 'embedded-react';

export function App() {
const [taps, setTaps] = useState(0);
return (
<View style={{flex: 1, padding: 20, backgroundColor: '#1a1a2e'}}>
<Text style={{color: '#fff', fontSize: 24}}>Hello from an ESP32.</Text>
<Pressable onPress={() => setTaps(taps + 1)}>
<Text style={{color: '#e94560', marginTop: 12}}>
Tapped {taps} times
</Text>
</Pressable>
</View>
);
}

That component runs natively on a microcontroller driving a raw SPI or RGB display.

What it is, and what it isn't​

Most projects that pair "React" with an "ESP32" run React in a web browser on your phone or laptop, talking to the microcontroller over REST or BLE. The MCU is only a backend; the component tree, layout, and rendering all live somewhere else.

Embedded React is the opposite. It takes React Native's approach: React is a component and reconciliation model, not a DOM thing. React Native swapped the browser's host primitives (div, CSS, the browser layout engine) for native ones (View, Yoga, native draw calls). Embedded React does that swap again, one level deeper. The host primitives are a pure C99 engine drawing straight into a framebuffer or SPI display.

You write the same JSX components, the same Animated API, and the same flexbox styles you would use on iOS or Android. Your app runs on an ESP32, STM32, or RP2040 instead of a phone.

One app, two flows​

The same JSX reaches the device through one of two flows. Both target the same C engine; the difference is when the dynamism is resolved.

Flow A: runtimeFlow B: ahead of time
How it runsA real React reconciler on QuickJS, on the chipJSX compiled to a package that a small runtime runs
You getFull runtime dynamism, hot reload on the device, UI updates without reflashing firmwareNo JavaScript engine, no garbage collector, a smaller and deterministic binary
NeedsExternal RAM for the JavaScript heap: PSRAM on an ESP32-S3, SDRAM on an STM32H7Nothing extra: runs in internal RAM on MCUs with no external memory
Trade-offRAM and per-frame dispatch costA subset of the API

Choosing between them is a build flag, not a rewrite. The two flows goes deeper.

Status​

Embedded React is in beta. The engine, both flows, the hardware backends below, and the simulators are built and verified on real hardware; from here the work is fixes and features, tracked in the roadmap.

TargetFlowStatus
ESP32-S3 with an 800×480 RGB panelAVerified on hardware
ESP32 "Cheap Yellow Display" (no PSRAM, SPI)BVerified on hardware
RP2040 with a 240×280 SPI displayBVerified on hardware
Linux, macOS or Windows desktop (SDL)A and BWorking
Browser (WebAssembly simulator)AWorking
STM32H7 with SDRAM (Chrom-ART backend)ARunning on hardware; a public example project is planned
Raspberry PiPlanned

Where to go next​

  • Getting started: create a project and see it running in your browser in a couple of minutes, with no hardware.
  • Playground: try it without installing anything.
  • Concepts: how the engine, the flows, and the rendering pipeline fit together.