This guide will teach you how to create a simple Firebase Web App to control and monitor your ESP32 board. The Web App you’ll create can be accessed worldwide to control and monitor your ESP32 from anywhere in the world. This Web App makes the bridge between the Firebase Realtime Database and the ESP32.

Updated April 22, 2025
Complete the following tutorial before proceeding:
Here are the major steps to complete this tutorial.
We have a similar tutorial for the ESP8266 board: ESP8266 NodeMCU with Firebase – Creating a Web App
To follow this project, you need to install the following software:
Follow the next instructions to install VS Code on your Operating System:
Go to https://code.visualstudio.com/ and download the stable build for your operating system (Windows).

Click on the installation wizard to start the installation and follow all the steps to complete the installation. Accept the agreement and press the Next button.

Select the following options and click Next.

Press the Install button.

Finally, click Finish to finish the installation.

Open VS Code, and you’ll be greeted by a Welcome tab with the released notes of the newest version.

That’s it. Visual Studio Code was successfully installed.
Go to https://code.visualstudio.com/ and download the stable build for your operating system (Mac OS X).

After downloading the Visual Studio Code application file, you’ll be prompted with the following message. Press the “Open” button.

Or open your Downloads folder and open Visual Studio Code.

After that, you’ll be greeted by a Welcome tab with the released notes of the newest version.

That’s it. Visual Studio Code was successfully installed.
Go to https://code.visualstudio.com/ and download the stable build for your operating system (Linux Ubuntu).

Save the installation file:

To install it, open a Terminal window, navigate to your Downloads folder and run the following command to install VS Code.
$ cd Downloads ~/Downloads $ sudo apt install ./code_1.49.1-1600299189_amd64.deb
When the installation is finished, VS Code should be available in your applications menu.

Open VS Code, and you’ll be greeted by a Welcome tab with the released notes of the newest version.

That’s it. Visual Studio Code was successfully installed.
1) Go to nodejs.org and download the LTS version.

2) Run the executable file and follow the installation process.
3) Enable automatically install all the necessary tools.

4) When it’s done, click Finish.

5) A Terminal window will open to install the Additional Tools for Node.js. When it’s done, click any key to continue. When it’s finished, you can close the Terminal Window.

1) Open VS Code. Close all opened projects, if any.
2) Open a new Terminal window. Go to Terminal > New Terminal.
3) Run the following command to change to the C:\ path (you can install it in any other path):
cd \
Before installing Firebase tools, run the following command to install the latest npm package:
npm install -g npm@latest
4) Run the following command to install firebase tools globally:
npm -g install firebase-tools
5) Firebase tools will be installed (you can ignore any warning about deprecated libraries).
6) Test if Firebase was successfully installed with the following command:
firebase --versionIt should return the Firebase version currently installed.
Before creating the Firebase Web App, you need to set up a Firebase Project on VS Code. These are the steps:
1) Create a folder on your computer where you want to save your Firebase project—for example, Firebase-Project.
2) Open VS Code. Go to File > Open Folder… and select the folder you’ve just created.
3) Go to Terminal > New Terminal. A new Terminal window should open on your project path.

4) On the previous Terminal window, type the following:
firebase login5) You’ll be asked to collect CLI usage and error reporting information. Enter “n” and press Enter to deny.

6) After this, it will pop up a new window on your browser to login into your firebase account.

7) Allow Firebase CLI to access your google account.

8) After this, Firebase CLI login should be successful. You can close the browser window.

9) After successfully logging in, run the following command to start a Firebase project directory in the current folder.
firebase init10) You’ll be asked if you want to initialize a Firebase project in the current directory. Enter Y and hit Enter.

11) Then, use they up and down arrows and the Space key to select the options. Select the following options:
The selected options will show up with a green asterisk. Then, hit Enter.

12) Select the option “Use an existing project”—it should be highlighted in blue—then, hit Enter.

13) After that, select the Firebase project for this directory—it should be the project created in this previous tutorial. In my case, it is called ESP-Project. Then hit Enter.

14) Then, select the hosting options as shown below:

15) Press Enter on the following question to select the default database security rules file: “What file should be used for Realtime Database Security Rules?“
16) The Firebase project should now be initialized successfully. Notice that VS Code created some essential files under your project folder.

