diff --git a/daemon.py b/daemon.py
index e0e00afe5..98d0c32bd 100644
--- a/daemon.py
+++ b/daemon.py
@@ -1195,7 +1195,11 @@ class PubServer(BaseHTTPRequestHandler):
                                    self.server.sharedItemsFederatedDomains,
                                    self.server.sharedItemFederationTokens,
                                    self.server.lowBandwidth,
-                                   self.server.signingPrivateKeyPem)
+                                   self.server.signingPrivateKeyPem,
+                                   self.server.peertubeInstances,
+                                   self.server.themeName,
+                                   self.server.maxLikeCount,
+                                   self.server.maxRecentPosts)
 
     def _postToOutboxThread(self, messageJson: {}) -> bool:
         """Creates a thread to send a post
diff --git a/inbox.py b/inbox.py
index 16dd8314f..df51ab579 100644
--- a/inbox.py
+++ b/inbox.py
@@ -2025,6 +2025,7 @@ def inboxUpdateIndex(boxname: str, baseDir: str, handle: str,
     if '/' in destinationFilename:
         destinationFilename = destinationFilename.split('/')[-1]
 
+    written = False
     if os.path.isfile(indexFilename):
         try:
             with open(indexFilename, 'r+') as indexFile:
@@ -2032,6 +2033,7 @@ def inboxUpdateIndex(boxname: str, baseDir: str, handle: str,
                 if destinationFilename + '\n' not in content:
                     indexFile.seek(0, 0)
                     indexFile.write(destinationFilename + '\n' + content)
+                written = True
                 return True
         except Exception as e:
             print('WARN: Failed to write entry to index ' + str(e))
@@ -2039,10 +2041,11 @@ def inboxUpdateIndex(boxname: str, baseDir: str, handle: str,
         try:
             with open(indexFilename, 'w+') as indexFile:
                 indexFile.write(destinationFilename + '\n')
+                written = True
         except Exception as e:
             print('WARN: Failed to write initial entry to index ' + str(e))
 
-    return False
+    return written
 
 
 def _updateLastSeen(baseDir: str, handle: str, actor: str) -> None:
diff --git a/outbox.py b/outbox.py
index 1e56d0446..de654dc77 100644
--- a/outbox.py
+++ b/outbox.py
@@ -40,6 +40,7 @@ from inbox import inboxUpdateIndex
 from announce import outboxAnnounce
 from announce import outboxUndoAnnounce
 from follow import outboxUndoFollow
+from follow import followerApprovalActive
 from skills import outboxSkills
 from availability import outboxAvailability
 from like import outboxLike
@@ -49,6 +50,7 @@ from bookmarks import outboxUndoBookmark
 from delete import outboxDelete
 from shares import outboxShareUpload
 from shares import outboxUndoShareUpload
+from webapp_post import individualPostAsHtml
 
 
 def _outboxPersonReceiveUpdate(recentPostsCache: {},
@@ -195,7 +197,10 @@ def postMessageToOutbox(session, translate: {},
                         sharedItemsFederatedDomains: [],
                         sharedItemFederationTokens: {},
                         lowBandwidth: bool,
-                        signingPrivateKeyPem: str) -> bool:
+                        signingPrivateKeyPem: str,
+                        peertubeInstances: str, theme: str,
+                        maxLikeCount: int,
+                        maxRecentPosts: int) -> bool:
     """post is received by the outbox
     Client to server message post
     https://www.w3.org/TR/activitypub/#client-to-server-outbox-delivery
@@ -425,6 +430,36 @@ def postMessageToOutbox(session, translate: {},
                     inboxUpdateIndex(boxNameIndex, baseDir,
                                      postToNickname + '@' + domain,
                                      savedFilename, debug)
+
+                    # regenerate the html
+                    useCacheOnly = False
+                    pageNumber = 1
+                    showIndividualPostIcons = True
+                    manuallyApproveFollowers = \
+                        followerApprovalActive(baseDir, postToNickname, domain)
+                    individualPostAsHtml(signingPrivateKeyPem,
+                                         False, recentPostsCache,
+                                         maxRecentPosts,
+                                         translate, pageNumber,
+                                         baseDir, session,
+                                         cachedWebfingers,
+                                         personCache,
+                                         postToNickname, domain, port,
+                                         messageJson, None, True,
+                                         allowDeletion,
+                                         httpPrefix, __version__,
+                                         boxNameIndex,
+                                         YTReplacementDomain,
+                                         showPublishedDateOnly,
+                                         peertubeInstances,
+                                         allowLocalNetworkAccess,
+                                         theme, systemLanguage,
+                                         maxLikeCount,
+                                         boxNameIndex != 'dm',
+                                         showIndividualPostIcons,
+                                         manuallyApproveFollowers,
+                                         False, True, useCacheOnly)
+
     if outboxAnnounce(recentPostsCache,
                       baseDir, messageJson, debug):
         if debug:
diff --git a/schedule.py b/schedule.py
index e29d46cff..165160ced 100644
--- a/schedule.py
+++ b/schedule.py
@@ -116,7 +116,11 @@ def _updatePostSchedule(baseDir: str, handle: str, httpd,
                                        httpd.sharedItemsFederatedDomains,
                                        httpd.sharedItemFederationTokens,
                                        httpd.lowBandwidth,
-                                       httpd.signingPrivateKeyPem):
+                                       httpd.signingPrivateKeyPem,
+                                       httpd.peertubeInstances,
+                                       httpd.themeName,
+                                       httpd.maxLikeCount,
+                                       httpd.maxRecentPosts):
                 indexLines.remove(line)
                 os.remove(postFilename)
                 continue
