diff --git a/examples/webui-preact/Makefile b/examples/webui-preact/Makefile
new file mode 100644
index 00000000..9addcb99
--- /dev/null
+++ b/examples/webui-preact/Makefile
@@ -0,0 +1,20 @@
+PROG ?= example
+SSL = ?
+
+ifeq "$(SSL)" "MBEDTLS"
+CFLAGS += -DMG_ENABLE_MBEDTLS=1 -lmbedtls -lmbedcrypto -lmbedx509
+endif
+
+ifeq "$(SSL)" "OPENSSL"
+CFLAGS += -DMG_ENABLE_OPENSSL=1 -lssl -lcrypto
+endif
+
+all: $(PROG)
+ $(DEBUGGER) ./$(PROG) $(ARGS)
+
+
+$(PROG): main.c
+ $(CC) ../../mongoose.c -I../.. -W -Wall $(CFLAGS) $(EXTRA_CFLAGS) -o $(PROG) main.c
+
+clean:
+ rm -rf $(PROG) *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb
diff --git a/examples/webui-preact/ca.pem b/examples/webui-preact/ca.pem
new file mode 120000
index 00000000..8addd9e2
--- /dev/null
+++ b/examples/webui-preact/ca.pem
@@ -0,0 +1 @@
+../../test/data/ca.pem
\ No newline at end of file
diff --git a/examples/webui-preact/main.c b/examples/webui-preact/main.c
new file mode 120000
index 00000000..5f0bdc78
--- /dev/null
+++ b/examples/webui-preact/main.c
@@ -0,0 +1 @@
+../webui-plain/main.c
\ No newline at end of file
diff --git a/examples/webui-preact/web_root/index.html b/examples/webui-preact/web_root/index.html
new file mode 100644
index 00000000..1ac23a2b
--- /dev/null
+++ b/examples/webui-preact/web_root/index.html
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/examples/webui-preact/web_root/main.js b/examples/webui-preact/web_root/main.js
new file mode 100644
index 00000000..7ac7d25b
--- /dev/null
+++ b/examples/webui-preact/web_root/main.js
@@ -0,0 +1,86 @@
+'use strict';
+import { h, html, render, useEffect, useState } from './preact.min.js';
+
+
+const Configuration = function (props) {
+ const [url, setUrl] = useState(props.config.url || '');
+ const [pub, setPub] = useState(props.config.pub || '');
+ const [sub, setSub] = useState(props.config.sub || '');
+
+ useEffect(() => {
+ setUrl(props.config.url);
+ setPub(props.config.pub);
+ setSub(props.config.sub);
+ }, [props.config]);
+
+ const update = (name, val) =>
+ fetch('/api/config/set', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ [name]: val
+ })
+ })
+ .catch(err => {
+ console.log(err);
+ enable(false);
+ });
+
+ const updateurl = ev => update('url', url);
+ const updatepub = ev => update('pub', pub);
+ const updatesub = ev => update('sub', sub);
+
+ return html`
+
+ Device Configuration
+
+ MQTT server:
+ setUrl(ev.target.value)} />
+
+
+
+ Subscribe topic:
+ setSub(ev.target.value)} />
+
+
+
+ Publish topic:
+ setPub(ev.target.value)} />
+
+
`;
+};
+
+
+const App = function (props) {
+ const [config, setConfig] = useState({});
+
+ const getconfig = () =>
+ fetch('/api/config/get')
+ .then(r => r.json())
+ .then(r => setConfig(r))
+ .catch(err => console.log(err));
+
+ useEffect(() => {
+ getconfig();
+ }, []);
+
+ return html`
+Basic Preact-based UI demo
+
+ ${h(Configuration, { config })}
+
+`;
+};
+
+window.onload = () => render(h(App), document.body);
diff --git a/examples/webui-preact/web_root/preact.min.js b/examples/webui-preact/web_root/preact.min.js
new file mode 100644
index 00000000..e24f87b9
--- /dev/null
+++ b/examples/webui-preact/web_root/preact.min.js
@@ -0,0 +1 @@
+var e,n,_,t,o,r,u,l={},i=[],c=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;function s(e,n){for(var _ in n)e[_]=n[_];return e}function f(e){var n=e.parentNode;n&&n.removeChild(e)}function a(n,_,t){var o,r,u,l={};for(u in _)"key"==u?o=_[u]:"ref"==u?r=_[u]:l[u]=_[u];if(arguments.length>2&&(l.children=arguments.length>3?e.call(arguments,2):t),"function"==typeof n&&null!=n.defaultProps)for(u in n.defaultProps)void 0===l[u]&&(l[u]=n.defaultProps[u]);return p(n,l,o,r,null)}function p(e,t,o,r,u){var l={type:e,props:t,key:o,ref:r,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==u?++_:u};return null!=n.vnode&&n.vnode(l),l}function h(e){return e.children}function d(e,n){this.props=e,this.context=n}function v(e,n){if(null==n)return e.__?v(e.__,e.__.__k.indexOf(e)+1):null;for(var _;n0?p(m.type,m.props,m.key,null,m.__v):m)){if(m.__=_,m.__b=_.__b+1,null===(y=H[a])||y&&m.key==y.key&&m.type===y.type)H[a]=void 0;else for(d=0;d=t.__.length&&t.__.push({}),t.__[e]}function G(e){return R=1,z(ie,e)}function z(e,n,_){var t=j(L++,2);return t.t=e,t.__c||(t.__=[_?_(n):ie(void 0,n),function(e){var n=t.t(t.__[0],e);t.__[0]!==n&&(t.__=[n,t.__[1]],t.__c.setState({}))}],t.__c=N),t.__}function J(e,_){var t=j(L++,3);!n.__s&&le(t.__H,_)&&(t.__=e,t.__H=_,N.__H.__h.push(t))}function K(e,_){var t=j(L++,4);!n.__s&&le(t.__H,_)&&(t.__=e,t.__H=_,N.__h.push(t))}function Q(e){return R=5,Y(function(){return{current:e}},[])}function X(e,n,_){R=6,K(function(){"function"==typeof e?e(n()):e&&(e.current=n())},null==_?_:_.concat(e))}function Y(e,n){var _=j(L++,7);return le(_.__H,n)&&(_.__=e(),_.__H=n,_.__h=e),_.__}function Z(e,n){return R=8,Y(function(){return e},n)}function ee(e){var n=N.context[e.__c],_=j(L++,9);return _.c=e,n?(null==_.__&&(_.__=!0,n.sub(N)),n.props.value):e.__}function ne(e,_){n.useDebugValue&&n.useDebugValue(_?_(e):e)}function _e(e){var n=j(L++,10),_=G();return n.__=e,N.componentDidCatch||(N.componentDidCatch=function(e){n.__&&n.__(e),_[1](e)}),[_[0],function(){_[1](void 0)}]}function te(){I.forEach(function(e){if(e.__P)try{e.__H.__h.forEach(re),e.__H.__h.forEach(ue),e.__H.__h=[]}catch(_){e.__H.__h=[],n.__e(_,e.__v)}}),I=[]}n.__b=function(e){N=null,O&&O(e)},n.__r=function(e){V&&V(e),L=0;var n=(N=e.__c).__H;n&&(n.__h.forEach(re),n.__h.forEach(ue),n.__h=[])},n.diffed=function(e){q&&q(e);var _=e.__c;_&&_.__H&&_.__H.__h.length&&(1!==I.push(_)&&W===n.requestAnimationFrame||((W=n.requestAnimationFrame)||function(e){var n,_=function(){clearTimeout(t),oe&&cancelAnimationFrame(n),setTimeout(e)},t=setTimeout(_,100);oe&&(n=requestAnimationFrame(_))})(te)),N=void 0},n.__c=function(e,_){_.some(function(e){try{e.__h.forEach(re),e.__h=e.__h.filter(function(e){return!e.__||ue(e)})}catch(t){_.some(function(e){e.__h&&(e.__h=[])}),_=[],n.__e(t,e.__v)}}),B&&B(e,_)},n.unmount=function(e){$&&$(e);var _=e.__c;if(_&&_.__H)try{_.__H.__.forEach(re)}catch(e){n.__e(e,_.__v)}};var oe="function"==typeof requestAnimationFrame;function re(e){var n=N;"function"==typeof e.__c&&e.__c(),N=n}function ue(e){var n=N;e.__c=e.__(),N=n}function le(e,n){return!e||e.length!==n.length||n.some(function(n,_){return n!==e[_]})}function ie(e,n){return"function"==typeof n?n(e):n}var ce=function(e,n,_,t){var o;n[0]=0;for(var r=1;r=5&&((o||!e&&5===t)&&(u.push(t,0,o,_),t=6),e&&(u.push(t,e,0,_),t=6)),o=""},i=0;i"===n?(t=1,o=""):o=n+o[0]:r?n===r?r="":o+=n:'"'===n||"'"===n?r=n:">"===n?(l(),t=1):t&&("="===n?(t=5,_=o,o=""):"/"===n&&(t<5||">"===e[i][c+1])?(l(),3===t&&(u=u[0]),t=u,(u=u[0]).push(2,0,t),t=0):" "===n||"\t"===n||"\n"===n||"\r"===n?(l(),t=2):o+=n),3===t&&"!--"===o&&(t=4,u=u[0])}return l(),u}(e)),n),arguments,[])).length>1?n:n[0]}.bind(a);export{a as h,fe as html,M as render,d as Component,F as createContext,G as useState,z as useReducer,J as useEffect,K as useLayoutEffect,Q as useRef,X as useImperativeHandle,Y as useMemo,Z as useCallback,ee as useContext,ne as useDebugValue,_e as useErrorBoundary};
diff --git a/examples/webui-preact/web_root/style.css b/examples/webui-preact/web_root/style.css
new file mode 100644
index 00000000..b483f801
--- /dev/null
+++ b/examples/webui-preact/web_root/style.css
@@ -0,0 +1,43 @@
+* { box-sizing: border-box; }
+html, body { margin: 0; padding: 0; height: 100%; font: 16px sans-serif; }
+select, input, label::before, textarea { outline: none; box-shadow:none !important; border: 1px solid #ccc !important; }
+code, pre { color: #373; font-family: monospace; font-weight: bolder; font-size: smaller; background: #ddd; padding: 0.1em 0.3em; border-radius: 0.2em; }
+textarea, input, .addon { font-size: 15px; border: 1px solid #ccc; padding: 0.5em; }
+a, a:visited, a:active { color: #55f; }
+.addon { background: #eee; min-width: 9em;}
+.btn {
+ background: #ccc; border-radius: 0.3em; border: 0; color: #fff; cursor: pointer;
+ display: inline-block; padding: 0.6em 2em; font-weight: bolder;
+}
+.btn[disabled] { opacity: 0.5; cursor: auto;}
+.smooth { transition: all .2s; }
+.container { margin: 0 20px; width: auto; }
+.d-flex { display: flex; }
+.d-none { display: none; }
+.border { border: 1px solid #ddd; }
+.rounded { border-radius: 0.5em; }
+.nowrap { white-space: nowrap; }
+.msg { background: #def; border-left: 5px solid #59d; padding: 0.5em; font-size: 90%; margin: 1em 0; }
+.section { margin: 0 1em; }
+.topic, .data, .qos { padding: 0.2em 0.5em; border-radius: 0.4em; margin-right: 0.5em; }
+.qos { background: #efa; }
+.topic { background: #fea; }
+.data { background: #aef; }
+
+/* Grid */
+.row { display: flex; flex-wrap: wrap; }
+.col { margin: 0; padding: 0; overflow: auto; }
+.col-12 { width: 100%; }
+.col-11 { width: 91.66%; }
+.col-10 { width: 83.33%; }
+.col-9 { width: 75%; }
+.col-8 { width: 66.66%; }
+.col-7 { width: 58.33%; }
+.col-6 { width: 50%; }
+.col-5 { width: 41.66%; }
+.col-4 { width: 33.33%; }
+.col-3 { width: 25%; }
+.col-2 { width: 16.66%; }
+.col-1 { width: 8.33%; }
+@media (min-width: 1310px) { .container { margin: auto; width: 1270px; } }
+@media (max-width: 920px) { .row .col { width: 100%; } }