Improve caching support and some of the navigations in the hosting environment.

git-svn-id: https://svn.apache.org/repos/asf/tuscany/sca-cpp/trunk@1361914 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/.gitignore b/.gitignore
index af24aca..539b830 100644
--- a/.gitignore
+++ b/.gitignore
@@ -57,6 +57,7 @@
 config.sub
 config.status
 all.js
+cache-manifest.cmf
 *-min.html
 *-min.js
 *-min.css
diff --git a/hosting/server/htdocs/account/index.html b/hosting/server/htdocs/account/index.html
index dce34d2..a0c2e78 100644
--- a/hosting/server/htdocs/account/index.html
+++ b/hosting/server/htdocs/account/index.html
@@ -27,7 +27,7 @@
 <tr><td><img id="userimg" style="width: 50px; height: 50px; vertical-align: top;"></td></tr>
 <tr><tr><td style="padding-top: 6px;"><b>Name:</b></td></tr>
 <tr><td><input type="text" id="userTitle" class="flatentry" size="30" placeholder="Enter your name" style="width: 300px;"/></td></tr>
-<tr><tr><td style="padding-top: 6px;"><b>Description:</b></td></tr>
+<tr><tr><td style="padding-top: 6px;"><b>About Me:</b></td></tr>
 <tr><td><textarea id="userDescription" class="flatentry" cols="40" rows="3" placeholder="Enter a short description of yourself" style="width: 300px;"></textarea></td></tr>
 </table>
 
@@ -70,17 +70,24 @@
 </div>
 
 <script type="text/javascript">
+(function() {
 
-// Init service references
-var editWidget = sca.component("EditWidget");
-var user= sca.defun(sca.reference(editWidget, "user"));
-var accounts = sca.reference(editWidget, "accounts");
+/**
+ * Init service references.
+ */
+var editorComp = sca.component("Editor");
+var user= sca.defun(sca.reference(editorComp, "user"));
+var accounts = sca.reference(editorComp, "accounts");
 
-// Set page titles
-document.title = ui.windowtitle(location.hostname) + ' - Account';
-$('viewhead').innerHTML = '<span class="smenu">' + username + '</span>';
+/**
+ * Set page titles.
+ */
+document.title = config.windowtitle() + ' - Account';
+$('viewhead').innerHTML = '<span class="cmenu">' + username + '</span>';
 
-// Set images
+/**
+ * Set images.
+ */
 $('userimg').src = ui.b64img(appcache.get('/public/user.b64'));
 
 /**
@@ -95,18 +102,16 @@
 function getaccount() {
     showStatus('Loading');
 
-    return accounts.get(name, function(doc) {
+    return accounts.get('', function(doc) {
 
         // Stop now if we didn't get an account
         if (doc == null) {
-            showError('App not available');
+            showError('Account info not available');
             return false;
         }
-        showStatus(defaultStatus());
+        showOnlineStatus();
 
         accountentry = car(elementsToValues(atom.readATOMEntry(mklist(doc))));
-        //username = cadr(assoc("'id", cdr(accountentry)));
-        $('userNameHeader').innerHTML = username;
         $('userTitle').value = cadr(assoc("'title", cdr(accountentry)));
 
         var content = cadr(assoc("'content", cdr(accountentry)));
@@ -146,7 +151,7 @@
         return false;
     showStatus('Saving');
     savedaccountentryxml = entryxml;
-    accounts.put(username, savedaccountentryxml, function(e) {
+    accounts.put('', savedaccountentryxml, function(e) {
         if (e) {
             showStatus('Local copy');
             return false;
@@ -206,9 +211,12 @@
     return false;
 };
 
-// Get the user's account
+/**
+ * Get the user's account.
+ */
 getaccount();
 
+})();
 </script>
 
 </div>
diff --git a/hosting/server/htdocs/app/cache-manifest.cmf b/hosting/server/htdocs/app/cache-template.cmf
similarity index 92%
rename from hosting/server/htdocs/app/cache-manifest.cmf
rename to hosting/server/htdocs/app/cache-template.cmf
index 6ea5397..5881cf8 100644
--- a/hosting/server/htdocs/app/cache-manifest.cmf
+++ b/hosting/server/htdocs/app/cache-template.cmf
@@ -1,6 +1,6 @@
 CACHE MANIFEST
 
-# Version 5
+# Version SHA1
 
 # App resources
 /favicon.ico
diff --git a/hosting/server/htdocs/app/index.html b/hosting/server/htdocs/app/index.html
index 30bd1d9..cddf4fb 100644
--- a/hosting/server/htdocs/app/index.html
+++ b/hosting/server/htdocs/app/index.html
@@ -26,6 +26,7 @@
 <link rel="apple-touch-icon" href="/public/touchicon.png"/>
 <base href="/"/>
 <script type="text/javascript">
+(function() {
 
 window.appcache = {};
 
@@ -50,50 +51,60 @@
     http.send(null);
     if (http.status == 200) {
         if (http.getResponseHeader("X-Login") != null) {
-            if (debug) debug('http error', u, 'X-Login');
+            if (window.debug) debug('http error', u, 'X-Login');
             // Redirect to login page if not signed in
             document.location = '/login/';
             return null;
         } else if (http.responseText == '' || http.getResponseHeader("Content-Type") == null) {
-            if (debug) debug('http error', u, 'No-Content');
+            if (window.debug) debug('http error', u, 'No-Content');
             return null;
         }
         try { ls.setItem(u, http.responseText); } catch(e) {}
         return http.responseText;
     }
-    if (debug) debug('http error', u, http.status, http.statusText);
+    if (window.debug) debug('http error', u, http.status, http.statusText);
     // Redirect to login page if not signed in
     if (http.status == 403)
         document.location = '/login/';
     return null;
 };
 
-// Load Javascript and CSS
-(function() {
-    var bootjs = document.createElement('script');
-    bootjs.type = 'text/javascript';
-    bootjs.text = appcache.get('/all-min.js');
-    document.head.appendChild(bootjs);
-    document.head.appendChild(ui.declareCSS(appcache.get('/ui-min.css')));
 })();
 
-</script>
+/**
+ * Load Javascript and CSS.
+ */
+(function() {
 
-<script type="text/javascript">
+var bootjs = document.createElement('script');
+bootjs.type = 'text/javascript';
+bootjs.text = appcache.get('/all-min.js');
+document.head.appendChild(bootjs);
+document.head.appendChild(ui.declareCSS(appcache.get('/ui-min.css')));
 
-// Redirect to login page if not signed in
+})();
+
+/**
+ * Redirect to login page if not signed in.
+ */
+(function() {
+
 if (document.location.protocol == 'https:' && !hasauthcookie())
     document.location = '/login/';
 
+})();
+
 </script>
 </head>
-<body class="delayed" onload="onload();">
+<body class="delayed">
 <div id="mainbodydiv" class="mainbodydiv">
 
 <div id="headdiv" class="hsection">
 <script type="text/javascript">
 (function() {
+
 $('headdiv').appendChild(ui.declareScript(appcache.get('/config-min.js')));
+
 })();
 </script>
 </div>
@@ -102,13 +113,16 @@
 </div>
 
 <script type="text/javascript">
+(function() {
 
 /**
  * Get the app name
  */
 var appname = location.pathname.split('/')[1];
 
-// Set page title
+/**
+ * Set page title.
+ */
 document.title = appname;
 
 /**
@@ -125,9 +139,9 @@
 /**
  * Initialize the app HTTP clients.
  */
-var appWidget = sca.component('AppWidget');
-var pagecomp = sca.reference(appWidget, 'pages');
-var composcomp = sca.reference(appWidget, 'composites');
+var appComp = sca.component('App');
+var pagecomp = sca.reference(appComp, 'pages');
+var composcomp = sca.reference(appComp, 'composites');
 var startcomp = sca.httpclient('start', '/' + appname + '/start');
 var stopcomp = sca.httpclient('stop', '/' + appname + '/stop');
 var timercomp = sca.httpclient('timer', '/' + appname + '/timer');
@@ -964,7 +978,7 @@
 }
 
 /**
- * Document load post processing.
+ * Initialize the document.
  */
 function onload() {
     //debug('onload');
@@ -984,6 +998,9 @@
     return true;
 }
 
+onload();
+
+})();
 </script>
 
 <div id="footdiv" class="fsection">
diff --git a/hosting/server/htdocs/cache-manifest.cmf b/hosting/server/htdocs/cache-template.cmf
similarity index 92%
rename from hosting/server/htdocs/cache-manifest.cmf
rename to hosting/server/htdocs/cache-template.cmf
index e2c44de..8d9aa26 100644
--- a/hosting/server/htdocs/cache-manifest.cmf
+++ b/hosting/server/htdocs/cache-template.cmf
@@ -1,6 +1,6 @@
 CACHE MANIFEST
 
-# Version 6
+# Version SHA1
 
 # App resources
 /
diff --git a/hosting/server/htdocs/clone/index.html b/hosting/server/htdocs/clone/index.html
index f5557ef..0a2f773 100644
--- a/hosting/server/htdocs/clone/index.html
+++ b/hosting/server/htdocs/clone/index.html
@@ -41,22 +41,31 @@
 </div>
 
 <script type="text/javascript">
+(function() {
 
-// Get the app name
+/**
+ * Get the app name.
+ */
 var appname = ui.fragmentParams(location)['app'];
 
-// Set page titles
-document.title = ui.windowtitle(location.hostname) + ' - ' + config.clone + ' - ' + appname;
-$('viewhead').innerHTML = '<span class="smenu">' + config.clone + ' ' + appname + '</span>';
-$('cloneAppOKButton').value = config.clone;
-$('cloneAppOKButton').title = config.clone + ' this app';
+/**
+ * Set page titles.
+ */
+document.title = config.windowtitle() + ' - ' + config.clone() + ' - ' + appname;
+$('viewhead').innerHTML = '<span class="smenu">' + config.clone() + ' ' + appname + '</span>';
+$('cloneAppOKButton').value = config.clone();
+$('cloneAppOKButton').title = config.clone() + ' this app';
 
-// Set images
+/**
+ * Set images.
+ */
 $('appimg').src = ui.b64img(appcache.get('/public/app.b64'));
 
-// Init service references
-var editWidget = sca.component("EditWidget");
-var apps = sca.reference(editWidget, "apps");
+/**
+ * Init service references.
+ */
+var editorComp = sca.component("Editor");
+var apps = sca.reference(editorComp, "apps");
 
 /**
  * The current app entry and corresponding saved XML content.
@@ -79,7 +88,7 @@
             showError('App not available');
             return false;
         }
-        showStatus(defaultStatus());
+        showOnlineStatus();
 
         appentry = doc != null? car(elementsToValues(atom.readATOMEntry(mklist(doc)))) : mklist("'entry", mklist("'title", ''), mklist("'id", name));
         $('appTitle').value = cadr(assoc("'title", cdr(appentry)));
@@ -137,9 +146,12 @@
     history.back();
 };
 
-// Get the current app
+/**
+ * Get the current app.
+ */
 getapp(appname);
 
+})();
 </script>
 
 </div>
diff --git a/hosting/server/htdocs/config.js b/hosting/server/htdocs/config.js
index de1d141..70d3ea1 100644
--- a/hosting/server/htdocs/config.js
+++ b/hosting/server/htdocs/config.js
@@ -23,9 +23,31 @@
 /**
  * UI configuration.
  */
-config.windowtitle = 'App Builder'
-config.pagetitle = '<span style="font-weight: bold;">App Builder</span>';
-config.hometitle = '<br/><span style="font-weight: bold;">Create SCA Composite Apps</span><br/><br/>';
-config.clone = 'Clone';
-config.logic = 'Logic';
+config.windowtitle = function() {
+    return 'App Builder';
+};
+
+config.pagetitle = function() {
+    return '<span style="font-weight: bold;">App Builder</span>';
+};
+
+config.hometitle = function() {
+    return '<br/><span style="font-weight: bold;">Create SCA Composite Apps</span><br/><br/>';
+};
+
+config.clone = function() {
+    return 'Clone';
+};
+
+config.logic = function() {
+    return 'Logic';
+};
+
+config.viewfoot = function() {
+    return ui.menubar(mklist(ui.menu('menuabout', 'About', '/', '_view', 'note')), mklist());
+};
+
+config.appresources = function() {
+    return mklist();
+};
 
diff --git a/hosting/server/htdocs/create/index.html b/hosting/server/htdocs/create/index.html
index 8255876..d8d2b30 100644
--- a/hosting/server/htdocs/create/index.html
+++ b/hosting/server/htdocs/create/index.html
@@ -41,17 +41,24 @@
 </div>
 
 <script type="text/javascript">
+(function() {
 
-// Set page titles
-document.title = ui.windowtitle(location.hostname) + ' - Create App';
+/**
+ * Set page titles.
+ */
+document.title = config.windowtitle() + ' - Create App';
 $('viewhead').innerHTML = '<span class="smenu">Create an App</span>';
 
-// Set images
+/**
+ * Set images.
+ */
 $('appimg').src = ui.b64img(appcache.get('/public/app.b64'));
 
-// Init service references
-var editWidget = sca.component("EditWidget");
-var apps = sca.reference(editWidget, "apps");
+/**
+ * Init service references.
+ */
+var editorComp = sca.component("Editor");
+var apps = sca.reference(editorComp, "apps");
 
 /**
  * The current app entry and corresponding saved XML content.
@@ -105,8 +112,12 @@
     history.back();
 };
 
-showStatus(defaultStatus());
+/**
+ * Show the status.
+ */
+showOnlineStatus();
 
+})();
 </script>
 
 </div>
diff --git a/hosting/server/htdocs/delete/index.html b/hosting/server/htdocs/delete/index.html
index 75869a4..5a668af 100644
--- a/hosting/server/htdocs/delete/index.html
+++ b/hosting/server/htdocs/delete/index.html
@@ -43,20 +43,29 @@
 </div>
 
 <script type="text/javascript">
+(function() {
 
-// Get the app name
+/**
+ * Get the app name.
+ */
 var appname = ui.fragmentParams(location)['app'];
 
-// Set page titles
-document.title = ui.windowtitle(location.hostname) + ' - ' + 'Delete' + ' - ' + appname;
+/**
+ * Set page titles.
+ */
+document.title = config.windowtitle() + ' - ' + 'Delete' + ' - ' + appname;
 $('viewhead').innerHTML = '<span class="smenu">Delete ' + appname + '</span>';
 
-// Set images
+/**
+ * Set images.
+ */
 $('appimg').src = ui.b64img(appcache.get('/public/app.b64'));
 
-// Init service references
-var editWidget = sca.component("EditWidget");
-var apps = sca.reference(editWidget, "apps");
+/**
+ * Init service references.
+ */
+var editorComp = sca.component("Editor");
+var apps = sca.reference(editorComp, "apps");
 
 /**
  * The current app entry and corresponding saved XML content.
@@ -78,7 +87,7 @@
             showError('App not available');
             return false;
         }
-        showStatus(defaultStatus());
+        showOnlineStatus();
 
         appentry = doc != null? car(elementsToValues(atom.readATOMEntry(mklist(doc)))) : mklist("'entry", mklist("'title", ''), mklist("'id", name));
         $('appTitle').value = cadr(assoc("'title", cdr(appentry)));
@@ -103,7 +112,7 @@
             showStatus('Local copy');
             return false;
         }
-        showStatus(defaultStatus());
+        showOnlineStatus();
 
         // Return to the app store
         ui.navigate('/#view=store', '_view');
@@ -119,9 +128,12 @@
     history.back();
 };
 
-// Get the current app
+/**
+ * Get the current app.
+ */
 getapp(appname);
 
+})();
 </script>
 
 </div>
diff --git a/hosting/server/htdocs/graph/index.html b/hosting/server/htdocs/graph/index.html
index 6f73aec..d360336 100644
--- a/hosting/server/htdocs/graph/index.html
+++ b/hosting/server/htdocs/graph/index.html
@@ -25,8 +25,11 @@
 </div>
 
 <script type="text/javascript">
+(function() {
 
-// Get the app name
+/**
+ * Get the current app name.
+ */
 var appname = ui.fragmentParams(location)['app'];
 var ispalette = false;
 if (isNil(appname)) {
@@ -37,10 +40,14 @@
         ispalette = true;
 }
 
-// Set page title
-document.title = ui.windowtitle(location.hostname) + ' - ' + config.logic + ' - ' + appname;
+/**
+ * Set page title.
+ */
+document.title = config.windowtitle() + ' - ' + config.logic() + ' - ' + appname;
 
-// Set header div
+/**
+ * Set header div.
+ */
 $('viewhead').innerHTML = '<span id="appTitle" class="cmenu">' + appname + '</span>' +
 '<input type="button" id="deleteCompButton" title="Delete a component" class="graybutton redbutton plusminus" style="position: absolute; top: 4px; left: 5px;" disabled="true" value="-"/>' +
 '<span style="position: absolute; top: 0px; left: 45px; right: 115px; padding: 0px; background: transparent;"><input id="compValue" type="text" value="" class="flatentry" title="Component value" autocapitalize="off" placeholder="Value" style="position: absolute; left: 0px; top: 4px; width: 100%; visibility: hidden;" readonly="readonly"/></span>' +
@@ -66,13 +73,12 @@
 var ccopy = $('copyCompButton');
 var cplay = $('playCompButton');
 
-// Init componnent references
-var editWidget = sca.component("EditWidget");
-var palettes = sca.reference(editWidget, "palettes");
-var composites = sca.reference(editWidget, ispalette? "palettes" : "composites");
-
-// Setup remote log
-//rconsole = sca.defun(sca.reference(editWidget, "log"), "log");
+/**
+ * Init componnent references.
+ */
+var editorComp = sca.component("Editor");
+var palettes = sca.reference(editorComp, "palettes");
+var composites = sca.reference(editorComp, ispalette? "palettes" : "composites");
 
 /**
  * Composite rendering functions.
@@ -1843,7 +1849,7 @@
         author = elementValue(namedElementChild("'author", composentry));
         editable = author == username;
         cadd.disabled = !editable;
-        showStatus(editable? defaultStatus() : 'Read only');
+        showStatus(editable? onlineStatus() : 'Read only');
         return true;
     });
 }
@@ -2058,10 +2064,14 @@
     return showdata(gcomp);
 }
 
-// Create editor graph area
+/**
+ * Create editor graph area.
+ */
 graph.mkedit(graphdiv, graph.mkpath().move(-2500,0), atitle, cvalue, cadd, ccopy, cdelete, oncomposchange, oncompselect);
 
-// Install the palettes
+/**
+ * Install the palettes.
+ */
 var bg = graph.mkgroup(graph.mkpath());
 var pos = graph.mkpath().move(0, 0);
 bpalette = installpalette('control', pos.rmove(5,2), graphdiv, bg, spalette, gpalettes);
@@ -2079,9 +2089,12 @@
 installpalette('math', pos.rmove(0, 28), graphdiv, bg, spalette, gpalettes);
 installpalette('python', pos.rmove(0, 28), graphdiv, bg, spalette, gpalettes);
 
-// Get and display the current app
+/**
+ * Get and display the current app.
+ */
 getapp(appname, graphdiv);
 
+})();
 </script>
 
 </div>
