diff --git a/editor/css/editor.css b/editor/css/editor.css
index 025c03832bf43ef5c4161b78cdbb0d22acaadd22..393db7dd4071cb737f12941ad825627614d9e2cc 100644
--- a/editor/css/editor.css
+++ b/editor/css/editor.css
@@ -58,6 +58,6 @@ div#ks-editor img.preview-image {
     height: auto;
 }
 
-div#ks-editor #toolbar-settings {
+div#ks-editor #toolbar-settings, div#ks-editor #toolbar-save {
     float: right;
 }
diff --git a/editor/editor.php b/editor/editor.php
index 659acdfa07e470f761f24a808b7f1653b0977887..f9b65cc70e6df7456f9d85c34bc78bc4b0532e36 100644
--- a/editor/editor.php
+++ b/editor/editor.php
@@ -90,5 +90,4 @@
             </input>
         </div>
     </section>
-    <button id="save" type="submit" class="primary">Save and publish</button>
 </div>
\ No newline at end of file
diff --git a/editor/js/interactions.js b/editor/js/interactions.js
index 2c34de8152189f8640282ca6ff1b087430022e32..d24fec2652d2f9940210fa5f13021cf0fe201f6e 100644
--- a/editor/js/interactions.js
+++ b/editor/js/interactions.js
@@ -1,6 +1,6 @@
 import jQuery from "jquery";
