diff --git a/.travis.yml b/.travis.yml
index 5b22fc2b3cf4085ee826335d830e39b662c5f302..dec966c9235592216ef58737d7280b5582d0f2ef 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -23,6 +23,7 @@ env:
   #- TEST_PLATFORM="STM32F1"
   - TEST_PLATFORM="teensy35"
   - TEST_PLATFORM="linux_native"
+  - TEST_PLATFORM="esp32"
 
 addons:
   apt:
diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index 0f1b0218c968672fb0be68524ee82569a1a7e5aa..c74153409f124d5a014ff55efe10df91ae9ed8bc 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/Marlin/src/HAL/HAL_ESP32/HAL.cpp b/Marlin/src/HAL/HAL_ESP32/HAL.cpp
index 1ef279855357f0bc3faf21a26c882748585d0b75..76b961b7b9f75ba140cf5579fca05276fedcc9ea 100644
--- a/Marlin/src/HAL/HAL_ESP32/HAL.cpp
+++ b/Marlin/src/HAL/HAL_ESP32/HAL.cpp
@@ -34,7 +34,14 @@
 #include "../../inc/MarlinConfigPre.h"
 
 #if ENABLED(WIFISUPPORT)
-  #include "ota.h"
+  #include <ESPAsyncWebServer.h>
+  #include "wifi.h"
+  #if ENABLED(OTASUPPORT)
+    #include "ota.h"
+  #endif
+  #if ENABLED(WEBSUPPORT)
+    #include "web.h"
+  #endif
 #endif
 
 // --------------------------------------------------------------------------
@@ -83,14 +90,21 @@ esp_adc_cal_characteristics_t characteristics;
 
 void HAL_init(void) {
   #if ENABLED(WIFISUPPORT)
-    OTA_init();
+    wifi_init();
+    #if ENABLED(OTASUPPORT)
+      OTA_init();
+    #endif
+    #if ENABLED(WEBSUPPORT)
+      web_init();
+    #endif
+    server.begin();
   #endif
 
   i2s_init();
 }
 
 void HAL_idletask(void) {
-  #if ENABLED(WIFISUPPORT)
+  #if ENABLED(OTASUPPORT)
     OTA_handle();
   #endif
 }
diff --git a/Marlin/src/HAL/HAL_ESP32/HAL.h b/Marlin/src/HAL/HAL_ESP32/HAL.h
index e1249c71eeee386cbf6cd69a04d0f0ea95cf2cac..f13c3798de1918185800f5d7d8a0eea8c9cabe4d 100644
--- a/Marlin/src/HAL/HAL_ESP32/HAL.h
+++ b/Marlin/src/HAL/HAL_ESP32/HAL.h
@@ -47,14 +47,17 @@
 
 #include "HAL_timers_ESP32.h"
 
+#include "WebSocketSerial.h"
+
 // --------------------------------------------------------------------------
 // Defines
 // --------------------------------------------------------------------------
 
 extern portMUX_TYPE spinlock;
 
-#define NUM_SERIAL 1
+#define NUM_SERIAL 2
 #define MYSERIAL0 Serial
+#define MYSERIAL1 webSocketSerial
 
 #define CRITICAL_SECTION_START portENTER_CRITICAL(&spinlock)
 #define CRITICAL_SECTION_END   portEXIT_CRITICAL(&spinlock)
