Let's say you have a project for an ESP with a number of webpages, stylesheets and images.

Normaly you would do thinks like that:

const char settingspage[] PROGMEM = "This is my settingspage" ;
const char defaultpage[] PROGMEM = R"===(This is my defaultpage")==="; // This is the easier way to pass large strings to an array

 

 


In your setup - function you would do something like this :
setup():

server.on("/mypage.html", [] {server.send_P(200, "text/html",settingspage); });
server.on("/default.html", [] {server.send_P(200, "text/html",defaultpage); });

It's working fine. But when you project grow up, it could be get a little bit confusing.
Okay. You could put every "page" in a new include-file (.h), but you've to remember the variables you're using.

Now here comes a little preprocessor-magic to make the page-handling a little bit easier.
Create a new Include-File and call it pagehelper.h and paste this code in there:

pagehelper.h:

#define HTMLPAGE const char HtmlPage[] PROGMEM
#define IMAGE const char Image[] PROGMEM
#define CreatePageName String PageName() { return GetPageName(__PRETTY_FUNCTION__); }

// This function returns only the name of the namespace and replaces a few chars.
// Also, some chars will be replaced to get a "real" file name.
// E.g. the namespace "settings_html" will be changed to "/settings.html"
//
// If you want to use directories in your pages simply use the dollar-sign($)
// E.g. the namespace "css$styles_css" will be transformed to "/css/styles.css"
String GetPageName(String Pretty)
{
String PageName;
int StartIndex = Pretty.indexOf(' ');
int EndIndex = Pretty.indexOf(':');
PageName = (Pretty.substring(StartIndex+1, EndIndex));
PageName.replace("$", "/");
PageName.replace("_", ".");
PageName = "/" + PageName;
return PageName;
}

Now, let's say you would create two new webpages e.g. a startpage and a settingspage with an image and a stylesheet.

For the startpage create a header-file an call it index.html.h and call the namespace of this file index_html.

In that file you include the "pagehelper.h" (or include it globally in you INO-file) and insert the macro "CreatePageName" after you opened the namespace.
For better operability you can use the "HTMLPAGE" - macro which puts the contend in to a PROGMEM - Variable called "HtmlPage".

index.html.h.:

#pragma once
#include "pagehelper.h"    
namespace index_html
{
    CreatePageName; // Include this on every of your namespaced-webpages
HTMLPAGE = R"===(
            <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
            <html lang="en">
            <head>
                <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" name="viewport" />
                <meta name="viewport" content="width=device-width, initial-scale=1" />
                <link rel="stylesheet" type="text/css" href="/css/style.css"/>
            </head>
            <body>
                This is the startpage
                <br>
                <a href="/settings.html">Link to settingspage</a>
                <br>An image:
                <br><img src="/images/smiley.jpg">
            </body>
            </html>
    )===";
}



Create a new headerfile and call it like the filename you would normally use for a webpage, let's say settings.html.h.

settings.html.h:

#pragma once
#include "pagehelper.h"

namespace settings_html
{
CreatePageName; // Include this on every of your namespaced-webpages
HTMLPAGE = R"===(<!DOCTYPE HTML>
            <html lang="en">
            <head>
             <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" name="viewport" />
             <meta name="viewport" content="width=device-width, initial-scale=1" />
             <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
            </head>
            <body>
                This is the Settingspage
            </body>
            </html>)===";
} // End of Namespace

Now it's time for the stylesheet. If you want to use a kind of directory-style in your webpages you have to use the dollarsign to seperate the directories.
For Example, if you want your stylesheet file under "/css/style.css" your namespace should named "css$style_css".

style.css.h:

#pragma once
#include "pagehelper.h"    
namespace css$style_css
{
    CreatePageName; // Include this on every of your namespaced-webpages
HTMLPAGE = R"===(
                    body { background-color: lightblue ; }
    )===";
}

Last but not least a picture should not be missing. It's also in a subdirectory (images/). So the namespace is calles images$smiley_jpg and will be transformed bei "CreatePageName" to /images/smiley.jpg.


smiley.jpg.h:

#pragma once
#include "pagehelper.h"