diff --git a/hosting/server/htdocs/home/index.html b/hosting/server/htdocs/home/index.html
index 914eb1d..130c05f 100644
--- a/hosting/server/htdocs/home/index.html
+++ b/hosting/server/htdocs/home/index.html
@@ -37,17 +37,22 @@
 </div>
 
 <script type="text/javascript">
+(function() {
 
-// Set page titles
-document.title = ui.windowtitle(location.hostname);
-$('viewhead').innerHTML = '<span class="bcmenu">' + config.pagetitle + '</span>';
-$('hometitle').innerHTML = config.hometitle;
+/**
+ * Set page titles.
+ */
+document.title = config.windowtitle();
+$('viewhead').innerHTML = '<span class="bcmenu">' + config.pagetitle() + '</span>';
+$('hometitle').innerHTML = config.hometitle();
 
 $('getstarted').onclick = function() {
     return ui.navigate('/#view=store', '_view');
 };
 
-// Display animation
+/**
+ * Display animation.
+ */
 var anim = $('homeanimation');
 if (!isNil(anim)) {
     anim.style.background = 'url(\'' + ui.b64img(appcache.get('/home/home.b64')) + '\')';
@@ -60,8 +65,12 @@
     }, 2000);
 }
 
-showStatus(defaultStatus());
+/**
+ * Show the status.
+ */
+showOnlineStatus();
 
+})();
 </script>
 
 </div>
diff --git a/hosting/server/htdocs/index.html b/hosting/server/htdocs/index.html
index b461419..e3e0461 100644
--- a/hosting/server/htdocs/index.html
+++ b/hosting/server/htdocs/index.html
@@ -26,6 +26,7 @@
 <link rel="apple-touch-icon" href="/public/touchicon.png"/>
 <base href="/"/>
 <script type="text/javascript">
+(function() {
 
 window.appcache = {};
 
@@ -44,59 +45,77 @@
         return item;
 
     // Get resource from network
+    //if (window.debug) debug('appcache.get', u);
     var http = new XMLHttpRequest();
     http.open("GET", u, false);
     http.setRequestHeader("Accept", "*/*");
     http.send(null);
     if (http.status == 200) {
         if (http.getResponseHeader("X-Login") != null) {
-            if (debug) debug('http error', u, 'X-Login');
+            if (window.debug) debug('http error', u, 'X-Login');
             // Redirect to login page if not signed in
             document.location = '/login/';
             return null;
         } else if (http.responseText == '' || http.getResponseHeader("Content-Type") == null) {
-            if (debug) debug('http error', u, 'No-Content');
+            if (window.debug) debug('http error', u, 'No-Content');
             return null;
         }
         try { ls.setItem(u, http.responseText); } catch(e) {}
         return http.responseText;
     }
-    if (debug) debug('http error', u, http.status, http.statusText);
+    if (window.debug) debug('http error', u, http.status, http.statusText);
     // Redirect to login page if not signed in
     if (http.status == 403)
         document.location = '/login/';
     return null;
 };
 
-// Load Javascript and CSS
-(function() {
-    var bootjs = document.createElement('script');
-    bootjs.type = 'text/javascript';
-    bootjs.text = appcache.get('/all-min.js');
-    document.head.appendChild(bootjs);
-    document.head.appendChild(ui.declareCSS(appcache.get('/ui-min.css')));
-
-    // Disable cache for testing
-    lstorage.enabled = false;
+appcache.remove = function(uri) {
+    var h = uri.indexOf('#');
+    var u = h == -1? uri : uri.substring(0, h);
+    var ls = window.lstorage || localStorage;
+    try { ls.removeItem(u); } catch(e) {}
+    return true;
+};
 
 })();
 
-</script>
-<script type="text/javascript">
+/**
+ * Load Javascript and CSS.
+ */
+(function() {
 
-// Redirect to login page if not signed in
+var bootjs = document.createElement('script');
+bootjs.type = 'text/javascript';
+bootjs.text = appcache.get('/all-min.js');
+document.head.appendChild(bootjs);
+document.head.appendChild(ui.declareCSS(appcache.get('/ui-min.css')));
+
+// Disable cache for testing
+//lstorage.enabled = false;
+
+})();
+
+/**
+ * Redirect to login page if not signed in.
+ */
+(function() {
+
 if (document.location.protocol == 'https:' && !hasauthcookie())
     document.location = '/login/';
 
+})();
 </script>
 </head>
-<body class="delayed" onload="onload();">
+<body class="delayed">
 <div id="mainbodydiv" class="mainbody">
 
 <div id="headdiv" class="hsection">
 <script type="text/javascript">
 (function() {
+
 $('headdiv').appendChild(ui.declareScript(appcache.get('/config-min.js')));
+
 })();
 </script>
 </div>
@@ -109,28 +128,45 @@
 
 <div id="viewcontainer"></div>
 
+<div id="viewfootbackground" class="viewfootbackground fixed"></div>
+<div id="viewfoot" class="viewfoot fixed"></div>
+<div id="status" class="status fixed" style="visibility: hidden;"></div>
+
 <script type="text/javascript">
+(function() {
 
-// Init service references
-var editWidget = sca.component("EditWidget");
-var user= sca.defun(sca.reference(editWidget, "user"));
-var accounts = sca.reference(editWidget, "accounts");
+/**
+ * Init service references.
+ */
+var editorComp = sca.component("Editor");
+var user= sca.defun(sca.reference(editorComp, "user"));
+var accounts = sca.reference(editorComp, "accounts");
 
-// Set page title
-document.title = ui.windowtitle(location.hostname);
+/**
+ * Set page title.
+ */
+document.title = config.windowtitle();
 
-// Init div variables
+/**
+ * Init div variables.
+ */
 var bdiv = $('mainbodydiv');
 var mdiv = $('menu'); 
 var hdiv = $('viewhead'); 
 var vcontainer = $('viewcontainer');
 vcontainer.className = ui.isMobile()? 'viewcontainer3dm' : 'viewcontainer3d';
+var fdiv = $('viewfoot'); 
 
 /**
  * The current user name and account entry.
  */
-var username;
-var accountentry;
+window.username = 'anonymous';
+
+/**
+ * The current store category.
+ */
+var storecat = 'top';
+var storeidx = 0;
 
 /**
  * Pre-fetch app resources.
@@ -138,26 +174,66 @@
 var appresources = [
     ['/all-min.js'],
     ['/ui-min.css'],
-    ['/account/', '9'],
-    ['/clone/', '3'],
-    ['/create/', '2'],
-    ['/delete/', '3'],
-    ['/graph/', '5'],
+    ['/account/', 9],
+    ['/clone/', 3],
+    ['/create/', 2],
+    ['/delete/', 3],
+    ['/graph/', 5],
     ['/config-min.js'],
-    ['/home/', '0'],
+    ['/home/', 0],
     ['/home/home.b64'],
-    ['/page/', '4'],
+    ['/page/', 4],
     ['/public/app.b64'],
     ['/public/config-min.js'],
     ['/public/grid72.b64'],
     ['/public/iframe-min.html'],
     ['/public/img.b64'],
     ['/public/user.b64'],
-    ['/stats/', '2'],
-    ['/store/', '1']
+    ['/stats/', 2],
+    ['/store/', 1]
 ];
 
 /**
+ * Show a status message.
+ */
+window.showStatus = function(s, c) {
+    //debug('status', s);
+    var sdiv = $('status');
+    if (isNil(sdiv))
+        return s;
+    sdiv.innerHTML = '<span class="' + (c? c : 'okstatus') + '">' + s + '</span>';
+    sdiv.className = 'status fixed';
+    sdiv.style.visibility = 'visible';
+    
+    function divtransitionend(e) {
+        e.target.style.visibility = 'hidden';
+        e.target.className = 'status fixed';
+    }
+    if (!sdiv.addedTransitionEnd) {
+        sdiv.addEventListener('webkitTransitionEnd', divtransitionend, false);
+        sdiv.addEventListener('transitionend', divtransitionend, false);
+        sdiv.addedTransitionEnd = true;
+    }
+    sdiv.className = 'statusout3 fixed';
+    return s;
+}
+
+/**
+ * Show an error message.
+ */
+window.showError = function(s) {
+    //debug('error', s);
+    return showStatus(s, 'errorstatus');
+}
+
+/**
+ * Show the online/offline status.
+ */
+window.showOnlineStatus = function() {
+    return navigator.onLine? showStatus('Online') : showError('Offline');
+}
+
+/**
  * Handle application cache events.
  */
 applicationCache.addEventListener('checking', function(e) {
@@ -166,11 +242,11 @@
 }, false);
 applicationCache.addEventListener('error', function(e) {
     //debug('appcache error', e);
-    showStatus(defaultStatus());
+    showOnlineStatus();
 }, false);
 applicationCache.addEventListener('noupdate', function(e) {
     //debug('appcache noupdate', e);
-    showStatus(defaultStatus());
+    showOnlineStatus();
 }, false);
 applicationCache.addEventListener('downloading', function(e) {
     //debug('appcache downloading', e);
@@ -185,16 +261,27 @@
     try {
         applicationCache.swapCache();
     } catch(e) {}
-    showStatus(defaultStatus());
+    showOnlineStatus();
     //debug('appcache swapped', e);
+
+    // Update offline resources in local storage and reload the page
+    map(function(res) {
+        showStatus('Updating');
+        appcache.remove(res[0]);
+        appcache.get(res[0]);
+    }, append(appresources, config.appresources()));
+    window.location.reload();
 }, false);
 applicationCache.addEventListener('cached', function(e) {
     //debug('appcache cached', e);
+    showOnlineStatus();
+
+    // Install offline resources in local storage
     map(function(res) {
-        showStatus('Updating');
+        showStatus('Installing');
+        appcache.remove(res[0]);
         appcache.get(res[0]);
-    }, appresources);
-    showStatus(defaultStatus());
+    }, append(appresources, config.appresources()));
 }, false);
 
 /**
@@ -214,11 +301,9 @@
 /**
  * Handle view transitions.
  */
-
-// Keep track of the current view url and uri
 var viewurl = '';
 var viewuri = '';
-var viewidx = '';
+var viewidx = 0;
 var viewdiv;
 
 /**
@@ -228,7 +313,7 @@
 map(function(res) {
     if (res.length > 1)
         apptransitions[res[0]] = res[1];
-}, appresources);
+}, append(appresources, config.appresources()));
 
 /**
  * Return the transition that should be applied to a resource.
@@ -266,7 +351,9 @@
  * Return the last visited location.
  */
 function lastvisited() {
-    return lstorage.getItem('ui.lastvisited');
+    if (username != lstorage.getItem('ui.lastvisit.user'))
+        return null;
+    return lstorage.getItem('ui.lastvisit.url');
 }
 
 /**
@@ -274,49 +361,22 @@
  */
 function showmenu(mdiv, view, appname) {
     mdiv.innerHTML = ui.menubar(
-        append(mklist(ui.menu('Home', '/', '_view', view == 'home'), ui.menu('Store', '/#view=store', '_view', view === 'store')),
+        append(mklist(ui.menu('menuhome', 'Home', '/', '_view', view == 'home'),
+                    ui.menu('menustore', 'Store', '/#view=store&category=' + storecat + '&idx=' + storeidx, '_view', view === 'store')),
                 (isNil(appname) || appname == 'undefined')?
                     mklist() :
                     mklist(
-                        ui.menu('Stats', '/#view=stats&app=' + appname, '_view', view == 'stats'),
-                        ui.menu('Page', '/#view=page&app=' + appname, '_view', view == 'page'),
-                        ui.menu(config.logic, '/#view=graph&app=' + appname, '_view', view == 'graph'),
-                        ui.menu('<span class="greentext" style="font-weight: bold">Run!</span>', '/' + appname + '/', '_blank', false))),
+                        ui.menu('menustats', 'Stats', '/#view=stats&app=' + appname, '_view', view == 'stats'),
+                        ui.menu('menupage', 'Page', '/#view=page&app=' + appname, '_view', view == 'page'),
+                        ui.menu('menulogic', config.logic(), '/#view=graph&app=' + appname, '_view', view == 'graph'),
+                        ui.menu('menurun', '<span class="greentext" style="font-weight: bold">Run!</span>', '/' + appname + '/', '_blank', false))),
         (isNil(appname) || appname == 'undefined')? mklist(
-            hasauthcookie()? ui.menufunc('Sign out', 'logout();', false) : ui.menu('Sign in', '/login/', '_self', false),
-            ui.menu('Account', '/#view=account', '_view', view == 'account')) :
+            hasauthcookie()? ui.menufunc('menusignout', 'Sign out', 'return logout();', false) : ui.menu('menusignin', 'Sign in', '/login/', '_self', false),
+            ui.menu('menuaccount', 'Account', '/#view=account', '_view', view == 'account')) :
             mklist());
-}
 
-/**
- * Show a status message.
- */
-function showStatus(s) {
-    var sdiv = $('status');
-    if (isNil(sdiv))
-        return s;
-    sdiv.style.color = '#808080'
-    sdiv.innerHTML = s;
-    return s;
-}
-
-/**
- * Show an error message.
- */
-function showError(s) {
-    var sdiv = $('status');
-    if (isNil(sdiv))
-        return s;
-    sdiv.style.color = '#dd4b39'
-    sdiv.innerHTML = s;
-    return s;
-}
-
-/**
- * Return the default status message.
- */
-function defaultStatus() {
-    return navigator.onLine? 'Online' : 'Offline';
+    if (fdiv.innerHTML == '') 
+        fdiv.innerHTML = config.viewfoot();
 }
 
 /**
@@ -326,12 +386,10 @@
     var doc = accounts.get();
 
     // Stop now if we didn't get an account
-    if (doc == null) {
-        username = 'anonymous';
+    if (doc == null)
         return false;
-    }
 
-    accountentry = car(elementsToValues(atom.readATOMEntry(mklist(doc))));
+    var accountentry = car(elementsToValues(atom.readATOMEntry(mklist(doc))));
     username = cadr(assoc("'id", cdr(accountentry)));
     return true;
 }
@@ -343,13 +401,20 @@
     //debug('showview', url);
 
     // Save last visited location
-    lstorage.setItem('ui.lastvisited', url);
+    lstorage.setItem('ui.lastvisit.user', username);
+    lstorage.setItem('ui.lastvisit.url', url);
 
     // Determine the view to show
     var params = ui.fragmentParams(url);
     var view = isNil(params['view'])? 'home' : params['view'];;
     var uri = '/' + view + '/';
-    var idx = isNil(params['idx'])? '1' : params['idx'];
+    var idx = isNil(params['idx'])? 0 : parseInt(params['idx']);
+
+    // Track store category view
+    if (view == 'store') {
+        storecat = isNil(params['category'])? 'top' : params['category'];
+        storeidx = idx;
+    }
 
     // Determine the transition to use
     var vtransition = uri == viewuri? (idx >= viewidx? 'left' : 'right') : viewtransition(viewuri, uri);
@@ -424,7 +489,7 @@
 
     // Track the current visible view
     viewdiv = vdiv;
-
+    
     return true;
 }
 
@@ -455,6 +520,7 @@
 window.onnavigate = function(url) {
     //debug('onnavigate', url);
 
+    // Update the browser window location
     updatelocation(url);
 
     // Show the specified view
@@ -473,13 +539,13 @@
 /**
  * Log the current user out.
  */
-function logout() {
+window.logout = function() {
     // Clear session cookie and user-specific local storage entries
     clearauthcookie();
-    lstorage.removeItem('/r/EditWidget/accounts');
-    lstorage.removeItem('/r/EditWidget/dashboards');
+    lstorage.removeItem('/r/Editor/accounts');
+    lstorage.removeItem('/r/Editor/dashboards');
     document.location = '/login/';
-    return true;
+    return false;
 }
 
 /**
@@ -523,7 +589,7 @@
 };
 
 /**
- * Document load post processing.
+ * Initialize the document.
  */
 function onload() {
     //debug('onload', history.length);
@@ -542,8 +608,10 @@
     }
 
     // Show the last visited view
-    if (ui.isMobile() && (document.referrer == null || document.referrer == '')) {
-        //debug('show lastvisited');
+    if (ui.isMobile() && (document.referrer == null || document.referrer == '' ||
+        document.referrer.indexOf('//' + location.hostname + '/login/') != -1 ||
+        document.referrer.indexOf('//accounts.google.com/ServiceLogin') != -1 ||
+        document.referrer.indexOf('//www.facebook.com/login.php') != -1)) {
         var lv = lastvisited();
         var url = isNil(lv)? location.pathname : lv;
         updatelocation(url);
@@ -559,6 +627,9 @@
     return showview(url);
 }
 
+onload();
+
+})();
 </script>
 
 <div id="footdiv" class="fsection">
diff --git a/hosting/server/htdocs/login/index.html b/hosting/server/htdocs/login/index.html
index f9fa9f6..bf09339 100644
--- a/hosting/server/htdocs/login/index.html
+++ b/hosting/server/htdocs/login/index.html
@@ -25,6 +25,7 @@
 <meta name="apple-mobile-web-app-status-bar-style" content="black"/>
 <base href="/login/"/>
 <script type="text/javascript">
+(function() {
 
 window.appcache = {};
 
@@ -49,37 +50,45 @@
     http.send(null);
     if (http.status == 200) {
         if (http.getResponseHeader("X-Login") != null) {
-            if (debug) debug('http error', u, 'X-Login');
+            if (window.debug) debug('http error', u, 'X-Login');
             return null;
         } else if (http.responseText == '' || http.getResponseHeader("Content-Type") == null) {
-            if (debug) debug('http error', u, 'No-Content');
+            if (window.debug) debug('http error', u, 'No-Content');
             return null;
         }
         try { ls.setItem(u, http.responseText); } catch(e) {}
         return http.responseText;
     }
-    if (debug) debug('http error', u, http.status, http.statusText);
+    if (window.debug) debug('http error', u, http.status, http.statusText);
     return null;
 };
 
-// Load Javascript and CSS
+})();
+
+/**
+ * Load Javascript and CSS.
+ */
 (function() {
-    var bootjs = document.createElement('script');
-    bootjs.type = 'text/javascript';
-    bootjs.text = appcache.get('/all-min.js');
-    document.head.appendChild(bootjs);
-    document.head.appendChild(ui.declareCSS(appcache.get('/ui-min.css')));
+
+var bootjs = document.createElement('script');
+bootjs.type = 'text/javascript';
+bootjs.text = appcache.get('/all-min.js');
+document.head.appendChild(bootjs);
+document.head.appendChild(ui.declareCSS(appcache.get('/ui-min.css')));
+
 })();
 
 </script>
 </head>
-<body class="delayed" onload="onload();">
+<body class="delayed"">
 <div id="mainbodydiv" class="bodydiv">
 
 <div id="headdiv" class="hsection">
 <script type="text/javascript">
 (function() {
+
 $('headdiv').appendChild(ui.declareScript(appcache.get('/public/config-min.js')));
+
 })();
 </script>
 </div>
@@ -96,22 +105,31 @@
 <div id="view">
 <div id="viewcontent" class="viewcontent" style="margin-left: auto; margin-right: auto; text-align: center;">
 
