diff --git a/webinterface.py b/webinterface.py
index 91e4ebb6..e89ec92c 100644
--- a/webinterface.py
+++ b/webinterface.py
@@ -5917,6 +5917,218 @@ def getBannerFile(baseDir: str, nickname: str, domain: str) -> (str, str):
     return bannerFile, bannerFilename
 
 
+def getTimelineButtonHeader(defaultTimeline: str,
+                            boxName: str,
+                            pageNumber: int,
+                            translate: {},
+                            usersPath: str,
+                            mediaButton: str,
+                            blogsButton: str,
+                            newsButton: str,
+                            inboxButton: str,
+                            dmButton: str,
+                            newDM: str,
+                            repliesButton: str,
+                            newReply: str,
+                            minimal: bool,
+                            sentButton: str,
+                            sharesButtonStr: str,
+                            bookmarksButtonStr: str,
+                            eventsButtonStr: str,
+                            moderationButtonStr: str,
+                            newPostButtonStr: str,
+                            baseDir: str,
+                            nickname: str, domain: str,
+                            iconsDir: str,
+                            timelineStartTime,
+                            newCalendarEvent: bool,
+                            calendarPath: str,
+                            calendarImage: str,
+                            followApprovals: str) -> str:
+    """Returns the header at the top of the timeline, containing
+    buttons for inbox, outbox, search, calendar, etc
+    """
+    # start of the button header with inbox, outbox, etc
+    tlStr = '    
\n'
+    # first button
+    if defaultTimeline == 'tlmedia':
+        tlStr += \
+            '      
\n'
+    elif defaultTimeline == 'tlblogs':
+        tlStr += \
+            '      
\n'
+    elif defaultTimeline == 'tlnews':
+        tlStr += \
+            '      
\n'
+    else:
+        tlStr += \
+            '      
\n'
+
+    tlStr += \
+        '      
\n'
+
+    tlStr += \
+        '      
\n'
+
+    # typically the media button
+    if defaultTimeline != 'tlmedia':
+        if not minimal:
+            tlStr += \
+                '      
\n'
+    else:
+        if not minimal:
+            tlStr += \
+                '      
\n'
+
+    # typically the blogs button
+    # but may change if this is a blogging oriented instance
+    if defaultTimeline != 'tlblogs':
+        if not minimal or defaultTimeline == 'tlnews':
+            tlStr += \
+                '      
\n'
+    else:
+        if not minimal:
+            tlStr += \
+                '      
\n'
+
+    # typically the news button
+    # but may change if this is a news oriented instance
+    if defaultTimeline != 'tlnews':
+        tlStr += \
+            '      
\n'
+    else:
+        tlStr += \
+            '      
\n'
+
+    # button for the outbox
+    tlStr += \
+        '      
\n'
+
+    # add other buttons
+    tlStr += \
+        sharesButtonStr + bookmarksButtonStr + eventsButtonStr + \
+        moderationButtonStr + newPostButtonStr
+
+    # show todays events buttons on the first inbox page
+    if boxName == 'inbox' and pageNumber == 1:
+        if todaysEventsCheck(baseDir, nickname, domain):
+            now = datetime.now()
+
+            # happening today button
+            tlStr += \
+                '    
\n'
+
+            # happening this week button
+            if thisWeeksEventsCheck(baseDir, nickname, domain):
+                tlStr += \
+                    '    
\n'
+        else:
+            # happening this week button
+            if thisWeeksEventsCheck(baseDir, nickname, domain):
+                tlStr += \
+                    '    
\n'
+
+    # the search button
+    tlStr += \
+        '        
![' + \
+        translate['Search and follow'] + ' | ' + \
+        translate['Search and follow'] + '](/' + \
+        iconsDir + '/search.png)
\n'
+
+    # benchmark 5
+    timeDiff = int((time.time() - timelineStartTime) * 1000)
+    if timeDiff > 100:
+        print('TIMELINE TIMING ' + boxName + ' 5 = ' + str(timeDiff))
+
+    # the calendar button
+    calendarAltText = translate['Calendar']
+    if newCalendarEvent:
+        # indicate that the calendar icon is highlighted
+        calendarAltText = '*' + calendarAltText + '*'
+    tlStr += \
+        '        
![' + translate['Calendar'] + \
+        ' | ' + calendarAltText + '](/' + iconsDir + '/' + \
+        calendarImage + ')
\n'
+
+    # the show/hide button, for a simpler header appearance
+    tlStr += \
+        '        
![' + translate['Show/Hide Buttons'] + \
+        ' | ' + translate['Show/Hide Buttons'] + \
+        '](/' + iconsDir + \
+        '/showhide.png)
\n'
+
+    # the newswire button to show right column links
+    tlStr += \
+        '        
' + \
+        '![' + translate['News'] + \
+        ' | ' + translate['News'] + \
+        '](/' + iconsDir + \
+        '/newswire.png)
\n'
+
+    # the links button to show left column links
+    tlStr += \
+        '        
' + \
+        '![' + translate['Edit Links'] + \
+        ' | ' + translate['Edit Links'] + \
+        '](/' + iconsDir + \
+        '/links.png)
\n'
+
+    tlStr += followApprovals
+    # end of the button header with inbox, outbox, etc
+    tlStr += '    
\n'
 
