VueJS is a declarative JavaScript framework for building reactive web interfaces, and we can also use it on a page served from an ESP32 or ESP8266.
The example is oriented to ESP32. In many cases it can also be adapted to ESP8266 by changing libraries and a few pin details.
Up to this point, we have used vanilla JavaScript, without any extra libraries, to implement the client-side logic. In general that is a very good habit, and much better than falling back to old jQuery-style habits.
In larger web applications, declarative programming is often more comfortable than manually manipulating the DOM. In other words, we define relations between the interface and the program logic, and let the framework update the view.
In this article we are going to start with this declarative approach to client programming, using the VueJS framework. It is a very popular framework for web development, lightweight but powerful, and it fits perfectly in projects served from an ESP board.
We are going to start with a basic example, our VueJS “hello world”, but running from the ESP32. In other words, the goal here is simply to get it up and running.
Don’t worry, at this point it shouldn’t be particularly difficult for you.
Starting off, our main program is as simple as can be.
#include <ESP8266WiFi.h>
#include <ESPAsyncWebServer.h>
#include <FS.h>
#include "config.h" // Replace with your network data
#include "Server.hpp"
#include "ESP8266_Utils.hpp"
void setup(void)
{
Serial.begin(115200);
SPIFFS.begin();
ConnectWiFi_STA();
InitServer();
}
void loop(void)
{
}
Our ‘Server.hpp’ file, also very simple.
AsyncWebServer server(80);
void InitServer()
{
server.serveStatic("/", SPIFFS, "/").setDefaultFile("index.html");
server.onNotFound([](AsyncWebServerRequest *request) {
request->send(400, "text/plain", "Not found");
});
server.begin();
Serial.println("HTTP server started");
}
On the client side,
The ‘index.html’ file contains the bare minimum to ensure our Vue App works. Just to highlight that we include the VueJS library, either from the ESP8266 memory, or (the commented line) from a CDN.
<!doctype html>
<html lang="">
<head>
<title>ESP8266 VueJS</title>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="app">
<ol>
<!-- We use the component defined in Vue.JS -->
<todo-item v-for="item in myList" v-bind:todo="item" v-bind:key="item.id"></todo-item>
</ol>
</div>
<!-- From CDN -->
<!--<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>-->
<!-- From ESP8266 -->
<script type="text/javascript" src="vendor/vue.min.js"></script>
<!-- Load the file that contains our App in Vue.JS -->
<script type="text/javascript" src="js/app.js"></script>
</body>
</html>
The ‘app.js’ file that contains the mini VueJS application, with a list of “to-do items”.
// Component definition
Vue.component('todo-item', {
props: ['todo'],
template: '<li> {{ todo.text }} \
<input type="checkbox" id="checkbox" v-model="todo.value"> \
<span v-if="todo.value">{{ todo.hidden }}</span> \
</li>'
})
// Definition of our example app
var app = new Vue({
el: '#app',
data: {
myList: [
{ id: 0, text: 'Item1', hidden: 'Hidden1' },
{ id: 1, text: 'Item2', hidden: 'Hidden2' },
{ id: 2, text: 'Item3', hidden: 'Hidden3' }
]
}
})
Result
We upload everything to the ESP8266 and go to the web page. If everything went correctly, we will see a list of three “tasks”, with a checkbox. And if we click on the checkbox, the “hidden” field of the corresponding line will appear.

So far, that easy. We have simply loaded a VueJS “hello world” mini application and verified that, of course, it works without problems when served from the ESP8266.
Unfortunately, our page is again as ugly as can be. But, this is where Vuetify comes into play, a framework that brings Material Design aesthetics to VueJS applications.
The page is very simple, but we already have the important part: a VueJS application served from the device itself. From here we can add styles, visual components, or communication with the ESP32 backend.
Download the Code
All the code from this post is available for download on Github.
Version for ESP8266: https://github.com/luisllamasbinaburo/ESP8266-Examples
Version for ESP32: https://github.com/luisllamasbinaburo/ESP32-Examples