-<form name="facebookOAuth2Form" style="width: 100%;">
-<p style="font-size: 16px;">Sign in with your <span style="font-weight: bold;">Facebook</span> account</p>
-<p><input type="button" value="Sign in" class="graybutton bluebutton" style="font-size: 16px; line-height: 16px; padding: 6px; height: 32px" onclick="submitOAuth2Signin(withFacebook)"/></p>
+<br/>
+<form id="formSignin" name="formSignin" method="POST" action="/login/dologin" style="width: 100%;">
+<table style="width: 100%;">
+<tr><td><span id="loginprompt" style="font-size: 16px;"></span></tr></td>
+<tr><td><input type="text" class="flatentry" name="httpd_username" value="" placeholder="User id"/></td></tr>
+<tr><td><input type="password" class="flatentry" name="httpd_password" value="" placeholder="Password"/></td></tr>
+<tr><td><input type="submit" class="graybutton bluebutton" style="font-size: 16px; line-height: 16px; padding: 6px; height: 32px" value="Sign in"/></td></tr>
+</table>
+<input type="hidden" name="httpd_location" value="/"/>
 </form>
+<br/>
+
+<form name="facebookOAuth2Form" style="width: 100%;">
+<table style="width: 100%;">
+<tr><td><span style="font-size: 16px;">Sign in with your <span style="font-weight: bold;">Facebook</span> account</span></td></tr>
+<tr><td><input type="button" id="facebookOAuth2Signin" value="Sign in" class="graybutton bluebutton" style="font-size: 16px; line-height: 16px; padding: 6px; height: 32px"/></td></tr>
+</table>
+</form>
+<br/>
 
 <form name="googleOAuth2Form" style="width: 100%;">
-<p style="font-size: 16px;">Sign in with your <span style="font-weight: bold;" >Google</span> account</p>
-<p><input type="button" value="Sign in" class="graybutton bluebutton" style="font-size: 16px; line-height: 16px; padding: 6px; height: 32px" onclick="submitOAuth2Signin(withGoogleOAuth)"/></p>
-</form>
-
-<form name="formSignin" method="POST" action="/login/dologin" onsubmit="submitFormSignin()" style="width: 100%;">
-<p id="loginprompt" style="font-size: 16px;"></p>
-<p><input type="text" class="flatentry" name="httpd_username" value="" placeholder="User id"/></p>
-<p><input type="password" class="flatentry" name="httpd_password" value="" placeholder="Password"/></p>
-<p><input type="submit" class="graybutton bluebutton" style="font-size: 16px; line-height: 16px; padding: 6px; height: 32px" value="Sign in"/></p>
-<input type="hidden" name="httpd_location" value="/"/>
+<table style="width: 100%;">
+<tr><td><span style="font-size: 16px;">Sign in with your <span style="font-weight: bold;" >Google</span> account</span></td></tr>
+<tr><td><input type="button" id="googleOAuth2Signin" value="Sign in" class="graybutton bluebutton" style="font-size: 16px; line-height: 16px; padding: 6px; height: 32px"/></td></tr>
+</table>
 </form>
 <br/>
 
@@ -129,31 +147,75 @@
 </div>
 </div>
 
-<script type="text/javascript">
+<div id="viewfootbackground" class="viewfootbackground fixed"></div>
+<div id="viewfoot" class="viewfoot fixed"></div>
+<div id="status" class="status fixed" style="visibility: hidden;"></div>
 
-// Init div variables
+<script type="text/javascript">
+(function() {
+
+/**
+ * Init div variables.
+ */
 var mbdiv = $('menubackground'); 
 var mdiv = $('menu'); 
 var hdiv = $('viewhead'); 
 var hbdiv = $('viewheadbackground'); 
 $('viewcontainer').className = ui.isMobile()? 'viewcontainer3d' : 'viewcontainer3dm';
 $('view').className = ui.isMobile()? 'viewloaded3d' : 'viewloaded3dm';
-$('loginprompt').innerHTML = config.loginprompt;
+$('loginprompt').innerHTML = config.loginprompt();
+var fdiv = $('viewfoot'); 
 
-// Set page titles
-document.title = ui.windowtitle(location.hostname) + ' - Sign in';
-$('viewhead').innerHTML = '<span class="bcmenu">' + config.pagetitle + '</span>';
+/**
+ * Set page titles.
+ */
+document.title = config.windowtitle() + ' - Sign in';
+$('viewhead').innerHTML = '<span class="bcmenu">' + config.pagetitle() + '</span>';
 
 /**
  * Build and show the menu bar.
  */
 function showmenu(mdiv) {
-    mdiv.innerHTML = ui.menubar(mklist(ui.menu('Home', '/', '_self', false)), mklist(ui.menu('Sign in', '/login/', '_self', true)));
+    mdiv.innerHTML = ui.menubar(mklist(ui.menu('menuhome', 'Home', '/', '_self', false)), mklist());
+    fdiv.innerHTML = config.viewfoot();
 }
 
 showmenu(mdiv);
 
 /**
+ * Show a status message.
+ */
+window.showStatus = function(s, c) {
+    //debug('status', s);
+    var sdiv = $('status');
+    if (isNil(sdiv))
+        return s;
+    sdiv.innerHTML = '<span class="' + (c? c : 'okstatus') + '">' + s + '</span>';
+    sdiv.className = 'status fixed';
+    sdiv.style.visibility = 'visible';
+    
+    function divtransitionend(e) {
+        e.target.style.visibility = 'hidden';
+        e.target.className = 'status fixed';
+    }
+    if (!sdiv.addedTransitionEnd) {
+        sdiv.addEventListener('webkitTransitionEnd', divtransitionend, false);
+        sdiv.addEventListener('transitionend', divtransitionend, false);
+        sdiv.addedTransitionEnd = true;
+    }
+    sdiv.className = 'statusout3 fixed';
+    return s;
+}
+
+/**
+ * Show an error message.
+ */
+window.showError = function(s) {
+    //debug('error', s);
+    return showStatus(s, 'errorstatus');
+}
+
+/**
  * Parse the query parameeters.
  */
 function queryParams() {
@@ -168,6 +230,18 @@
 }
 
 /**
+ * Show login status.
+ */
+function showLoginStatus() {
+    var a = queryParams()['openauth_attempt'];
+    debug('a', a);
+    if (typeof(a) != 'undefined' && a == '1')
+        showError('Incorrect email or password, please try again');
+}
+
+showLoginStatus();
+
+/**
  * Return the referrer URL.
  */
 function openauthReferrer() {
@@ -181,31 +255,13 @@
 }
 
 /**
- * Signin with OpenID.
- */
-/*
-function submitOpenIDSignin(w) {
-    clearauthcookie();
-    lstorage.removeItem('/r/EditWidget/accounts');
-    lstorage.removeItem('/r/EditWidget/dashboards');
-    document.openIDSignin.openid_identifier.value = w();
-    document.openIDSignin.action = openauthReferrer();
-    document.openIDSignin.submit();
-}
-
-function withGoogleOpenID() {
-    return 'https://www.google.com/accounts/o8/id';
-}
-*/
-
-/**
  * Signin with OAuth 2.0.
  */
 function submitOAuth2Signin(w) {
     parms = w();
     clearauthcookie();
-    lstorage.removeItem('/r/EditWidget/accounts');
-    lstorage.removeItem('/r/EditWidget/dashboards');
+    lstorage.removeItem('/r/Editor/accounts');
+    lstorage.removeItem('/r/Editor/dashboards');
     document.oauth2Signin.oauth2_authorize.value = parms[0];
     document.oauth2Signin.oauth2_access_token.value = parms[1];
     document.oauth2Signin.oauth2_client_id.value = parms[2];
@@ -222,11 +278,19 @@
     return parms;
 }
 
-function withGoogleOAuth() {
+function withGoogle() {
     var parms = ['https://accounts.google.com/o/oauth2/auth', 'https://accounts.google.com/o/oauth2/token', 'google.com', 'https://www.googleapis.com/oauth2/v1/userinfo', 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile', ''];
     return parms;
 }
 
+$('facebookOAuth2Signin').onclick = function() {
+    return submitOAuth2Signin(withFacebook);
+};
+
+$('googleOAuth2Signin').onclick = function() {
+    return submitOAuth2Signin(withGoogle);
+};
+
 /**
  * Signin with a userid and password.
  */
@@ -236,6 +300,8 @@
     document.formSignin.submit();
 }
 
+$('formSignin').onsubmit = submitFormSignin;
+
 /**
  * Handle orientation change.
  */
@@ -250,7 +316,7 @@
 };
 
 /**
- * Load post processing.
+ * Initialize the document.
  */
 function onload() {
     //debug('onload');
@@ -261,6 +327,9 @@
     return true;
 }
 
+onload();
+
+})();
 </script>
 
 </div>
diff --git a/hosting/server/htdocs/page/index.html b/hosting/server/htdocs/page/index.html
index 215383c..6a6e042 100644
--- a/hosting/server/htdocs/page/index.html
+++ b/hosting/server/htdocs/page/index.html
@@ -71,8 +71,11 @@
 <div id="buffer" style="visibility: hidden; width: 0px; height: 0px"></div>
 
 <script type="text/javascript">
+(function() {
 
-// Get the app name
+/**
+ * Get the current app name.
+ */
 var appname = ui.fragmentParams(location)['app'];
 
 /**
@@ -88,10 +91,14 @@
     return link;
 }
 
-// Set page titles
-document.title = ui.windowtitle(location.hostname) + ' - Page - ' + appname;
+/**
+ * Set page titles.
+ */
+document.title = config.windowtitle() + ' - Page - ' + appname;
 
-// Set header div
+/**
+ * Set header div.
+ */
 $('viewhead').innerHTML = '<span id="appTitle" class="cmenu">' + appname + '</span>' +
 '<input type="button" id="deleteWidgetButton" title="Delete a Widget" class="graybutton redbutton plusminus" style="position: absolute; top: 4px; left: 5px;" disabled="true" value="-"/>' +
 '<span style="position: absolute; top: 0px; left: 45px; right: 115px; padding: 0px; background: transparent;"><input id="widgetValue" type="text" value="" class="flatentry" title="Widget value" autocapitalize="off" placeholder="Value" style="position: absolute; left: 0px; top: 4px; width: 100%; visibility: hidden;" readonly="readonly"/></span>' +
@@ -120,12 +127,16 @@
 var atitle = $('appTitle');
 var pplay = $('playPageButton');
 
-// Set images
+/**
+ * Set images.
+ */
 $('imgimg').src = ui.b64img(appcache.get('/public/img.b64'));
 
-// Init component references
-var editWidget = sca.component('EditWidget');
-var pages = sca.reference(editWidget, 'pages');
+/**
+ * Init component references.
+ */
+var editorComp = sca.component('Editor');
+var pages = sca.reference(editorComp, 'pages');
 
 /**
  * Page editing functions.
@@ -868,7 +879,7 @@
         author = elementValue(namedElementChild("'author", pageentry));
         editable = author == username;
         wadd.disabled = !editable;
-        showStatus(editable? defaultStatus() : 'Read only');
+        showStatus(editable? onlineStatus() : 'Read only');
 
         return true;
     });
@@ -1054,12 +1065,17 @@
     return playpage();
 }
 
-// Initialize the page editor
+/**
+ * Initialize the page editor.
+ */
 page.mkedit(pagediv, atitle, wvalue, wadd, wcopy, wdelete, onpagechange, onselectwidget);
 
-// Get and display the current app page
+/**
+ * Get and display the current app page.
+ */
 getpage(appname, pagediv);
 
+})();
 </script>
 
 </div>
diff --git a/hosting/server/htdocs/proxy/public/oops/index.html b/hosting/server/htdocs/proxy/public/oops/index.html
index 9c795bf..b1d118d 100644
--- a/hosting/server/htdocs/proxy/public/oops/index.html
+++ b/hosting/server/htdocs/proxy/public/oops/index.html
@@ -25,6 +25,7 @@
 <meta name="apple-mobile-web-app-status-bar-style" content="black"/>
 <base href="/proxy/public/oops/"/>
 <script type="text/javascript">
+(function() {
 
 window.appcache = {};
 
@@ -49,37 +50,45 @@
     http.send(null);
     if (http.status == 200) {
         if (http.getResponseHeader("X-Login") != null) {
-            if (debug) debug('http error', u, 'X-Login');
+            if (window.debug) debug('http error', u, 'X-Login');
             return null;
         } else if (http.responseText == '' || http.getResponseHeader("Content-Type") == null) {
-            if (debug) debug('http error', u, 'No-Content');
+            if (window.debug) debug('http error', u, 'No-Content');
             return null;
         }
         try { ls.setItem(u, http.responseText); } catch(e) {}
         return http.responseText;
     }
-    if (debug) debug('http error', u, http.status, http.statusText);
+    if (window.debug) debug('http error', u, http.status, http.statusText);
     return null;
 };
 
-// Load Javascript and CSS
+})();
+
+/**
+ * Load Javascript and CSS.
+ */
 (function() {
-    var bootjs = document.createElement('script');
-    bootjs.type = 'text/javascript';
-    bootjs.text = appcache.get('/proxy/all-min.js');
-    document.head.appendChild(bootjs);
-    document.head.appendChild(ui.declareCSS(appcache.get('/proxy/ui-min.css')));
+
+var bootjs = document.createElement('script');
+bootjs.type = 'text/javascript';
+bootjs.text = appcache.get('/proxy/all-min.js');
+document.head.appendChild(bootjs);
+document.head.appendChild(ui.declareCSS(appcache.get('/proxy/ui-min.css')));
+
 })();
 
 </script>
 </head>
-<body class="delayed" onload="onload();">
+<body class="delayed">
 <div id="mainbodydiv" class="mainbodydiv">
 
 <div id="headdiv" class="hsection">
 <script type="text/javascript">
 (function() {
+
 $('headdiv').appendChild(ui.declareScript(appcache.get('/proxy/public/config-min.js')));
+
 })();
 </script>
 </div>
@@ -101,25 +110,35 @@
 </div>
 </div>
 
-<script type="text/javascript">
+<div id="viewfootbackground" class="viewfootbackground fixed"></div>
+<div id="viewfoot" class="viewfoot fixed"></div>
 
-// Init div variables
+<script type="text/javascript">
+(function() {
+
+/**
+ * Init div variables.
+ */
 var mdiv = $('menu'); 
 var hdiv = $('viewhead'); 
 $('viewcontainer').className = ui.isMobile()? 'viewcontainer3d' : 'viewcontainer3dm';
 $('view').className = ui.isMobile()? 'viewloaded3d' : 'viewloaded3dm';
+var fdiv = $('viewfoot'); 
 
-// Set page title
-document.title = ui.windowtitle(location.hostname) + ' - Oops';
-$('viewhead').innerHTML = '<span class="bcmenu">' + config.pagetitle + '</span>';
+/**
+ * Set page title.
+ */
+document.title = config.windowtitle() + ' - Oops';
+$('viewhead').innerHTML = '<span class="bcmenu">' + config.pagetitle() + '</span>';
 
 /**
  * Build and show the menu bar.
  */
 function showmenu(mdiv) {
     mdiv.innerHTML = ui.menubar(
-        mklist(ui.menu('Home', '/', '_view', false)),
-            mklist(hasauthcookie()? ui.menufunc('Sign out', 'logout();', false) : ui.menu('Sign in', '/login/', '_self', false)));
+        mklist(ui.menu('menuhome', 'Home', '/', '_self', false)),
+            mklist(hasauthcookie()? ui.menufunc('menusignout', 'Sign out', 'return logout();', false) : ui.menu('menusignin', 'Sign in', '/login/', '_self', false)));
+    fdiv.innerHTML = config.viewfoot();
 }
 
 showmenu(mdiv);
@@ -127,13 +146,13 @@
 /**
  * Log the current user out.
  */
-function logout() {
+window.logout = function() {
     // Clear session cookie and user-specific local storage entries
     clearauthcookie();
-    lstorage.removeItem('/r/EditWidget/accounts');
-    lstorage.removeItem('/r/EditWidget/dashboards');
+    lstorage.removeItem('/r/Editor/accounts');
+    lstorage.removeItem('/r/Editor/dashboards');
     document.location = '/login/';
-    return true;
+    return false;
 }
 
 /**
@@ -150,7 +169,7 @@
 };
 
 /**
- * Load post processing.
+ * Initialize the document.
  */
 function onload() {
     //debug('onload');
@@ -161,6 +180,9 @@
     return true;
 }
 
+onload();
+
+})();
 </script>
 
 <div id="footdiv" class="fsection">
diff --git a/hosting/server/htdocs/public/config.js b/hosting/server/htdocs/public/config.js
index 41a3bf6..54818f4 100644
--- a/hosting/server/htdocs/public/config.js
+++ b/hosting/server/htdocs/public/config.js
@@ -23,7 +23,23 @@
 /**
  * UI configuration.
  */
-config.windowtitle = 'App Builder'
-config.pagetitle = '<span style="font-weight: bold;">App Builder</span>';
-config.loginprompt = '<span>Sign in with your userid and password</span>';
+config.windowtitle = function() {
+    return 'App Builder';
+};
+
+config.pagetitle = function() {
+    return '<span style="font-weight: bold;">App Builder</span>';
+};
+
+config.loginprompt = function() {
+    return '<span>Sign in with your userid and password</span>';
+};
+
+config.viewfoot = function() {
+    return ui.menubar(mklist(ui.menu('menuabout', 'About', '/', '_view', 'note')), mklist());
+};
+
+config.appresources = function() {
+    return mklist();
+};
 
diff --git a/hosting/server/htdocs/public/notauth/index.html b/hosting/server/htdocs/public/notauth/index.html
index 959c6be..8985239 100644
--- a/hosting/server/htdocs/public/notauth/index.html
+++ b/hosting/server/htdocs/public/notauth/index.html
@@ -25,6 +25,7 @@
 <meta name="apple-mobile-web-app-status-bar-style" content="black"/>
 <base href="/public/notauth/"/>
 <script type="text/javascript">
+(function() {
 
 window.appcache = {};
 
@@ -49,37 +50,45 @@
     http.send(null);
     if (http.status == 200) {
         if (http.getResponseHeader("X-Login") != null) {
-            if (debug) debug('http error', u, 'X-Login');
+            if (window.debug) debug('http error', u, 'X-Login');
             return null;
         } else if (http.responseText == '' || http.getResponseHeader("Content-Type") == null) {
-            if (debug) debug('http error', u, 'No-Content');
+            if (window.debug) debug('http error', u, 'No-Content');
             return null;
         }
         try { ls.setItem(u, http.responseText); } catch(e) {}
         return http.responseText;
     }
-    if (debug) debug('http error', u, http.status, http.statusText);
+    if (window.debug) debug('http error', u, http.status, http.statusText);
     return null;
 };
 
-// Load Javascript and CSS
+})();
+
+/**
+ * Load Javascript and CSS.
+ */
 (function() {
-    var bootjs = document.createElement('script');
-    bootjs.type = 'text/javascript';
-    bootjs.text = appcache.get('/all-min.js');
-    document.head.appendChild(bootjs);
-    document.head.appendChild(ui.declareCSS(appcache.get('/ui-min.css')));
+
+var bootjs = document.createElement('script');
+bootjs.type = 'text/javascript';
+bootjs.text = appcache.get('/all-min.js');
+document.head.appendChild(bootjs);
+document.head.appendChild(ui.declareCSS(appcache.get('/ui-min.css')));
+
 })();
 
 </script>
 </head>