-    # start of the button header with inbox, outbox, etc
-    tlStr += ' \n'
+        getTimelineButtonHeader(defaultTimeline, boxName, pageNumber,
+                                translate, usersPath, mediaButton,
+                                blogsButton, newsButton, inboxButton,
+                                dmButton, newDM, repliesButton,
+                                newReply, minimal, sentButton,
+                                sharesButtonStr, bookmarksButtonStr,
+                                eventsButtonStr, moderationButtonStr,
+                                newPostButtonStr, baseDir, nickname,
+                                domain, iconsDir, timelineStartTime,
+                                newCalendarEvent, calendarPath,
+                                calendarImage, followApprovals)
 
     # second row of buttons for moderator actions
     if moderator and boxName == 'moderation':\n'
-    # first button
-    if defaultTimeline == 'tlmedia':
-        tlStr += \
-            '       \n'
-    elif defaultTimeline == 'tlblogs':
-        tlStr += \
-            '       \n'
-    elif defaultTimeline == 'tlnews':
-        tlStr += \
-            '       \n'
-    else:
-        tlStr += \
-            '       \n'
-
     tlStr += \
-        '       \n'
-
-    tlStr += \
-        '       \n'
-
-    # typically the media button
-    if defaultTimeline != 'tlmedia':
-        if not minimal:
-            tlStr += \
-                '       \n'
-    else:
-        if not minimal:
-            tlStr += \
-                '       \n'
-
-    # typically the blogs button
-    # but may change if this is a blogging oriented instance
-    if defaultTimeline != 'tlblogs':
-        if not minimal or defaultTimeline == 'tlnews':
-            tlStr += \
-                '       \n'
-    else:
-        if not minimal:
-            tlStr += \
-                '       \n'
-
-    # typically the news button
-    # but may change if this is a news oriented instance
-    if defaultTimeline != 'tlnews':
-        tlStr += \
-            '       \n'
-    else:
-        tlStr += \
-            '       \n'
-
-    # button for the outbox
-    tlStr += \
-        '       \n'
-
-    # add other buttons
-    tlStr += \
-        sharesButtonStr + bookmarksButtonStr + eventsButtonStr + \
-        moderationButtonStr + newPostButtonStr
-
-    # show todays events buttons on the first inbox page
-    if boxName == 'inbox' and pageNumber == 1:
-        if todaysEventsCheck(baseDir, nickname, domain):
-            now = datetime.now()
-
-            # happening today button
-            tlStr += \
-                '     \n'
-
-            # happening this week button
-            if thisWeeksEventsCheck(baseDir, nickname, domain):
-                tlStr += \
-                    '     \n'
-        else:
-            # happening this week button
-            if thisWeeksEventsCheck(baseDir, nickname, domain):
-                tlStr += \
-                    '     \n'
-
-    # the search button
-    tlStr += \
-        '         ![' + \
-        translate['Search and follow'] + ' | ' + \
-        translate['Search and follow'] + '](/' + \
-        iconsDir + '/search.png) \n'
-
-    # benchmark 5
-    timeDiff = int((time.time() - timelineStartTime) * 1000)
-    if timeDiff > 100:
-        print('TIMELINE TIMING ' + boxName + ' 5 = ' + str(timeDiff))
-
-    # the calendar button
-    calendarAltText = translate['Calendar']
-    if newCalendarEvent:
-        # indicate that the calendar icon is highlighted
-        calendarAltText = '*' + calendarAltText + '*'
-    tlStr += \
-        '         ![' + translate['Calendar'] + \
-        ' | ' + calendarAltText + '](/' + iconsDir + '/' + \
-        calendarImage + ') \n'
-
-    # the show/hide button, for a simpler header appearance
-    tlStr += \
-        '         ![' + translate['Show/Hide Buttons'] + \
-        ' | ' + translate['Show/Hide Buttons'] + \
-        '](/' + iconsDir + \
-        '/showhide.png) \n'
-
-    # the newswire button to show right column links
-    tlStr += \
-        '        ' + \
-        ' ![' + translate['News'] + \
-        ' | ' + translate['News'] + \
-        '](/' + iconsDir + \
-        '/newswire.png) \n'
-
-    # the links button to show left column links
-    tlStr += \
-        '        ' + \
-        ' ![' + translate['Edit Links'] + \
-        ' | ' + translate['Edit Links'] + \
-        '](/' + iconsDir + \
-        '/links.png) \n'
-
-    tlStr += followApprovals
-    # end of the button header with inbox, outbox, etc
-    tlStr += '     |