diff --git a/Marlin/src/HAL/HAL_ESP32/WebSocketSerial.cpp b/Marlin/src/HAL/HAL_ESP32/WebSocketSerial.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..450cf683075a9896faaac0187cf7a3f7b94036ac
--- /dev/null
+++ b/Marlin/src/HAL/HAL_ESP32/WebSocketSerial.cpp
@@ -0,0 +1,232 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#ifdef ARDUINO_ARCH_ESP32
+
+#include "../../inc/MarlinConfig.h"
+
+#if ENABLED(WIFISUPPORT)
+
+#include "WebSocketSerial.h"
+#include "wifi.h"
+
+#include <AsyncTCP.h>
+#include <ESPAsyncWebServer.h>
+
+struct ring_buffer_r {
+  unsigned char buffer[RX_BUFFER_SIZE];
+  volatile ring_buffer_pos_t head, tail;
+};
+
+struct ring_buffer_t {
+  unsigned char buffer[256];
+  volatile uint8_t head, tail;
+};
+
+ring_buffer_r rx_buffer = { { 0 }, 0, 0 };
+ring_buffer_t tx_buffer = { { 0 }, 0, 0 };
+
+static bool _written;
+
+#if ENABLED(EMERGENCY_PARSER)
+  static EmergencyParser::State emergency_state; // = EP_RESET
+#endif
+
+AsyncWebSocket ws("/ws"); // access at ws://[esp ip]/ws
+
+FORCE_INLINE int next_rx_index(const int i) { return (ring_buffer_pos_t)(i + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1); }
+FORCE_INLINE int next_tx_index(const int i) { return (ring_buffer_pos_t)(i + 1) & (ring_buffer_pos_t)(TX_BUFFER_SIZE - 1); }
+
+static void addToBuffer(uint8_t * const data, const size_t len) {
+  for (size_t i = 0; i < len; i++) {
+    ring_buffer_pos_t h = rx_buffer.head;
+    const ring_buffer_pos_t t = rx_buffer.tail, n = next_rx_index(h);
+
+    if (n != t) { rx_buffer.buffer[h] = data[i]; h = n; }
+
+    // TODO: buffer is full, handle?
+
+    rx_buffer.head = h;
+  }
+}
+
+// Handle WebSocket event
+static void onEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len) {
+  switch (type) {
+    case WS_EVT_CONNECT: client->ping(); break; // client connected
+    case WS_EVT_DISCONNECT:                     // client disconnected
+    case WS_EVT_ERROR:                          // error was received from the other end
+    case WS_EVT_PONG: break;                    // pong message was received (in response to a ping request maybe)
+    case WS_EVT_DATA: {                         // data packet
+      AwsFrameInfo * info = (AwsFrameInfo*)arg;
+      if (info->opcode == WS_TEXT || info->message_opcode == WS_TEXT)
+        addToBuffer(data, len);
+    }
+  }
+}
+
+// Public Methods
+void WebSocketSerial::begin(const long baud_setting) {
+  ws.onEvent(onEvent);
+  server.addHandler(&ws); // attach AsyncWebSocket
+}
+
+void WebSocketSerial::end() { }
+
+int WebSocketSerial::peek(void) {
+  const int v = rx_buffer.head == rx_buffer.tail ? -1 : rx_buffer.buffer[rx_buffer.tail];
+  return v;
+}
+
+int WebSocketSerial::read(void) {
+  const ring_buffer_pos_t h = rx_buffer.head, t = rx_buffer.tail;
+  if (h == t) return -1;  // Nothing to read? Return now
+
+  const int v = rx_buffer.buffer[t];
+
+  rx_buffer.tail = (ring_buffer_pos_t)(t + 1) & (RX_BUFFER_SIZE - 1); // Advance tail
+
+  return v;
+}
+
+bool WebSocketSerial::available(void) {
+  const ring_buffer_pos_t h = rx_buffer.head, t = rx_buffer.tail;
+  return (ring_buffer_pos_t)(RX_BUFFER_SIZE + h - t) & (RX_BUFFER_SIZE - 1);
+}
+
+void WebSocketSerial::flush(void) {
+  ws.textAll("flush");
+  rx_buffer.tail = rx_buffer.head;
+}
+
+#if TX_BUFFER_SIZE
+
+  void WebSocketSerial::write(const uint8_t c) {
+    _written = true;
+
+    const uint8_t i = (tx_buffer.head + 1) & (TX_BUFFER_SIZE - 1);
+
+    // Store new char. head is always safe to move
+    tx_buffer.buffer[tx_buffer.head] = c;
+    tx_buffer.head = i;
+
+    if (c == '\n') {
+      ws.textAll(tx_buffer.buffer, tx_buffer.head);
+      tx_buffer.head = 0;
+    }
+  }
+
+  void WebSocketSerial::flushTx(void) {
+    ws.textAll("flushTx");
+    if (!_written) return;
+  }
+
+#else
+
+ //void WebSocketSerial::write(const uint8_t c) { _written = true; }
+ //void WebSocketSerial::flushTx(void) { if (!_written) return; }
+
+#endif
+
+/**
+ * Imports from print.h
+ */
+
+void WebSocketSerial::print(char c, int base) { print((long)c, base); }
+void WebSocketSerial::print(unsigned char b, int base) { print((unsigned long)b, base); }
+void WebSocketSerial::print(int n, int base) { print((long)n, base); }
+void WebSocketSerial::print(unsigned int n, int base) { print((unsigned long)n, base); }
+void WebSocketSerial::print(long n, int base) {
+  if (base == 0)
+    write(n);
+  else if (base == 10) {
+    if (n < 0) { print('-'); n = -n; }
+    printNumber(n, 10);
+  }
+  else
+    printNumber(n, base);
+}
+
+void WebSocketSerial::print(unsigned long n, int base) {
+  if (base == 0) write(n); else printNumber(n, base);
+}
+
+void WebSocketSerial::print(double n, int digits)         { printFloat(n, digits); }
+
+void WebSocketSerial::println(void)                       { print('\r'); print('\n'); }
+void WebSocketSerial::println(const String& s)            { print(s); println(); }
+void WebSocketSerial::println(const char c[])             { print(c); println(); }
+void WebSocketSerial::println(char c, int base)           { print(c, base); println(); }
+void WebSocketSerial::println(unsigned char b, int base)  { print(b, base); println(); }
+void WebSocketSerial::println(int n, int base)            { print(n, base); println(); }
+void WebSocketSerial::println(unsigned int n, int base)   { print(n, base); println(); }
+void WebSocketSerial::println(long n, int base)           { print(n, base); println(); }
+void WebSocketSerial::println(unsigned long n, int base)  { print(n, base); println(); }
+void WebSocketSerial::println(double n, int digits)       { print(n, digits); println(); }
+
+// Private Methods
+
+void WebSocketSerial::printNumber(unsigned long n, uint8_t base) {
+  if (n) {
+    unsigned char buf[8 * sizeof(long)]; // Enough space for base 2
+    int8_t i = 0;
+    while (n) {
+      buf[i++] = n % base;
+      n /= base;
+    }
+    while (i--)
+      print((char)(buf[i] + (buf[i] < 10 ? '0' : 'A' - 10)));
+  }
+  else
+    print('0');
+}
+
+void WebSocketSerial::printFloat(double number, uint8_t digits) {
+  // Handle negative numbers
+  if (number < 0.0) { print('-'); number = -number; }
+
+  // Round correctly so that print(1.999, 2) prints as "2.00"
+  // Use a lookup table for performance
+  constexpr double rounds[] = { 0.5, 0.05, 0.005, 0.0005, 0.00005, 0.000005, 0.0000005, 0.00000005 };
+  number += rounds[digits];
+
+  //number += pow(10, -(digits + 1)); // slower single-line equivalent
+
+  // Extract the integer part of the number and print it
+  unsigned long int_part = (unsigned long)number;
+  print(int_part);
+
+  // Print the decimal point, but only if there are digits beyond
+  double remainder = number - (double)int_part;
+  if (digits) {
+    print('.');
+    // Extract digits from the remainder one at a time
+    while (digits--) {
+      remainder *= 10.0;
+      const int toPrint = int(remainder);
+      print(toPrint);
+      remainder -= toPrint;
+    }
+  }
+}
+
+#endif // WIFISUPPORT
+#endif // ARDUINO_ARCH_ESP32
diff --git a/Marlin/src/HAL/HAL_ESP32/WebSocketSerial.h b/Marlin/src/HAL/HAL_ESP32/WebSocketSerial.h
new file mode 100644
index 0000000000000000000000000000000000000000..43c804410700f75e34921124eee539a9d19f7537
--- /dev/null
+++ b/Marlin/src/HAL/HAL_ESP32/WebSocketSerial.h
@@ -0,0 +1,99 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#pragma once
+
+#include "../../inc/MarlinConfig.h"
+
+#include <WString.h>
+
+#define DEC 10
+#define HEX 16
+#define OCT 8
+#define BIN 2
+
+#ifndef RX_BUFFER_SIZE
+  #define RX_BUFFER_SIZE 128
+#endif
+#ifndef TX_BUFFER_SIZE
+  #define TX_BUFFER_SIZE 32
+#endif
+#if TX_BUFFER_SIZE <= 0
+  #error "TX_BUFFER_SIZE is required for the WebSocket."
+#endif
+
+#if RX_BUFFER_SIZE > 256
+  typedef uint16_t ring_buffer_pos_t;
+#else
+  typedef uint8_t ring_buffer_pos_t;
+#endif
+
+class WebSocketSerial {
+public:
+  WebSocketSerial() {};
+  static void begin(const long);
+  static void end();
+  static int peek(void);
+  static int read(void);
+  static void flush(void);
+  static void flushTx(void);
+  static bool available(void);
+  static void write(const uint8_t c);
+
+  #if ENABLED(SERIAL_STATS_DROPPED_RX)
+    FORCE_INLINE static uint32_t dropped() { return 0; }
+  #endif
+
+  #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
+    FORCE_INLINE static int rxMaxEnqueued() { return 0; }
+  #endif
+
+  FORCE_INLINE static void write(const char* str) { while (*str) write(*str++); }
+  FORCE_INLINE static void write(const uint8_t* buffer, size_t size) { while (size--) write(*buffer++); }
+  FORCE_INLINE static void print(const String& s) { for (int i = 0; i < (int)s.length(); i++) write(s[i]); }
+  FORCE_INLINE static void print(const char* str) { write(str); }
+
+  static void print(char, int = 0);
+  static void print(unsigned char, int = 0);
+  static void print(int, int = DEC);
+  static void print(unsigned int, int = DEC);
+  static void print(long, int = DEC);
+  static void print(unsigned long, int = DEC);
+  static void print(double, int = 2);
+
+  static void println(const String& s);
+  static void println(const char[]);
+  static void println(char, int = 0);
+  static void println(unsigned char, int = 0);
+  static void println(int, int = DEC);
+  static void println(unsigned int, int = DEC);
+  static void println(long, int = DEC);
+  static void println(unsigned long, int = DEC);
+  static void println(double, int = 2);
+  static void println(void);
+  operator bool() { return true; }
+
+private:
+  static void printNumber(unsigned long, const uint8_t);
+  static void printFloat(double, uint8_t);
+};
+
+extern WebSocketSerial webSocketSerial;
diff --git a/Marlin/src/HAL/HAL_ESP32/ota.cpp b/Marlin/src/HAL/HAL_ESP32/ota.cpp
index 52129ac92bc91d506cdf6507912fd8043000dbf9..40ec1ab8754bc22d7a9c9042b07648a1760143fe 100644
--- a/Marlin/src/HAL/HAL_ESP32/ota.cpp
+++ b/Marlin/src/HAL/HAL_ESP32/ota.cpp
@@ -21,7 +21,7 @@
 
 #include "../../inc/MarlinConfigPre.h"
 
-#if ENABLED(WIFISUPPORT)
+#if ENABLED(OTASUPPORT)
 
 #include <WiFi.h>
 #include <ESPmDNS.h>
