diff --git a/web/lib/events/telegram.js b/web/lib/events/telegram.js
new file mode 100644
index 0000000000000000000000000000000000000000..45ab4b5d9ede0d12ceb38e1e1acd33f78439219f
--- /dev/null
+++ b/web/lib/events/telegram.js
@@ -0,0 +1,12 @@
+var last_run = 0;
+var frequency = 15;
+
+function cycle() {
+    if (user.alias === settings.guest) return;
+    if (time() - last_run <= frequency) return;
+    last_run = time();
+    const tg = system.get_telegram(user.number);
+    if (tg !== null) emit({ event: 'telegram', data: JSON.stringify(tg) });
+}
+
+this;
diff --git a/web/root/index.xjs b/web/root/index.xjs
index 9c6c78d99f4bf5ba8ae4718ff70c485b3bb36b99..cae608b34e2fc4476e92f9d8ecfdde782f711c59 100644
--- a/web/root/index.xjs
+++ b/web/root/index.xjs
@@ -98,9 +98,6 @@
 		<?xjs if (file_exists(settings.web_root + 'css/custom.css')) { ?>
 			<link href="./css/custom.css" rel="stylesheet">
 		<?xjs } ?>
-        <script type="text/javascript">
-            const _sbbs_events = {};
-        </script>
 	</head>
 
 	<body>
@@ -238,13 +235,6 @@
     				);
     			}
     		);
-            const _evtqs = Object.keys(_sbbs_events).reduce(function (a, c, i) {
-                return a + (i == 0 ? '?' : '&') + 'subscribe=' + c; }, ''
-            );
-            const _es = new EventSource('/api/events.ssjs' + _evtqs);
-            Object.keys(_sbbs_events).forEach(function (e) {
-                _es.addEventListener(e, _sbbs_events[e]);
-            });
     	</script>
 
 	</body>
diff --git a/web/root/js/common.js b/web/root/js/common.js
index 0649837d1ab89a2cbac48015c9fe1c7b12153fb7..7850c82ab9993b342670511077091a691618dab9 100644
--- a/web/root/js/common.js
+++ b/web/root/js/common.js
@@ -1,45 +1,36 @@
 // How often to check for unread mail, new telegrams (milliseconds)
 var updateInterval = 60000;
