Uploading code to an ESP32 microcontroller is not limited to firmware alone—you can upload almost any type of data, including frontend assets, to your microcontroller. Most tutorials focus on uploading firmware to a microcontroller, but what if you want to upload a website or frontend files instead? In this article, we will explore how uploading works in embedded systems and how to store and serve a frontend from an ESP32.
Before starting, make sure you have the necessary prerequisites for ESP32 development. In this guide, we use a combination of VS Code IDE, PlatformIO extension, and the Arduino framework.
What Does “Upload” Mean?
Uploading refers to transferring data into a microcontroller’s non-volatile memory, such as Flash, EEPROM, SPIFFS, or an SD card. Typically, we upload the firmware—the program code that the microcontroller executes—but you can also upload additional files, such as frontend assets, to the microcontroller.
ESP32 Memory Overview
ESP32 contains several types of memory:
ROM: Read-only memory inside the chip containing system code provided by Espressif, typically around 448 KB.
SRAM (RAM): On-chip memory for temporary data storage during program execution, approximately 520 KB.
Flash: External memory connected via SPI, used for storing firmware, filesystem data, and other non-volatile information. Flash size varies between 1 MB and 16 MB depending on the module.
RTC Memory: Small on-chip memory (about 8 KB) used to store data during deep sleep or for timer functionality
Before uploading your code, it is important to define how flash memory is partitioned. Flash memory is divided into several sections:
Bootloader
Partition Table
Factory App
OTA App
NVS / EEPROM
SPIFFS / LittleFS
The SPIFFS / LittleFS partition is a filesystem where user files, such as frontend assets, are stored. Both SPIFFS and LittleFS are types of file systems.
SPIFFS: Older filesystem, now deprecated.
LittleFS: Recommended modern filesystem, with real directory structures, better stability, faster performance, and more resistance to corruption.
To configure LittleFS in PlatformIO, set the following in your platformio.ini:
board_build.filesystem = littlefs
board_build.filesystem_size = 2MB
This defines LittleFS as the filesystem and allocates 2 MB of flash memory for it.
Preparing and Uploading Frontend Files
When uploading frontend files, it is important to minimize their size to save microcontroller resources. At the beginning of development, choose the frontend technology carefully. For very small projects, writing raw HTML, CSS, and JavaScript without libraries can produce minimal bundle sizes.
For more advanced projects, frameworks are often necessary. Selecting a framework with a small output size is crucial. For example, Vue.js is lightweight, feature-complete, and works well with Tailwind CSS for styling. Using this combination without additional libraries, you can keep the bundle size under 100 KB.
After developing your frontend, build it in production mode. For Vue.js, run:
npm run build
This produces a dist folder containing index.html and an assets directory.
PlatformIO Filesystem Structure
In PlatformIO, the data/ directory corresponds to the microcontroller’s filesystem. Everything inside this directory will be uploaded to LittleFS. To upload:
Upload firmware first: pio run -t upload
or use the GUI upload button.
Upload filesystem data: pio run -t uploadfs
Note: Running
uploadfsclears all existing data in the filesystem and transfers the contents of thedata/directory to LittleFS.
Serving Frontend Files on ESP32
Once uploaded, your files can be served from ESP32 using the ESPAsyncWebServer library. Here’s a minimal example to serve a frontend built with Vue.js:
// main.cpp
#include
#include
#include "LittleFS.h"
#include
AsyncWebServer server(80);
void setup() {
LittleFS.begin(true);
server.serveStatic("/", LittleFS, "/").setDefaultFile("index.html");
server.begin();
}
void loop() {
// Nothing needed here
}
Notes:
-
In Single Page Applications (SPA) like Vue.js, all routes must serve
index.htmlfor proper functioning. -
Static files like CSS and JS are automatically served from LittleFS.
Additional Optimization
For better performance and lower memory usage:
-
Consider Gzipping frontend assets to reduce the transferred data size.
-
Minimize external libraries in your frontend bundle.
-
Optimize images and assets for embedded devices.
We plan to cover advanced optimization strategies in a follow-up article.