-<body class="delayed" onload="onload();">
+<body class="delayed">
 <div id="mainbodydiv" class="mainbodydiv">
 
 <div id="headdiv" class="hsection">
 <script type="text/javascript">
 (function() {
+
 $('headdiv').appendChild(ui.declareScript(appcache.get('/public/config-min.js')));
+
 })();
 </script>
 </div>
@@ -101,26 +110,36 @@
 </div>
 </div>
 
-<script type="text/javascript">
+<div id="viewfootbackground" class="viewfootbackground fixed"></div>
+<div id="viewfoot" class="viewfoot fixed"></div>
 
-// Init div variables
+<script type="text/javascript">
+(function() {
+
+/**
+ * Init div variables.
+ */
 var mdiv = $('menu'); 
 var hdiv = $('viewhead'); 
-$('viewhead').innerHTML = '<span class="bcmenu">' + config.pagetitle + '</span>';
+$('viewhead').innerHTML = '<span class="bcmenu">' + config.pagetitle() + '</span>';
 $('viewcontainer').className = ui.isMobile()? 'viewcontainer3d' : 'viewcontainer3dm';
 $('view').className = ui.isMobile()? 'viewloaded3d' : 'viewloaded3dm';
+var fdiv = $('viewfoot'); 
 
-// Set page title
-document.title = ui.windowtitle(location.hostname) + ' - Sorry';
-$('viewhead').innerHTML = '<span class="bcmenu">' + config.pagetitle + '</span>';
+/**
+ * Set page title.
+ */
+document.title = config.windowtitle() + ' - Sorry';
+$('viewhead').innerHTML = '<span class="bcmenu">' + config.pagetitle() + '</span>';
 
 /**
  * Build and show the menu bar.
  */
 function showmenu(mdiv) {
     mdiv.innerHTML = ui.menubar(
-        mklist(ui.menu('Home', '/', '_view', false)),
-            mklist(hasauthcookie()? ui.menufunc('Sign out', 'logout();', false) : ui.menu('Sign in', '/login/', '_self', false)));
+        mklist(ui.menu('menuhome', 'Home', '/', '_self', false)),
+            mklist(hasauthcookie()? ui.menufunc('menusignout', 'Sign out', 'return logout();', false) : ui.menu('menusignin', 'Sign in', '/login/', '_self', false)));
+    fdiv.innerHTML = config.viewfoot();
 }
 
 showmenu(mdiv);
@@ -128,13 +147,13 @@
 /**
  * Log the current user out.
  */
-function logout() {
+window.logout = function() {
     // Clear session cookie and user-specific local storage entries
     clearauthcookie();
-    lstorage.removeItem('/r/EditWidget/accounts');
-    lstorage.removeItem('/r/EditWidget/dashboards');
+    lstorage.removeItem('/r/Editor/accounts');
+    lstorage.removeItem('/r/Editor/dashboards');
     document.location = '/login/';
-    return true;
+    return false;
 }
 
 /**
@@ -152,7 +171,7 @@
 };
 
 /**
- * Load post processing.
+ * Initialize the document.
  */
 function onload() {
     //debug('onload');
@@ -163,6 +182,9 @@
     return true;
 }
 
+onload();
+
+})();
 </script>
 
 <div id="footdiv" class="fsection">
diff --git a/hosting/server/htdocs/public/notfound/index.html b/hosting/server/htdocs/public/notfound/index.html
index f2e4f66..8f0d486 100644
--- a/hosting/server/htdocs/public/notfound/index.html
+++ b/hosting/server/htdocs/public/notfound/index.html
@@ -25,6 +25,7 @@
 <meta name="apple-mobile-web-app-status-bar-style" content="black"/>
 <base href="/public/notfound/"/>
 <script type="text/javascript">
+(function() {
 
 window.appcache = {};
 
@@ -49,37 +50,45 @@
     http.send(null);
     if (http.status == 200) {
         if (http.getResponseHeader("X-Login") != null) {
-            if (debug) debug('http error', u, 'X-Login');
+            if (window.debug) debug('http error', u, 'X-Login');
             return null;
         } else if (http.responseText == '' || http.getResponseHeader("Content-Type") == null) {
-            if (debug) debug('http error', u, 'No-Content');
+            if (window.debug) debug('http error', u, 'No-Content');
             return null;
         }
         try { ls.setItem(u, http.responseText); } catch(e) {}
         return http.responseText;
     }
-    if (debug) debug('http error', u, http.status, http.statusText);
+    if (window.debug) debug('http error', u, http.status, http.statusText);
     return null;
 };
 
-// Load Javascript and CSS
+})();
+
+/**
+ * Load Javascript and CSS.
+ */
 (function() {
-    var bootjs = document.createElement('script');
-    bootjs.type = 'text/javascript';
-    bootjs.text = appcache.get('/all-min.js');
-    document.head.appendChild(bootjs);
-    document.head.appendChild(ui.declareCSS(appcache.get('/ui-min.css')));
+
+var bootjs = document.createElement('script');
+bootjs.type = 'text/javascript';
+bootjs.text = appcache.get('/all-min.js');
+document.head.appendChild(bootjs);
+document.head.appendChild(ui.declareCSS(appcache.get('/ui-min.css')));
+
 })();
 
 </script>
 </head>
-<body class="delayed" onload="onload();">
+<body class="delayed">
 <div id="mainbodydiv" class="mainbodydiv">
 
 <div id="headdiv" class="hsection">
 <script type="text/javascript">
 (function() {
+
 $('headdiv').appendChild(ui.declareScript(appcache.get('/public/config-min.js')));
+
 })();
 </script>
 </div>
@@ -102,25 +111,35 @@
 </div>
 </div>
 
-<script type="text/javascript">
+<div id="viewfootbackground" class="viewfootbackground fixed"></div>
+<div id="viewfoot" class="viewfoot fixed"></div>
 
-// Init div variables
+<script type="text/javascript">
+(function() {
+
+/**
+ * Init div variables.
+ */
 var mdiv = $('menu'); 
 var hdiv = $('viewhead'); 
 $('viewcontainer').className = ui.isMobile()? 'viewcontainer3d' : 'viewcontainer3dm';
 $('view').className = ui.isMobile()? 'viewloaded3d' : 'viewloaded3dm';
+var fdiv = $('viewfoot'); 
 
-// Set page title
-document.title = ui.windowtitle(location.hostname) + ' - Page not found';
-$('viewhead').innerHTML = '<span class="bcmenu">' + config.pagetitle + '</span>';
+/**
+ * Set page title.
+ */
+document.title = config.windowtitle() + ' - Page not found';
+$('viewhead').innerHTML = '<span class="bcmenu">' + config.pagetitle() + '</span>';
 
 /**
  * Build and show the menu bar.
  */
 function showmenu(mdiv) {
     mdiv.innerHTML = ui.menubar(
-        mklist(ui.menu('Home', '/', '_view', false)),
-            mklist(hasauthcookie()? ui.menufunc('Sign out', 'logout();', false) : ui.menu('Sign in', '/login/', '_self', false)));
+        mklist(ui.menu('menuhome', 'Home', '/', '_self', false)),
+            mklist(hasauthcookie()? ui.menufunc('menusignout', 'Sign out', 'return logout();', false) : ui.menu('menusignin', 'Sign in', '/login/', '_self', false)));
+    fdiv.innerHTML = config.viewfoot();
 }
 
 showmenu(mdiv);
@@ -128,13 +147,13 @@
 /**
  * Log the current user out.
  */
-function logout() {
+window.logout = function() {
     // Clear session cookie and user-specific local storage entries
     clearauthcookie();
-    lstorage.removeItem('/r/EditWidget/accounts');
-    lstorage.removeItem('/r/EditWidget/dashboards');
+    lstorage.removeItem('/r/Editor/accounts');
+    lstorage.removeItem('/r/Editor/dashboards');
     document.location = '/login/';
-    return true;
+    return false;
 }
 
 /**
@@ -151,7 +170,7 @@
 };
 
 /**
- * Load post processing.
+ * Initialize the document.
  */
 function onload() {
     //debug('onload');
@@ -162,6 +181,9 @@
     return true;
 }
 
+onload();
+
+})();
 </script>
 
 <div id="footdiv" class="fsection">
diff --git a/hosting/server/htdocs/public/notyet/index.html b/hosting/server/htdocs/public/notyet/index.html
index 24f738e..e43a992 100644
--- a/hosting/server/htdocs/public/notyet/index.html
+++ b/hosting/server/htdocs/public/notyet/index.html
@@ -25,6 +25,7 @@
 <meta name="apple-mobile-web-app-status-bar-style" content="black"/>
 <base href="/public/notyet/"/>
 <script type="text/javascript">
+(function() {
 
 window.appcache = {};
 
@@ -49,37 +50,45 @@
     http.send(null);
     if (http.status == 200) {
         if (http.getResponseHeader("X-Login") != null) {
-            if (debug) debug('http error', u, 'X-Login');
+            if (window.debug) debug('http error', u, 'X-Login');
             return null;
         } else if (http.responseText == '' || http.getResponseHeader("Content-Type") == null) {
-            if (debug) debug('http error', u, 'No-Content');
+            if (window.debug) debug('http error', u, 'No-Content');
             return null;
         }
         try { ls.setItem(u, http.responseText); } catch(e) {}
         return http.responseText;
     }
-    if (debug) debug('http error', u, http.status, http.statusText);
+    if (window.debug) debug('http error', u, http.status, http.statusText);
     return null;
 };
 
-// Load Javascript and CSS
+})();
+
+/**
+ * Load Javascript and CSS.
+ */
 (function() {
-    var bootjs = document.createElement('script');
-    bootjs.type = 'text/javascript';
-    bootjs.text = appcache.get('/all-min.js');
-    document.head.appendChild(bootjs);
-    document.head.appendChild(ui.declareCSS(appcache.get('/ui-min.css')));
+
+var bootjs = document.createElement('script');
+bootjs.type = 'text/javascript';
+bootjs.text = appcache.get('/all-min.js');
+document.head.appendChild(bootjs);
+document.head.appendChild(ui.declareCSS(appcache.get('/ui-min.css')));
+
 })();
 
 </script>
 </head>
-<body class="delayed" onload="onload();">
+<body class="delayed">
 <div id="mainbodydiv" class="mainbodydiv">
 
 <div id="headdiv" class="hsection">
 <script type="text/javascript">
 (function() {
+
 $('headdiv').appendChild(ui.declareScript(appcache.get('/public/config-min.js')));
+
 })();
 </script>
 </div>
@@ -102,25 +111,35 @@
 </div>
 </div>
 
-<script type="text/javascript">
+<div id="viewfootbackground" class="viewfootbackground fixed"></div>
+<div id="viewfoot" class="viewfoot fixed"></div>
 
-// Init div variables
+<script type="text/javascript">
+(function() {
+
+/**
+ * Init div variables.
+ */
 var mdiv = $('menu'); 
 var hdiv = $('viewhead'); 
 $('viewcontainer').className = ui.isMobile()? 'viewcontainer3d' : 'viewcontainer3dm';
 $('view').className = ui.isMobile()? 'viewloaded3d' : 'viewloaded3dm';
+var fdiv = $('viewfoot'); 
 
-// Set page title
-document.title = ui.windowtitle(location.hostname) + ' - Page not found';
-$('viewhead').innerHTML = '<span class="bcmenu">' + config.pagetitle + '</span>';
+/**
+ * Set page title.
+ */
+document.title = config.windowtitle() + ' - Page not found';
+$('viewhead').innerHTML = '<span class="bcmenu">' + config.pagetitle() + '</span>';
 
 /**
  * Build and show the menu bar.
  */
 function showmenu(mdiv) {
     mdiv.innerHTML = ui.menubar(
-        mklist(ui.menu('Home', '/', '_view', false)),
-            mklist(hasauthcookie()? ui.menufunc('Sign out', 'logout();', false) : ui.menu('Sign in', '/login/', '_self', false)));
+        mklist(ui.menu('menuhome', 'Home', '/', '_self', false)),
+            mklist(hasauthcookie()? ui.menufunc('menusignout', 'Sign out', 'return logout();', false) : ui.menu('menusignin', 'Sign in', '/login/', '_self', false)));
+    fdiv.innerHTML = config.viewfoot();
 }
 
 showmenu(mdiv);
@@ -128,13 +147,13 @@
 /**
  * Log the current user out.
  */
-function logout() {
+window.logout = function() {
     // Clear session cookie and user-specific local storage entries
     clearauthcookie();
-    lstorage.removeItem('/r/EditWidget/accounts');
-    lstorage.removeItem('/r/EditWidget/dashboards');
+    lstorage.removeItem('/r/Editor/accounts');
+    lstorage.removeItem('/r/Editor/dashboards');
     document.location = '/login/';
-    return true;
+    return false;
 }
 
 /**
@@ -151,7 +170,7 @@
 };
 
 /**
- * Load post processing.
+ * Initialize the document.
  */
 function onload() {
     //debug('onload');
@@ -162,6 +181,9 @@
     return true;
 }
 
+onload();
+
+})();
 </script>
 
 <div id="footdiv" class="fsection">
diff --git a/hosting/server/htdocs/public/oops/index.html b/hosting/server/htdocs/public/oops/index.html
index ea190f4..cc97c53 100644
--- a/hosting/server/htdocs/public/oops/index.html
+++ b/hosting/server/htdocs/public/oops/index.html
@@ -25,6 +25,7 @@
 <meta name="apple-mobile-web-app-status-bar-style" content="black"/>
 <base href="/public/oops/"/>
 <script type="text/javascript">
+(function() {
 
 window.appcache = {};
 
@@ -49,37 +50,45 @@
     http.send(null);
     if (http.status == 200) {
         if (http.getResponseHeader("X-Login") != null) {
-            if (debug) debug('http error', u, 'X-Login');
+            if (window.debug) debug('http error', u, 'X-Login');
             return null;
         } else if (http.responseText == '' || http.getResponseHeader("Content-Type") == null) {
-            if (debug) debug('http error', u, 'No-Content');
+            if (window.debug) debug('http error', u, 'No-Content');
             return null;
         }
         try { ls.setItem(u, http.responseText); } catch(e) {}
         return http.responseText;
     }
-    if (debug) debug('http error', u, http.status, http.statusText);
+    if (window.debug) debug('http error', u, http.status, http.statusText);
     return null;
 };
 
-// Load Javascript and CSS
+})();
+
+/**
+ * Load Javascript and CSS.
+ */
 (function() {
-    var bootjs = document.createElement('script');
-    bootjs.type = 'text/javascript';
-    bootjs.text = appcache.get('/all-min.js');
-    document.head.appendChild(bootjs);
-    document.head.appendChild(ui.declareCSS(appcache.get('/ui-min.css')));
+
+var bootjs = document.createElement('script');
+bootjs.type = 'text/javascript';
+bootjs.text = appcache.get('/all-min.js');
+document.head.appendChild(bootjs);
+document.head.appendChild(ui.declareCSS(appcache.get('/ui-min.css')));
+
 })();
 
 </script>
 </head>
-<body class="delayed" onload="onload();">
+<body class="delayed">
 <div id="mainbodydiv" class="mainbodydiv">
 
 <div id="headdiv" class="hsection">
 <script type="text/javascript">
 (function() {
+
 $('headdiv').appendChild(ui.declareScript(appcache.get('/public/config-min.js')));
+
 })();
 </script>
 </div>
@@ -101,25 +110,35 @@
 </div>
 </div>
 
-<script type="text/javascript">
+<div id="viewfootbackground" class="viewfootbackground fixed"></div>
+<div id="viewfoot" class="viewfoot fixed"></div>
 
-// Init div variables
+<script type="text/javascript">
+(function() {
+
+/**
+ * Init div variables.
+ */
 var mdiv = $('menu'); 
 var hdiv = $('viewhead'); 
 $('viewcontainer').className = ui.isMobile()? 'viewcontainer3d' : 'viewcontainer3dm';
 $('view').className = ui.isMobile()? 'viewloaded3d' : 'viewloaded3dm';
+var fdiv = $('viewfoot'); 
 
-// Set page title
-document.title = ui.windowtitle(location.hostname) + ' - Oops';
-$('viewhead').innerHTML = '<span class="bcmenu">' + config.pagetitle + '</span>';
+/**
+ * Set page title.
+ */
+document.title = config.windowtitle() + ' - Oops';
+$('viewhead').innerHTML = '<span class="bcmenu">' + config.pagetitle() + '</span>';
 
 /**
  * Build and show the menu bar.
  */
 function showmenu(mdiv) {
     mdiv.innerHTML = ui.menubar(
-        mklist(ui.menu('Home', '/', '_view', false)),
-            mklist(hasauthcookie()? ui.menufunc('Sign out', 'logout();', false) : ui.menu('Sign in', '/login/', '_self', false)));
+        mklist(ui.menu('menuhome', 'Home', '/', '_self', false)),
+            mklist(hasauthcookie()? ui.menufunc('menusignout', 'Sign out', 'return logout();', false) : ui.menu('menusignin', 'Sign in', '/login/', '_self', false)));
+    fdiv.innerHTML = config.viewfoot();
 }
 
 showmenu(mdiv);
@@ -127,13 +146,13 @@
 /**
  * Log the current user out.
  */
-function logout() {
+window.logout = function() {
     // Clear session cookie and user-specific local storage entries
     clearauthcookie();
-    lstorage.removeItem('/r/EditWidget/accounts');
-    lstorage.removeItem('/r/EditWidget/dashboards');
+    lstorage.removeItem('/r/Editor/accounts');
+    lstorage.removeItem('/r/Editor/dashboards');
     document.location = '/login/';
-    return true;
+    return false;
 }
 
 /**
@@ -150,7 +169,7 @@
 };
 
 /**
- * Load post processing.
+ * Initialize the document.
  */
 function onload() {
     //debug('onload');
@@ -161,6 +180,9 @@
     return true;
 }
 
+onload();
+
+})();
 </script>
 
 <div id="footdiv" class="fsection">
diff --git a/hosting/server/htdocs/stats/index.html b/hosting/server/htdocs/stats/index.html
index 1dd12de..7c3d9a6 100644
--- a/hosting/server/htdocs/stats/index.html
+++ b/hosting/server/htdocs/stats/index.html
@@ -39,22 +39,31 @@
 </div>
 
 <script type="text/javascript">
