Building a Dual-Mode Web Server with ESP32: AP and Station Simultaneously

Introduction
In today’s IoT landscape, flexibility is key. What if you could have your ESP32 connect to your home network while simultaneously creating its own access point? In this tutorial, we’ll build a sophisticated web server that does exactly that, complete with multiple pages, animations, and authentication.
What We’ll Create
Our ESP32 will:
- Connect to your existing WiFi network (Station mode)
- Create its own access point
- Serve a multi-page website with:
- A welcoming homepage with network information
- A live-updating clock
- A secure page with detailed network stats
- A goodbye page with animations
The Hardware
For this project, you’ll need:
- An ESP32 development board
- A micro USB cable
- A computer with Arduino IDE/VsCode installed
The Code Structure
Our code is organized into several key components:
- Network Configuration
// Station Mode Credentials
const char* sta_ssid = "YourWiFiName";
const char* sta_password = "YourWiFiPassword";
// AP Mode Credentials
const char* ap_ssid = "ESP32_AP";
const char* ap_password = "12345678";
- HTML Template System We use a function to generate consistent HTML across all pages:
String getPage(String content) {
String html = "<!DOCTYPE html><html><head>";
// ... styling and navigation ...
html += content;
html += "</div></body></html>";
return html;
}
- Page Handlers Each page has its own handler function:
void handleHome() {
String content = "<h1>Welcome to ESP32 Web Server</h1>";
// ... page content ...
server.send(200, "text/html", getPage(content));
}
Key Features
1. Dual-Mode Operation
void setup() {
WiFi.mode(WIFI_AP_STA); // Enable both AP and Station modes
WiFi.softAP(ap_ssid, ap_password); // Start the access point
WiFi.begin(sta_ssid, sta_password); // Connect to existing network
}
2. Authentication
bool is_authenticated() {
if (!server.authenticate("admin", "admin")) {
server.requestAuthentication();
return false;
}
return true;
}
3. Live Updates
We use JavaScript for real-time clock updates:
function updateClock() {
const now = new Date();
document.getElementById('clock').textContent = now.toLocaleTimeString();
}
setInterval(updateClock, 1000);
Implementation Details

Setting Up the Web Server
WebServer server(80);
void setup() {
// ... network setup ...
server.on("/", handleHome);
server.on("/timer", handleTimer);
server.on("/info", handleInfo);
server.on("/goodbye", handleGoodbye);
server.begin();
}

Main Loop
void loop() {
server.handleClient();
}
Accessing Your Web Server
Connect your device to either:
- Your home network (using the station mode IP)
- The ESP32’s access point (default IP: 192.168.4.1)
Open a web browser and enter the appropriate IP address
Navigate through the pages using the top navigation bar
Security Considerations
- The info page is protected with basic HTTP authentication
- Consider changing default credentials in production
- AP mode password should be at least 8 characters

Potential Enhancements
- Add HTTPS support for secure connections
- Implement a captive portal for the AP mode
- Add WebSocket support for real-time sensor data
- Create a configuration page to change network settings
Troubleshooting
Common issues and solutions:
- Can’t connect to WiFi: Double-check credentials
- Web server not responding: Verify IP addresses
- Authentication issues: Clear browser cache
Conclusion
This project demonstrates the versatility of the ESP32, showing how it can operate in both AP and station modes simultaneously while serving a feature-rich web interface. The possibilities for expanding this foundation are endless — from home automation to sensor monitoring and beyond.
Code Repository
The complete code for this project is available on GitHub: ESP32 Dual-Mode Web Server
Have you built something similar with ESP32? Share your experiences in the comments below!
#ESP32 #IoT #WebDevelopment #Arduino #Microcontrollers