diff --git a/tests.py b/tests.py
index be014979e..4b5692f61 100644
--- a/tests.py
+++ b/tests.py
@@ -2874,7 +2874,7 @@ def testClientToServer():
     showTestBoxes('alice', aliceInboxPath, aliceOutboxPath)
     showTestBoxes('bob', bobInboxPath, bobOutboxPath)
     assert len([name for name in os.listdir(bobOutboxPath)
-                if os.path.isfile(os.path.join(bobOutboxPath, name))]) == 3
+                if os.path.isfile(os.path.join(bobOutboxPath, name))]) == 4
     assert len([name for name in os.listdir(aliceInboxPath)
                 if os.path.isfile(os.path.join(aliceInboxPath, name))]) == 1
     print('EVENT: Post repeated')
diff --git a/webapp_post.py b/webapp_post.py
index be70bf37e..6c5ea8bad 100644
--- a/webapp_post.py
+++ b/webapp_post.py
@@ -245,13 +245,20 @@ def _getAvatarImageHtml(showAvatarOptions: bool,
     avatarLink = ''
     if '/users/news/' not in avatarUrl:
         avatarLink = '        '
+        showProfileStr = 'Show profile'
+        if translate.get(showProfileStr):
+            showProfileStr = translate[showProfileStr]
         avatarLink += \
             '\n'
 
     if showAvatarOptions and \
        domainFull + '/users/' + nickname not in postActor:
+        showOptionsForThisPersonStr = 'Show options for this person'
+        if translate.get(showOptionsForThisPersonStr):
+            showOptionsForThisPersonStr = \
+                translate[showOptionsForThisPersonStr]
         if '/users/news/' not in avatarUrl:
             avatarLink = \
                 '        \n'
             avatarLink += \
                 '        
\n'
         else:
             # don't link to the person options for the news account
             avatarLink += \
                 '        
\n'
     return avatarLink.strip()
@@ -305,7 +312,9 @@ def _getReplyIconHtml(nickname: str, isPublicRepeat: bool,
     replyToLink += pageNumberParam
 
     replyStr = ''
-    replyToThisPostStr = translate['Reply to this post']
+    replyToThisPostStr = 'Reply to this post'
+    if translate.get(replyToThisPostStr):
+        replyToThisPostStr = translate[replyToThisPostStr]
     conversationStr = ''
     if conversationId:
         conversationStr = '?conversationId=' + conversationId
@@ -363,7 +372,9 @@ def _getEditIconHtml(baseDir: str, nickname: str, domainFull: str,
             return editStr
 
         if isBlogPost(postJsonObject):
-            editBlogPostStr = translate['Edit blog post']
+            editBlogPostStr = 'Edit blog post'
+            if translate.get(editBlogPostStr):
+                editBlogPostStr = translate[editBlogPostStr]
             if not isNewsPost(postJsonObject):
                 editStr += \
                     '        ' + \
@@ -388,7 +399,9 @@ def _getEditIconHtml(baseDir: str, nickname: str, domainFull: str,
                     editBlogPostStr + '" alt="' + editBlogPostStr + \
                     ' |" src="/icons/edit.png"/>\n'
         elif isEvent:
-            editEventStr = translate['Edit event']
+            editEventStr = 'Edit event'
+            if translate.get(editEventStr):
+                editEventStr = translate[editEventStr]
             editStr += \
                 '        ' + \
                 '\n'
+            '" title="' + muteThisPostStr + '">\n'
         muteStr += \
             '          ' + \
             '
![' + translate['Mute this post'] + \
+            muteThisPostStr + \
+            ' | ' + \
-            translate['Mute this post'] + \
-            ' |](/icons/mute.png) \n'
     else:
+        undoMuteStr = 'Undo mute'
+        if translate.get(undoMuteStr):
+            undoMuteStr = translate[undoMuteStr]
         muteStr = \
             '        \n'
+            timelinePostBookmark + '" title="' + undoMuteStr + '">\n'
         muteStr += \
             '          ' + \
-            '
\n'
     else:
+        undoMuteStr = 'Undo mute'
+        if translate.get(undoMuteStr):
+            undoMuteStr = translate[undoMuteStr]
         muteStr = \
             '        \n'
+            timelinePostBookmark + '" title="' + undoMuteStr + '">\n'
         muteStr += \
             '          ' + \
-            '![' + translate['Undo mute'] + \
+            '<img loading= 🔇 ' + translate['Undo mute'] + \
-            ' |](/icons/unmute.png) \n'
     return muteStr
 
@@ -622,16 +654,19 @@ def _getDeleteIconHtml(nickname: str, domainFull: str,
          messageId.startswith(postActor))):
         if '/users/' + nickname + '/' in messageId:
             if not isNewsPost(postJsonObject):
+                deleteThisPostStr = 'Delete this post'
+                if translate.get(deleteThisPostStr):
+                    deleteThisPostStr = translate[deleteThisPostStr]
                 deleteStr = \
                     '        \n'
+                    '" title="' + deleteThisPostStr + '">\n'
                 deleteStr += \
                     '          ' + \
                     '
\n'
     return muteStr
 
@@ -622,16 +654,19 @@ def _getDeleteIconHtml(nickname: str, domainFull: str,
          messageId.startswith(postActor))):
         if '/users/' + nickname + '/' in messageId:
             if not isNewsPost(postJsonObject):
+                deleteThisPostStr = 'Delete this post'
+                if translate.get(deleteThisPostStr):
+                    deleteThisPostStr = translate[deleteThisPostStr]
                 deleteStr = \
                     '        \n'
+                    '" title="' + deleteThisPostStr + '">\n'
                 deleteStr += \
                     '          ' + \
                     '![' + translate['Delete this post'] + \
+                    deleteThisPostStr + \
+                    ' | ' + \
-                    translate['Delete this post'] + \
-                    ' |](/icons/delete.png) \n'
     return deleteStr
 
@@ -699,7 +734,10 @@ def _getBlogCitationsHtml(boxName: str,
             '' + tagJson['name'] + '\n'
 
     if citationsStr:
-        citationsStr = '
\n'
     return deleteStr
 
@@ -699,7 +734,10 @@ def _getBlogCitationsHtml(boxName: str,
             '' + tagJson['name'] + '\n'
 
     if citationsStr:
-        citationsStr = '
' + translate['Citations'] + ':
' + \ + translatedCitationsStr = 'Citations' + if translate.get(translatedCitationsStr): + translatedCitationsStr = translate[translatedCitationsStr] + citationsStr = '' + translatedCitationsStr + ':
' + \ '![' + \
-        translate['announces'] + \
-        ' ' + translate['announces'] + \
+        announcesStr + \
+        '](/icons' + \
         '/repeat_inactive.png) \n'
 
@@ -719,9 +760,12 @@ def _announceUnattributedHtml(translate: {},
     """Returns the html for an announce title where there
     is no attribution on the announced post
     """
+    announcesStr = 'announces'
+    if translate.get(announcesStr):
+        announcesStr = translate[announcesStr]
     return '
\n'
 
@@ -719,9 +760,12 @@ def _announceUnattributedHtml(translate: {},
     """Returns the html for an announce title where there
     is no attribution on the announced post
     """
+    announcesStr = 'announces'
+    if translate.get(announcesStr):
+        announcesStr = translate[announcesStr]
     return '    ![' + \
-        translate['replying to themselves'] + \
-        ' ' + translate['replying to themselves'] + \
+        replyingToThemselvesStr + \
+        '](/icons' + \
         '/reply.png) \n'
 
@@ -853,9 +907,12 @@ def _replyToUnknownHtml(translate: {},
                         postJsonObject: {}) -> str:
     """Returns the html title for a reply to an unknown handle
     """
+    replyingToStr = 'replying to'
+    if translate.get(replyingToStr):
+        replyingToStr = translate[replyingToStr]
     return '
\n'
 
@@ -853,9 +907,12 @@ def _replyToUnknownHtml(translate: {},
                         postJsonObject: {}) -> str:
     """Returns the html title for a reply to an unknown handle
     """
+    replyingToStr = 'replying to'
+    if translate.get(replyingToStr):
+        replyingToStr = translate[replyingToStr]
     return '        ' + translate['Liked by'] + \
-            ' @' + \
+            ' ' + likedByStr + ' @' + \
             likedByHandle + '\n'
 
         domainFull = getFullDomain(domain, port)
@@ -1726,10 +1800,16 @@ def htmlIndividualPost(cssCache: {},
             '    \n'
         if not isFollowingActor(baseDir, nickname, domainFull, likedBy):
+            translateFollowStr = 'Follow'
+            if translate.get(translateFollowStr):
+                translateFollowStr = translate[translateFollowStr]
             followStr += '    \n'
+                'name="submitSearch">' + translateFollowStr + '\n'
+        goBackStr = 'Go Back'
+        if translate.get(goBackStr):
+            goBackStr = translate[goBackStr]
         followStr += '    \n'
+            'name="submitBack">' + goBackStr + '\n'
         followStr += '  \n'
         postStr += followStr + '