@@ -30,15 +30,6 @@
 #include "driver/timer.h"
 
 void OTA_init() {
-  WiFi.mode(WIFI_STA);
-  WiFi.begin(WIFI_SSID, WIFI_PWD);
-
-  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
-    Serial.println("Connection Failed! Rebooting...");
-    delay(5000);
-    ESP.restart();
-  }
-
   ArduinoOTA
     .onStart([]() {
       timer_pause(TIMER_GROUP_0, TIMER_0);
@@ -76,6 +67,6 @@ void OTA_handle() {
   ArduinoOTA.handle();
 }
 
-#endif // WIFISUPPORT
+#endif // OTASUPPORT
 
 #endif // ARDUINO_ARCH_ESP32
diff --git a/Marlin/src/HAL/HAL_ESP32/web.cpp b/Marlin/src/HAL/HAL_ESP32/web.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a3a6cce729bc16658fa3a2fd29ff28c2a57fae59
--- /dev/null
+++ b/Marlin/src/HAL/HAL_ESP32/web.cpp
@@ -0,0 +1,49 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ * Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef ARDUINO_ARCH_ESP32
+
+#include "../../inc/MarlinConfigPre.h"
+
+#if ENABLED(WEBSUPPORT)
+
+#include "../../core/serial.h"
+
+#include "FS.h"
+#include "SPIFFS.h"
+#include "wifi.h"
+
+AsyncEventSource events("/events"); // event source (Server-Sent events)
+
+void onNotFound(AsyncWebServerRequest *request){
+  request->send(404);
+}
+
+void web_init() {
+  server.addHandler(&events);       // attach AsyncEventSource
+  if (SPIFFS.begin()) {
+    server.serveStatic("/", SPIFFS, "/www").setDefaultFile("index.html");
+    server.onNotFound(onNotFound);
+  }
+  else
+    SERIAL_ECHO_MSG("SPIFFS Mount Failed");
+}
+
+#endif // WEBSUPPORT
+#endif // ARDUINO_ARCH_ESP32
diff --git a/Marlin/src/HAL/HAL_ESP32/web.h b/Marlin/src/HAL/HAL_ESP32/web.h
new file mode 100644
index 0000000000000000000000000000000000000000..7f8796e7d494a914cccf4d3c3fad794d85116597
--- /dev/null
+++ b/Marlin/src/HAL/HAL_ESP32/web.h
@@ -0,0 +1,21 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ * Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+void web_init();
diff --git a/Marlin/src/HAL/HAL_ESP32/wifi.cpp b/Marlin/src/HAL/HAL_ESP32/wifi.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7afc7a87a85a0e89db2d06a8ae0a773306dfb4b7
--- /dev/null
+++ b/Marlin/src/HAL/HAL_ESP32/wifi.cpp
@@ -0,0 +1,55 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ * Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef ARDUINO_ARCH_ESP32
+
+#include "../../inc/MarlinConfigPre.h"
+
+#if ENABLED(WIFISUPPORT)
+
+#include <WiFi.h>
+#include <ESPmDNS.h>
+#include <ESPAsyncWebServer.h>
+#include "wifi.h"
+
+AsyncWebServer server(80);
+
+#ifndef WIFI_HOSTNAME
+  #define WIFI_HOSTNAME DEFAULT_WIFI_HOSTNAME
+#endif
+
+void wifi_init() {
+  WiFi.mode(WIFI_STA);
+  WiFi.begin(WIFI_SSID, WIFI_PWD);
+
+  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
+    delay(5000);
+    ESP.restart();
+  }
+
+  delay(10);
+
+  // Loop forever (watchdog kill) on failure
+  if (!MDNS.begin(WIFI_HOSTNAME)) for(;;) delay(5000);
+
+  MDNS.addService("http", "tcp", 80);
+}
+
+#endif // WIFISUPPORT
+#endif // ARDUINO_ARCH_ESP32
diff --git a/Marlin/src/HAL/HAL_ESP32/wifi.h b/Marlin/src/HAL/HAL_ESP32/wifi.h
new file mode 100644
index 0000000000000000000000000000000000000000..ef35cf14cab51af23c86b5c491e39898af124bad
--- /dev/null
+++ b/Marlin/src/HAL/HAL_ESP32/wifi.h
@@ -0,0 +1,27 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ * Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <ESPAsyncWebServer.h>
+
+extern AsyncWebServer server;
+
+#define DEFAULT_WIFI_HOSTNAME "marlin"
+
+void wifi_init();
diff --git a/Marlin/src/HAL/HAL_LINUX/hardware/LinearAxis.cpp b/Marlin/src/HAL/HAL_LINUX/hardware/LinearAxis.cpp
index 2682f8be0c544028119ba55aca4f754d2ab67f53..c50390d7369a786c44481e2c09af5d49ed685768 100644
--- a/Marlin/src/HAL/HAL_LINUX/hardware/LinearAxis.cpp
+++ b/Marlin/src/HAL/HAL_LINUX/hardware/LinearAxis.cpp
@@ -58,7 +58,7 @@ void LinearAxis::interrupt(GpioEvent ev) {
       position += -1 + 2 * Gpio::pin_map[dir_pin].value;
       Gpio::pin_map[min_pin].value = (position < min_position);
       //Gpio::pin_map[max_pin].value = (position > max_position);
-      //if(position < min_position) printf("axis(%d) endstop : pos: %d, mm: %f, min: %d\n", step_pin, position, position / 80.0, Gpio::pin_map[min_pin].value);
+      //if (position < min_position) printf("axis(%d) endstop : pos: %d, mm: %f, min: %d\n", step_pin, position, position / 80.0, Gpio::pin_map[min_pin].value);
     }
   }
 }
diff --git a/Marlin/src/core/serial.h b/Marlin/src/core/serial.h
index b9af72aea5e30ca9da5bc4c5e44455bd95a19d28..a0f3cb36a637c854a444e05b011d13dbc1e4cbba 100644
--- a/Marlin/src/core/serial.h
+++ b/Marlin/src/core/serial.h
@@ -49,13 +49,13 @@ extern uint8_t marlin_debug_flags;
   #define _PORT_REDIRECT(n,p)   REMEMBER(n,serial_port_index,p)
   #define _PORT_RESTORE(n)      RESTORE(n)
   #define SERIAL_OUT(WHAT, ...) do{ \
-    if (!serial_port_index || serial_port_index == SERIAL_BOTH) MYSERIAL0.WHAT(__VA_ARGS__); \
-    if ( serial_port_index) MYSERIAL1.WHAT(__VA_ARGS__); \
+    if (!serial_port_index || serial_port_index == SERIAL_BOTH) (void)MYSERIAL0.WHAT(__VA_ARGS__); \
+    if ( serial_port_index) (void)MYSERIAL1.WHAT(__VA_ARGS__); \
   }while(0)
 #else
   #define _PORT_REDIRECT(n,p)   NOOP
   #define _PORT_RESTORE(n)      NOOP
-  #define SERIAL_OUT(WHAT, ...) MYSERIAL0.WHAT(__VA_ARGS__)
+  #define SERIAL_OUT(WHAT, ...) (void)MYSERIAL0.WHAT(__VA_ARGS__)
 #endif
 
 #define PORT_REDIRECT(p)        _PORT_REDIRECT(1,p)
diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h
index d230c1972b8dc7b42a831539849bd3dd29b7424f..dce3bed907b596eaa5ea151a3b96da365278474e 100644
--- a/Marlin/src/inc/SanityCheck.h
+++ b/Marlin/src/inc/SanityCheck.h
@@ -393,7 +393,7 @@
   #elif RX_BUFFER_SIZE && (RX_BUFFER_SIZE < 2 || !IS_POWER_OF_2(RX_BUFFER_SIZE))
     #error "RX_BUFFER_SIZE must be a power of 2 greater than 1."
   #elif TX_BUFFER_SIZE && (TX_BUFFER_SIZE < 2 || TX_BUFFER_SIZE > 256 || !IS_POWER_OF_2(TX_BUFFER_SIZE))
-    #error "TX_BUFFER_SIZE must be 0, a power of 2 greater than 1, and no greater than 256."
+    #error "TX_BUFFER_SIZE must be 0 or a power of 2 between 1 and 256."
   #endif
 #elif ENABLED(SERIAL_XON_XOFF) || ENABLED(SERIAL_STATS_MAX_RX_QUEUED) || ENABLED(SERIAL_STATS_DROPPED_RX)
   #error "SERIAL_XON_XOFF and SERIAL_STATS_* features not supported on USB-native AVR devices."