+(function() {
 
-// Get the app name
+/**
+ * Get the app name.
+ */
 var appname = ui.fragmentParams(location)['app'];
 
-// Set page titles
-document.title = ui.windowtitle(location.hostname) + ' - Stats - ' + appname;
+/**
+ * Set page titles.
+ */
+document.title = config.windowtitle() + ' - Stats - ' + appname;
 $('viewhead').innerHTML = '<span id="appname" class="cmenu">' + appname + '</span>' +
 '<input type="button" class="graybutton redbutton plusminus" style="position: absolute; top: 4px; left: 5px;" id="deleteApp" value="-" title="Delete the app" disabled="true"/>' +
-'<input type="button" class="graybutton bluebutton" style="position: absolute; top: 4px; right: 5px;" id="cloneApp" value="'+ config.clone +'" title="' + config.clone + ' this app"/>';
+'<input type="button" class="graybutton bluebutton" style="position: absolute; top: 4px; right: 5px;" id="cloneApp" value="'+ config.clone() +'" title="' + config.clone() + ' this app"/>';
 
-// Set images
+/**
+ * Set images.
+ */
 $('appimg').src = ui.b64img(appcache.get('/public/app.b64'));
 
-// Init service references
-var editWidget = sca.component("EditWidget");
-var apps = sca.reference(editWidget, "apps");
+/**
+ * Init service references.
+ */
+var editorComp = sca.component("Editor");
+var apps = sca.reference(editorComp, "apps");
 
 /**
  * The current app entry, author and saved XML content.
@@ -97,7 +106,7 @@
             $('deleteApp').onclick = function() {
                 return ui.navigate('/#view=delete&app=' + appname, '_view');
             }
-            showStatus(defaultStatus());
+            showOnlineStatus();
         } else {
             $('appTitle').placeholder = '';
             $('appDescription').placeholder = '';
@@ -159,9 +168,12 @@
     return ui.navigate('/#view=clone&app=' + appname, '_view');
 }
 
-// Get the current app
+/**
+ * Get the current app.
+ */
 getapp(appname);
 
+})();
 </script>
 
 </div>
diff --git a/hosting/server/htdocs/store/index.html b/hosting/server/htdocs/store/index.html
index 471229d..1264007 100644
--- a/hosting/server/htdocs/store/index.html
+++ b/hosting/server/htdocs/store/index.html
@@ -22,43 +22,67 @@
 <div id="apps" class="viewcontent"></div>
 
 <script type="text/javascript">
-
-// Set page titles
-document.title = ui.windowtitle(location.hostname) + ' - Store';
-
-// Get the store category
-var category = ui.fragmentParams(location)['category'];
-if (isNil(category))
-    category = 'top';
+(function() {
 
 /**
- * Build store menu bar
+ * Set page titles.
+ */
+document.title = config.windowtitle() + ' - Store';
+
+/**
+ * The store categories
+ */
+var categories = [
+    //['Featured', 'featured', 1],
+    ['Top', 'top', 2],
+    ['New', 'new', 3],
+    ['Search', 'all', 4],
+    ['My Apps', 'myapps', 5]
+];
+
+/**
+ * Find a store category.
+ */
+function findcategory(name) {
+    if (isNil(name))
+        return findcategory('top');
+    var f = filter(function(c) { return cadr(c) == name }, categories);
+    if (isNil(f))
+        return findcategory('top');
+    return car(f);
+}
+
+/**
+ * Get the current store category.
+ */
+var catname = cadr(findcategory(ui.fragmentParams(location)['category']));
+
+/**
+ * Build the store menu bar
  */
 function catmenu() {
     function catmenuitem(name, cat, idx) {
-        var c = cat == category? 'smenu' : 'amenu';
-        return '<span>' + ui.ahref('/#view=store&category=' + cat + '&idx=' + idx, '_view', '<span class="' + c + '">' + name + '</span>') + '</span>';
+        var c = cat == catname? 'smenu' : 'amenu';
+        return '<span>' + ui.href('storecat_' + cat, '/#view=store&category=' + cat + '&idx=' + idx, '_view', '<span class="' + c + '">' + name + '</span>') + '</span>';
     }
 
     var m = '';
-    //m += catmenuitem('Featured', 'featured', '1');
-    m += catmenuitem('Top', 'top', '2');
-    m += catmenuitem('New', 'new', '3');
-    m += catmenuitem('Search', 'all', '4');
-    m += catmenuitem('My Apps', 'myapps', '5');
+    map(function(c) { m += catmenuitem(car(c), cadr(c), caddr(c)); }, categories);
     m += '<span class="rmenu"><input type="button" class="graybutton bluebutton" id="createApp" title="Create a new app" Value="Create"/></span>';
     return m;
 }
 
-// Build store menu bar
+/**
+ * Build the store menu bar.
+ */
 $('viewhead').innerHTML = catmenu();
 
 /**
- * Service references.
+ * Init service references.
  */
-var editWidget = sca.component("EditWidget");
-var store = sca.reference(editWidget, "store");
-var dashboards = sca.reference(editWidget, "dashboards");
+var editorComp = sca.component("Editor");
+var store = sca.reference(editorComp, "store");
+var dashboards = sca.reference(editorComp, "dashboards");
 
 /**
  * Edit an app.
@@ -84,8 +108,8 @@
 /**
  * Get and display list of apps.
  */
-function getapps(category) {
-    //debug('category', category);
+function getapps(catname) {
+    //debug('catname', catname);
     showStatus('Loading');
 
     function display(doc) {
@@ -95,7 +119,7 @@
             showError('App not available');
             return false;
         }
-        showStatus(defaultStatus());
+        showOnlineStatus();
 
         var apps = '<div>';
         var feed = car(elementsToValues(atom.readATOMFeed(mklist(doc))));
@@ -114,10 +138,10 @@
             var updated = cadr(assoc("'updated", entry));
 
             apps += '<div class="box">'
-            apps += '<span class="appicon">' + ui.ahref('/#view=stats&app=' + name, '_view', '<img src="' + appimg + '" width="50" height="50"></img>') + '</span>';
+            apps += '<span class="appicon">' + ui.href('appicon_' + name, '/#view=stats&app=' + name, '_view', '<img src="' + appimg + '" width="50" height="50"></img>') + '</span>';
             apps += '<span>'
-            apps += '<span class="apptitle">' + ui.ahref('/#view=stats&app=' + name, '_view', name) + '</span>';
-            if (category != 'myapps')
+            apps += '<span class="apptitle">' + ui.href('apptitle_' + name, '/#view=stats&app=' + name, '_view', name) + '</span>';
+            if (catname != 'myapps')
                 apps += '<br/><span>' + 'by&nbsp;' + author.split('@')[0] + '</span>';
             apps += '</span>';
             apps += '</div>';
@@ -130,14 +154,17 @@
         $('apps').innerHTML = apps;
     }
 
-    if (category == 'myapps')
+    if (catname == 'myapps')
         return dashboards.get('', display);
-    return store.get(category, display);
+    return store.get(catname, display);
 }
 
-// Get and display the list of apps
-getapps(category);
+/**
+ * Get and display the list of apps.
+ */
+getapps(catname);
 
+})();
 </script>
 
 </div>
diff --git a/hosting/server/logic-test b/hosting/server/logic-test
new file mode 100755
index 0000000..d4767e8
--- /dev/null
+++ b/hosting/server/logic-test
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#  
+#    http://www.apache.org/licenses/LICENSE-2.0
+#    
+#  Unless required by applicable law or agreed to in writing,
+#  software distributed under the License is distributed on an
+#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+#  specific language governing permissions and limitations
+#  under the License.
+
+# Run Python test cases
+here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here`
+python_prefix=`cat $here/../../modules/python/python.prefix`
+export LD_LIBRARY_PATH=$python_prefix/lib:$LD_LIBRARY_PATH
+
+$python_prefix/bin/python test.py 2>/dev/null
+rc=$?
+
+exit $rc
diff --git a/hosting/server/proxy-start b/hosting/server/proxy-start
new file mode 100755
index 0000000..f06de9f
--- /dev/null
+++ b/hosting/server/proxy-start
@@ -0,0 +1,164 @@
+#!/bin/sh
+
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#  
+#    http://www.apache.org/licenses/LICENSE-2.0
+#    
+#  Unless required by applicable law or agreed to in writing,
+#  software distributed under the License is distributed on an
+#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+#  specific language governing permissions and limitations
+#  under the License.
+
+# For this module to work, add the www.example.com domain to your /etc/hosts as
+# follows:
+# 127.0.0.1 www.example.com
+
+here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here`
+
+# Configure and start logging
+if [ -x ../../components/log/scribe-cat ]; then
+    ../../components/log/scribed-central-conf tmp
+    ../../components/log/scribed-client-conf tmp localhost
+    ../../components/log/scribed-central-start tmp
+    ../../components/log/scribed-client-start tmp
+fi
+
+# Start memcached
+../../components/cache/memcached-start tmp 11211
+../../components/cache/memcached-start tmp 11212
+
+# Configure server
+../../modules/http/httpd-conf tmp www.example.com 9090 htdocs
+../../modules/http/httpd-event-conf tmp
+
+# Configure Python component support
+../../modules/server/server-conf tmp
+../../modules/python/python-conf tmp
+
+# Configure server log streaming
+if [ -x ../../components/log/scribe-cat ]; then
+    cat >tmp/conf/log.conf <<EOF
+# Generated by: proxy-start $*
+LogLevel notice
+ErrorLog "|$here/../../components/log/scribe-cat localhost server"
+CustomLog "|$here/../../components/log/scribe-cat localhost server" combined
+
+EOF
+
+fi
+#../../modules/http/httpd-loglevel-conf tmp debug
+
+# Configure error pages
+cat >>tmp/conf/svhost.conf <<EOF
+# Generated by: proxy-start $*
+# Error pages
+ErrorDocument 404 /public/notfound/
+ErrorDocument 401 /public/notauth/
+ErrorDocument 403 /public/notauth/
+ErrorDocument 400 /public/oops/
+ErrorDocument 405 /public/oops/
+ErrorDocument 500 /public/oops/
+ErrorDocument 502 /public/oops/
+ErrorDocument 503 /public/oops/
+
+EOF
+
+# Configure SCA contributions
+cat >>tmp/conf/httpd.conf <<EOF
+# Generated by: proxy-start $*
+# Configure SCA Composite
+SCAContribution $here/
+SCAComposite server.composite
+
+# Configure SCA Composite for mass dynamic virtual Hosting
+#SCAVirtualContribution $here/data/apps/
+#SCAVirtualComposite app.composite
+SCAVirtualContributor Composites
+
+# Configure SCA wiring timeout
+SCAWiringTimeout 10
+
+EOF
+
+# Configure resource aliases
+cat >>tmp/conf/httpd.conf <<EOF
+# Generated by: proxy-start $*
+Alias /home/home.png $here/htdocs/home/home.png
+Alias /home/home.b64 $here/htdocs/home/home.b64
+Alias /proxy/public/config.js $here/htdocs/public/config.js
+Alias /proxy/public/config-min.js $here/public/config-min.js
+
+EOF
+
+# Configure app resource aliases
+cat >>tmp/conf/svhost.conf <<EOF
+# Generated by: proxy-start $*
+# Map /v/<app-name>/<path> to htdocs/app/<path>
+AliasMatch /v/([^/]+)(.*)$ $here/htdocs/app\$2
+
+EOF
+
+# Start server
+../../modules/http/httpd-start tmp
+
+# Clear document cache
+rm -rf tmp/proxy/cache
+
+# Configure proxy balancer
+../../modules/http/httpd-conf tmp/proxy www.example.com 8090 tmp/htdocs
+../../modules/http/alt-host-conf tmp/proxy ww1.example.com
+../../modules/http/alt-host-conf tmp/proxy ww2.example.com
+../../modules/http/proxy-conf tmp/proxy
+../../modules/js/js-conf tmp/proxy
+../../modules/http/httpd-event-conf tmp/proxy
+#../../modules/http/cache-conf tmp/proxy
+
+# Configure proxy balancer members
+../../modules/http/proxy-member-conf tmp/proxy localhost 9090
+
+# Configure proxy log streaming
+if [ -x ../../components/log/scribe-cat ]; then
+    cat >tmp/proxy/conf/log.conf <<EOF
+# Generated by: proxy-start $*
+ErrorLog "|$here/../../components/log/scribe-cat www.example.com proxy"
+CustomLog "|$here/../../components/log/scribe-cat www.example.com access" combined
+
+EOF
+
+fi
+#../../modules/http/httpd-loglevel-conf tmp/proxy debug
+
+# Configure resource aliases
+cat >>tmp/proxy/conf/httpd.conf <<EOF
+# Generated by: proxy-start $*
+Alias /proxy/public/config.js $here/htdocs/public/config.js
+Alias /proxy/public/config-min.js $here/htdocs/public/config-min.js
+
+EOF
+
+# Configure error pages
+cat >>tmp/proxy/conf/vhost.conf <<EOF
+# Generated by: proxy-start $*
+# Error pages
+ErrorDocument 404 /proxy/public/oops/
+ErrorDocument 401 /proxy/public/oops/
+ErrorDocument 403 /proxy/public/oops/
+ErrorDocument 400 /proxy/public/oops/
+ErrorDocument 405 /proxy/public/oops/
+ErrorDocument 500 /proxy/public/oops/
+ErrorDocument 502 /proxy/public/oops/
+ErrorDocument 503 /proxy/public/oops/
+
+EOF
+
+# Start proxy balancer
+../../modules/http/httpd-start tmp/proxy
+
diff --git a/hosting/server/server-test b/hosting/server/server-test
index d4767e8..4d4d06f 100755
--- a/hosting/server/server-test
+++ b/hosting/server/server-test
@@ -17,12 +17,15 @@
 #  specific language governing permissions and limitations
 #  under the License.
 
