diff --git a/mod/ping.php b/mod/ping.php
index d5b43d6ea4..813ea6a1ad 100644
--- a/mod/ping.php
+++ b/mod/ping.php
@@ -31,6 +31,7 @@ use Friendica\Model\Group;
 use Friendica\Model\Notification;
 use Friendica\Model\Post;
 use Friendica\Model\Verb;
+use Friendica\Navigation\Notifications\Entity;
 use Friendica\Protocol\Activity;
 use Friendica\Util\DateTimeFormat;
 use Friendica\Util\Proxy;
@@ -253,58 +254,53 @@ function ping_init(App $a)
 		$data['birthdays']        = $birthdays;
 		$data['birthdays-today']  = $birthdays_today;
 
-		if (DBA::isResult($notifications)) {
-			foreach ($notifications as $notif) {
-				if ($notif['seen'] == 0) {
-					$sysnotify_count ++;
-				}
+		foreach ($notifications as $notification) {
+			if ($notification['seen'] == 0) {
+				$sysnotify_count ++;
 			}
 		}
 
 		// merge all notification types in one array
 		if (DBA::isResult($intros)) {
 			foreach ($intros as $intro) {
-				$notif = [
-					'id'      => 0,
+				$notifications[] = [
 					'href'    => DI::baseUrl() . '/notifications/intros/' . $intro['id'],
-					'name'    => BBCode::convert($intro['name']),
-					'url'     => $intro['url'],
-					'photo'   => $intro['photo'],
+					'contact' => [
+						'name'    => strip_tags(BBCode::convert($intro['name'])),
+						'url'     => $intro['url'],
+					],
+					'message' => DI::l10n()->t('{0}} wants to follow you'),
 					'date'    => $intro['datetime'],
 					'seen'    => false,
-					'message' => DI::l10n()->t('{0} wants to be your friend'),
 				];
-				$notifications[] = $notif;
 			}
 		}
 
 		if (DBA::isResult($regs)) {
 			if (count($regs) <= 1 || DI::pConfig()->get(local_user(), 'system', 'detailed_notif')) {
 				foreach ($regs as $reg) {
-					$notif = [
-						'id'      => 0,
+					$notifications[] = [
 						'href'    => DI::baseUrl()->get(true) . '/admin/users/pending',
-						'name'    => $reg['name'],
-						'url'     => $reg['url'],
-						'photo'   => $reg['micro'],
+						'contact' => [
+							'name'    => $reg['name'],
+							'url'     => $reg['url'],
+						],
+						'message' => DI::l10n()->t('{0} requested registration'),
 						'date'    => $reg['created'],
 						'seen'    => false,
-						'message' => DI::l10n()->t('{0} requested registration'),
 					];
-					$notifications[] = $notif;
 				}
 			} else {
-				$notif = [
-					'id'      => 0,
+				$notifications[] = [
 					'href'    => DI::baseUrl()->get(true) . '/admin/users/pending',
-					'name'    => $regs[0]['name'],
-					'url'     => $regs[0]['url'],
-					'photo'   => $regs[0]['micro'],
+					'contact' => [
+						'name'    => $regs[0]['name'],
+						'url'     => $regs[0]['url'],
+					],
+					'message' => DI::l10n()->t('{0} and %d others requested registration', count($regs) - 1),
 					'date'    => $regs[0]['created'],
 					'seen'    => false,
-					'message' => DI::l10n()->t('{0} and %d others requested registration', count($regs) - 1),
 				];
-				$notifications[] = $notif;
 			}
 		}
 
@@ -328,12 +324,6 @@ function ping_init(App $a)
 			return ($adate < $bdate) ? 1 : -1;
 		};
 		usort($notifications, $sort_function);
-
-		array_walk($notifications, function (&$notification) {
-			$notification['photo']     = Contact::getAvatarUrlForUrl($notification['url'], local_user(), Proxy::SIZE_MICRO);
-			$notification['timestamp'] = DateTimeFormat::local($notification['date']);
-			$notification['date']      = Temporal::getRelativeDate($notification['date']);
-		});
 	}
 
 	$sysmsgs = [];
@@ -351,11 +341,26 @@ function ping_init(App $a)
 
 	if ($format == 'json') {
 		$notification_count = $sysnotify_count + $intro_count + $register_count;
-		
+
+		$tpl = \Friendica\Core\Renderer::getMarkupTemplate('notifications/nav/notify.tpl');
+
 		$data['groups'] = $groups_unseen;
 		$data['forums'] = $forums_unseen;
 		$data['notification'] = ($notification_count < 50) ? $notification_count : '49+';
-		$data['notifications'] = $notifications;
+		$data['notifications'] = array_map(function ($navNotification) use ($tpl) {
+			$navNotification['contact']['photo'] = Contact::getAvatarUrlForUrl($navNotification['contact']['url'], local_user(), Proxy::SIZE_MICRO);
+
+			$navNotification['timestamp'] = strtotime($navNotification['date']);
+			$navNotification['localdate'] = DateTimeFormat::local($navNotification['date']);
+			$navNotification['ago']       = Temporal::getRelativeDate($navNotification['date']);
+			$navNotification['richtext']  = Entity\Notify::formatMessage($navNotification['contact']['name'], $navNotification['message']);
+			$navNotification['plaintext'] = strip_tags($navNotification['richtext']);
+			$navNotification['html']      = \Friendica\Core\Renderer::replaceMacros($tpl, [
+				'notify' => $navNotification,
+			]);
+
+			return $navNotification;
+		}, $notifications);
 		$data['sysmsgs'] = [
 			'notice' => $sysmsgs,
 			'info' => $sysmsgs_info
@@ -394,14 +399,15 @@ function ping_get_notifications($uid)
 	$result  = [];
 	$offset  = 0;
 	$seen    = false;
-	$seensql = "NOT";
-	$order   = "DESC";
+	$seensql = 'NOT';
+	$order   = 'DESC';
 	$quit    = false;
 
 	do {
-		$r = DBA::toArray(DBA::p(
+		$notifies = DBA::toArray(DBA::p(
 			"SELECT `notify`.*, `post`.`visible`, `post`.`deleted`
-			FROM `notify` LEFT JOIN `post` ON `post`.`uri-id` = `notify`.`uri-id`
+			FROM `notify`
+			LEFT JOIN `post` ON `post`.`uri-id` = `notify`.`uri-id`
 			WHERE `notify`.`uid` = ? AND `notify`.`msg` != ''
 			AND NOT (`notify`.`type` IN (?, ?))
 			AND $seensql `notify`.`seen` ORDER BY `notify`.`date` $order LIMIT ?, 50",
@@ -411,48 +417,52 @@ function ping_get_notifications($uid)
 			$offset
 		));
 
-		if (!$r && !$seen) {
+		if (!$notifies && !$seen) {
 			$seen = true;
-			$seensql = "";
-			$order = "DESC";
+			$seensql = '';
+			$order = 'DESC';
 			$offset = 0;
-		} elseif (!$r) {
+		} elseif (!$notifies) {
 			$quit = true;
 		} else {
 			$offset += 50;
 		}
 
-		foreach ($r as $notification) {
-			if (is_null($notification["visible"])) {
-				$notification["visible"] = true;
-			}
+		foreach ($notifies as $notify) {
+			$notify['visible'] = $notify['visible'] ?? true;
+			$notify['deleted'] = $notify['deleted'] ?? 0;
 
-			if (is_null($notification["deleted"])) {
-				$notification["deleted"] = 0;
-			}
-
-			if ($notification["msg_cache"]) {
-				$notification["name"] = $notification["name_cache"];
-				$notification["message"] = $notification["msg_cache"];
+			if ($notify['msg_cache']) {
+				$notify['name'] = $notify['name_cache'];
+				$notify['message'] = $notify['msg_cache'];
 			} else {
-				$notification["name"] = strip_tags(BBCode::convert($notification["name"]));
-				$notification["message"] = \Friendica\Navigation\Notifications\Entity\Notify::formatMessage($notification["name"], BBCode::toPlaintext($notification["msg"]));
+				$notify['name'] = strip_tags(BBCode::convert($notify['name']));
+				$notify['message'] = BBCode::toPlaintext($notify['msg']);
 
 				// @todo Replace this with a call of the Notify model class
-				DBA::update('notify', ['name_cache' => $notification["name"], 'msg_cache' => $notification["message"]], ['id' => $notification["id"]]);
+				DBA::update('notify', ['name_cache' => $notify['name'], 'msg_cache' => $notify['message']], ['id' => $notify['id']]);
 			}
 
-			$notification["href"] = DI::baseUrl() . "/notify/" . $notification["id"];
-
-			if ($notification["visible"]
-				&& !$notification["deleted"]
-				&& empty($result['p:' . $notification['parent']])
+			if ($notify['visible']
+				&& !$notify['deleted']
+				&& empty($result['p:' . $notify['parent']])
 			) {
+				$notification = [
+					'href' => DI::baseUrl() . '/notify/' . $notify['id'],
+					'contact' => [
+						'name'  => $notify['name'],
+						'url'   => $notify['url'],
+					],
+					'message' => $notify['message'],
+					'date'    => $notify['date'],
+					'seen'    => $notify['seen'],
+				];
+
 				// Should we condense the notifications or show them all?
-				if (($notification['verb'] != Activity::POST) || DI::pConfig()->get(local_user(), 'system', 'detailed_notif')) {
+				if (($notify['verb'] != Activity::POST) || DI::pConfig()->get(local_user(), 'system', 'detailed_notif')) {
 					$result[] = $notification;
 				} else {
-					$result['p:' . $notification['parent']] = $notification;
+					$result['p:' . $notify['parent']] = $notification;
 				}
 			}
 		}
diff --git a/src/Navigation/Notifications/Entity/Notify.php b/src/Navigation/Notifications/Entity/Notify.php
index 8f8166ab90..1070440073 100644
--- a/src/Navigation/Notifications/Entity/Notify.php
+++ b/src/Navigation/Notifications/Entity/Notify.php
@@ -134,16 +134,6 @@ class Notify extends BaseEntity
 	 */
 	public static function formatMessage(string $name, string $message): string
 	{
-		if ($name != '') {
-			$pos = strpos($message, $name);
-		} else {
-			$pos = false;
-		}
-
-		if ($pos !== false) {
-			$message = substr_replace($message, '{0}', $pos, strlen($name));
-		}
-
-		return $message;
+		return str_replace('{0}', '<span class="contactname">' . strip_tags(BBCode::convert($name)) . '</span>', $message);
 	}
 }
diff --git a/view/js/main.js b/view/js/main.js
index d029ec13bc..c4109a8c70 100644
--- a/view/js/main.js
+++ b/view/js/main.js
@@ -239,7 +239,6 @@ $(function() {
 	});
 
 	/* notifications template */
-	var notifications_tpl= unescape($("#nav-notifications-template[rel=template]").html());
 	var notifications_all = unescape($('<div>').append($("#nav-notifications-see-all").clone()).html()); //outerHtml hack
 	var notifications_mark = unescape($('<div>').append($("#nav-notifications-mark-all").clone()).html()); //outerHtml hack
 	var notifications_empty = unescape($("#nav-notifications-menu").html());
@@ -315,34 +314,20 @@ $(function() {
 			var notification_id = 0;
 
 			// Insert notifs into the notifications-menu
-			$(data.notifications).each(function(key, notification) {
-				var text = notification.message.format('<span class="contactname">' + notification.name + '</span>');
-				var contact = ('<a href="' + notification.url + '"><span class="contactname">' + notification.name + '</span></a>');
-				var seenclass = (notification.seen == 1) ? "notification-seen" : "notification-unseen";
-				var html = notifications_tpl.format(
-					notification.href,                     // {0}  // link to the source
-					notification.photo,                    // {1}  // photo of the contact
-					text,                           // {2}  // preformatted text (autor + text)
-					notification.date,                     // {3}  // date of notification (time ago)
-					seenclass,                      // {4}  // visited status of the notification
-					new Date(notification.timestamp*1000), // {5}  // date of notification
-					notification.url,                      // {6}  // profile url of the contact
-					notification.message.format(contact),  // {7}  // preformatted html (text including author profile url)
-					''                              // {8}  // Deprecated
-				);
-				nnm.append(html);
+			$(data.notifications).each(function(key, navNotif) {
+				nnm.append(navNotif.html);
 			});
 
 			// Desktop Notifications
-			$(data.notifications.reverse()).each(function(key, e) {
-				notification_id = parseInt(e.timestamp);
-				if (notification_lastitem !== null && notification_id > notification_lastitem && Number(e.seen) === 0) {
+			$(data.notifications.reverse()).each(function(key, navNotif) {
+				notification_id = parseInt(navNotif.timestamp);
+				if (notification_lastitem !== null && notification_id > notification_lastitem && Number(navNotif.seen) === 0) {
 					if (getNotificationPermission() === "granted") {
 						var notification = new Notification(document.title, {
-										  body: decodeHtml(e.message.replace('&rarr; ', '').format(e.name)),
-										  icon: e.photo,
-										});
-						notification['url'] = e.href;
+							body: decodeHtml(navNotif.plaintext),
+							icon: navNotif.contact.photo,
+						});
+						notification['url'] = navNotif.href;
 						notification.addEventListener("click", function(ev) {
 							window.location = ev.target.url;
 						});
diff --git a/view/templates/nav.tpl b/view/templates/nav.tpl
index fbce697eaf..3c1b9f26b2 100644
--- a/view/templates/nav.tpl
+++ b/view/templates/nav.tpl
@@ -65,7 +65,3 @@
 	<span id="nav-end"></span>
 	<span id="banner">{{$banner nofilter}}</span>
 </nav>
-
-<ul id="nav-notifications-template" style="display:none;" rel="template">
-	<li class="{4}"><a href="{0}" title="{5}"><img data-src="{1}" height="24" width="24" alt="" />{2} <span class="notif-when">{3}</span></a></li>
-</ul>
diff --git a/view/templates/notifications/nav/notify.tpl b/view/templates/notifications/nav/notify.tpl
new file mode 100644
index 0000000000..dfcf9d3346
--- /dev/null
+++ b/view/templates/notifications/nav/notify.tpl
@@ -0,0 +1,3 @@
+<li class="notification-{{if !$notify.seen}}un{{/if}}seen">
+	<a href="{{$notify.href}}" title="{{$notify.localdate}}"><img data-src="{{$notify.contact.photo}}" height="24" width="24" alt="" />{{$notify.richtext nofilter}} <span class="notif-when">{{$notify.ago}}</span></a>
+</li>
diff --git a/view/theme/duepuntozero/templates/nav.tpl b/view/theme/duepuntozero/templates/nav.tpl
index 85c6b047e7..8e386d5e6a 100644
--- a/view/theme/duepuntozero/templates/nav.tpl
+++ b/view/theme/duepuntozero/templates/nav.tpl
@@ -67,7 +67,3 @@
 	<span id="nav-end"></span>
 	<span id="banner">{{$banner nofilter}}</span>
 </nav>
-
-<ul id="nav-notifications-template" style="display:none;" rel="template">
-	<li class="{4}"><a href="{0}" title="{5}"><img data-src="{1}" height="24" width="24" alt="" />{2} <span class="notif-when">{3}</span></a></li>
-</ul>
diff --git a/view/theme/frio/templates/nav.tpl b/view/theme/frio/templates/nav.tpl
index 53176fe92c..a8a9b935de 100644
--- a/view/theme/frio/templates/nav.tpl
+++ b/view/theme/frio/templates/nav.tpl
@@ -461,22 +461,6 @@
 	</div>
 </div>
 
-{{*The second part of the notifications dropdown menu. It handles the notifications *}}
-{{if $nav.notifications}}
-	<ul id="nav-notifications-template" class="media-list" style="display:none;" rel="template">
-		<li class="{4} notif-entry">
-			<div class="notif-entry-wrapper media">
-				<div class="notif-photo-wrapper media-object pull-left" aria-hidden="true"><a href="{6}"
-						class="userinfo click-card" tabIndex="-1"><img data-src="{1}"></a></div>
-				<a href="{0}" class="notif-desc-wrapper media-body">
-					{2}
-					<div><time class="notif-when time" data-toggle="tooltip" title="{5}">{3}</time></div>
-				</a>
-			</div>
-		</li>
-	</ul>
-{{/if}}
-
 {{* This is the mask of the firefox logo. We set the background of #logo-img to the user icon color and apply this mask to it
 The result is a friendica logo in the user icon color.*}}
 <svg id="friendica-logo-mask" x="0px" y="0px" width="0px" height="0px" viewBox="0 0 250 250">
diff --git a/view/theme/frio/templates/notifications/nav/notify.tpl b/view/theme/frio/templates/notifications/nav/notify.tpl
new file mode 100644
index 0000000000..ab1743d1b9
--- /dev/null
+++ b/view/theme/frio/templates/notifications/nav/notify.tpl
@@ -0,0 +1,11 @@
+<li class="notification-{{if !$notify.seen}}un{{/if}}seen notif-entry">
+	<div class="notif-entry-wrapper media">
+		<div class="notif-photo-wrapper media-object pull-left" aria-hidden="true">
+			<a href="{{$notify.contact.url}}" class="userinfo click-card" tabIndex="-1"><img data-src="{{$notify.contact.photo}}" alt=""></a>
+		</div>
+		<a href="{{$notify.href}}" class="notif-desc-wrapper media-body">
+            {{$notify.richtext nofilter}}
+			<div><time class="notif-when time" data-toggle="tooltip" title="{{$notify.localdate}}">{{$notify.ago}}</time></div>
+		</a>
+	</div>
+</li>
diff --git a/view/theme/quattro/templates/nav.tpl b/view/theme/quattro/templates/nav.tpl
index fc757c9a4d..5ad091408e 100644
--- a/view/theme/quattro/templates/nav.tpl
+++ b/view/theme/quattro/templates/nav.tpl
@@ -108,8 +108,5 @@
 	</ul>
 
 </nav>
-<ul id="nav-notifications-template" style="display:none;" rel="template">
-	<li class="{4}"><a href="{0}" title="{5}"><img data-src="{1}">{2} <span class="notif-when">{3}</span></a></li>
-</ul>
 
 <div style="position: fixed; top: 3px; left: 5px; z-index:9999">{{$langselector}}</div>
diff --git a/view/theme/smoothly/templates/nav.tpl b/view/theme/smoothly/templates/nav.tpl
index 6d8ad1071e..aff22a79ef 100644
--- a/view/theme/smoothly/templates/nav.tpl
+++ b/view/theme/smoothly/templates/nav.tpl
@@ -58,10 +58,6 @@
 	</div>
 </nav>
 
-<ul id="nav-notifications-template" style="display:none;" rel="template">
-	<li class="{4}"><a href="{0}"><img data-src="{1}" height="24" width="24" alt="" />{2} <span class="notif-when">{3}</span></a></li>
-</ul>
-
 <div style="position: fixed; top: 3px; left: 5px; z-index:9999">{{$langselector}}</div>
 
 <script>
diff --git a/view/theme/vier/templates/nav.tpl b/view/theme/vier/templates/nav.tpl
index b2da2b0d7a..8eabe95323 100644
--- a/view/theme/vier/templates/nav.tpl
+++ b/view/theme/vier/templates/nav.tpl
@@ -141,17 +141,7 @@
 	</ul>
 
 </nav>
-<ul id="nav-notifications-template" style="display:none;" rel="template">
-	<li class="{4}" onclick="location.href='{0}';">
-		<div class="notif-entry-wrapper">
-			<div class="notif-photo-wrapper"><a href="{6}"><img data-src="{1}"></a></div>
-			<div class="notif-desc-wrapper">
-				{8}{7}
-				<div><time class="notif-when" title="{5}">{3}</time></div>
-			</div>
-		</div>
-	</li>
-</ul>
+
 <!--
 <div class="icon-flag" style="position: fixed; bottom: 10px; left: 20px; z-index:9;">{{$langselector}}</div>
 -->
diff --git a/view/theme/vier/templates/notifications/nav/notify.tpl b/view/theme/vier/templates/notifications/nav/notify.tpl
new file mode 100644
index 0000000000..3067d5b0c8
--- /dev/null
+++ b/view/theme/vier/templates/notifications/nav/notify.tpl
@@ -0,0 +1,9 @@
+<li class="notification-{{if !$notify.seen}}un{{/if}}seen" onclick="location.href='{{$notify.href}}';">
+	<div class="notif-entry-wrapper">
+		<div class="notif-photo-wrapper"><a href="{{$notify.contact.url}}"><img data-src="{{$notify.contact.photo}}"></a></div>
+		<div class="notif-desc-wrapper">
+            {{$notify.richtext nofilter}}
+			<div><time class="notif-when" title="{{$notify.localdate}}">{{$notify.ago}}</time></div>
+		</div>
+	</div>
+</li>