diff --git a/buildroot/share/tests/esp32-tests b/buildroot/share/tests/esp32-tests
new file mode 100755
index 0000000000000000000000000000000000000000..30c1aa6e40eabffb05e9826144d0a6fbd2421654
--- /dev/null
+++ b/buildroot/share/tests/esp32-tests
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+#
+# Build tests for esp32
+#
+
+# exit on first failure
+set -e
+
+restore_configs
+opt_set MOTHERBOARD BOARD_ESP32
+opt_enable WIFISUPPORT
+opt_set "WIFI_SSID \"ssid\""
+opt_set "WIFI_PWD \"password\""
+opt_set TX_BUFFER_SIZE 64
+opt_add WEBSUPPORT
+exec_test $1 $2 "ESP32 with WIFISUPPORT and WEBSUPPORT"
+
+# cleanup
+restore_configs
diff --git a/config/default/Configuration_adv.h b/config/default/Configuration_adv.h
index 0f1b0218c968672fb0be68524ee82569a1a7e5aa..c74153409f124d5a014ff55efe10df91ae9ed8bc 100644
--- a/config/default/Configuration_adv.h
+++ b/config/default/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/3DFabXYZ/Migbot/Configuration_adv.h b/config/examples/3DFabXYZ/Migbot/Configuration_adv.h
index a8867960611eb6044487f2357eb8c3be50b1dce4..e2f36fedd4eee3dc06b5ef502b112ccc56d8f82a 100644
--- a/config/examples/3DFabXYZ/Migbot/Configuration_adv.h
+++ b/config/examples/3DFabXYZ/Migbot/Configuration_adv.h
@@ -2230,6 +2230,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/AlephObjects/TAZ4/Configuration_adv.h b/config/examples/AlephObjects/TAZ4/Configuration_adv.h
index 5f7ac359be1a568ca3d7be3e09b6cfb08951ae25..288e8e94d27eeb661459a7927a9ba3864f8003d6 100644
--- a/config/examples/AlephObjects/TAZ4/Configuration_adv.h
+++ b/config/examples/AlephObjects/TAZ4/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/AliExpress/UM2pExt/Configuration_adv.h b/config/examples/AliExpress/UM2pExt/Configuration_adv.h
index a44d0ecdb69ed43e32656b9e458a0382cdcc532b..37f4636df9e1f1b1fa531c03591711f187fb030a 100644
--- a/config/examples/AliExpress/UM2pExt/Configuration_adv.h
+++ b/config/examples/AliExpress/UM2pExt/Configuration_adv.h
@@ -2230,6 +2230,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Anet/A2/Configuration_adv.h b/config/examples/Anet/A2/Configuration_adv.h
index d7ba51bfb6475827fd4b22a7e1ec89f4057b3bc8..36000e7227a9e6067f3669bc2db542883c03701d 100644
--- a/config/examples/Anet/A2/Configuration_adv.h
+++ b/config/examples/Anet/A2/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Anet/A2plus/Configuration_adv.h b/config/examples/Anet/A2plus/Configuration_adv.h
index d7ba51bfb6475827fd4b22a7e1ec89f4057b3bc8..36000e7227a9e6067f3669bc2db542883c03701d 100644
--- a/config/examples/Anet/A2plus/Configuration_adv.h
+++ b/config/examples/Anet/A2plus/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Anet/A6/Configuration_adv.h b/config/examples/Anet/A6/Configuration_adv.h
index 0ec457419b7dc22a7a5e61f2e0742ae326751509..262462cfc1a7037fd0d0f741616b7a29e4555825 100644
--- a/config/examples/Anet/A6/Configuration_adv.h
+++ b/config/examples/Anet/A6/Configuration_adv.h
@@ -2227,6 +2227,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Anet/A8/Configuration_adv.h b/config/examples/Anet/A8/Configuration_adv.h
index 6621d78893a86d8835fdbf318c1559c5abf43feb..e94c3cd5fcb2a2aa6ff7178654751d3de6579f68 100644
--- a/config/examples/Anet/A8/Configuration_adv.h
+++ b/config/examples/Anet/A8/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/AnyCubic/i3/Configuration_adv.h b/config/examples/AnyCubic/i3/Configuration_adv.h
index d6b5d1df1e28b9db2647b317230238ed73b541b8..141c644333a8d77ff95b875bdf759c30f6813746 100644
--- a/config/examples/AnyCubic/i3/Configuration_adv.h
+++ b/config/examples/AnyCubic/i3/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/ArmEd/Configuration_adv.h b/config/examples/ArmEd/Configuration_adv.h
index fd646fdea51789645d168cc6d4c1bef7077ed0ec..0a65423e8412c6e0a69fe0b07803b52935b130f5 100644
--- a/config/examples/ArmEd/Configuration_adv.h
+++ b/config/examples/ArmEd/Configuration_adv.h
@@ -2232,6 +2232,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/BIBO/TouchX/cyclops/Configuration_adv.h b/config/examples/BIBO/TouchX/cyclops/Configuration_adv.h
index c77e300f14446325b9840a0743ad79d320c2e254..067c4bceb1d6de1b500abd3fc9d98d9a6fe8df7d 100644
--- a/config/examples/BIBO/TouchX/cyclops/Configuration_adv.h
+++ b/config/examples/BIBO/TouchX/cyclops/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/BIBO/TouchX/default/Configuration_adv.h b/config/examples/BIBO/TouchX/default/Configuration_adv.h
index a02c2d91c0324f990ed58017dc4350074280a9bb..97f618350276472c9472ba546c7969b85f293147 100644
--- a/config/examples/BIBO/TouchX/default/Configuration_adv.h
+++ b/config/examples/BIBO/TouchX/default/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/BQ/Hephestos/Configuration_adv.h b/config/examples/BQ/Hephestos/Configuration_adv.h
index 63a040b822dd5bd405873abf973a23614d29027d..f6f2f9c68f18da0c3bc3f62263d47a7988f5dd4f 100644
--- a/config/examples/BQ/Hephestos/Configuration_adv.h
+++ b/config/examples/BQ/Hephestos/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/BQ/Hephestos_2/Configuration_adv.h b/config/examples/BQ/Hephestos_2/Configuration_adv.h
index a13e5210fa75c800f645a69a374bf3620608b489..591035258803b759f33d17f77d04bb452bd30ef8 100644
--- a/config/examples/BQ/Hephestos_2/Configuration_adv.h
+++ b/config/examples/BQ/Hephestos_2/Configuration_adv.h
@@ -2236,6 +2236,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/BQ/WITBOX/Configuration_adv.h b/config/examples/BQ/WITBOX/Configuration_adv.h
index 63a040b822dd5bd405873abf973a23614d29027d..f6f2f9c68f18da0c3bc3f62263d47a7988f5dd4f 100644
--- a/config/examples/BQ/WITBOX/Configuration_adv.h
+++ b/config/examples/BQ/WITBOX/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Cartesio/Configuration_adv.h b/config/examples/Cartesio/Configuration_adv.h
index ef1ff1a40c05face63c1e5c395eade151fb46191..4fc220355c8e1d463da6a91edf69a049a112b60b 100644
--- a/config/examples/Cartesio/Configuration_adv.h
+++ b/config/examples/Cartesio/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Creality/CR-10/Configuration_adv.h b/config/examples/Creality/CR-10/Configuration_adv.h
index a190c0a81d9fbfe7ee2ce9cc540e7ec44299dfb8..411e02ed415e6ad7ddf78ed69952700759d09e52 100644
--- a/config/examples/Creality/CR-10/Configuration_adv.h
+++ b/config/examples/Creality/CR-10/Configuration_adv.h
@@ -2231,6 +2231,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Creality/CR-10S/Configuration_adv.h b/config/examples/Creality/CR-10S/Configuration_adv.h
index d2b068805b540538b65334350921d3638cdf8fb3..de59d8d3d348a9de0cec5f896524583e4b96736d 100644
--- a/config/examples/Creality/CR-10S/Configuration_adv.h
+++ b/config/examples/Creality/CR-10S/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Creality/CR-10_5S/Configuration_adv.h b/config/examples/Creality/CR-10_5S/Configuration_adv.h
index 25d2869cbc1db437baa0f1c57bba2b2cde688cd8..345b6ae04fba30ec01e44398a4540978eb6e6d88 100644
--- a/config/examples/Creality/CR-10_5S/Configuration_adv.h
+++ b/config/examples/Creality/CR-10_5S/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Creality/CR-10mini/Configuration_adv.h b/config/examples/Creality/CR-10mini/Configuration_adv.h
index a5c16e925bbfb9e4b1d2a919313f0ffa422d6691..ab9125e10d16ac34ea14a490b53bc6c66e8e4cd8 100644
--- a/config/examples/Creality/CR-10mini/Configuration_adv.h
+++ b/config/examples/Creality/CR-10mini/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Creality/CR-8/Configuration_adv.h b/config/examples/Creality/CR-8/Configuration_adv.h
index de7200f3a7ffae4d2707fceaa78098617ea88268..d41a87ff618980516b964baba430f97c646f5a6c 100644
--- a/config/examples/Creality/CR-8/Configuration_adv.h
+++ b/config/examples/Creality/CR-8/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Creality/Ender-2/Configuration_adv.h b/config/examples/Creality/Ender-2/Configuration_adv.h
index 8e8bbd8e077c68cc628949032eb12254229b519b..3141520b0d73e55ad92682dcbe3b9518f838149c 100644
--- a/config/examples/Creality/Ender-2/Configuration_adv.h
+++ b/config/examples/Creality/Ender-2/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Creality/Ender-3/Configuration_adv.h b/config/examples/Creality/Ender-3/Configuration_adv.h
index 41f1f44fd3a789f95d5afe84f135a3e1ddd06c7c..d819b8b57ea17b094407b8c2763736f74da5b90b 100644
--- a/config/examples/Creality/Ender-3/Configuration_adv.h
+++ b/config/examples/Creality/Ender-3/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Creality/Ender-4/Configuration_adv.h b/config/examples/Creality/Ender-4/Configuration_adv.h
index cca349c029f4186106fedd56d6aa524496de7710..6e257a71f254e1e6bd971ae9d5481715c2b97180 100644
--- a/config/examples/Creality/Ender-4/Configuration_adv.h
+++ b/config/examples/Creality/Ender-4/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Einstart-S/Configuration_adv.h b/config/examples/Einstart-S/Configuration_adv.h
index a633e75e6df473c06b69741291eeac26ad883ab5..9dd093d87ac35f95e5b11092205ae4ac0b0b7abb 100644
--- a/config/examples/Einstart-S/Configuration_adv.h
+++ b/config/examples/Einstart-S/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Felix/Configuration_adv.h b/config/examples/Felix/Configuration_adv.h
index 1e3ac38f5f92ff8e0919d3335f797d703d3389b1..a1cad99156446becc9f5712538c4025a860ebe2a 100644
--- a/config/examples/Felix/Configuration_adv.h
+++ b/config/examples/Felix/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/FlashForge/CreatorPro/Configuration_adv.h b/config/examples/FlashForge/CreatorPro/Configuration_adv.h
index 9297e692b8d6d72df87c9756ae69b06a450de8fc..bd7a02c398319fde323afde1ac90ab2609621c2e 100644
--- a/config/examples/FlashForge/CreatorPro/Configuration_adv.h
+++ b/config/examples/FlashForge/CreatorPro/Configuration_adv.h
@@ -2227,6 +2227,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/FolgerTech/i3-2020/Configuration_adv.h b/config/examples/FolgerTech/i3-2020/Configuration_adv.h
index 09a38fccc60829b68b2de181453776b6e738cd20..c5784ac4eff2090a107f7a2ad79ab6c3ba515a43 100644
--- a/config/examples/FolgerTech/i3-2020/Configuration_adv.h
+++ b/config/examples/FolgerTech/i3-2020/Configuration_adv.h
@@ -2236,6 +2236,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Formbot/Raptor/Configuration_adv.h b/config/examples/Formbot/Raptor/Configuration_adv.h
index 7be041e4029a9a40c25a480d7fa1ae7e92168deb..bca10833bd1846c28a3b55275e70203ec11058c4 100644
--- a/config/examples/Formbot/Raptor/Configuration_adv.h
+++ b/config/examples/Formbot/Raptor/Configuration_adv.h
@@ -2232,6 +2232,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Formbot/T_Rex_2+/Configuration_adv.h b/config/examples/Formbot/T_Rex_2+/Configuration_adv.h
index ecb295d107d95f2394975651f30a4d8e6a26ba05..ad77482931869d04e366398d709fdb8af44c5eee 100644
--- a/config/examples/Formbot/T_Rex_2+/Configuration_adv.h
+++ b/config/examples/Formbot/T_Rex_2+/Configuration_adv.h
@@ -2242,6 +2242,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Formbot/T_Rex_3/Configuration_adv.h b/config/examples/Formbot/T_Rex_3/Configuration_adv.h
index 21c509397ea907c8470df7a5efe9b265a201cfcc..42bacf17e8cd34e14136153c2f89d231e012a07a 100644
--- a/config/examples/Formbot/T_Rex_3/Configuration_adv.h
+++ b/config/examples/Formbot/T_Rex_3/Configuration_adv.h
@@ -2238,6 +2238,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Geeetech/A10M/Configuration_adv.h b/config/examples/Geeetech/A10M/Configuration_adv.h
index b05466d327374bb145ad3e70e0f6ebd83e3dd36d..8d2bc17db9d400765782cfced80dc7e17b92afb3 100644
--- a/config/examples/Geeetech/A10M/Configuration_adv.h
+++ b/config/examples/Geeetech/A10M/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Geeetech/A20M/Configuration_adv.h b/config/examples/Geeetech/A20M/Configuration_adv.h
index 162132edac11484097ea7b55ac36df346f7ff13a..e513edd0b0c8db6119741af86c26a8539b62e484 100644
--- a/config/examples/Geeetech/A20M/Configuration_adv.h
+++ b/config/examples/Geeetech/A20M/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Geeetech/MeCreator2/Configuration_adv.h b/config/examples/Geeetech/MeCreator2/Configuration_adv.h
index 8c971ed7977f5a07b0db24395a1d2609694598ed..e43430f3474b20c03aac1138fa731fa87cc2d617 100644
--- a/config/examples/Geeetech/MeCreator2/Configuration_adv.h
+++ b/config/examples/Geeetech/MeCreator2/Configuration_adv.h
@@ -2213,6 +2213,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Geeetech/Prusa i3 Pro C/Configuration_adv.h b/config/examples/Geeetech/Prusa i3 Pro C/Configuration_adv.h
index cbdea1140f1ef98eadaafb9f9c7f6e2faf615728..a637a609bbecc410b3137cbed07a1db95b5d0399 100644
--- a/config/examples/Geeetech/Prusa i3 Pro C/Configuration_adv.h	
+++ b/config/examples/Geeetech/Prusa i3 Pro C/Configuration_adv.h	
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Geeetech/Prusa i3 Pro W/Configuration_adv.h b/config/examples/Geeetech/Prusa i3 Pro W/Configuration_adv.h
index cbdea1140f1ef98eadaafb9f9c7f6e2faf615728..a637a609bbecc410b3137cbed07a1db95b5d0399 100644
--- a/config/examples/Geeetech/Prusa i3 Pro W/Configuration_adv.h	
+++ b/config/examples/Geeetech/Prusa i3 Pro W/Configuration_adv.h	
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Infitary/i3-M508/Configuration_adv.h b/config/examples/Infitary/i3-M508/Configuration_adv.h
index 98cc9977631f20b715af7925eb397c39d2147963..561f59b3c8bb9c33018b5331b444907b33a88855 100644
--- a/config/examples/Infitary/i3-M508/Configuration_adv.h
+++ b/config/examples/Infitary/i3-M508/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/JGAurora/A5/Configuration_adv.h b/config/examples/JGAurora/A5/Configuration_adv.h
index 47b89b5b90337205680662d1f77e0a0522723212..fbcb3906326be78d271342451f505ae1f4ac1760 100644
--- a/config/examples/JGAurora/A5/Configuration_adv.h
+++ b/config/examples/JGAurora/A5/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/MakerParts/Configuration_adv.h b/config/examples/MakerParts/Configuration_adv.h
index 0af872388cb292bdfa4a647ae201af695e72622e..1c7dcd945c42e7c2e6866c8739e5324c6b09e252 100644
--- a/config/examples/MakerParts/Configuration_adv.h
+++ b/config/examples/MakerParts/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Malyan/M150/Configuration_adv.h b/config/examples/Malyan/M150/Configuration_adv.h
index fb39d0decfd4b2ca342ef63fda318bf8055aedae..7d50523b9f33ebf709953687a2954bd19ed43ebd 100644
--- a/config/examples/Malyan/M150/Configuration_adv.h
+++ b/config/examples/Malyan/M150/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Malyan/M200/Configuration_adv.h b/config/examples/Malyan/M200/Configuration_adv.h
index f54d733baa9991b7bee4eef6cc0b32e1478a7fea..aaf83a2b97f5a502af4db90ea6fac55d5d12ec96 100644
--- a/config/examples/Malyan/M200/Configuration_adv.h
+++ b/config/examples/Malyan/M200/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Micromake/C1/enhanced/Configuration_adv.h b/config/examples/Micromake/C1/enhanced/Configuration_adv.h
index 0f1b0218c968672fb0be68524ee82569a1a7e5aa..c74153409f124d5a014ff55efe10df91ae9ed8bc 100644
--- a/config/examples/Micromake/C1/enhanced/Configuration_adv.h
+++ b/config/examples/Micromake/C1/enhanced/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Mks/Robin/Configuration_adv.h b/config/examples/Mks/Robin/Configuration_adv.h
index d7cfa249243d303adac17c8b21aea517066d8a31..781fae34d35e42e8debf571b5e3c3637b1e40bc8 100644
--- a/config/examples/Mks/Robin/Configuration_adv.h
+++ b/config/examples/Mks/Robin/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Mks/Sbase/Configuration_adv.h b/config/examples/Mks/Sbase/Configuration_adv.h
index 9d1c7dfb26480457bafc298b84a67983ae8a39aa..ba4c3686dee6553ebee1fe3b9e5ba12f8c72106b 100644
--- a/config/examples/Mks/Sbase/Configuration_adv.h
+++ b/config/examples/Mks/Sbase/Configuration_adv.h
@@ -2229,6 +2229,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/RapideLite/RL200/Configuration_adv.h b/config/examples/RapideLite/RL200/Configuration_adv.h
index 79d042a7869da254ede2b081c6c1cf9731be8358..2fa8de50b7cb6b2cc17e747f38f837bce780d57a 100644
--- a/config/examples/RapideLite/RL200/Configuration_adv.h
+++ b/config/examples/RapideLite/RL200/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/RigidBot/Configuration_adv.h b/config/examples/RigidBot/Configuration_adv.h
index 7ef8f8683cc938f7a2e823cd91d7dd3851dc53da..eef286c6ec68e7b4bef25eb40333ac070f502b20 100644
--- a/config/examples/RigidBot/Configuration_adv.h
+++ b/config/examples/RigidBot/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/SCARA/Configuration_adv.h b/config/examples/SCARA/Configuration_adv.h
index f92d49506d6c38ca0f24fc443baa59bc7b987b96..31776eb3a64b1c7d9efaf6a294e56b52924097e8 100644
--- a/config/examples/SCARA/Configuration_adv.h
+++ b/config/examples/SCARA/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Sanguinololu/Configuration_adv.h b/config/examples/Sanguinololu/Configuration_adv.h
index 914d04452561da7d174a64fe7bdc6ed3d0098d85..ba865f2f0daa15926d918d52d073f8e91cb1aea4 100644
--- a/config/examples/Sanguinololu/Configuration_adv.h
+++ b/config/examples/Sanguinololu/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/TheBorg/Configuration_adv.h b/config/examples/TheBorg/Configuration_adv.h
index 8cd64e3583b9066614b7771559cc8f1c2cd9825b..193ef628a6dd2997a2c9b87f1e637e33a314876f 100644
--- a/config/examples/TheBorg/Configuration_adv.h
+++ b/config/examples/TheBorg/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/TinyBoy2/Configuration_adv.h b/config/examples/TinyBoy2/Configuration_adv.h
index 34282804bfc56dfbe35d5e1859cad78e5b4d66d2..564dd6298ecb12ba2f54e238df2b5833862bf33b 100644
--- a/config/examples/TinyBoy2/Configuration_adv.h
+++ b/config/examples/TinyBoy2/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Tronxy/X3A/Configuration_adv.h b/config/examples/Tronxy/X3A/Configuration_adv.h
index 8b96625a7e02ba240871e9784815adcdec571893..7aaad25094d8208818b5675070d1a29c5d7b1a97 100644
--- a/config/examples/Tronxy/X3A/Configuration_adv.h
+++ b/config/examples/Tronxy/X3A/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Tronxy/X5S-2E/Configuration_adv.h b/config/examples/Tronxy/X5S-2E/Configuration_adv.h
index 149367edbd1827fcf4c418ffe8abaa4fe296cb40..19ecd1a76821e4e30f9aa12486fed52c67a71ee6 100644
--- a/config/examples/Tronxy/X5S-2E/Configuration_adv.h
+++ b/config/examples/Tronxy/X5S-2E/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/UltiMachine/Archim1/Configuration_adv.h b/config/examples/UltiMachine/Archim1/Configuration_adv.h
index b757c6a84398be8016c531c824640d5e326e40ed..4fd2b6a8eff0661e9195b6ada7fdd2645995a290 100644
--- a/config/examples/UltiMachine/Archim1/Configuration_adv.h
+++ b/config/examples/UltiMachine/Archim1/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/UltiMachine/Archim2/Configuration_adv.h b/config/examples/UltiMachine/Archim2/Configuration_adv.h
index 80dc0b7de374251189aae843acfc45dc3577a1ba..6bc4fb64f73b0c5cc6e8b6152b2850efa88320a8 100644
--- a/config/examples/UltiMachine/Archim2/Configuration_adv.h
+++ b/config/examples/UltiMachine/Archim2/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/VORONDesign/Configuration_adv.h b/config/examples/VORONDesign/Configuration_adv.h
index 26af56d027f14426d92483069c7c59b827ed8314..592c08f85ca6b1b5619cfcb97f0fe5bbc88b46e2 100644
--- a/config/examples/VORONDesign/Configuration_adv.h
+++ b/config/examples/VORONDesign/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Velleman/K8200/Configuration_adv.h b/config/examples/Velleman/K8200/Configuration_adv.h
index 130cdc4eaf381fc8c21b690204619397fa31bf1d..e8a01f98071d1f4d238472e0f17f4443b0c99374 100644
--- a/config/examples/Velleman/K8200/Configuration_adv.h
+++ b/config/examples/Velleman/K8200/Configuration_adv.h
@@ -2241,6 +2241,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Velleman/K8400/Configuration_adv.h b/config/examples/Velleman/K8400/Configuration_adv.h
index 4856d338607e7e129501619b130257fcffb579d3..51b6a84e251a3749c8d2460596ddf8e20d37ff92 100644
--- a/config/examples/Velleman/K8400/Configuration_adv.h
+++ b/config/examples/Velleman/K8400/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/WASP/PowerWASP/Configuration_adv.h b/config/examples/WASP/PowerWASP/Configuration_adv.h
index 2df053bf85483beff63a9c03f7eee647b16fda3c..aaf7785a4b72ed92722312b6daf69af50f1ffdf6 100644
--- a/config/examples/WASP/PowerWASP/Configuration_adv.h
+++ b/config/examples/WASP/PowerWASP/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/Wanhao/Duplicator 6/Configuration_adv.h b/config/examples/Wanhao/Duplicator 6/Configuration_adv.h
index 1bbef86e1af3dc41d90254186e5279f8d84fc55f..ec1bc5df1ae38cbd70b1863722f56f1f53968802 100644
--- a/config/examples/Wanhao/Duplicator 6/Configuration_adv.h	
+++ b/config/examples/Wanhao/Duplicator 6/Configuration_adv.h	
@@ -2230,6 +2230,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/delta/Anycubic/Kossel/Configuration_adv.h b/config/examples/delta/Anycubic/Kossel/Configuration_adv.h
index 984bcc303c62e2bd2132e66a6ad72811dab7568f..f2710f72999c0bd1e0fa6c522e58f144806a34f9 100644
--- a/config/examples/delta/Anycubic/Kossel/Configuration_adv.h
+++ b/config/examples/delta/Anycubic/Kossel/Configuration_adv.h
@@ -2230,6 +2230,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/delta/FLSUN/auto_calibrate/Configuration_adv.h b/config/examples/delta/FLSUN/auto_calibrate/Configuration_adv.h
index 1d46b4b2fa5be9a2b4d2fcee6e11456d80146ab3..e7edc63e6c0e8dcfdc1d21bc5add0d93e6304f6d 100644
--- a/config/examples/delta/FLSUN/auto_calibrate/Configuration_adv.h
+++ b/config/examples/delta/FLSUN/auto_calibrate/Configuration_adv.h
@@ -2230,6 +2230,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/delta/FLSUN/kossel/Configuration_adv.h b/config/examples/delta/FLSUN/kossel/Configuration_adv.h
index 1d46b4b2fa5be9a2b4d2fcee6e11456d80146ab3..e7edc63e6c0e8dcfdc1d21bc5add0d93e6304f6d 100644
--- a/config/examples/delta/FLSUN/kossel/Configuration_adv.h
+++ b/config/examples/delta/FLSUN/kossel/Configuration_adv.h
@@ -2230,6 +2230,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/delta/FLSUN/kossel_mini/Configuration_adv.h b/config/examples/delta/FLSUN/kossel_mini/Configuration_adv.h
index 11880ff13d7687b45a05162d05f469e53e84d750..53a5a22227b250a17ef8f67aad650db95fc75528 100644
--- a/config/examples/delta/FLSUN/kossel_mini/Configuration_adv.h
+++ b/config/examples/delta/FLSUN/kossel_mini/Configuration_adv.h
@@ -2230,6 +2230,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/delta/Geeetech/Rostock 301/Configuration_adv.h b/config/examples/delta/Geeetech/Rostock 301/Configuration_adv.h
index 11880ff13d7687b45a05162d05f469e53e84d750..53a5a22227b250a17ef8f67aad650db95fc75528 100644
--- a/config/examples/delta/Geeetech/Rostock 301/Configuration_adv.h	
+++ b/config/examples/delta/Geeetech/Rostock 301/Configuration_adv.h	
@@ -2230,6 +2230,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/delta/MKS/SBASE/Configuration_adv.h b/config/examples/delta/MKS/SBASE/Configuration_adv.h
index 631cc420754c3cd8e32ed251c8d379a0e7d2b9f8..97e1381b04f0081ccf0aa84c1fde3e079ddf7297 100644
--- a/config/examples/delta/MKS/SBASE/Configuration_adv.h
+++ b/config/examples/delta/MKS/SBASE/Configuration_adv.h
@@ -2230,6 +2230,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/delta/Tevo Little Monster/Configuration_adv.h b/config/examples/delta/Tevo Little Monster/Configuration_adv.h
index 3417cbdecd425fd67559968997786d41ca21426e..5ca37150818391c4b563bc7997acf91725cbf120 100644
--- a/config/examples/delta/Tevo Little Monster/Configuration_adv.h	
+++ b/config/examples/delta/Tevo Little Monster/Configuration_adv.h	
@@ -2218,6 +2218,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/delta/generic/Configuration_adv.h b/config/examples/delta/generic/Configuration_adv.h
index 11880ff13d7687b45a05162d05f469e53e84d750..53a5a22227b250a17ef8f67aad650db95fc75528 100644
--- a/config/examples/delta/generic/Configuration_adv.h
+++ b/config/examples/delta/generic/Configuration_adv.h
@@ -2230,6 +2230,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/delta/kossel_mini/Configuration_adv.h b/config/examples/delta/kossel_mini/Configuration_adv.h
index 45eac55ba586aaeab8b0f960288fd297e5f9b9b9..2f934cb44bb2e9281651421c65d3ce7449b69f11 100644
--- a/config/examples/delta/kossel_mini/Configuration_adv.h
+++ b/config/examples/delta/kossel_mini/Configuration_adv.h
@@ -2229,6 +2229,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/delta/kossel_xl/Configuration_adv.h b/config/examples/delta/kossel_xl/Configuration_adv.h
index 669a0641149fd119f54433c4ba7c3066c9ac99f6..b46014df90f6302b0c9fd5df907acd6ad413d167 100644
--- a/config/examples/delta/kossel_xl/Configuration_adv.h
+++ b/config/examples/delta/kossel_xl/Configuration_adv.h
@@ -2230,6 +2230,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/gCreate/gMax1.5+/Configuration_adv.h b/config/examples/gCreate/gMax1.5+/Configuration_adv.h
index 1fcbf1e44c52003dc9424ff34f5b18dcb840eb4c..344563f44899e9416b46104ceae40bbcbb782589 100644
--- a/config/examples/gCreate/gMax1.5+/Configuration_adv.h
+++ b/config/examples/gCreate/gMax1.5+/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/makibox/Configuration_adv.h b/config/examples/makibox/Configuration_adv.h
index e4ba06ed464207c09eca1975443497098e4f3167..b5d8b482717040634fe8cd05fa4b53086607ba49 100644
--- a/config/examples/makibox/Configuration_adv.h
+++ b/config/examples/makibox/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/tvrrug/Round2/Configuration_adv.h b/config/examples/tvrrug/Round2/Configuration_adv.h
index ca6df57f1f73c6a261b4049676e2d2f753e10e1e..18072ba322e007dbc3cdaf9b8eead66e0f514458 100644
--- a/config/examples/tvrrug/Round2/Configuration_adv.h
+++ b/config/examples/tvrrug/Round2/Configuration_adv.h
@@ -2228,6 +2228,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/config/examples/wt150/Configuration_adv.h b/config/examples/wt150/Configuration_adv.h
index 81c13772ac685f409b5be51ed64c804f6f4c39ff..faaee70bf20e015ce96973ae9e3672063c228b18 100644
--- a/config/examples/wt150/Configuration_adv.h
+++ b/config/examples/wt150/Configuration_adv.h
@@ -2229,6 +2229,8 @@
 #if ENABLED(WIFISUPPORT)
   #define WIFI_SSID "Wifi SSID"
   #define WIFI_PWD  "Wifi Password"