-# Run Python test cases
-here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here`
-python_prefix=`cat $here/../../modules/python/python.prefix`
-export LD_LIBRARY_PATH=$python_prefix/lib:$LD_LIBRARY_PATH
+# Setup
+./ssl-proxy-start
+sleep 2
 
-$python_prefix/bin/python test.py 2>/dev/null
+# Test
+./client-test 2>/dev/null
 rc=$?
 
+# Cleanup
+./stop
+sleep 2
 exit $rc
diff --git a/hosting/server/ssl-proxy-start b/hosting/server/ssl-proxy-start
new file mode 100755
index 0000000..e38f540
--- /dev/null
+++ b/hosting/server/ssl-proxy-start
@@ -0,0 +1,252 @@
+#!/bin/sh
+
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#  
+#    http://www.apache.org/licenses/LICENSE-2.0
+#    
+#  Unless required by applicable law or agreed to in writing,
+#  software distributed under the License is distributed on an
+#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+#  specific language governing permissions and limitations
+#  under the License.
+
+# For this module to work, add the www.example.com domain to your /etc/hosts as
+# follows:
+# 127.0.0.1 www.example.com
+
+here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here`
+
+# Configure and start logging
+if [ -x ../../components/log/scribe-cat ]; then
+    ../../components/log/scribed-central-conf tmp
+    ../../components/log/scribed-client-conf tmp localhost
+    ../../components/log/scribed-central-start tmp
+    ../../components/log/scribed-client-start tmp
+fi
+
+# Start memcached
+../../components/cache/memcached-start tmp 11211
+../../components/cache/memcached-start tmp 11212
+
+# Configure server
+../../modules/http/httpd-conf tmp www.example.com 9090 htdocs
+../../modules/http/httpd-event-conf tmp
+
+# Configure HTTP basic auth
+../../modules/http/basic-auth-conf tmp component
+
+# Configure OAuth authentication
+# Configure your OAuth app keys here
+../../modules/oauth/oauth-conf tmp component
+../../modules/oauth/oauth-memcached-conf tmp localhost 11212
+../../modules/oauth/oauth2-appkey-conf tmp facebook.com 12345 67890
+../../modules/oauth/oauth2-appkey-conf tmp google.com 12345 67890
+
+# Configure form-based authentication
+../../modules/http/open-auth-conf tmp component 80b67f38-b79e-4a72-bb5c-22c69fb00820
+
+# Configure authorized admins
+../../modules/http/passwd-auth-conf tmp admin admin
+
+# Configure Python component support
+../../modules/server/server-conf tmp
+../../modules/python/python-conf tmp
+
+# Configure server log streaming
+if [ -x ../../components/log/scribe-cat ]; then
+    cat >tmp/conf/log.conf <<EOF
+# Generated by: ssl-proxy-start $*
+LogLevel notice
+ErrorLog "|$here/../../components/log/scribe-cat localhost server"
+CustomLog "|$here/../../components/log/scribe-cat localhost server" combined
+
+EOF
+
+fi
+../../modules/http/httpd-loglevel-conf tmp debug
+
+# Configure error pages
+cat >>tmp/conf/svhost.conf <<EOF
+# Generated by: ssl-proxy-start $*
+# Error pages
+ErrorDocument 404 /public/notfound/
+ErrorDocument 401 /public/notauth/
+ErrorDocument 403 /public/notauth/
+ErrorDocument 400 /public/oops/
+ErrorDocument 405 /public/oops/
+ErrorDocument 500 /public/oops/
+ErrorDocument 502 /public/oops/
+ErrorDocument 503 /public/oops/
+
+EOF
+
+# Configure SCA contributions
+cat >>tmp/conf/httpd.conf <<EOF
+# Generated by: ssl-proxy-start $*
+# Configure SCA Composite
+SCAContribution $here/
+SCAComposite server.composite
+
+# Configure SCA Composite for mass dynamic virtual Hosting
+SCAVirtualContributor Composites
+
+# Configure SCA Authenticator component
+SCAAuthenticator Authenticator
+
+# Configure SCA wiring timeout
+SCAWiringTimeout 10
+
+EOF
+
+# Configure resource aliases
+cat >>tmp/conf/httpd.conf <<EOF
+# Generated by: ssl-proxy-start $*
+Alias /home/home.png $here/htdocs/home/home.png
+Alias /home/home.b64 $here/htdocs/home/home.b64
+Alias /proxy/public/config.js $here/htdocs/public/config.js
+Alias /proxy/public/config-min.js $here/public/config-min.js
+
+EOF
+
+# Configure app resource aliases
+cat >>tmp/conf/svhost-ssl.conf <<EOF
+# Generated by: ssl-proxy-start $*
+# Map /v/<app-name>/<path> to htdocs/app/<path>
+AliasMatch /v/([^/]+)(.*)$ $here/htdocs/app\$2
+
+EOF
+
+# Configure admin access to server status and info
+cat >tmp/conf/adminauth.conf <<EOF
+# Generated by: ssl-proxy-start $*
+# Allow the server admin to view the server status and info
+<Location /server-status>
+AuthType None
+Require all granted
+</Location>
+
+<Location /server-info>
+AuthType None
+Require all granted
+</Location>
+
+EOF
+
+# Configure admin access to components
+cat >>tmp/conf/locauth-ssl.conf <<EOF
+# Generated by: ssl-proxy-start $*
+# Allow the server admin to access all components
+<Location /c>
+Require user admin
+</Location>
+<Location /r>
+Require user admin
+</Location>
+<Location /r/Editor>
+Require valid-user
+</Location>
+<Location /r/App>
+Require valid-user
+</Location>
+EOF
+
+# Start server
+../../modules/http/httpd-start tmp
+sleep 2
+
+# Configure authorized users
+./put-auth tmp admin admin admin admin
+./put-auth tmp admin admin john john
+./put-auth tmp admin admin jane jane
+# Configure the email addresses associated with your OAuth ids here
+./put-auth tmp admin admin /oauth1/john@example.com password
+./put-auth tmp admin admin /oauth2/jane@example.com password
+
+# Clear document cache
+rm -rf tmp/proxy/cache
+
+# Create SSL certificates
+../../modules/http/ssl-ca-conf tmp/proxy www.example.com
+../../modules/http/ssl-cert-conf tmp/proxy www.example.com server
+
+# Configure proxy balancer
+../../modules/http/httpd-conf tmp/proxy www.example.com 8090 tmp/htdocs
+../../modules/http/alt-host-conf tmp/proxy ww1.example.com
+../../modules/http/alt-host-conf tmp/proxy ww2.example.com
+../../modules/http/proxy-conf tmp/proxy
+../../modules/js/js-conf tmp/proxy
+../../modules/http/httpd-event-conf tmp/proxy
+#../../modules/http/cache-conf tmp/proxy
+../../modules/http/httpd-ssl-conf tmp/proxy 8453
+../../modules/http/proxy-ssl-conf tmp/proxy
+#../../modules/http/cache-ssl-conf tmp/proxy
+
+# Configure password authentication
+../../modules/http/basic-auth-conf tmp/proxy file /balancer-manager
+../../modules/http/basic-auth-conf tmp/proxy file /server-status
+../../modules/http/passwd-auth-conf tmp/proxy file admin admin
+
+# Configure mod-security
+../../modules/http/mod-security-conf tmp/proxy
+#../../modules/http/mod-security-audit-conf tmp/proxy
+
+# Configure proxy balancer members
+../../modules/http/proxy-ssl-nossl-member-conf tmp/proxy localhost 9090
+
+# Configure proxy log streaming
+if [ -x ../../components/log/scribe-cat ]; then
+    cat >tmp/proxy/conf/log.conf <<EOF
+# Generated by: ssl-proxy-start $*
+ErrorLog "|$here/../../components/log/scribe-cat www.example.com proxy"
+CustomLog "|$here/../../components/log/scribe-cat www.example.com access" combined
+
+EOF
+
+    cat >tmp/proxy/conf/log-ssl.conf <<EOF
+# Generated by: ssl-proxy-start $*
+CustomLog "|$here/../../components/log/scribe-cat www.example.com access" sslcombined
+
+EOF
+
+#    cat >tmp/proxy/conf/mod-security-audit-log.conf <<EOF
+## Generated by: start $*
+#SecAuditLog "|$here/../../components/log/scribe-cat $host secaudit secaudit"
+#
+#EOF
+
+fi
+../../modules/http/httpd-loglevel-conf tmp/proxy debug
+
+# Configure resource aliases
+cat >>tmp/proxy/conf/httpd.conf <<EOF
+# Generated by: ssl-proxy-start $*
+Alias /proxy/public/config.js $here/htdocs/public/config.js
+Alias /proxy/public/config-min.js $here/htdocs/public/config-min.js
+
+EOF
+
+# Configure error pages
+cat >>tmp/proxy/conf/vhost-ssl.conf <<EOF
+# Generated by: ssl-proxy-start $*
+# Error pages
+ErrorDocument 404 /proxy/public/oops/
+ErrorDocument 401 /proxy/public/oops/
+ErrorDocument 403 /proxy/public/oops/
+ErrorDocument 400 /proxy/public/oops/
+ErrorDocument 405 /proxy/public/oops/
+ErrorDocument 500 /proxy/public/oops/
+ErrorDocument 502 /proxy/public/oops/
+ErrorDocument 503 /proxy/public/oops/
+
+EOF
+
+# Start proxy balancer
+../../modules/http/httpd-start tmp/proxy
+
diff --git a/hosting/server/start b/hosting/server/start
index 5675e85..d4443cb 100755
--- a/hosting/server/start
+++ b/hosting/server/start
@@ -22,7 +22,6 @@
 # 127.0.0.1 www.example.com
 
 here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here`
-jsprefix=`echo "import os; print os.path.realpath('$here/../../modules/js')" | python`
 host=`hostname`
 
 # Configure and start logging
@@ -37,9 +36,15 @@
 ../../components/cache/memcached-start tmp 11211
 ../../components/cache/memcached-start tmp 11212
 
+# Clear document cache
+rm -rf tmp/cache
+
 # Configure server
 ../../modules/http/httpd-conf tmp www.example.com 8090 htdocs
+../../modules/http/alt-host-conf tmp ww1.example.com
+../../modules/http/alt-host-conf tmp ww2.example.com
 ../../modules/http/httpd-event-conf tmp
+#../../modules/http/cache-conf tmp
 
 # Configure Python component support
 ../../modules/server/server-conf tmp
@@ -64,6 +69,7 @@
 EOF
 
 fi
+#../../modules/http/httpd-loglevel-conf tmp debug
 
 # Configure error pages
 cat >>tmp/conf/svhost.conf <<EOF
@@ -72,8 +78,11 @@
 ErrorDocument 404 /public/notfound/
 ErrorDocument 401 /public/notauth/
 ErrorDocument 403 /public/notauth/
-ErrorDocument 500 /public/oops/
+ErrorDocument 400 /public/oops/
 ErrorDocument 405 /public/oops/
+ErrorDocument 500 /public/oops/
+ErrorDocument 502 /public/oops/
+ErrorDocument 503 /public/oops/
 
 EOF
 
@@ -89,6 +98,9 @@
 #SCAVirtualComposite app.composite
 SCAVirtualContributor Composites
 
+# Configure SCA wiring timeout
+SCAWiringTimeout 10
+
 EOF
 
 # Configure resource aliases
@@ -101,14 +113,6 @@
 
 EOF
 
-# Create app implementation resource links
-if [ ! -e "nuvem" ]; then
-    ln -s "../../../nuvem/nuvem-parallel/nuvem" "nuvem"
-fi
-if [ ! -e "lib" ]; then
-    ln -s "../../components" "lib"
-fi
-
 # Configure app resource aliases
 cat >>tmp/conf/svhost.conf <<EOF
 # Generated by: start $*
@@ -118,6 +122,5 @@
 EOF
 
 # Start server
-#../../modules/http/httpd-loglevel-conf tmp debug
 ../../modules/http/httpd-start tmp
 
diff --git a/hosting/server/stop b/hosting/server/stop
index e1fd927..82ecd10 100755
--- a/hosting/server/stop
+++ b/hosting/server/stop
@@ -17,6 +17,7 @@
 #  specific language governing permissions and limitations
 #  under the License.
 
+../../modules/http/httpd-stop tmp/proxy
 ../../modules/http/httpd-stop tmp
 
 ../../components/cache/memcached-stop tmp 11211
diff --git a/modules/http/Makefile.am b/modules/http/Makefile.am
index 4fd7cc0..a504adc 100644
--- a/modules/http/Makefile.am
+++ b/modules/http/Makefile.am
@@ -20,7 +20,7 @@
 incl_HEADERS = *.hpp
 incldir = $(prefix)/include/modules/http
 
-dist_mod_SCRIPTS = httpd-conf httpd-addr httpd-start httpd-stop httpd-restart ssl-ca-conf ssl-cert-conf ssl-cert-find httpd-ssl-conf basic-auth-conf cert-auth-conf form-auth-conf open-auth-conf passwd-auth-conf group-auth-conf proxy-conf proxy-base-conf proxy-ssl-conf proxy-balancer-conf proxy-member-conf proxy-ssl-member-conf proxy-ssl-nossl-member-conf vhost-conf vhost-ssl-conf tunnel-ssl-conf httpd-worker-conf httpd-event-conf httpd-loglevel-conf minify-html minify-js minify-css
+dist_mod_SCRIPTS = httpd-conf httpd-addr httpd-start httpd-stop httpd-restart ssl-ca-conf ssl-cert-conf ssl-cert-find httpd-ssl-conf basic-auth-conf cert-auth-conf form-auth-conf open-auth-conf passwd-auth-conf group-auth-conf cache-conf cache-ssl-conf cache-manifest proxy-conf proxy-base-conf proxy-ssl-conf proxy-balancer-conf proxy-member-conf proxy-ssl-member-conf proxy-ssl-nossl-member-conf alt-host-conf mass-host-conf mass-host-ssl-conf httpd-tunnel-ssl-conf tunnel-ssl-conf httpd-worker-conf httpd-event-conf httpd-loglevel-conf minify-html minify-js minify-css
 moddir = $(prefix)/modules/http
 
 curl_test_SOURCES = curl-test.cpp
diff --git a/modules/http/alt-host-conf b/modules/http/alt-host-conf
new file mode 100755
index 0000000..f614817
--- /dev/null
+++ b/modules/http/alt-host-conf
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#  
+#    http://www.apache.org/licenses/LICENSE-2.0
+#    
+#  Unless required by applicable law or agreed to in writing,
+#  software distributed under the License is distributed on an
+#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+#  specific language governing permissions and limitations
+#  under the License.
+
+# Generate an alternate host name configuration
+here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here`
+mkdir -p $1
+root=`echo "import os; print os.path.realpath('$1')" | python`
+
+host=$2
+
+cat >>$root/conf/hostcond.conf <<EOF
+# Generated by: alt-host-conf $*
+RewriteCond %{HTTP_HOST} !^$host [NC]
+
+EOF
+
diff --git a/modules/http/cache-conf b/modules/http/cache-conf
new file mode 100755
index 0000000..09ad5dc
--- /dev/null
+++ b/modules/http/cache-conf
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#  
+#    http://www.apache.org/licenses/LICENSE-2.0
+#    
+#  Unless required by applicable law or agreed to in writing,
+#  software distributed under the License is distributed on an
+#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+#  specific language governing permissions and limitations
+#  under the License.
+
+# Generate a minimal HTTPD cache configuration
+here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here`
+mkdir -p $1
+root=`echo "import os; print os.path.realpath('$1')" | python`
+
+mkdir -p $root/cache
+
+cat >>$root/conf/vhost.conf <<EOF
+# Generated by: cache-conf $*
+
+# Enable caching
+CacheEnable disk / 
+CacheQuickHandler Off
+CacheRoot $root/cache
+CacheHeader On
+#CacheDetailHeader On
+CacheIgnoreQueryString On
+CacheIgnoreCacheControl On
+CacheIgnoreHeaders Set-Cookie
+
+EOF
+
diff --git a/modules/http/cache-manifest b/modules/http/cache-manifest
new file mode 100755
index 0000000..3752a61
--- /dev/null
+++ b/modules/http/cache-manifest
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#  
+#    http://www.apache.org/licenses/LICENSE-2.0
+#    
+#  Unless required by applicable law or agreed to in writing,
+#  software distributed under the License is distributed on an
+#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+#  specific language governing permissions and limitations
+#  under the License.
+
+# Generate a cache-manifest.cmf file from a template and the list
+# of files in the cached application
+root=$1
+shift
+sha=`cat $* | shasum | awk '{ print $1 }'`
+cat $root/cache-template.cmf | sed -e "s/SHA1/$sha/" >$root/cache-manifest.cmf
+
diff --git a/modules/http/cache-ssl-conf b/modules/http/cache-ssl-conf
new file mode 100755
index 0000000..7a902c3
--- /dev/null
+++ b/modules/http/cache-ssl-conf
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#  
+#    http://www.apache.org/licenses/LICENSE-2.0
+#    
+#  Unless required by applicable law or agreed to in writing,
+#  software distributed under the License is distributed on an
+#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+#  specific language governing permissions and limitations
+#  under the License.
+
+# Generate a minimal HTTPD cache configuration
+here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here`
+mkdir -p $1
+root=`echo "import os; print os.path.realpath('$1')" | python`
+
+mkdir -p $root/cache
+
+cat >>$root/conf/vhost-ssl.conf <<EOF
+# Generated by: cache-conf $*
+
+# Enable caching
+CacheEnable disk / 
+CacheQuickHandler Off
+CacheRoot $root/cache
+CacheHeader On
+#CacheDetailHeader On
+CacheIgnoreQueryString On
+CacheIgnoreCacheControl On
+CacheIgnoreHeaders Set-Cookie
+
+EOF
+
diff --git a/modules/http/htdocs/index.html b/modules/http/htdocs/index.html
index da71ab2..236864e 100644
--- a/modules/http/htdocs/index.html
+++ b/modules/http/htdocs/index.html
@@ -22,7 +22,7 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <title>It works</title>
 </head>
 <body>
diff --git a/modules/http/htdocs/login/index.html b/modules/http/htdocs/login/index.html
index 3936730..fd3bc21 100644
--- a/modules/http/htdocs/login/index.html
+++ b/modules/http/htdocs/login/index.html
@@ -22,8 +22,8 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
-<script type="text/javascript" src="/all.js"></script>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
+<script type="text/javascript" src="/all-min.js"></script>
 <title>Sign in</title>
 </head>
 <body>
diff --git a/modules/http/htdocs/logout/index.html b/modules/http/htdocs/logout/index.html
index 66f2893..218dd5d 100644
--- a/modules/http/htdocs/logout/index.html
+++ b/modules/http/htdocs/logout/index.html
@@ -23,8 +23,8 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
-<script type="text/javascript" src="/all.js"></script>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
+<script type="text/javascript" src="/all-min.js"></script>
 <title>Sign out</title>
 </head>
 <h1>Sign out</h1>
diff --git a/modules/http/httpd-conf b/modules/http/httpd-conf
index 54154e1..730775f 100755
--- a/modules/http/httpd-conf
+++ b/modules/http/httpd-conf
@@ -22,8 +22,6 @@
 mkdir -p $1
 root=`echo "import os; print os.path.realpath('$1')" | python`
 
-jsprefix=`echo "import os; print os.path.realpath('$here/../js')" | python`
-
 host=$2
 port=`$here/httpd-addr port $3`
 pport=`$here/httpd-addr pport $3`
@@ -44,8 +42,10 @@
 uname=`uname -s`
 if [ $uname = "Darwin" ]; then
     libsuffix=".dylib"
+    sendfile=Off
 else
     libsuffix=".so"
+    sendfile=On
 fi
 
 modules_prefix=`cat $here/httpd-modules.prefix`
@@ -76,6 +76,8 @@
 RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500
 LimitRequestBody 1048576
 HostNameLookups Off
+#MaxKeepAliveRequests 25
+#MaxConnectionsPerChild 100
 
 # Log HTTP requests
 # [timestamp] [access] remote-host remote-ident remote-user "request-line"
@@ -92,9 +94,13 @@
 # Configure cache control
 <Directory />
 ExpiresActive On
-ExpiresDefault M604800
+ExpiresDefault A604800
+Header onsuccess merge Cache-Control public env=!private-cache
 </Directory>
 
+# Enable Linux Kernel sendfile
+EnableSendFile $sendfile
+
 # Configure auth modules
 Include conf/auth.conf
 
@@ -133,7 +139,7 @@
 
 <Location />
 RewriteEngine on
-RewriteCond %{HTTP_HOST} !^$host [NC]
+Include conf/hostcond.conf
 RewriteCond %{HTTP:X-Forwarded-Server} ^$ [NC]
 RewriteCond %{REQUEST_URI} !^/server-status [NC]
 RewriteCond %{REQUEST_URI} !^/balancer-manager [NC]
@@ -166,11 +172,16 @@
 # Generated by: httpd-conf $*
 LoadModule mpm_prefork_module ${modules_prefix}/modules/mod_mpm_prefork.so
 
+EOF
+
+if [ $uname = "Darwin" ]; then
+    cat >>$root/conf/mpm.conf <<EOF
 # Generated by: httpd-conf $*
 # Set thread stack size
 ThreadStackSize 2097152
 
 EOF
+fi
 
 # Generate modules list
 cat >$root/conf/modules.conf <<EOF
@@ -181,6 +192,7 @@
 LoadModule headers_module ${modules_prefix}/modules/mod_headers.so
 LoadModule alias_module ${modules_prefix}/modules/mod_alias.so
 LoadModule authn_file_module ${modules_prefix}/modules/mod_authn_file.so
+LoadModule authn_socache_module ${modules_prefix}/modules/mod_authn_socache.so
 LoadModule authn_core_module ${modules_prefix}/modules/mod_authn_core.so
 LoadModule authz_host_module ${modules_prefix}/modules/mod_authz_host.so
 LoadModule authz_groupfile_module ${modules_prefix}/modules/mod_authz_groupfile.so
@@ -197,8 +209,9 @@
 LoadModule proxy_http_module ${modules_prefix}/modules/mod_proxy_http.so
 LoadModule proxy_balancer_module ${modules_prefix}/modules/mod_proxy_balancer.so
 LoadModule lbmethod_byrequests_module ${modules_prefix}/modules/mod_lbmethod_byrequests.so
-LoadModule ssl_module ${modules_prefix}/modules/mod_ssl.so
 LoadModule socache_shmcb_module ${modules_prefix}/modules/mod_socache_shmcb.so
+LoadModule cache_module ${modules_prefix}/modules/mod_cache.so
+LoadModule cache_disk_module ${modules_prefix}/modules/mod_cache_disk.so
 LoadModule rewrite_module ${modules_prefix}/modules/mod_rewrite.so
 LoadModule mime_module ${modules_prefix}/modules/mod_mime.so
 LoadModule status_module ${modules_prefix}/modules/mod_status.so
@@ -218,12 +231,10 @@
 LoadModule unixd_module ${modules_prefix}/modules/mod_unixd.so
 LoadModule session_module ${modules_prefix}/modules/mod_session.so
 LoadModule session_crypto_module ${modules_prefix}/modules/mod_session_crypto.so
-LoadModule session_cookie_module ${modules_prefix}/modules/mod_session_cookie.so
 LoadModule slotmem_shm_module ${modules_prefix}/modules/mod_slotmem_shm.so
 LoadModule ratelimit_module ${modules_prefix}/modules/mod_ratelimit.so
 LoadModule reqtimeout_module ${modules_prefix}/modules/mod_reqtimeout.so
-
-LoadModule mod_tuscany_ssltunnel $here/libmod_tuscany_ssltunnel$libsuffix
+LoadModule ssl_module ${modules_prefix}/modules/mod_ssl.so
 
 EOF
 
@@ -303,7 +314,6 @@
 # Generated by: httpd-conf $*
 EOF
 
-
 # Allow public access to server resources
 cat >$root/conf/noauth.conf <<EOF
 # Generated by: httpd-conf $*
@@ -331,7 +341,7 @@
 
 # Enable HTTP reverse proxy
 ProxyRequests Off
-ProxyPreserveHost Off
+ProxyPreserveHost On
 ProxyStatus On
 
 # Enable server status
@@ -356,3 +366,10 @@
 
 EOF
 
+# Generate host name check condition
+cat >$root/conf/hostcond.conf <<EOF
+# Generated by: httpd-conf $*
+RewriteCond %{HTTP_HOST} !^$host [NC]
+
+EOF
+
diff --git a/modules/http/httpd.hpp b/modules/http/httpd.hpp
index 7147e88..6470d6c 100644
--- a/modules/http/httpd.hpp
+++ b/modules/http/httpd.hpp
@@ -26,6 +26,7 @@
  * HTTPD module implementation functions.
  */
 
+extern "C" {
 #include <apr_strings.h>
 #include <apr_fnmatch.h>
 #include <apr_lib.h>
@@ -72,6 +73,7 @@
 #include <ap_provider.h>
 #include <mod_auth.h>
 #include <mod_session.h>
+}
 
 #include "string.hpp"
 #include "stream.hpp"