namespace
images$smiley_jpg
{
CreatePageName; // Include this on every of your namespaced-webpages
IMAGE = { 0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x01, 0x00, 0x48, 0x00, 0x48, 0x00, 0x00, 0xFF, 0xDB, 0x00, 0x43, 0x00, 0x03, 0x02, 0x02, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x03, 0x03, 0x04, 0x05, 0x08, 0x05, 0x05, 0x04, 0x04, 0x05, 0x0A, 0x07, 0x07, 0x06, 0x08, 0x0C, 0x0A, 0x0C, 0x0C, 0x0B, 0x0A, 0x0B, 0x0B, 0x0D, 0x0E, 0x12, 0x10, 0x0D, 0x0E, 0x11, 0x0E, 0x0B, 0x0B, 0x10, 0x16, 0x10, 0x11, 0x13, 0x14, 0x15, 0x15, 0x15, 0x0C, 0x0F, 0x17, 0x18, 0x16, 0x14, 0x18, 0x12, 0x14, 0x15, 0x14, 0xFF, 0xDB, 0x00, 0x43, 0x01, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x09, 0x05, 0x05, 0x09, 0x14, 0x0D, 0x0B, 0x0D, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00, 0x10, 0x00, 0x10, 0x03, 0x01, 0x11, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xFF, 0xC4, 0x00, 0x16, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x02, 0xFF, 0xC4, 0x00, 0x22, 0x10, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x02, 0x04, 0x05, 0x11, 0x06, 0x12, 0x07, 0x13, 0x08, 0x23, 0x21, 0x22, 0x42, 0xFF, 0xC4, 0x00, 0x19, 0x01, 0x00, 0x02, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x01, 0x04, 0x05, 0x07, 0xFF, 0xC4, 0x00, 0x23, 0x11, 0x01, 0x00, 0x00, 0x06, 0x02, 0x01, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x11, 0x21, 0x31, 0x41, 0x00, 0x05, 0x03, 0x12, 0x13, 0x14, 0x51, 0x71, 0x22, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3F, 0x00, 0x63, 0xF2, 0x47, 0xCD, 0xEC, 0x3D, 0x0F, 0x21, 0x0C, 0x26, 0x7F, 0x88, 0x65, 0x73, 0x0E, 0xB7, 0x69, 0x48, 0xA3, 0x8B, 0x85, 0x95, 0xF5, 0x08, 0x6E, 0x8A, 0x59, 0xE8, 0x32, 0x10, 0x64, 0x99, 0x19, 0x46, 0x5D, 0xA5, 0x22, 0x3F, 0x6E, 0xA3, 0xA8, 0x07, 0x7C, 0xFA, 0x61, 0xF2, 0x76, 0x50, 0x7C, 0x96, 0x21, 0x81, 0xB8, 0x35, 0xF4, 0x90, 0xE9, 0xA6, 0x15, 0x2E, 0xAD, 0x69, 0x82, 0xD9, 0x60, 0x86, 0x92, 0xAF, 0xB5, 0x08, 0x89, 0x97, 0x6B, 0xBB, 0xE8, 0x35, 0x4F, 0xD7, 0x98, 0xE1, 0xDF, 0x37, 0xF1, 0x35, 0xBC, 0x9F, 0x47, 0x8E, 0x71, 0xFE, 0x1F, 0x94, 0xAC, 0xC2, 0xD7, 0x46, 0xFD, 0x0A, 0xD6, 0x16, 0x56, 0x84, 0xAB, 0x65, 0xC5, 0xA8, 0xED, 0xD1, 0x4C, 0x84, 0x61, 0x39, 0x6E, 0x12, 0xFE, 0x7A, 0x9E, 0xC0, 0x8D, 0x04, 0xB3, 0xE5, 0xEB, 0x20, 0x26, 0x7D, 0x70, 0x90, 0x17, 0x42, 0xB4, 0x61, 0xDD, 0xB0, 0x21, 0x71, 0x02, 0xB8, 0x6D, 0x89, 0x89, 0x26, 0x9F, 0x6A, 0x21, 0x62, 0x70, 0xDA, 0xB5, 0xD5, 0xF6, 0x7D, 0xD7, 0xF4, 0xE3, 0x57, 0x2E, 0xE3, 0xAE, 0xE1, 0x33, 0xAE, 0xB9, 0x2A, 0x95, 0x69, 0xE3, 0xFE, 0xBA, 0x59, 0x0B, 0xEB, 0xEA, 0x87, 0x55, 0x1B, 0x10, 0x5F, 0xBF, 0x5A, 0x54, 0xE2, 0x0C, 0x41, 0x12, 0xD6, 0xFA, 0x6C, 0x6C, 0x13, 0xA5, 0x0E, 0xEB, 0xAA, 0x98, 0x90, 0xF2, 0x24, 0x2D, 0x20, 0xD3, 0x81, 0x35, 0x76, 0xC4, 0x41, 0x64, 0x52, 0xB4, 0xA9, 0xCD, 0x29, 0x6F, 0x34, 0x13, 0x5F, 0xD6, 0x57, 0x26, 0xC7, 0x76, 0xCA, 0x2D, 0xED, 0xF7, 0x47, 0x97, 0x8C, 0xF1, 0xA1, 0xCE, 0x9A, 0xC8, 0xD6, 0xAD, 0x51, 0xAD, 0xBC, 0xBF, 0x4D, 0xFC, 0x85, 0x3F, 0xB1, 0x0B, 0x41, 0x20, 0x32, 0x21, 0xE2, 0x20, 0x32, 0x72, 0x8E, 0xE2, 0x22, 0x37, 0xAE, 0xDB, 0x3A, 0xD7, 0xE6, 0xB7, 0x49, 0xD3, 0x4C, 0xCF, 0xF9, 0xAB, 0x1B, 0x58, 0x3E, 0xF4, 0x0E, 0x6E, 0x59, 0x89, 0x2A, 0x00, 0xB4, 0xAD, 0x5E, 0x14, 0xCC, 0xC4, 0x12, 0xA5, 0x70, 0x98, 0x36, 0xBA, 0xB6, 0x40, 0x6F, 0x7F, 0xC3, 0x9F, 0xFF, 0xD9 };
}

 

 

Now it's time to glue everything together.
ESP_Web_Namespace_Example.ino:

 

#include <ESP8266WebServer.h>
#include "pagehelper.h"
#include "index.html.h"
#include "settings.html.h"
#include "style.css.h"
#include "smiley.jpg.h"
ESP8266WebServer server(80);

const char* ssid = "yourssid";
const char* password = "yourpassword";
void setup()
{  
    WiFi.begin(ssid, password);
    Serial.begin(115200);
    delay(100);
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    Serial.println("Connected to ");
    Serial.print(ssid);
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());


    // HTML - PAGES
    server.on("/", [] {server.send_P(200, "text/html", index_html::HtmlPage); });  // Startpage
    server.on(settings_html::PageName(), [] {server.send_P(200, "text/html", settings_html::HtmlPage); });  // Settings

    // CSS
    server.on(css$style_css::PageName(), [] {server.send_P(200, "text/html", css$style_css::HtmlPage); });

    // IMAGES
    server.on(images$smiley_jpg::PageName(), [] {server.sendContent_P(images$smiley_jpg::Image, sizeof(images$smiley_jpg::Image)); });


    server.begin();
}

void loop()
{
server.handleClient();
}