Quickstart
Flash ESP32 firmware from a browser with optional NVS configuration.
Installation
Browser (CDN)
<script src="https://cdn.jsdelivr.net/gh/adam-weber/esp-webflash-toolkit@main/dist/esp-webflash-toolkit-full.min.js"></script>
npm
npm install esp-webflash-toolkit
Vanilla JavaScript (Browser)
One-Liner Flash
<script src="https://cdn.jsdelivr.net/gh/adam-weber/esp-webflash-toolkit@main/dist/esp-webflash-toolkit-full.min.js"></script>
<script>
document.getElementById('flash-btn').onclick = async () => {
await ESPWebFlash.flashDevice({
firmware: 'https://example.com/firmware.bin',
config: { wifi_ssid: 'MyNetwork', wifi_pass: 'secret' },
onProgress: (pct) => console.log(pct + '%')
});
};
</script>
With More Control
<script src="https://cdn.jsdelivr.net/gh/adam-weber/esp-webflash-toolkit@main/dist/esp-webflash-toolkit-full.min.js"></script>
<script>
const { ESPFlasher } = ESPWebFlash;
const flasher = new ESPFlasher({
chip: 'esp32',
firmwareUrl: 'https://example.com/firmware.bin',
fields: ['wifi'] // expands to wifi_ssid + wifi_pass fields
});
flasher.addEventListener('progress', e => {
document.getElementById('progress').textContent = e.detail.percent + '%';
});
flasher.addEventListener('log', e => {
console.log(e.detail.message);
});
document.getElementById('connect').onclick = () => flasher.connect();
document.getElementById('flash').onclick = () => flasher.flash();
</script>
ES Modules (npm)
import { flashDevice } from 'esp-webflash-toolkit';
await flashDevice({
firmware: 'https://example.com/firmware.bin',
config: { wifi_ssid: 'MyNetwork', wifi_pass: 'secret' },
onProgress: (pct) => console.log(`${pct}%`)
});
Advanced API
import { ESPFlasher } from 'esp-webflash-toolkit';
const flasher = new ESPFlasher({
chip: 'esp32s3',
firmwareUrl: 'https://example.com/firmware.bin',
fields: ['wifi', 'mqtt', { key: 'device_name', label: 'Device Name', type: 'text' }]
});
flasher.addEventListener('progress', e => updateProgressBar(e.detail.percent));
flasher.addEventListener('log', e => appendToConsole(e.detail.message));
await flasher.connect();
flasher.setConfig({ wifi_ssid: 'MyNetwork', wifi_pass: 'secret' });
await flasher.flash();
flasher.dispose();
2. Read Config in Firmware
The NVS partition is standard ESP-IDF format. Read it with native APIs:
ESP-IDF (C)
#include "nvs_flash.h"
#include "nvs.h"
void read_config() {
nvs_flash_init();
nvs_handle_t handle;
nvs_open("config", NVS_READONLY, &handle);
char ssid[32], password[64], api_url[128];
size_t len;
len = sizeof(ssid);
nvs_get_str(handle, "wifi_ssid", ssid, &len);
len = sizeof(password);
nvs_get_str(handle, "wifi_pass", password, &len);
len = sizeof(api_url);
nvs_get_str(handle, "api_url", api_url, &len);
uint32_t device_id;
nvs_get_u32(handle, "device_id", &device_id);
nvs_close(handle);
printf("WiFi: %s, Device: %lu\n", ssid, device_id);
}
Arduino
#include <Preferences.h>
Preferences prefs;
void setup() {
prefs.begin("config", true); // true = read-only
String ssid = prefs.getString("wifi_ssid", "");
String pass = prefs.getString("wifi_pass", "");
String api = prefs.getString("api_url", "");
uint32_t id = prefs.getUInt("device_id", 0);
prefs.end();
}
Rust (esp-idf-svc)
use esp_idf_svc::nvs::*;
fn read_config() -> Result<(), EspError> {
let nvs = EspDefaultNvsPartition::take()?;
let ns = EspNvs::new(nvs, "config", true)?;
let mut buf = [0u8; 128];
let ssid = ns.get_str("wifi_ssid", &mut buf)?;
let pass = ns.get_str("wifi_pass", &mut buf)?;
let api_url = ns.get_str("api_url", &mut buf)?;
let device_id: u32 = ns.get_u32("device_id")?.unwrap_or(0);
Ok(())
}
Key Concepts
- Namespace: The first-level key in your config object (
configabove) becomes the NVS namespace - Keys: Limited to 15 characters, alphanumeric + underscore, case-sensitive
- Partition offset: Default is
0x9000(matches most ESP-IDF partition tables) - Partition size:
0x6000(24KB) is typical, must match your partition table
Next Steps
- View more code examples
- Scaffold a complete web flasher
- Partition Table Generator - create custom layouts
- JavaScript API reference