@@ -154,6 +156,14 @@
 }
 
 /**
+ * Convert a host name to a realm.
+ */
+const string realm(const string& host) {
+    const string pre = substr(host, 0, 4);
+    return pre == "www." || pre == "ww1." || pre == "ww2." || pre == "ww3."? substr(host, 4) : host;
+}
+
+/**
  * Return the protocol scheme for a server.
  */
 const string scheme(const server_rec* s, const string& def = "http") {
@@ -410,6 +420,7 @@
     // Make sure browsers come back and check for updated dynamic content
     apr_table_set(r->headers_out, "Cache-Control", "must-revalidate, max-age=0");
     apr_table_set(r->headers_out, "Expires", "Tue, 01 Jan 1980 00:00:00 GMT");
+    apr_table_set(r->subprocess_env, "private-cache", "1");
 
     // Compute and return an Etag for the returned content
     const string etag(ap_md5_binary(r->pool, (const unsigned char*)c_str(ob), (int)length(ob)));
@@ -474,9 +485,9 @@
  * Create an HTTPD internal redirect request.
  * Similar to httpd/modules/http/http_request.c::internal_internal_redirect.
  */
-const failable<request_rec*, int> internalRedirectRequest(const string& nr_uri, request_rec* r) {
+const failable<request_rec*> internalRedirectRequest(const string& nr_uri, request_rec* r) {
     if (ap_is_recursion_limit_exceeded(r))
-        return mkfailure<request_rec*, int>(HTTP_INTERNAL_SERVER_ERROR);
+        return mkfailure<request_rec*>("Redirect recursion limit exceeded", HTTP_INTERNAL_SERVER_ERROR);
 
     // Create a new request
     request_rec* nr = (request_rec*)apr_pcalloc(r->pool, sizeof(request_rec));
@@ -532,7 +543,7 @@
     redirectFilters(nr->output_filters, r, nr);
     const int rrc = ap_run_post_read_request(nr);
     if (rrc != OK && rrc != DECLINED)
-        return mkfailure<request_rec*, int>(rrc);
+        return mkfailure<request_rec*>("Error handling internal redirect", rrc);
 
     return nr;
 }
@@ -561,9 +572,9 @@
  */
 const int internalRedirect(const string& uri, request_rec* r) {
     debug(uri, "httpd::internalRedirect");
-    const failable<request_rec*, int> nr = httpd::internalRedirectRequest(uri, r);
+    const failable<request_rec*> nr = httpd::internalRedirectRequest(uri, r);
     if (!hasContent(nr))
-        return reason(nr);
+        return rcode(nr);
     return httpd::internalRedirect(content(nr));
 }
 
@@ -571,9 +582,9 @@
  * Create an HTTPD sub request.
  * Similar to httpd/server/request.c::make_sub_request
  */
-const failable<request_rec*, int> internalSubRequest(const string& nr_uri, request_rec* r) {
+const failable<request_rec*> internalSubRequest(const string& nr_uri, request_rec* r) {
     if (ap_is_recursion_limit_exceeded(r))
-        return mkfailure<request_rec*, int>(HTTP_INTERNAL_SERVER_ERROR);
+        return mkfailure<request_rec*>("Redirect recursion limit exceeded", HTTP_INTERNAL_SERVER_ERROR);
 
     // Create a new sub pool
     apr_pool_t *nrp;
@@ -640,7 +651,8 @@
     debug(uri, "httpd::externalRedirect");
     r->status = HTTP_MOVED_TEMPORARILY;
     apr_table_setn(r->headers_out, "Location", apr_pstrdup(r->pool, c_str(uri)));
-    apr_table_setn(r->headers_out, "Cache-Control", "no-cache");
+    apr_table_setn(r->headers_out, "Cache-Control", "no-store");
+    apr_table_addn(r->err_headers_out, "Cache-Control", "no-store");
     r->filename = apr_pstrdup(r->pool, c_str(string("/redirect:/") + uri));
     return HTTP_MOVED_TEMPORARILY;
 }
@@ -705,7 +717,7 @@
  * Log a request.
  */
 const bool debugRequest(request_rec* r, const string& msg) {
-    gc_scoped_pool();
+    gc_scoped_pool pool;
     cdebug << msg << ":" << endl;
     cdebug << "  unparsed uri: " << debugOptional(r->unparsed_uri) << endl;
     cdebug << "  uri: " << debugOptional(r->uri) << endl;
diff --git a/modules/http/vhost-conf b/modules/http/mass-host-conf
similarity index 96%
rename from modules/http/vhost-conf
rename to modules/http/mass-host-conf
index 6d977eb..2da8f4f 100755
--- a/modules/http/vhost-conf
+++ b/modules/http/mass-host-conf
@@ -37,7 +37,7 @@
 htdocs=`echo "import os; print os.path.realpath('$htdocs')" | python`
 
 cat >>$root/conf/httpd.conf <<EOF
-# Generated by: vhost-conf $*
+# Generated by: mass-host-conf $*
 # Enable mass dynamic virtual hosting
 NameVirtualHost $vhost
 
@@ -52,7 +52,7 @@
 
 # Configure authentication
 Include conf/noauth.conf
-Include conf/auth.conf
+Include conf/locauth.conf
 Include conf/pubauth.conf
 Include conf/adminauth.conf
 
diff --git a/modules/http/vhost-ssl-conf b/modules/http/mass-host-ssl-conf
similarity index 91%
rename from modules/http/vhost-ssl-conf
rename to modules/http/mass-host-ssl-conf
index 915137b..68bd5b4 100755
--- a/modules/http/vhost-ssl-conf
+++ b/modules/http/mass-host-ssl-conf
@@ -31,7 +31,7 @@
 sslpport=`$here/httpd-addr pport $ssladdr`
 sslvhost=`$here/httpd-addr vhost $ssladdr`
 
-vhostconf=`cat $root/conf/httpd.conf | grep "# Generated by: vhost-conf"`
+vhostconf=`cat $root/conf/httpd.conf | grep "# Generated by: mass-host-conf"`
 vroot=`echo $vhostconf | awk '{ print $6 }'`; vroot=`echo "import os; print os.path.realpath('$vroot')" | python`
 vhtdocs=`echo $vhostconf | awk '{ print $7 }'`
 
@@ -40,7 +40,7 @@
 htdocs=`echo "import os; print os.path.realpath('$htdocs')" | python`
 
 cat >>$root/conf/httpd.conf <<EOF
-# Generated by: vhost-ssl-conf $*
+# Generated by: mass-host-ssl-conf $*
 # Enable mass dynamic virtual hosting over HTTPS
 SSLStrictSNIVHostCheck Off
 
@@ -57,9 +57,12 @@
 
 # Configure authentication
 Include conf/noauth-ssl.conf
-Include conf/auth-ssl.conf
+Include conf/locauth-ssl.conf
 Include conf/pubauth-ssl.conf
 Include conf/adminauth-ssl.conf
 
+# Configure tracking
+Include conf/tracking-ssl.conf
+
 </VirtualHost>
 
diff --git a/modules/js/htdocs/ui.css b/modules/js/htdocs/ui.css
index 3dde10a..ddc21b2 100644
--- a/modules/js/htdocs/ui.css
+++ b/modules/js/htdocs/ui.css
@@ -34,7 +34,7 @@
 }
 
 .fixed {
-position: absolute;
+position: fixed;
 }
 
 .devicewidth {
@@ -175,13 +175,95 @@
 
 .viewheadbackground {
 position: absolute; left: 0px; top: 35px; height: 35px; line-height: 35px; width: 2500px; z-index: 7;
-font-size: 110%; font-weight: bold; background-color: #f1f1f1; color: #000000;
+background-color: #f1f1f1;
 border-top: 1px; border-bottom: 1px; border-left: 0px; border-right: 0px;
 border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #e5e5e5;
 overflow: hidden;
 -webkit-backface-visibility: hidden;
 }
 
+.viewfoot {
+position: absolute; left: 0px; bottom: 0px; height: 25px; line-height: 25px; width: 100%; z-index: 8;
+font-size: 12px; background-color: #ffffff; color: #404040;
+border-top: 1px; border-bottom: 1px; border-left: 0px; border-right: 0px;
+border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #ffffff;
+overflow: hidden;
+-webkit-backface-visibility: hidden;
+}
+
+.status {
+position: absolute; left: 0px; bottom: 0px; height: 35px; line-height: 35px; width: 100%; z-index: 9;
+font-size: 12px; background-color: #ffffff; color: #404040;
+border-top: 0px; border-bottom: 0px; border-left: 0px; border-right: 0px;
+border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #ffffff;
+overflow: hidden;
+-webkit-transform: translate(0px, 0px);
+-moz-transform: translate(0px, 0px);
+-ms-transform: translate(0px, 0px);
+-o-transform: translate(0px, 0px);
+transform: translate(0px, 0px);
+-webkit-backface-visibility: hidden;
+}
+
+.statusout3 {
+position: absolute; left: 0px; bottom: 0px; height: 35px; line-height: 35px; width: 100%; z-index: 9;
+font-size: 12px; background-color: #ffffff; color: #404040;
+border-top: 0px; border-bottom: 0px; border-left: 0px; border-right: 0px;
+border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #ffffff;
+overflow: hidden;
+-webkit-transition: -webkit-transform 0.4s ease-in-out 3s;
+-moz-transition: -moz-transform 0.4s ease-in-out 3s;
+-ms-transition: -ms-transform 0.4s ease-in-out 3s;
+-o-transition: -o-transform 0.4s ease-in-out 3s;
+transition: transform 0.4s ease-in-out 3s;
+-webkit-transform: translate(0px, 35px);
+-moz-transform: translate(0px, 35px);
+-ms-transform: translate(0px, 35px);
+-o-transform: translate(0px, 35px);
+transform: translate(0px, 35px);
+-webkit-backface-visibility: hidden;
+}
+
+.statusout1 {
+position: absolute; left: 0px; bottom: 0px; height: 35px; line-height: 35px; width: 100%; z-index: 9;
+font-size: 12px; background-color: #ffffff; color: #404040;
+border-top: 0px; border-bottom: 0px; border-left: 0px; border-right: 0px;
+border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #ffffff;
+overflow: hidden;
+-webkit-transition: -webkit-transform 0.4s ease-in-out 1s;
+-moz-transition: -moz-transform 0.4s ease-in-out 1s;
+-ms-transition: -ms-transform 0.4s ease-in-out 1s;
+-o-transition: -o-transform 0.4s ease-in-out 1s;
+transition: transform 0.4s ease-in-out 1s;
+-webkit-transform: translate(0px, 35px);
+-moz-transform: translate(0px, 35px);
+-ms-transform: translate(0px, 35px);
+-o-transform: translate(0px, 35px);
+transform: translate(0px, 35px);
+-webkit-backface-visibility: hidden;
+}
+
+.okstatus {
+font-size: 110%; font-weight: bold; padding-left: 6px; padding-right: 6px; white-space: nowrap; text-decoration: none;
+background-color: #f1f1f1; color: #000000;
+width: 100%; margin-left: auto; margin-right: auto; text-align: center; float: right;
+}
+
+.errorstatus {
+font-size: 110%; font-weight: bold; padding-left: 6px; padding-right: 6px; white-space: nowrap; text-decoration: none;
+background-color: #d14836; color: #ffffff;
+width: 100%; margin-left: auto; margin-right: auto; text-align: center; float: right;
+}
+
+.viewfootbackground {
+position: absolute; left: 0px; bottom: 0px; height: 25px; line-height: 25px; width: 2500px; z-index: 7;
+background-color: #ffffff;
+border-top: 1px; border-bottom: 1px; border-left: 0px; border-right: 0px;
+border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #ffffff;
+overflow: hidden;
+-webkit-backface-visibility: hidden;
+}
+
 .viewcontent {
 position: absolute; left: 0px; top: 38px; width: 100%;
 -webkit-backface-visibility: hidden;
diff --git a/modules/js/htdocs/ui.js b/modules/js/htdocs/ui.js
index f200321..fb53598 100644
--- a/modules/js/htdocs/ui.js
+++ b/modules/js/htdocs/ui.js
@@ -178,28 +178,6 @@
 };
 
 /**
- * Convert a host name to a home page title.
- */
-ui.hometitle = function(host) {
-    if (!isNil(window.top.config.hometitle))
-        return window.top.config.hometitle;
-    var h = reverse(host.split('.'));
-    var d = isNil(cdr(h))? car(h) : cadr(h);
-    return d.substr(0, 1).toUpperCase() + d.substr(1);
-};
-
-/**
- * Convert a host name to a window title.
- */
-ui.windowtitle = function(host) {
-    if (!isNil(window.top.config.windowtitle))
-        return window.top.config.windowtitle;
-    var h = reverse(host.split('.'));
-    var d = isNil(cdr(h))? car(h) : cadr(h);
-    return d.substr(0, 1).toUpperCase() + d.substr(1);
-};
-
-/**
  * Convert a CSS position to a numeric position.
  */
 ui.numpos = function(p) {
@@ -264,62 +242,75 @@
     //log('navigate', url, win);
 
     // Open a new window
-    if (win == '_blank')
-        return window.top.open(url, win);
+    if (win == '_blank') {
+        window.top.open(url, win);
+        return false;
+    }
 
     // Open a new document in the current window
-    if (win == '_self')
-        return window.top.open(url, win);
+    if (win == '_self') {
+        window.top.open(url, win);
+        return false;
+    }
 
     // Reload the current window
     if (win == '_reload') {
         window.top.location = url;
-        return window.top.location.reload();
+        window.top.location.reload();
+        return false;
     }
 
     // Let the current top window handle the navigation
     if (win == '_view') {
         if (!window.top.onnavigate)
             return window.top.open(url, '_self');
-        return window.top.onnavigate(url);
+        window.top.onnavigate(url);
+        return false;
     }
 
-    return window.top.open(url, win);
+    window.top.open(url, win);
+    return false;
 }
 
 /**
  * Build a portable <a href> tag.
  */
-ui.ahref = function(loc, target, html) {
+ui.href = function(id, loc, target, html) {
     if (target == '_blank')
-        return '<a href="' + loc + '" target="_blank">' + html + '</a>';
-    return '<a href="javascript:void(0)" onclick="ui.navigate(\'' + loc + '\', \'' + target + '\');">' + html + '</a>';
+        return '<a id="' + id + '" href="' + loc + '" target="_blank">' + html + '</a>';
+    return '<a id="' + id + '" href="' + loc + '" onclick="return ui.navigate(\'' + loc + '\', \'' + target + '\');">' + html + '</a>';
 };
 
 /**
  * Build a menu bar.
  */ 
-ui.menu = function(name, href, target, hilight) {
+ui.menu = function(id, name, href, target, hilight) {
     function Menu() {
         this.content = function() {
-            if (hilight)
-                return ui.ahref(href, target, '<span class="tbarsmenu">' + name + '</span>');
-            return ui.ahref(href, target, '<span class="tbaramenu">' + name + '</span>');
+            if (hilight == true)
+                return ui.href(id, href, target, '<span class="tbarsmenu">' + name + '</span>');
+            else if (hilight == false)
+                return ui.href(id, href, target, '<span class="tbaramenu">' + name + '</span>');
+            else
+                return ui.href(id, href, target, '<span class="' + hilight + '">' + name + '</span>');
         };
     }
     return new Menu();
 };
 
-ui.menufunc = function(name, fun, hilight) {
+ui.menufunc = function(id, name, fun, hilight) {
     function Menu() {
         this.content = function() {
-            function href(fun, html) {
-                return '<a href="javascript:void(0)" onclick="' + fun + '">' + html + '</a>';
+            function href(id, fun, html) {
+                return '<a id="' + id + '" href="/" onclick="' + fun + '">' + html + '</a>';
             }
 
-            if (hilight)
-                return href(fun, '<span class="tbarsmenu">' + name + '</span>');
-            return href(fun, '<span class="tbaramenu">' + name + '</span>');
+            if (hilight == true)
+                return href(id, fun, '<span class="tbarsmenu">' + name + '</span>');
+            else if (hilight == false)
+                return href(id, fun, '<span class="tbaramenu">' + name + '</span>');
+            else
+                return href(id, fun, '<span class="' + hilight + '">' + name + '</span>');
         };
     }
     return new Menu();
diff --git a/modules/js/js-conf b/modules/js/js-conf
index 09289a1..aa29920 100755
--- a/modules/js/js-conf
+++ b/modules/js/js-conf
@@ -25,47 +25,27 @@
 cat >>$root/conf/httpd.conf <<EOF
 # Generated by: js-conf $*
 # Serve JavaScript scripts and CSS
-Alias /ui.css $here/htdocs/ui.css
 Alias /ui-min.css $here/htdocs/ui-min.css
-Alias /all.js $here/htdocs/all.js
 Alias /all-min.js $here/htdocs/all-min.js
-Alias /proxy/ui.css $here/htdocs/ui.css
 Alias /proxy/ui-min.css $here/htdocs/ui-min.css
-Alias /proxy/all.js $here/htdocs/all.js
 Alias /proxy/all-min.js $here/htdocs/all-min.js
 
 EOF
 
 cat >>$root/conf/pubauth.conf <<EOF
 # Generated by: js-conf $*
-<Location /ui.css>
-AuthType None
-Require all granted
-</Location>
 <Location /ui-min.css>
 AuthType None
 Require all granted
 </Location>
-<Location /all.js>
-AuthType None
-Require all granted
-</Location>
 <Location /all-min.js>
 AuthType None
 Require all granted
 </Location>
-<Location /proxy/ui.css>
-AuthType None
-Require all granted
-</Location>
 <Location /proxy/ui-min.css>
 AuthType None
 Require all granted
 </Location>
-<Location /proxy/all.js>
-AuthType None
-Require all granted
-</Location>
 <Location /proxy/all-min.js>
 AuthType None
 Require all granted
diff --git a/modules/oauth/htdocs/index.html b/modules/oauth/htdocs/index.html
index 8fe4935..006aade 100644
--- a/modules/oauth/htdocs/index.html
+++ b/modules/oauth/htdocs/index.html
@@ -22,9 +22,9 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 
-<script type="text/javascript" src="/all.js"></script>
+<script type="text/javascript" src="/all-min.js"></script>
 <script type="text/javascript">
 var protected = sca.component("Protected");
 var userInfo = sca.defun(sca.reference(protected, "userInfo"), "getuser", "getemail", "getnickname", "getfullname", "getfirstname", "getlastname", "getrealm");
diff --git a/modules/oauth/htdocs/login/index.html b/modules/oauth/htdocs/login/index.html
index 0243915..0740afd 100644
--- a/modules/oauth/htdocs/login/index.html
+++ b/modules/oauth/htdocs/login/index.html
@@ -22,7 +22,7 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <title>Sign in</title>
 </head>
 <body>
diff --git a/modules/oauth/htdocs/login/mixed.html b/modules/oauth/htdocs/login/mixed.html
index 50d70f0..fdf2b64 100644
--- a/modules/oauth/htdocs/login/mixed.html
+++ b/modules/oauth/htdocs/login/mixed.html
@@ -22,7 +22,7 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <title>Sign in</title>
 </head>
 <body>
diff --git a/modules/oauth/htdocs/logout/index.html b/modules/oauth/htdocs/logout/index.html
index a9d2e62..8cf7860 100644
--- a/modules/oauth/htdocs/logout/index.html
+++ b/modules/oauth/htdocs/logout/index.html
@@ -22,7 +22,7 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <title>Sign out</title>
 </head>
 <body>
diff --git a/modules/oauth/htdocs/public/index.html b/modules/oauth/htdocs/public/index.html
index af56724..24db147 100644
--- a/modules/oauth/htdocs/public/index.html
+++ b/modules/oauth/htdocs/public/index.html
@@ -22,7 +22,7 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <title>Unprotected area</title>
 </head>
 <body>
diff --git a/modules/openid/htdocs/index.html b/modules/openid/htdocs/index.html
index 760320f..e5b1618 100644
--- a/modules/openid/htdocs/index.html
+++ b/modules/openid/htdocs/index.html
@@ -22,8 +22,8 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
-<script type="text/javascript" src="/all.js"></script>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
+<script type="text/javascript" src="/all-min.js"></script>
 
 <script type="text/javascript">
 var protected = sca.component("Protected");
diff --git a/modules/openid/htdocs/login/index.html b/modules/openid/htdocs/login/index.html
index 47fbb73..00b0bfd 100644
--- a/modules/openid/htdocs/login/index.html
+++ b/modules/openid/htdocs/login/index.html
@@ -22,7 +22,7 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <title>Sign in</title>
 </head>
 <body>
diff --git a/modules/openid/htdocs/logout/index.html b/modules/openid/htdocs/logout/index.html
index a9d2e62..8cf7860 100644
--- a/modules/openid/htdocs/logout/index.html
+++ b/modules/openid/htdocs/logout/index.html
@@ -22,7 +22,7 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <title>Sign out</title>
 </head>
 <body>
diff --git a/modules/openid/htdocs/public/index.html b/modules/openid/htdocs/public/index.html
index af56724..24db147 100644
--- a/modules/openid/htdocs/public/index.html
+++ b/modules/openid/htdocs/public/index.html
@@ -22,7 +22,7 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <title>Unprotected area</title>
 </head>
 <body>
diff --git a/modules/server/htdocs/index.html b/modules/server/htdocs/index.html
index da71ab2..236864e 100644
--- a/modules/server/htdocs/index.html
+++ b/modules/server/htdocs/index.html
@@ -22,7 +22,7 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <title>It works</title>
 </head>
 <body>
diff --git a/modules/wsgi/htdocs/index.html b/modules/wsgi/htdocs/index.html
index 5449f4e..cc7237b 100644
--- a/modules/wsgi/htdocs/index.html
+++ b/modules/wsgi/htdocs/index.html
@@ -21,7 +21,7 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <title>It works</title>
 </head>
 <body>
diff --git a/samples/relay-gae/htdocs/index.html b/samples/relay-gae/htdocs/index.html
index c3cf8d7..b8b606d 100644
--- a/samples/relay-gae/htdocs/index.html
+++ b/samples/relay-gae/htdocs/index.html
@@ -21,7 +21,7 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <title>Relay</title>
 </head>
 <body>
diff --git a/samples/relay-python/htdocs/index.html b/samples/relay-python/htdocs/index.html
index 2806139..ad5f86a 100644
--- a/samples/relay-python/htdocs/index.html
+++ b/samples/relay-python/htdocs/index.html
@@ -21,7 +21,7 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <title>Relay</title>
 <body>
 
diff --git a/samples/store-cluster/domains/jane/htdocs/index.html b/samples/store-cluster/domains/jane/htdocs/index.html
index 43f624a..832c0a1 100644
--- a/samples/store-cluster/domains/jane/htdocs/index.html
+++ b/samples/store-cluster/domains/jane/htdocs/index.html
@@ -21,10 +21,10 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <title>Jane's Store</title>
 
-<script type="text/javascript" src="/all.js"></script>
+<script type="text/javascript" src="/all-min.js"></script>
 
 <script type="text/javascript">
 var store = sca.component("Store");
diff --git a/samples/store-cluster/domains/jane/htdocs/login/index.html b/samples/store-cluster/domains/jane/htdocs/login/index.html
index 9fcafbd..2a7be01 100644
--- a/samples/store-cluster/domains/jane/htdocs/login/index.html
+++ b/samples/store-cluster/domains/jane/htdocs/login/index.html
@@ -22,8 +22,8 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
-<script type="text/javascript" src="/all.js"></script>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
+<script type="text/javascript" src="/all-min.js"></script>
 <title>Sign in</title>
 </head>
 <body>
diff --git a/samples/store-cluster/domains/jane/htdocs/logout/index.html b/samples/store-cluster/domains/jane/htdocs/logout/index.html
index 4140eb3..50a10bd 100644
--- a/samples/store-cluster/domains/jane/htdocs/logout/index.html
+++ b/samples/store-cluster/domains/jane/htdocs/logout/index.html
@@ -22,8 +22,8 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
-<script type="text/javascript" src="/all.js"></script>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
+<script type="text/javascript" src="/all-min.js"></script>
 <title>Sign out</title>
 </head>
 <body>
diff --git a/samples/store-cluster/domains/joe/htdocs/index.html b/samples/store-cluster/domains/joe/htdocs/index.html
index 34c8dd3..0caf8b3 100644
--- a/samples/store-cluster/domains/joe/htdocs/index.html
+++ b/samples/store-cluster/domains/joe/htdocs/index.html
@@ -21,10 +21,10 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <title>Joe's Store</title>
 
-<script type="text/javascript" src="/all.js"></script>
+<script type="text/javascript" src="/all-min.js"></script>
 
 <script type="text/javascript">
 var store = sca.component("Store");
diff --git a/samples/store-cluster/domains/joe/htdocs/login/index.html b/samples/store-cluster/domains/joe/htdocs/login/index.html
index 9fcafbd..2a7be01 100644
--- a/samples/store-cluster/domains/joe/htdocs/login/index.html
+++ b/samples/store-cluster/domains/joe/htdocs/login/index.html
@@ -22,8 +22,8 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
-<script type="text/javascript" src="/all.js"></script>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
+<script type="text/javascript" src="/all-min.js"></script>
 <title>Sign in</title>
 </head>
 <body>
diff --git a/samples/store-cluster/domains/joe/htdocs/logout/index.html b/samples/store-cluster/domains/joe/htdocs/logout/index.html
index 4140eb3..50a10bd 100644
--- a/samples/store-cluster/domains/joe/htdocs/logout/index.html
+++ b/samples/store-cluster/domains/joe/htdocs/logout/index.html
@@ -22,8 +22,8 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
-<script type="text/javascript" src="/all.js"></script>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
+<script type="text/javascript" src="/all-min.js"></script>
 <title>Sign out</title>
 </head>
 <body>
diff --git a/samples/store-cluster/htdocs/index.html b/samples/store-cluster/htdocs/index.html
index c1bd391..50c7e25 100644
--- a/samples/store-cluster/htdocs/index.html
+++ b/samples/store-cluster/htdocs/index.html
@@ -21,7 +21,7 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <title>Store</title>
 </head>
 
diff --git a/samples/store-cluster/htdocs/login/index.html b/samples/store-cluster/htdocs/login/index.html
index 9fcafbd..2a7be01 100644
--- a/samples/store-cluster/htdocs/login/index.html
+++ b/samples/store-cluster/htdocs/login/index.html
@@ -22,8 +22,8 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
-<script type="text/javascript" src="/all.js"></script>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
+<script type="text/javascript" src="/all-min.js"></script>
 <title>Sign in</title>
 </head>
 <body>
diff --git a/samples/store-cluster/htdocs/logout/index.html b/samples/store-cluster/htdocs/logout/index.html
index 4140eb3..50a10bd 100644
--- a/samples/store-cluster/htdocs/logout/index.html
+++ b/samples/store-cluster/htdocs/logout/index.html
@@ -22,8 +22,8 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
-<script type="text/javascript" src="/all.js"></script>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
+<script type="text/javascript" src="/all-min.js"></script>
 <title>Sign out</title>
 </head>
 <body>
diff --git a/samples/store-cluster/proxy-conf b/samples/store-cluster/proxy-conf
index 215c25f..c43feff 100755
--- a/samples/store-cluster/proxy-conf
+++ b/samples/store-cluster/proxy-conf
@@ -24,7 +24,7 @@
 
 # Configure a proxy balancer
 ../../modules/http/httpd-conf $root sca-store.com $port/80 $root/htdocs
-../../modules/http/vhost-conf $root $root/domains htdocs
+../../modules/http/mass-host-conf $root $root/domains htdocs
 ../../modules/http/proxy-conf $root
 ../../modules/http/httpd-event-conf $root
 
diff --git a/samples/store-cluster/proxy-ssl-conf b/samples/store-cluster/proxy-ssl-conf
index b8d2020..e4ddbb0 100755
--- a/samples/store-cluster/proxy-ssl-conf
+++ b/samples/store-cluster/proxy-ssl-conf
@@ -25,12 +25,13 @@
 
 # Configure an SSL-enabled proxy balancer
 ../../modules/http/httpd-conf $root sca-store.com $port $root/htdocs
-../../modules/http/vhost-conf $root $root/domains htdocs
+../../modules/http/mass-host-conf $root $root/domains htdocs
 ../../modules/http/proxy-conf $root
 ../../modules/http/httpd-event-conf $root
 tar -C tmp/ssl -c `../../modules/http/ssl-cert-find tmp/ssl` | tar -C $root -x
 ../../modules/http/httpd-ssl-conf $root $sslport
-../../modules/http/vhost-ssl-conf $root
+../../modules/http/httpd-tunnel-ssl-conf $root
+../../modules/http/mass-host-ssl-conf $root
 ../../modules/http/proxy-ssl-conf $root
 
 # Aggregate proxy balancer logs
diff --git a/samples/store-cluster/server-conf b/samples/store-cluster/server-conf
index 5113bc3..089e184 100755
--- a/samples/store-cluster/server-conf
+++ b/samples/store-cluster/server-conf
@@ -25,7 +25,7 @@
 # Configure an app server
 ../../modules/http/httpd-conf $root sca-store.com $port/80 htdocs
 ../../modules/http/httpd-event-conf $root
-../../modules/http/vhost-conf $root domains htdocs
+../../modules/http/mass-host-conf $root domains htdocs
 ../../modules/server/server-conf $root
 ../../modules/python/python-conf $root
 cat >>$root/conf/httpd.conf <<EOF
diff --git a/samples/store-cluster/server-ssl-conf b/samples/store-cluster/server-ssl-conf
index a7813b2..4180a44 100755
--- a/samples/store-cluster/server-ssl-conf
+++ b/samples/store-cluster/server-ssl-conf
@@ -26,11 +26,12 @@
 # Configure an SSL-enabled app server
 ../../modules/http/httpd-conf $root sca-store.com $port htdocs
 ../../modules/http/httpd-event-conf $root
-../../modules/http/vhost-conf $root domains htdocs
+../../modules/http/mass-host-conf $root domains htdocs
 
 tar -C tmp/ssl -c `../../modules/http/ssl-cert-find tmp/ssl` | tar -C $root -x
 ../../modules/http/httpd-ssl-conf $root $sslport
-../../modules/http/vhost-ssl-conf $root
+../../modules/http/httpd-tunnel-ssl-conf $root
+../../modules/http/mass-host-ssl-conf $root
 
 ../../modules/oauth/oauth-conf $root
 ../../modules/oauth/oauth-memcached-conf $root localhost 11211
diff --git a/samples/store-constdb/htdocs/index.html b/samples/store-constdb/htdocs/index.html
index 4a62163..0698a32 100644
--- a/samples/store-constdb/htdocs/index.html
+++ b/samples/store-constdb/htdocs/index.html
@@ -21,10 +21,10 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <title>Store</title>
 
-<script type="text/javascript" src="/all.js"></script>
+<script type="text/javascript" src="/all-min.js"></script>
 
 <script type="text/javascript">
 var store = sca.component("Store");
diff --git a/samples/store-cpp/htdocs/index.html b/samples/store-cpp/htdocs/index.html
index 4a62163..0698a32 100644
--- a/samples/store-cpp/htdocs/index.html
+++ b/samples/store-cpp/htdocs/index.html
@@ -21,10 +21,10 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <title>Store</title>
 
-<script type="text/javascript" src="/all.js"></script>
+<script type="text/javascript" src="/all-min.js"></script>
 
 <script type="text/javascript">
 var store = sca.component("Store");
diff --git a/samples/store-gae/htdocs/index.html b/samples/store-gae/htdocs/index.html
index 979d27e..7c9a9e9 100644
--- a/samples/store-gae/htdocs/index.html
+++ b/samples/store-gae/htdocs/index.html
@@ -21,10 +21,10 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <title>Store</title>
 
-<script type="text/javascript" src="/all.js"></script>
+<script type="text/javascript" src="/all-min.js"></script>
 
 <script type="text/javascript">
 var store = sca.component("Store");
diff --git a/samples/store-java/htdocs/index.html b/samples/store-java/htdocs/index.html
index 4a62163..0698a32 100644
--- a/samples/store-java/htdocs/index.html
+++ b/samples/store-java/htdocs/index.html
@@ -21,10 +21,10 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <title>Store</title>
 
-<script type="text/javascript" src="/all.js"></script>
+<script type="text/javascript" src="/all-min.js"></script>
 
 <script type="text/javascript">
 var store = sca.component("Store");
diff --git a/samples/store-python/htdocs/index.html b/samples/store-python/htdocs/index.html
index 4a62163..0698a32 100644
--- a/samples/store-python/htdocs/index.html
+++ b/samples/store-python/htdocs/index.html
@@ -21,10 +21,10 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <title>Store</title>
 
-<script type="text/javascript" src="/all.js"></script>
+<script type="text/javascript" src="/all-min.js"></script>
 
 <script type="text/javascript">
 var store = sca.component("Store");
diff --git a/samples/store-python/htdocs/login/index.html b/samples/store-python/htdocs/login/index.html
index 3936730..fd3bc21 100644
--- a/samples/store-python/htdocs/login/index.html
+++ b/samples/store-python/htdocs/login/index.html
@@ -22,8 +22,8 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
-<script type="text/javascript" src="/all.js"></script>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
+<script type="text/javascript" src="/all-min.js"></script>
 <title>Sign in</title>
 </head>
 <body>
diff --git a/samples/store-python/htdocs/logout/index.html b/samples/store-python/htdocs/logout/index.html
index 1108b00..92fd2a0 100644
--- a/samples/store-python/htdocs/logout/index.html
+++ b/samples/store-python/htdocs/logout/index.html
@@ -22,8 +22,8 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
-<script type="text/javascript" src="/all.js"></script>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
+<script type="text/javascript" src="/all-min.js"></script>
 <title>Sign out</title>
 </head>
 <body>
diff --git a/samples/store-scheme/htdocs/index.html b/samples/store-scheme/htdocs/index.html
index 4a62163..0698a32 100644
--- a/samples/store-scheme/htdocs/index.html
+++ b/samples/store-scheme/htdocs/index.html
@@ -21,10 +21,10 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <title>Store</title>
 
-<script type="text/javascript" src="/all.js"></script>
+<script type="text/javascript" src="/all-min.js"></script>
 
 <script type="text/javascript">
 var store = sca.component("Store");
diff --git a/samples/store-sql/htdocs/index.html b/samples/store-sql/htdocs/index.html
index 4a62163..0698a32 100644
--- a/samples/store-sql/htdocs/index.html
+++ b/samples/store-sql/htdocs/index.html
@@ -21,10 +21,10 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <title>Store</title>
 
-<script type="text/javascript" src="/all.js"></script>
+<script type="text/javascript" src="/all-min.js"></script>
 
 <script type="text/javascript">
 var store = sca.component("Store");
diff --git a/samples/store-vhost/domains/jane/htdocs/index.html b/samples/store-vhost/domains/jane/htdocs/index.html
index 43f624a..832c0a1 100644
--- a/samples/store-vhost/domains/jane/htdocs/index.html
+++ b/samples/store-vhost/domains/jane/htdocs/index.html
@@ -21,10 +21,10 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <title>Jane's Store</title>
 
-<script type="text/javascript" src="/all.js"></script>
+<script type="text/javascript" src="/all-min.js"></script>
 
 <script type="text/javascript">
 var store = sca.component("Store");
diff --git a/samples/store-vhost/domains/joe/htdocs/index.html b/samples/store-vhost/domains/joe/htdocs/index.html
index 34c8dd3..0caf8b3 100644
--- a/samples/store-vhost/domains/joe/htdocs/index.html
+++ b/samples/store-vhost/domains/joe/htdocs/index.html
@@ -21,10 +21,10 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <title>Joe's Store</title>
 
-<script type="text/javascript" src="/all.js"></script>
+<script type="text/javascript" src="/all-min.js"></script>
 
 <script type="text/javascript">
 var store = sca.component("Store");
diff --git a/samples/store-vhost/htdocs/index.html b/samples/store-vhost/htdocs/index.html
index a24ecd4..fc377e5 100644
--- a/samples/store-vhost/htdocs/index.html
+++ b/samples/store-vhost/htdocs/index.html
@@ -21,7 +21,7 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <title>Store</title>
 </head>
 
diff --git a/samples/store-vhost/ssl-start b/samples/store-vhost/ssl-start
index ef6e40f..528c0a5 100755
--- a/samples/store-vhost/ssl-start
+++ b/samples/store-vhost/ssl-start
@@ -25,9 +25,9 @@
 ../../modules/http/ssl-cert-conf tmp *.example.com vhost
 ../../modules/http/httpd-conf tmp example.com 8090 htdocs
 ../../modules/http/httpd-event-conf tmp
-../../modules/http/vhost-conf tmp domains htdocs
+../../modules/http/mass-host-conf tmp domains htdocs
 ../../modules/http/httpd-ssl-conf tmp 8453
-../../modules/http/vhost-ssl-conf tmp
+../../modules/http/mass-host-ssl-conf tmp
 ../../modules/http/basic-auth-conf tmp
 ../../modules/http/passwd-auth-conf tmp foo foo
 ../../modules/server/server-conf tmp
diff --git a/samples/store-vhost/start b/samples/store-vhost/start
index fef691a..6a20a60 100755
--- a/samples/store-vhost/start
+++ b/samples/store-vhost/start
@@ -20,7 +20,7 @@
 rm -rf tmp
 ../../modules/http/httpd-conf tmp example.com 8090 htdocs
 ../../modules/http/httpd-event-conf tmp
-../../modules/http/vhost-conf tmp domains htdocs
+../../modules/http/mass-host-conf tmp domains htdocs
 ../../modules/server/server-conf tmp
 ../../modules/python/python-conf tmp
 cat >>tmp/conf/httpd.conf <<EOF
diff --git a/samples/store-vhost/uec2-start b/samples/store-vhost/uec2-start
index d530d1d..f86ce0f 100755
--- a/samples/store-vhost/uec2-start
+++ b/samples/store-vhost/uec2-start
@@ -34,9 +34,9 @@
 ../../modules/http/ssl-cert-conf tmp "*.$host" vhost
 ../../modules/http/httpd-conf tmp $host 8090/80 htdocs
 ../../modules/http/httpd-event-conf tmp
-../../modules/http/vhost-conf tmp domains htdocs
+../../modules/http/mass-host-conf tmp domains htdocs
 ../../modules/http/httpd-ssl-conf tmp 8453/443
-../../modules/http/vhost-ssl-conf tmp
+../../modules/http/mass-host-ssl-conf tmp
 ../../modules/server/server-conf tmp
 ../../modules/python/python-conf tmp
 cat >>tmp/conf/httpd.conf <<EOF