The index.html file contains some HTML text to build a web page. For now, leave the default HTML text. The idea is to replace that with your own HTML text to build a custom web page for your needs. We’ll do that later in this tutorial.
17) To check if everything went as expected, run the following command on the VS Code Terminal window.
firebase deploy
After deploying, you should get your Hosting URL. Go to that URL. You should get access to a similar web page.

This web page is built using the files placed in the public folder of your Firebase project.
You can access that web page from anywhere in the world. Now, the idea is to change the files in the public folder to show your own web page instead of that one.
Leave VS Code open. Meanwhile, you need to go to your Firebase account to add Firebase to your app.
18) Go to your Firebase console and select your project. Then, click on the +Add app button and then, select the web app icon.

19) Give your app a name. I simply called it test. Then, check the box next to Also set up Firebase Hosting for this App. Click Register app.

20) Then, copy the firebaseConfig object because you’ll need it later.

Click Next on the proceeding steps.
After this, you can also access the firebaseConfig object if you go to your Project settings in your Firebase console.
21) Copy the authDomain. In my case, it is (the same we got in the Terminal window after setting up the Firebase project):
https://esp-project-a9add.web.app
This is the URL that allows you to access your web app.
Now that you’ve created a Firebase project app successfully on VS Code, follow the next steps to customize the app to display the values saved on the Realtime Database.
Copy the following to your index.html file. This HTML file creates a simple web page to display the readings saved on the Realtime Database created on this previous project.
<!-- Complete Project Details ESP32: https://RandomNerdTutorials.com/esp32-firebase-web-app/ ESP8266: https://RandomNerdTutorials.com/esp8266-nodemcu-firebase-web-app/ --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ESP Firebase App</title> <!-- Load your app.js script --> <script src="app.js" type="module"></script> </head> <body> <h1>ESP Firebase Web App Example</h1> <p>Reading int: <span id="reading-int"></span></p> <p>Reading float: <span id="reading-float"></span></p> <p>Reading string: <span id="reading-string"></span></p> </body> </html>
Let’s take a quick look at the HTML file.
In the <head> of the HTML file, we must add all the required metadata.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ESP Firebase App</title> <!-- Load your app.js script (place at the bottom) --> <script src="app.js" type="module"></script> </head>
The title of the web page is ESP Firebase App, but you can change it in the following line.
<title>ESP Firebase App</title>
We’ll take care of interacting with the Realtime Database on a JavaScript file called app.js (that we’ll create later). That file will also contain the JavaScript functions to update the HTML page with the database values. We need to load it here before displaying the body of the HTML page.
<script src="app.js" type="module"></script>
Now, let’s go to the HTML parts that are visible to the user—go between the <body> and </body> tags.
We create a heading with the following text: ESP32 Firebase Web App Example, but you can change it to whatever you want.
<h1>ESP32 Firebase Web App Example</h1>
Then, we add three paragraphs to display the int, float, and String values saved in the database. We create <span> tags with specific ids, so that we can refer to those HTML elements using JavaScript and insert the database values.
<p>Reading int: <span id="reading-int"></span></p> <p>Reading float: <span id="reading-float"></span></p> <p>Reading string: <span id="reading-string"></span></p>
After making the necessary changes, you can save the HTML file.
Inside the public folder, create a file called app.js. You can do this on VS Code by selecting the public folder and then clicking on the +file icon. This JavaScript file is responsible for interacting with the Realtime Database and updating the values on the web page whenever there’s a change in the database.
Copy the following to your app.js file and save it.
// Complete Project Details // ESP32: https://RandomNerdTutorials.com/esp32-firebase-web-app/ // ESP8266: https://RandomNerdTutorials.com/esp8266-nodemcu-firebase-web-app/ import { initializeApp } from "https://www.gstatic.com/firebasejs/11.6.0/firebase-app.js"; import { getDatabase, ref, onValue } from "https://www.gstatic.com/firebasejs/11.6.0/firebase-database.js"; // Firebase configuration const firebaseConfig = { apiKey: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION", authDomain: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION", databaseURL: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION", projectId: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION", storageBucket: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION", messagingSenderId: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION", appId: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION" }; // Initialize Firebase const app = initializeApp(firebaseConfig); // Get a reference to the database const database = getDatabase(app); // Database Paths const dataFloatPath = 'test/float'; const dataIntPath = 'test/int'; const dataStringPath = 'test/string'; // Get database references const databaseFloatRef = ref(database, dataFloatPath); const databaseIntRef = ref(database, dataIntPath); const databaseStringRef = ref(database, dataStringPath); // Variables to save database current values let floatReading; let intReading; let stringReading; // Attach listeners onValue(databaseFloatRef, (snapshot) => { floatReading = snapshot.val(); console.log("Float reading: " + floatReading); document.getElementById("reading-float").innerHTML = floatReading; }); onValue(databaseIntRef, (snapshot) => { intReading = snapshot.val(); console.log("Int reading: " + intReading); document.getElementById("reading-int").innerHTML = intReading; }); onValue(databaseStringRef, (snapshot) => { stringReading = snapshot.val(); console.log("String reading: " + stringReading); document.getElementById("reading-string").innerHTML = stringReading; });
Let’s take a quick look to see how it works.
The following lines load the Firebase tools that will be required for this example to connect and read from the Realtime Database. We use the Firebase CDN URLs, so we don’t need to install Firebase locally.
import { initializeApp } from "https://www.gstatic.com/firebasejs/11.6.0/firebase-app.js"; import { getDatabase, ref, onValue } from "https://www.gstatic.com/firebasejs/11.6.0/firebase-database.js";
Add your firebaseConfig object below. This is required to authenticate and locate the RTDB of your project. You get these values from the Firebase Console when you create a project and add a web app (like we did in previous steps).
const firebaseConfig = { apiKey: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION", authDomain: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION", databaseURL: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION", projectId: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION", storageBucket: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION", messagingSenderId: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION", appId: "REPLACE_WITH_YOUR_Firebase_CONFIGURATION" };
The following line initializes a Firebase app using the configuration object defined earlier. It returns an app object that you can use to interact with the application.
const app = initializeApp(firebaseConfig);
The following command creates a reference to the Database associated with the app we initialized.
const database = getDatabase(app);
We define the database paths where the data we want to read is stored.
const dataFloatPath = 'test/float'; const dataIntPath = 'test/int'; const dataStringPath = 'test/string';
Then, we create references to specific locations on the database using those paths.
const databaseFloatRef = ref(database, dataFloatPath); const databaseIntRef = ref(database, dataIntPath); const databaseStringRef = ref(database, dataStringPath);
We create variables to store the current values read from the database.
let floatReading; let intReading; let stringReading;
Finally, to get values from the database, we can attach listeners to each of those database references. Then, anytime there’s a change in the database, we’ll update the HTML page with the corresponding values.
Let’s see how to do that. For example, we can use the onValue() function that accepts as arguments a reference to the database, and a callback function:
onValue(databaseFloatRef, (snapshot) => { floatReading = snapshot.val(); console.log("Float reading: " + floatReading); document.getElementById("reading-float").innerHTML = floatReading; });
In this case, the onValue() function attaches a listener to the databaseFloatRef (/test/float). Whenever the value at that path changes in the database, the callback function runs. In this case, we’re defining the callback function inside the onValue(). It is defined as an arrow function.
The (snapshot) is the parameter of the callback function. When Firebase calls the callback, it passes a snapshot object containing the current data at test/float. Then, the => arrow syntax indicates this is an arrow function, a concise way to define functions in JavaScript. The function body is defined between { }.
Let’s go back to the callback function: snapshot.val() gets the current value at the path. The value is stored in the floatReading variable.
floatReading = snapshot.val();
It’s logged to the console for debugging purposes.
console.log("Float reading: " + floatReading);
The webpage element with id=”reading-float” (defined in the index.html file) is updated to display the value.
document.getElementById("reading-float").innerHTML = floatReading;
We proceed in a similar way for the other database paths.
onValue(databaseIntRef, (snapshot) => { intReading = snapshot.val(); console.log("Int reading: " + intReading); document.getElementById("reading-int").innerHTML = intReading; }); onValue(databaseStringRef, (snapshot) => { stringReading = snapshot.val(); console.log("String reading: " + stringReading); document.getElementById("reading-string").innerHTML = stringReading; });
After saving the HTML and JavaScript files, deploy your app on VS Code by running the following command in VS Code Terminal window.
firebase deployUpload the following code to your ESP32. This is the same code used in this previous project to write to the database. This code simply writes to the database every 10 seconds.
Don’t forget to insert your network credentials, database URL, and Firebase Project API Key, and Firebase user email and password.
/********* Rui Santos & Sara Santos - Random Nerd Tutorials Complete instructions at https://RandomNerdTutorials.com/esp32-firebase-realtime-database/ *********/ #define ENABLE_USER_AUTH #define ENABLE_DATABASE #include <Arduino.h> #include <WiFi.h> #include <WiFiClientSecure.h> #include <FirebaseClient.h> // Network and Firebase credentials #define WIFI_SSID "REPLACE_WITH_YOUR_SSID" #define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD" #define Web_API_KEY "REPLACE_WITH_YOUR_FIREBASE_PROJECT_API_KEY" #define DATABASE_URL "REPLACE_WITH_YOUR_FIREBASE_DATABASE_URL" #define USER_EMAIL "REPLACE_WITH_FIREBASE_PROJECT_EMAIL_USER" #define USER_PASS "REPLACE_WITH_FIREBASE_PROJECT_USER_PASS" // User function void processData(AsyncResult &aResult); // Authentication UserAuth user_auth(Web_API_KEY, USER_EMAIL, USER_PASS); // Firebase components FirebaseApp app; WiFiClientSecure ssl_client; using AsyncClient = AsyncClientClass; AsyncClient aClient(ssl_client); RealtimeDatabase Database; // Timer variables for sending data every 10 seconds unsigned long lastSendTime = 0; const unsigned long sendInterval = 10000; // 10 seconds in milliseconds // Variables to send to the database int intValue = 0; float floatValue = 0.01; String stringValue = ""; void setup(){ Serial.begin(115200); // Connect to Wi-Fi WiFi.begin(WIFI_SSID, WIFI_PASSWORD); Serial.print("Connecting to Wi-Fi"); while (WiFi.status() != WL_CONNECTED) { Serial.print("."); delay(300); } Serial.println(); // Configure SSL client ssl_client.setInsecure(); ssl_client.setConnectionTimeout(1000); ssl_client.setHandshakeTimeout(5); // Initialize Firebase initializeApp(aClient, app, getAuth(user_auth), processData, "🔐 authTask"); app.getApp<RealtimeDatabase>(Database); Database.url(DATABASE_URL); } void loop(){ // Maintain authentication and async tasks app.loop(); // Check if authentication is ready if (app.ready()){ // Periodic data sending every 10 seconds unsigned long currentTime = millis(); if (currentTime - lastSendTime >= sendInterval){ // Update the last send time lastSendTime = currentTime; // send a string stringValue = "value_" + String(currentTime); Database.set<String>(aClient, "/test/string", stringValue, processData, "RTDB_Send_String"); // send an int Database.set<int>(aClient, "/test/int", intValue, processData, "RTDB_Send_Int"); intValue++; //increment intValue in every loop // send a string floatValue = 0.01 + random (0,100); Database.set<float>(aClient, "/test/float", floatValue, processData, "RTDB_Send_Float"); } } } void processData(AsyncResult &aResult) { if (!aResult.isResult()) return; if (aResult.isEvent()) Firebase.printf("Event task: %s, msg: %s, code: %d\n", aResult.uid().c_str(), aResult.eventLog().message().c_str(), aResult.eventLog().code()); if (aResult.isDebug()) Firebase.printf("Debug task: %s, msg: %s\n", aResult.uid().c_str(), aResult.debug().c_str()); if (aResult.isError()) Firebase.printf("Error task: %s, msg: %s, code: %d\n", aResult.uid().c_str(), aResult.error().message().c_str(), aResult.error().code()); if (aResult.available()) Firebase.printf("task: %s, payload: %s\n", aResult.uid().c_str(), aResult.c_str()); }
The ESP32 should be sending new readings every 10 seconds to the database.

Go to your App URL. New readings will show up on the web page every 10 seconds. The App updates the web page whenever the ESP32 writes a new value to the database.
If you don’t see this web page, you may need to hard refresh your web browser (CTRL+F5 or Cmd+R).

In your Firebase Console, you can go to your project page and check that new values are being written into the database every 10 seconds.

Congratulations! You’ve created a Firebase Web App to interface with the ESP32.
Copyright ©2025. All Rights Reserved Emblab THE RAVE INNOVATION