diff --git a/package.json b/package.json
index c67a694b3..bf134ad96 100644
--- a/package.json
+++ b/package.json
@@ -13,10 +13,10 @@
     "url": "https://github.com/zadam/trilium.git"
   },
   "scripts": {
-    "start-server": "cross-env TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev node ./src/www",
-    "start-server-no-dir": "cross-env TRILIUM_ENV=dev node ./src/www",
-    "start-electron": "cross-env TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev electron --inspect=5858 .",
-    "start-electron-no-dir": "cross-env TRILIUM_ENV=dev electron --inspect=5858 .",
+    "start-server": "cross-env TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 node ./src/www",
+    "start-server-no-dir": "cross-env TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 node ./src/www",
+    "start-electron": "cross-env TRILIUM_DATA_DIR=./data TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev electron --inspect=5858 .",
+    "start-electron-no-dir": "cross-env TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 electron --inspect=5858 .",
     "switch-server": "rm -rf ./node_modules/better-sqlite3 && npm install",
     "switch-electron": "rm -rf ./node_modules/better-sqlite3 && npm install && ./node_modules/.bin/electron-rebuild",
     "build-api-docs": "./bin/build-api-docs.sh",
diff --git a/src/public/app/components/tab_manager.js b/src/public/app/components/tab_manager.js
index 08c7da919..8f760cc95 100644
--- a/src/public/app/components/tab_manager.js
+++ b/src/public/app/components/tab_manager.js
@@ -477,13 +477,13 @@ export default class TabManager extends Component {
         this.openAndActivateEmptyTab();
     }
 
-    async removeAllTabsCommand() {
+    async closeAllTabsCommand() {
         for (const ntxIdToRemove of this.mainNoteContexts.map(nc => nc.ntxId)) {
             await this.removeNoteContext(ntxIdToRemove);
         }
     }
 
-    async removeAllTabsExceptForThisCommand({ntxId}) {
+    async closeOtherTabsCommand({ntxId}) {
         for (const ntxIdToRemove of this.mainNoteContexts.map(nc => nc.ntxId)) {
             if (ntxIdToRemove !== ntxId) {
                 await this.removeNoteContext(ntxIdToRemove);
@@ -491,6 +491,10 @@ export default class TabManager extends Component {
         }
     }
 
+    async closeTabCommand({ntxId}) {
+        await this.removeNoteContext(ntxId);
+    }
+
     async moveTabToNewWindowCommand({ntxId}) {
         const {notePath, hoistedNoteId} = this.getNoteContextById(ntxId);
 
diff --git a/src/public/app/services/note_content_renderer.js b/src/public/app/services/note_content_renderer.js
index 0a509af31..2fb805799 100644
--- a/src/public/app/services/note_content_renderer.js
+++ b/src/public/app/services/note_content_renderer.js
@@ -7,6 +7,7 @@ import openService from "./open.js";
 import froca from "./froca.js";
 import utils from "./utils.js";
 import linkService from "./link.js";
+import treeService from "./tree.js";
 
 let idCounter = 1;
 
@@ -31,6 +32,17 @@ async function getRenderedContent(note, options = {}) {
 
                 renderMathInElement($renderedContent[0], {trust: true});
             }
+
+            const getNoteIdFromLink = el => treeService.getNoteIdFromNotePath($(el).attr('href'));
+            const referenceLinks = $renderedContent.find("a.reference-link");
+            const noteIdsToPrefetch = referenceLinks.map(el => getNoteIdFromLink(el));
+            await froca.getNotes(noteIdsToPrefetch);
+
+            for (const el of referenceLinks) {
+                const noteId = getNoteIdFromLink(el);
+
+                await linkService.loadReferenceLinkTitle(noteId, $(el));
+            }
         }
         else {
             await renderChildrenList($renderedContent, note);
diff --git a/src/public/app/widgets/note_tree.js b/src/public/app/widgets/note_tree.js
index 4f6825c94..01f1ce23b 100644
--- a/src/public/app/widgets/note_tree.js
+++ b/src/public/app/widgets/note_tree.js
@@ -460,7 +460,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
                     if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) {
                         const files = [...dataTransfer.files]; // chrome has issue that dataTransfer.files empties after async operation
 
-                        const importService = await import('../services/import');
+                        const importService = await import('../services/import.js');
 
                         importService.uploadFiles(node.data.noteId, files, {
                             safeImport: true,
diff --git a/src/public/app/widgets/tab_row.js b/src/public/app/widgets/tab_row.js
index a401157fc..41249650a 100644
--- a/src/public/app/widgets/tab_row.js
+++ b/src/public/app/widgets/tab_row.js
@@ -262,9 +262,10 @@ export default class TabRowWidget extends BasicWidget {
                 x: e.pageX,
                 y: e.pageY,
                 items: [
-                    {title: "Move this tab to a new window", command: "moveTabToNewWindow", uiIcon: "bx bx-window-open"},
-                    {title: "Close all tabs", command: "removeAllTabs", uiIcon: "bx bx-x"},
-                    {title: "Close all tabs except for this", command: "removeAllTabsExceptForThis", uiIcon: "bx bx-x"},
+                    {title: "Close", command: "closeTab", uiIcon: "bx bx-x"},
+                    {title: "Close other tabs", command: "closeOtherTabs", uiIcon: "bx bx-x"},
+                    {title: "Close all tabs", command: "closeAllTabs", uiIcon: "bx bx-x"},
+                    {title: "Move this tab to a new window", command: "moveTabToNewWindow", uiIcon: "bx bx-window-open"}
                 ],
                 selectMenuItemHandler: ({command}) => {
                     this.triggerCommand(command, {ntxId});
diff --git a/src/public/app/widgets/type_widgets/editable_text.js b/src/public/app/widgets/type_widgets/editable_text.js
index 46bf218b2..67003dc68 100644
--- a/src/public/app/widgets/type_widgets/editable_text.js
+++ b/src/public/app/widgets/type_widgets/editable_text.js
@@ -172,7 +172,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
         this.watchdog.editor.model.document.on('change:data', () => this.spacedUpdate.scheduleUpdate());
 
         if (glob.isDev && ENABLE_INSPECTOR) {
-            await import(/* webpackIgnore: true */'../../../libraries/ckeditor/inspector');
+            await import(/* webpackIgnore: true */'../../../libraries/ckeditor/inspector.js');
             CKEditorInspector.attach(this.watchdog.editor);
         }
     }
diff --git a/src/routes/api/sender.js b/src/routes/api/sender.js
index 873f14c6f..f7ac768ca 100644
--- a/src/routes/api/sender.js
+++ b/src/routes/api/sender.js
@@ -2,10 +2,9 @@
 
 const imageType = require('image-type');
 const imageService = require('../../services/image');
-const dateNoteService = require('../../services/date_notes');
 const noteService = require('../../services/notes');
-const attributeService = require('../../services/attributes');
-const {sanitizeAttributeName} = require("../../services/sanitize_attribute_name");
+const {sanitizeAttributeName} = require("../../services/sanitize_attribute_name.js");
+const specialNotesService = require("../../services/special_notes.js");
 
 function uploadImage(req) {
     const file = req.file;
@@ -16,7 +15,7 @@ function uploadImage(req) {
 
     const originalName = `Sender image.${imageType(file.buffer).ext}`;
 
-    const parentNote = dateNoteService.getDayNote(req.headers['x-local-date']);
+    const parentNote = specialNotesService.getInboxNote(req.headers['x-local-date']);
 
     const {note, noteId} = imageService.saveImage(parentNote.noteId, file.buffer, originalName, true);
 
@@ -38,7 +37,7 @@ function uploadImage(req) {
 }
 
 function saveNote(req) {
-    const parentNote = dateNoteService.getDayNote(req.headers['x-local-date']);
+    const parentNote = specialNotesService.getInboxNote(req.headers['x-local-date']);
 
     const {note, branch} = noteService.createNewNote({
         parentNoteId: parentNote.noteId,
diff --git a/src/services/import/enex.js b/src/services/import/enex.js
index 1cce0b6a5..5f9489189 100644
--- a/src/services/import/enex.js
+++ b/src/services/import/enex.js
@@ -8,13 +8,19 @@ const noteService = require("../notes");
 const imageService = require("../image");
 const protectedSessionService = require('../protected_session');
 const htmlSanitizer = require("../html_sanitizer");
-const attributeService = require("../attributes");
-const {sanitizeAttributeName} = require("../sanitize_attribute_name");
+const {sanitizeAttributeName} = require("../sanitize_attribute_name.js");
 
-// date format is e.g. 20181121T193703Z
+/**
+ * date format is e.g. 20181121T193703Z or 2013-04-14T16:19:00.000Z (Mac evernote, see #3496)
+ * @returns trilium date format, e.g. 2013-04-14 16:19:00.000Z
+ */
 function parseDate(text) {
-    // insert - and : to make it ISO format
-    text = `${text.substr(0, 4)}-${text.substr(4, 2)}-${text.substr(6, 2)} ${text.substr(9, 2)}:${text.substr(11, 2)}:${text.substr(13, 2)}.000Z`;
+    // convert ISO format to the "20181121T193703Z" format
+    text = text.replace(/[-:]/g, "");
+
+    // insert - and : to convert it to trilium format
+    text = text.substr(0, 4) + "-" + text.substr(4, 2) + "-" + text.substr(6, 2)
+        + " " + text.substr(9, 2) + ":" + text.substr(11, 2) + ":" + text.substr(13, 2) + ".000Z";
 
     return text;
 }
@@ -263,7 +269,7 @@ function importEnex(taskContext, file, parentNote) {
                 continue;
             }
 
-            const mediaRegex = new RegExp(`<en-media hash="${hash}"[^>]*>`, 'g');
+            const mediaRegex = new RegExp(`<en-media [^>]*hash="${hash}"[^>]*>`, 'g');
 
             resource.mime = resource.mime || "application/octet-stream";
 
diff --git a/src/services/sync_options.js b/src/services/sync_options.js
index a63b89514..28ec9cca3 100644
--- a/src/services/sync_options.js
+++ b/src/services/sync_options.js
@@ -15,7 +15,9 @@ function get(name) {
 }
 
 module.exports = {
-    getSyncServerHost: () => get('syncServerHost'),
+    // env variable is the easiest way to guarantee we won't overwrite prod data during development
+    // after copying prod document/data directory
+    getSyncServerHost: () => process.env.TRILIUM_SYNC_SERVER_HOST || get('syncServerHost'),
     isSyncSetup: () => {
         const syncServerHost = get('syncServerHost');