+  //#define WEBSUPPORT        // Start a webserver with auto-discovery
+  //#define OTASUPPORT        // Support over-the-air firmware updates
 #endif
 
 /**
diff --git a/data/www/index.html b/data/www/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..d3291de8def7337383a91da1a812649831794bb8
--- /dev/null
+++ b/data/www/index.html
@@ -0,0 +1,37 @@
+<!doctype html>
+<html lang=en>
+<head>
+  <meta charset=utf-8>
+  <title>Marlin</title>
+
+  <link rel="stylesheet" type="text/css" href="marlin.css" />
+
+  <script type="text/javascript" src="marlin.js"></script>
+</head>
+<body>
+  <div class="tabs">
+    <div id="logo"></div>
+    <input class="input" name="tabs" type="radio" id="tab-1" checked="checked"/>
+    <label class="label" for="tab-1">console</label>
+    <div class="panel">
+      <div class="panel-content">
+        <ul id="serial-output"></ul>
+
+        <form id="serial-command-form" autocomplete="off">
+          <div class="form-wrapper">
+            <input type="text" id="serial-command">
+            <input type="submit" value="Send">
+          </div>
+        </form>
+      </div>
+    </div>
+    <input class="input" name="tabs" type="radio" id="tab-2"/>
+    <label class="label" for="tab-2">controls</label>
+    <div class="panel">
+      <div class="panel-content">
+        #controls
+      </div>
+    </div>
+  </div>
+</body>
+</html>
diff --git a/data/www/marlin-logo.png b/data/www/marlin-logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..d0ce790141c7ff77bead81d5ba6777692102a242
Binary files /dev/null and b/data/www/marlin-logo.png differ
diff --git a/data/www/marlin.css b/data/www/marlin.css
new file mode 100644
index 0000000000000000000000000000000000000000..b29ec2e24c13bb7be84092d9df720ba251a6fc79
--- /dev/null
+++ b/data/www/marlin.css
@@ -0,0 +1,166 @@
+/* CSS reset */
+
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, embed,
+figure, figcaption, footer, header, hgroup,
+menu, nav, output, ruby, section, summary,
+time, mark, audio, video {
+  margin: 0;
+  padding: 0;
+  border: 0;
+  font-size: 100%;
+  font: inherit;
+  vertical-align: baseline;
+  font-family: Impact, Charcoal, sans-serif;
+  }
+article, aside, details, figcaption, figure,
+footer, header, hgroup, menu, nav, section {
+  display: block;
+  }
+body { line-height: 1; }
+ol, ul { list-style: none; }
+blockquote, q { quotes: none; }
+blockquote:before, blockquote:after,
+q:before, q:after { content: ''; content: none; }
+table {
+  border-collapse: collapse;
+  border-spacing: 0;
+  }
+
+/* Custom */
+
+/* Tabs */
+* { box-sizing: border-box; }
+body {
+  display: flex;
+  justify-content: center;
+  padding: 0px;
+  background: #1e1e1e;
+  color: #efefef;
+  }
+h1 {
+  margin: 0;
+  font-size: 2em;
+  }
+.tabs {
+  display: flex;
+  width: 100%;
+  flex-wrap: wrap;
+  background: #e5e5e5;
+  }
+.input {
+  position: absolute;
+  opacity: 0;
+  }
+.label {
+  width: 100%;
+  padding: 18px 28px;
+  background: #e5e5e5;
+  cursor: pointer;
+  font-weight: bold;
+  font-size: 18px;
+  color: #7f7f7f;
+  transition: background 0.1s, color 0.1s;
+  border-style: solid;
+  border-width: 0 0 4px 0;
+  border-color: #acacac;
+  }
+.label:hover {
+  background: #d8d8d8;
+  }
+.label:active {
+  background: #ccc;
+  }
+.input:focus + .label {
+  z-index: 1;
+  }
+.input:checked + .label {
+  background: #1e1e1e;
+  color: #efefef;
+  border-width: 4px 0 0 0;
+  border-color: #65a57d;
+  }
+.panel {
+  display: none;
+  width: 100%;
+  padding: 20px 30px 30px;
+  background: #1e1e1e;
+  color: #e5e5e5;
+  }
+.panel .panel-content {
+  width: 100%;
+  max-width: 800px;
+  }
+
+@media (min-width: 600px) {
+  .label { width: auto; }
+  .panel { order: 99; }
+}
+
+.input:checked + .label + .panel { display: block; }
+
+#logo {
+  width: 130px;
+  height: 58px;
+  margin-right: 20px;
+  background: url(marlin-logo.png) no-repeat center center;
+  }
+
+input[type="text"], textarea {
+  background-color: #2c2c2c;
+  border: solid 2px #314b3b;
+  color: #e5e5e5;
+  outline: none;
+  }
+
+input[type="text"]:focus, textarea:focus {
+  border-color: #4d7a5e;
+  }
+
+ul#serial-output {
+  width: 100%;
+  height: 300px;
+  overflow-y: scroll;
+  background-color: #2c2c2c;
+  border: solid 2px #314b3b;
+  }
+
+ul#serial-output li {
+  padding: 4px;
+  font-family: "Lucida Console", Monaco, monospace;
+  font-size: 0.8em;
+  }
+
+ul#serial-output li:nth-child(odd) {
+  background-color: #3c3c3c;
+  }
+
+div.form-wrapper {
+  display: flex;
+  width: 100%;
+  margin: 6px 0;
+  }
+
+div.form-wrapper input {
+  font-size: 1.2em;
+  padding: 4px 6px;
+  }
+
+div.form-wrapper input[type="text"] {
+  flex: 1 1 auto;
+  }
+
+div.form-wrapper input[type="submit"],
+div.form-wrapper button {
+  border: solid 2px #314b3b;
+  background-color: #4d7a5e;
+  color: #e5e5e5;
+  }
diff --git a/data/www/marlin.js b/data/www/marlin.js
new file mode 100644
index 0000000000000000000000000000000000000000..0a95045affaf7cb664efc5bd7f160ff686b9a427
--- /dev/null
+++ b/data/www/marlin.js
@@ -0,0 +1,24 @@
+document.addEventListener('DOMContentLoaded', () => {
+  const ws = new WebSocket(`ws://${location.host}/ws`);
+
+  ws.onmessage = (e) => {
+    if (typeof e.data === 'string') {
+      let node = document.createElement('li');
+      let text = document.createTextNode(e.data);
+      node.appendChild(text);
+      document.getElementById('serial-output').appendChild(node);
+    }
+  };
+
+  document.getElementById('serial-command-form').addEventListener('submit', (e) => {
+    e.preventDefault();
+
+    let value = document.getElementById('serial-command').value.trim();
+
+    if (!value) return;
+
+    ws.send(`${value}\n`);
+
+    document.getElementById('serial-command').value = '';
+  });
+});
diff --git a/platformio.ini b/platformio.ini
index 5a1372d030db234b4c613c387a03967b21b4d015..6ca0fe71250e97c2d0bb32db680c48eb39b9df60 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -286,7 +286,7 @@ src_filter    = ${common.default_src_filter} +<src/HAL/HAL_STM32F4>
 monitor_speed = 250000
 
 #
-# ARMED
+# ARMED (STM32)
 #
 [env:ARMED]
 platform    = ststm32
@@ -331,6 +331,9 @@ lib_ignore    = Adafruit NeoPixel
 src_filter    = ${common.default_src_filter} +<src/HAL/HAL_TEENSY35_36>
 monitor_speed = 250000
 
+#
+# Malyan M200 (STM32F1)
+#
 [env:malyanm200]
 platform    = ststm32
 framework   = arduino
@@ -355,11 +358,15 @@ lib_ignore  =
 # Espressif ESP32
 #
 [env:esp32]
-platform    = https://github.com/platformio/platform-espressif32.git#feature/stage
+platform    = https://github.com/platformio/platform-espressif32.git ; #feature/stage
 board       = esp32dev
 framework   = arduino
 upload_speed = 115200
 monitor_speed = 115200
+upload_port = /dev/ttyUSB0
+lib_deps =
+  https://github.com/me-no-dev/AsyncTCP.git
+  https://github.com/me-no-dev/ESPAsyncWebServer.git
 lib_ignore  =
   LiquidCrystal_I2C
   LiquidCrystal