+const _sbbs_events = {};
 
 function login(evt) {
-	if ($('#input-username').val() === '' ||
-		$('#input-password').val() === ''
-	) {
+	if ($('#input-username').val() == '' || $('#input-password').val() == '') {
 		return;
 	}
 	if (typeof evt !== 'undefined') evt.preventDefault();
-	$.ajax(
-		{	'url' : './api/auth.ssjs',
-			'method' : 'POST',
-			'data' : {
-				username : $('#input-username').val(),
-				password : $('#input-password').val()
-			}
+	$.ajax({
+        url: './api/auth.ssjs',
+		method: 'POST',
+		data: {
+			username : $('#input-username').val(),
+			password : $('#input-password').val()
 		}
-	).done(
-		function (data) {
-			if (data.authenticated) {
-				window.location.reload(true);
-			} else {
-				$('#login-form').append(
-					'<p class="text-danger">Login failed</p>'
-				);
-			}
+	}).done(function (data) {
+		if (data.authenticated) {
+			window.location.reload(true);
+		} else {
+			$('#login-form').append('<p class="text-danger">Login failed</p>');
 		}
-	);
+	});
 }
 
 function logout() {
-	$.ajax(
-		{	'url' : './api/auth.ssjs',
-			'method' : 'GET',
-			'data' : {
-				'logout' : true
-			}
-		}
-	).done(
-		function (data) { if (!data.authenticated) window.location.href = '/'; }
-	);
+	$.ajax({
+        url: './api/auth.ssjs',
+		method: 'GET',
+		data: { logout: true }
+	}).done(function (data) {
+        if (!data.authenticated) window.location.href = '/';
+    });
 }
 
 function scrollUp() {
@@ -49,15 +40,10 @@ function scrollUp() {
 }
 
 function getMailUnreadCount() {
-	$.getJSON(
-		'./api/forum.ssjs?call=get-mail-unread-count',
-		function (data) {
-			$('#badge-unread-mail').text(data.count < 1 ? '' : data.count);
-			$('#badge-unread-mail-inner').text(
-				data.count < 1 ? '' : data.count
-			);
-		}
-	);
+	$.getJSON('./api/forum.ssjs?call=get-mail-unread-count', function (data) {
+		$('#badge-unread-mail').text(data.count < 1 ? '' : data.count);
+		$('#badge-unread-mail-inner').text(data.count < 1 ? '' : data.count);
+	});
 }
 
 function sendTelegram(alias) {
@@ -67,72 +53,60 @@ function sendTelegram(alias) {
 		'placeholder="My message" name="telegram" id="telegram">'
 	);
 	$('#popUpModalActionButton').show();
-	$('#popUpModalActionButton').click(
-		function () {
-			$.getJSON(
-				'./api/system.ssjs?call=send-telegram&user=' +
-				alias + '&telegram=' + $('#telegram').val(),
-				function(data) {}
-			);
-			$('#popUpModal').modal('hide');
-		}
-	);
+	$('#popUpModalActionButton').click(function () {
+		$.getJSON(
+			'./api/system.ssjs?call=send-telegram&user=' +
+			alias + '&telegram=' + $('#telegram').val(),
+			function(data) {}
+		);
+        $('#popUpModal').modal('hide');
+	});
 	$('#popUpModal').modal('show');
 }
 
-function getTelegram() {
-	$.getJSON(
-		'./api/system.ssjs?call=get-telegram',
-		function (data) {
-			if (typeof data.telegram === 'undefined' ||
-				data.telegram === null
-			) {
-				return;
-			}
-			var tg = data.telegram.replace(
-				/\1./g, ''
-			).replace(
-				/\r?\n/g, '<br>'
-			);
-			$('#popUpModalTitle').html('New telegram(s) received');
-			$('#popUpModalBody').append(tg);
-			$('#popUpModalActionButton').hide();
-			$('#popUpModal').modal('show');
-		}
-	);
-}
-
 window.onload =	function () {
 
 	$('#button-logout').click(logout);
 	$('#button-login').click(login);
 	$('#form-login').submit(login);
 
-	$('#popUpModal').on(
-		'hidden.bs.modal',
-		function (e) {
-			$('#popUpModalActionButton').off('click');
-			$('#popUpModalTitle').empty();
-			$('#popUpModalBody').empty();
-		}
-	);
-	$("#popUpModalCloseButton").click(
-		function () {
-			$('#popUpModal').modal('hide');
-		}
-	);
+	$('#popUpModal').on('hidden.bs.modal', function (e) {
+		$('#popUpModalActionButton').off('click');
+		$('#popUpModalTitle').empty();
+		$('#popUpModalBody').empty();
+	});
+	$("#popUpModalCloseButton").click(function () {
+		$('#popUpModal').modal('hide');
+	});
 
 	setTimeout(scrollUp, 25);
 	window.onhashchange = scrollUp;
 
 	if ($('#button-logout').length > 0) {
 
-        getMailUnreadCount();
-        setInterval(getMailUnreadCount, updateInterval);
+        // Write backing event module
+        // Switch to event subscription & callback
+		getMailUnreadCount();
+		setInterval(getMailUnreadCount, updateInterval);
 
-        getTelegram();
-        setInterval(getTelegram, updateInterval);
+        _sbbs_events.telegram = function (e) {
+            const tg = JSON.parse(e.data).replace(/\1./g, '').replace(
+                /\r?\n/g, '<br>'
+            );
+            $('#popUpModalTitle').html('New telegram(s) received');
+            $('#popUpModalBody').append(tg);
+            $('#popUpModalActionButton').hide();
+            $('#popUpModal').modal('show');
+        }
+
+	}
 
-    }
+    const _evtqs = Object.keys(_sbbs_events).reduce(function (a, c, i) {
+        return a + (i == 0 ? '?' : '&') + 'subscribe=' + c; }, ''
+    );
+    const _es = new EventSource('/api/events.ssjs' + _evtqs);
+    Object.keys(_sbbs_events).forEach(function (e) {
+        _es.addEventListener(e, _sbbs_events[e]);
+    });
 
 }