-import { state, graph } from "./editor";
-import { listAllSpaces, saveGraphJson } from "../../datasets/datasets";
+import { state } from "./editor";
+import { listAllSpaces } from "../../datasets/datasets";
 import { SPACE } from "../../config";
 
 /**
@@ -10,10 +10,6 @@ export function initInteractions() {
     jQuery("button#clear-collection").on("click", () => {
         state.clearSelectedItems();
     });
-    jQuery("button#save").on("click", () => {
-        saveGraphJson(SPACE, graph.getCleanData());    // space_id defined globaly through knowledge-space.php
-        graph.saveChanges();
-    });
 
     // Fill space dropdown
     var selectContainer = jQuery("#space-id-select");
diff --git a/editor/js/manageddata.js b/editor/js/manageddata.js
index a289ea46553fb4009eee11660786f4e5bf837d18..c35a2bb1b7890bb234404855f241d7f031a7aa14 100644
--- a/editor/js/manageddata.js
+++ b/editor/js/manageddata.js
@@ -1,34 +1,41 @@
+import jQuery from "jquery";
+
+const SAVE_BUTTON_ID = "div#ks-editor #toolbar-save";
+
 export default class ManagedData {
     constructor(data) {
         this.data = data;
         this.history = []; // Newest state is always at 0
         this.historyPosition = 0;
-        this.unsavedChanges = false;
+        this.savedHistoryId = 0;
 
         this.storeCurrentData("Initial state", false);
     }
 
     updateUnsavedChangesHandler() {
         if (this.hasUnsavedChanges()) {
+            jQuery(SAVE_BUTTON_ID).removeClass("hidden");
             window.addEventListener("beforeunload", this.handleBeforeUnload);
         } else {
+            jQuery(SAVE_BUTTON_ID).addClass("hidden");
             window.removeEventListener("beforeunload", this.handleBeforeUnload);
         }
     }
 
     handleBeforeUnload(e) {
-        var confirmationMessage = 'If you leave before saving, unsaved changes will be lost.';
-    
+        var confirmationMessage =
+            "If you leave before saving, unsaved changes will be lost.";
+
         (e || window.event).returnValue = confirmationMessage; //Gecko + IE
         return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
     }
 
     hasUnsavedChanges() {
-        return this.unsavedChanges;
+        return this.history[this.historyPosition].id !== this.savedHistoryId;
     }
 
     saveChanges() {
-        this.unsavedChanges = false;
+        this.savedHistoryId = this.history[this.historyPosition].id;
         this.updateUnsavedChangesHandler();
     }
 
@@ -37,6 +44,7 @@ export default class ManagedData {
 
     undo() {
         if (this.step(1)) {
+            this.updateUnsavedChangesHandler();
             this.onUndo();
             return true;
         } else {
@@ -46,6 +54,7 @@ export default class ManagedData {
 
     redo() {
         if (this.step(-1)) {
+            this.updateUnsavedChangesHandler();
             this.onRedo();
             return true;
         } else {
@@ -76,18 +85,27 @@ export default class ManagedData {
     storeCurrentData(description, relevantChanges = true) {
         var formattedData = this.storableData(this.data);
 
-        this.history.unshift({
-            description: description,
-            data: JSON.stringify(formattedData), // Creating a deep copy
-        });
+        var nextId = 0;
+        if (this.history.length > 0) {
+            nextId = this.history[0].id;
+
+            // Keep same as previous id, if nothing relevant changed
+            // Otherwise, increase by one
+            if (relevantChanges) {
+                nextId++;
+            }
+        }
 
         // Forget about the currently stored potential future
         this.history.splice(0, this.historyPosition);
         this.historyPosition = 0;
 
-        if (!this.hasUnsavedChanges() && relevantChanges) {
-            this.unsavedChanges = true;
-            this.updateUnsavedChangesHandler();
-        }
+        this.history.unshift({
+            description: description,
+            data: JSON.stringify(formattedData), // Creating a deep copy
+            id: nextId,
+        });
+
+        this.updateUnsavedChangesHandler();
     }
 }
diff --git a/editor/js/state.js b/editor/js/state.js
index 831043d7a58ed9e3af2ed8d4ba823176f742b279..490d3b6bf8ce310679d010123b9089d12c0f977a 100644
--- a/editor/js/state.js
+++ b/editor/js/state.js
@@ -7,6 +7,7 @@ import DeleteTool from "./tools/deletetool";
 import AddNodeTool from "./tools/addnodetool";
 import ConnectTool from "./tools/connecttool";
 import SettingsTool from "./tools/settingstool";
+import SaveTool from "./tools/savetool";
 import { graph } from "./editor";
 import Toolbar from "./toolbar";
 import * as Graph from "./graph";
@@ -20,6 +21,7 @@ export const TOOLS = {
     addnode: new AddNodeTool("addnode"),
     connect: new ConnectTool("connect"),
     settings: new SettingsTool("settings"),
+    save: new SaveTool("save"),
 };
 
 export const CONTEXT = {
diff --git a/editor/js/toolbar.js b/editor/js/toolbar.js
index 795628b92177c0f4d447a838a67a266f6ce3986b..658553f133d0904caa8ce40eefea2e3515734c26 100644
--- a/editor/js/toolbar.js
+++ b/editor/js/toolbar.js
@@ -3,6 +3,7 @@ import { PLUGIN_PATH } from "../../config";
 import { state } from "./editor";
 
 const ID_TOOLBAR = "#toolbar";
+const SAVE_BUTTON_ID = "div#ks-editor #toolbar-save";
 
 const TOOL_ICON_SRC = PLUGIN_PATH + "editor/images/tools/";
 const TOOL_ICON_FORMAT = ".png";
@@ -14,6 +15,9 @@ export default class Toolbar {
         this.previousTool = undefined;
 
         this.renderToolbar(this.tools);
+
+        // Special, intial treatment
+        jQuery(SAVE_BUTTON_ID).addClass("hidden");
     }
 
     setSelectedTool(tool) {
diff --git a/editor/js/tools/savetool.js b/editor/js/tools/savetool.js
new file mode 100644
index 0000000000000000000000000000000000000000..5bbb1137dca3c5b437c4dfe03ad5d3a4edeab677
--- /dev/null
+++ b/editor/js/tools/savetool.js
@@ -0,0 +1,16 @@
+import Tool from "./tool";
+import { saveGraphJson } from "../../../datasets/datasets";
+import { state, graph } from "../editor";
+import { SPACE } from "../../../config";
+
+export default class SaveTool extends Tool {
+    constructor(key) {
+        super("Save", "save", key);
+    }
+
+    onToolActivate() {
+        saveGraphJson(SPACE, graph.getCleanData());    // space_id defined globaly through knowledge-space.php
+        graph.saveChanges();
+        state.setTool(state.previousTool);
+    }
+}