diff --git a/editor/js/editor.js b/editor/js/editor.js
index cc29bcbe90d4298b708671076a02be2fafc8a0aa..27b51c4ed28ce753f4acd3c51953b0ebab64b1d3 100644
--- a/editor/js/editor.js
+++ b/editor/js/editor.js
@@ -1,6 +1,6 @@
 import { State } from "./state";
 import * as Graph from "./graph";
-import { loadGraphJson } from "../../datasets/datasets";
+import { loadSpaceJson } from "../../datasets/datasets";
 import ForceGraph from "force-graph";
 import * as Interactions from "./interactions";
 import { setSpace, SPACE } from "../../config";
@@ -30,11 +30,18 @@ export function loadSpace(spaceId) {
     }
     setSpace(spaceId);
 
-    return loadGraphJson(SPACE).then((graphConfig) => {
-        jquery("#ks-editor #header-space-title").text(" - " + graphConfig.name + " [" + graphConfig.id + "]");
+    return loadSpaceJson(SPACE).then((response) => {
+        if (response.spaces.length <= 0) {
+            return;
+        }
+        const space = Object.values(response.spaces)[0];
+
+        jquery("#ks-editor #header-space-title").text(
+            " - " + space.name + " [" + space.space_id + "]"
+        );
 
         state = new State();
-        graph = new Graph.Graph(graphConfig);
+        graph = new Graph.Graph(space);
         load();
 
         graph.restartSimulation();
@@ -57,10 +64,15 @@ function load() {
         .width(width)
         .graphData(graph.data)
         .nodeLabel(Graph.NODE_LABEL)
+        .nodeId(Graph.NODE_ID)
+        .linkSource(Graph.LINK_SOURCE)
+        .linkTarget(Graph.LINK_TARGET)
         .linkColor((link) => state.linkColor(link))
         .nodeColor((node) => state.nodeColor(node))
         .onNodeClick((node) => state.onNodeClick(node))
-        .onNodeDragEnd((node, translate) => state.onNodeDragEnd(node, translate))
+        .onNodeDragEnd((node, translate) =>
+            state.onNodeDragEnd(node, translate)
+        )
         .autoPauseRedraw(false) // keep redrawing after engine has stopped
         .linkWidth((link) => state.linkWidth(link))
         .linkDirectionalParticles(state.linkDirectionalParticles())
diff --git a/editor/js/graph.js b/editor/js/graph.js
index c3839268257b431ca705419ff3d2f28b82a1f583..13507054ad3d2e471be24de34d35bf2a0b978d82 100644
--- a/editor/js/graph.js
+++ b/editor/js/graph.js
@@ -1,38 +1,41 @@
 import ManagedData from "./manageddata";
-import { PLUGIN_PATH, COLOR_PALETTE } from "../../config";
+import { PLUGIN_PATH } from "../../config";
 
 const LINK_NAME_CONNECTOR = " → ";
 
-export const NODE_LABEL = "name";
-export const NODE_ID = "id";
+export const NODE_LABEL = "title";
+export const NODE_ID = "node_id";
 export const NODE_TYPE = "type";
 export const NODE_DESCRIPTION = "description";
-export const NODE_IMAGE = "image";
-export const NODE_REFERENCES = "infoLinks";
-export const NODE_VIDEO = "video";
-export const NODE_DETAIL_IMAGE = "infoImage";
-
-export const LINK_SOURCE = "source";
-export const LINK_TARGET = "target";
-export const LINK_TYPE = "type";
+export const NODE_ICON_IMG = "icon_url";
+export const NODE_REFERENCES = "references";
+export const NODE_VIDEO = "video_url";
+export const NODE_HEADER_IMG = "header_url";
+
+export const LINK_SOURCE_OBJ = "source";
+export const LINK_TARGET_OBJ = "target";
+export const LINK_SOURCE = "source_node_id";
+export const LINK_TARGET = "target_node_id";
+export const LINK_ID = "link_id";
 export const LINK_PARTICLE_COUNT = 4;
 
-export const GRAPH_NODES = "nodes";
-export const GRAPH_LINKS = "links";
+export const TAG_EDITED = "updated";
+export const TAG_DELETED = "deleted";
+export const TAG_CREATED = "created";
 
 export const IMAGE_SIZE = 12;
 export const IMAGE_SRC = PLUGIN_PATH + "datasets/images/";
 
-export const LINK_PARAMS = [];
+export const LINK_PARAMS = [LINK_ID];
 export const NODE_PARAMS = [
     NODE_ID,
     NODE_LABEL,
-    NODE_IMAGE,
+    NODE_ICON_IMG,
     NODE_DESCRIPTION,
     NODE_REFERENCES,
     NODE_VIDEO,
     NODE_TYPE,
-    NODE_DETAIL_IMAGE,
+    NODE_HEADER_IMG,
 ];
 export const LINK_SIM_PARAMS = ["index"];
 export const NODE_SIM_PARAMS = ["index", "x", "y", "vx", "vy", "fx", "fy"]; // Based on https://github.com/d3/d3-force#simulation_nodes
@@ -56,7 +59,6 @@ export class Graph extends ManagedData {
             clearTimeout(this.physicsStopTimeoutId);
         }
 
-        
         this.data = Graph.addIdentifiers(this.getCleanData(this.data, false));
         this.triggerOnChange();
 
@@ -84,44 +86,30 @@ export class Graph extends ManagedData {
         return this.getCleanData(data, true);
     }
 
-    /**
-     * Based on the function from the 3d-graph code from @JoschaRode
-     */
+    getNodeColor(node) {
+        return node.type.color;
+    }
+
     calculateNodeTypes() {
+        // TODO: Collect all types from database
         const nodeClasses = [];
 
-        this.data[GRAPH_NODES].forEach((node) =>
+        this.data.nodes.forEach((node) =>
             nodeClasses.push(node[NODE_TYPE])
         );
 
         this.nodeTypes = [...new Set(nodeClasses)];
     }
 
-    getNodeColor(node) {
-        return this.getTypeColor(node[NODE_TYPE]);
-    }
-
-    getTypeColor(typeClass) {
-        var classIndex = this.nodeTypes.indexOf(typeClass);
-
-        if (classIndex <= -1) {
-            return "black";
-        }
-
-        return COLOR_PALETTE[classIndex % COLOR_PALETTE.length];
-    }
-
     deleteNode(nodeId) {
         // Delete node from nodes
-        this.data[GRAPH_NODES] = this.data[GRAPH_NODES].filter(
-            (n) => n[NODE_ID] !== nodeId
-        );
+        this.data.nodes = this.data.nodes.filter((n) => n[NODE_ID] !== nodeId);
 
         // Delete links with node
-        this.data[GRAPH_LINKS] = this.data[GRAPH_LINKS].filter(
+        this.data.links = this.data.links.filter(
             (l) =>
-                l[LINK_SOURCE][NODE_ID] !== nodeId &&
-                l[LINK_TARGET][NODE_ID] !== nodeId
+                l[LINK_SOURCE_OBJ][NODE_ID] !== nodeId &&
+                l[LINK_TARGET_OBJ][NODE_ID] !== nodeId
         );
 
         this.storeCurrentData("Deleted node with id [" + nodeId + "]");
@@ -143,22 +131,24 @@ export class Graph extends ManagedData {
             this.enableStoring();
         }
 
-        this.storeCurrentData("Deleted nodes with ids [" + nodeIds.join(",") + "]");
+        this.storeCurrentData(
+            "Deleted nodes with ids [" + nodeIds.join(",") + "]"
+        );
     }
 
     stopPhysics() {
-        this.data[GRAPH_NODES].forEach((n) => {
+        this.data.nodes.forEach((n) => {
             n.fx = n.x;
             n.fy = n.y;
         });
     }
 
     static addIdentifiers(data) {
-        data[GRAPH_NODES].forEach((n) => {
+        data.nodes.forEach((n) => {
             n.node = true;
             n.link = false;
         });
-        data[GRAPH_LINKS].forEach((l) => {
+        data.links.forEach((l) => {
             l.node = false;
             l.link = true;
         });
@@ -168,10 +158,10 @@ export class Graph extends ManagedData {
 
     deleteLink(sourceId, targetId) {
         // Only keep links, of one of the nodes is different
-        this.data[GRAPH_LINKS] = this.data[GRAPH_LINKS].filter(
+        this.data.links = this.data.links.filter(
             (l) =>
-                l[LINK_SOURCE][NODE_ID] !== sourceId ||
-                l[LINK_TARGET][NODE_ID] !== targetId
+                l[LINK_SOURCE_OBJ][NODE_ID] !== sourceId ||
+                l[LINK_TARGET_OBJ][NODE_ID] !== targetId
         );
 
         this.storeCurrentData(
@@ -180,6 +170,7 @@ export class Graph extends ManagedData {
     }
 
     isLinkOnNode(link, node) {
+        // Parameters valid?
         if (link === undefined || node === undefined) {
             return false;
         }
@@ -188,20 +179,21 @@ export class Graph extends ManagedData {
             return false;
         }
 
+        // Is node on at least one end of the link?
         return (
-            link[LINK_SOURCE][NODE_ID] === node[NODE_ID] ||
-            link[LINK_TARGET][NODE_ID] === node[NODE_ID]
+            link[LINK_SOURCE_OBJ][NODE_ID] === node[NODE_ID] ||
+            link[LINK_TARGET_OBJ][NODE_ID] === node[NODE_ID]
         );
     }
 
     existsLink(sourceId, targetId) {
-        const links = this.data[GRAPH_LINKS];
+        const links = this.data.links;
 
         for (var i = 0; i < links.length; i++) {
             var link = links[i];
             if (
-                link[LINK_SOURCE][NODE_ID] === sourceId &&
-                link[LINK_TARGET][NODE_ID] === targetId
+                link[LINK_SOURCE_OBJ][NODE_ID] === sourceId &&
+                link[LINK_TARGET_OBJ][NODE_ID] === targetId
             ) {
                 return true;
             }
@@ -215,15 +207,15 @@ export class Graph extends ManagedData {
             this.changeNodeDetails(selectionDetails[NODE_ID], selectionDetails);
         } else if (selectionDetails.link === true) {
             this.changeLinkDetails(
-                selectionDetails[LINK_SOURCE][NODE_ID],
-                selectionDetails[LINK_TARGET][NODE_ID],
+                selectionDetails[LINK_SOURCE_OBJ][NODE_ID],
+                selectionDetails[LINK_TARGET_OBJ][NODE_ID],
                 selectionDetails
             );
         }
     }
 
     changeNodeDetails(nodeId, newDetails) {
-        var nodes = this.data[GRAPH_NODES];
+        var nodes = this.data.nodes;
         for (var i = 0; i < nodes.length; i++) {
             // Is relevant node?
             if (nodes[i][NODE_ID] !== nodeId) {
@@ -240,12 +232,12 @@ export class Graph extends ManagedData {
     }
 
     changeLinkDetails(sourceId, targetId, newDetails) {
-        var links = this.data[GRAPH_LINKS];
+        var links = this.data.links;
         for (var i = 0; i < links.length; i++) {
             // Is relevant link?
             if (
-                links[i][LINK_SOURCE][NODE_ID] !== sourceId ||
-                links[i][LINK_TARGET][NODE_ID] !== targetId
+                links[i][LINK_SOURCE_OBJ][NODE_ID] !== sourceId ||
+                links[i][LINK_TARGET_OBJ][NODE_ID] !== targetId
             ) {
                 continue; // No
             }
@@ -278,19 +270,15 @@ export class Graph extends ManagedData {
         }
 
         var cleanData = {};
-        cleanData[GRAPH_LINKS] = [];
-        cleanData[GRAPH_NODES] = [];
+        cleanData.links = [];
+        cleanData.nodes = [];
 
-        data[GRAPH_LINKS].forEach((link) =>
-            cleanData[GRAPH_LINKS].push(
-                this.getCleanLink(link, simulationParameters)
-            )
+        data.links.forEach((link) =>
+            cleanData.links.push(this.getCleanLink(link, simulationParameters))
         );
 
-        data[GRAPH_NODES].forEach((node) =>
-            cleanData[GRAPH_NODES].push(
-                this.getCleanNode(node, simulationParameters)
-            )
+        data.nodes.forEach((node) =>
+            cleanData.nodes.push(this.getCleanNode(node, simulationParameters))
         );
 
         return cleanData;
@@ -317,11 +305,11 @@ export class Graph extends ManagedData {
 
         // Assuming that all nodes are valid, there are two possible formats
         // 1. source and target are node objects
-        if (link[LINK_SOURCE][NODE_ID] !== undefined) {
-            // Source and target nodes
+        if (link[LINK_SOURCE_OBJ] !== undefined) {
+            // Source and target are nodes
             // Node ids will be converted to complete node objects on running graphs, gotta convert back
-            cleanLink[LINK_SOURCE] = link[LINK_SOURCE][NODE_ID];
-            cleanLink[LINK_TARGET] = link[LINK_TARGET][NODE_ID];
+            cleanLink[LINK_SOURCE] = link[LINK_SOURCE_OBJ][NODE_ID];
+            cleanLink[LINK_TARGET] = link[LINK_TARGET_OBJ][NODE_ID];
         } else {
             // 2. source and target are just node ids
             cleanLink[LINK_SOURCE] = link[LINK_SOURCE];
@@ -343,7 +331,7 @@ export class Graph extends ManagedData {
     }
 
     existsNodeId(nodeId) {
-        var nodes = this.data[GRAPH_NODES];
+        var nodes = this.data.nodes;
         for (var i = 0; i < nodes.length; i++) {
             if (nodes[i][NODE_ID] === nodeId) {
                 return true;
@@ -403,7 +391,7 @@ export class Graph extends ManagedData {
         newLink.node = false;
 
         // Add node
-        this.data[GRAPH_LINKS].push(newLink);
+        this.data.links.push(newLink);
         this.triggerOnChange();
 
         this.storeCurrentData(
@@ -433,7 +421,7 @@ export class Graph extends ManagedData {
         newNode.link = false;
 
         // Add node
-        this.data[GRAPH_NODES].push(newNode);
+        this.data.nodes.push(newNode);
         this.triggerOnChange();
 
         this.storeCurrentData(
@@ -452,9 +440,9 @@ export class Graph extends ManagedData {
             return item[NODE_LABEL];
         } else if (item.link) {
             return (
-                Graph.toStr(item[LINK_SOURCE]) +
+                Graph.toStr(item[LINK_SOURCE_OBJ]) +
                 LINK_NAME_CONNECTOR +
-                Graph.toStr(item[LINK_TARGET])
+                Graph.toStr(item[LINK_TARGET_OBJ])
             );
         } else {
             return "UNDEFINED";
diff --git a/editor/js/state.js b/editor/js/state.js
index cb2458abc4b245144a27dd561329f3888a694169..a581cae4b1c57d9b9a39b6e7d5d02afa091d95fd 100644
--- a/editor/js/state.js
+++ b/editor/js/state.js
@@ -95,11 +95,12 @@ export class State extends Tool {
 
     onNodeDragEnd(node, translate) {
         // Handle as click event, if drag distance under a certain threshold
-        var distanceDragged = Math.sqrt(Math.pow(translate.x, 2) + Math.pow(translate.y, 2));
+        var distanceDragged = Math.sqrt(
+            Math.pow(translate.x, 2) + Math.pow(translate.y, 2)
+        );
         if (distanceDragged < DRAG_THRESHOLD_2D) {
             this.onNodeClick(node);
             return;
-            
         } else {
             this.tool.onNodeDragEnd(node, translate);
         }
@@ -161,8 +162,8 @@ export class State extends Tool {
         }
 
         // Draw image
-        if (node[Graph.NODE_IMAGE] !== undefined) {
-            var path = node[Graph.NODE_IMAGE];
+        if (node[Graph.NODE_ICON_IMG] != null) {
+            var path = node[Graph.NODE_ICON_IMG];
 
             if (!path.includes("/")) {
                 path = Graph.IMAGE_SRC + path;
@@ -250,34 +251,40 @@ export class State extends Tool {
         }
 
         // Links already initialized?
-        if (link.source.x === undefined) {
+        if (link[Graph.LINK_SOURCE_OBJ] === undefined) {
             return undefined;
         }
 
         // Draw gradient link
         var gradient = ctx.createLinearGradient(
-            link.source.x,
-            link.source.y,
-            link.target.x,
-            link.target.y
+            link[Graph.LINK_SOURCE_OBJ].x,
+            link[Graph.LINK_SOURCE_OBJ].y,
+            link[Graph.LINK_TARGET_OBJ].x,
+            link[Graph.LINK_TARGET_OBJ].y
         );
         // Have reversed colors
         // Color at source node referencing the target node and vice versa
-        gradient.addColorStop("0", graph.getNodeColor(link.target));
-        gradient.addColorStop("1", graph.getNodeColor(link.source));
+        gradient.addColorStop(
+            "0",
+            "#" + graph.getNodeColor(link[Graph.LINK_TARGET_OBJ])
+        );
+        gradient.addColorStop(
+            "1",
+            "#" + graph.getNodeColor(link[Graph.LINK_SOURCE_OBJ])
+        );
 
         ctx.beginPath();
-        ctx.moveTo(link.source.x, link.source.y);
-        ctx.lineTo(link.target.x, link.target.y);
+        ctx.moveTo(
+            link[Graph.LINK_SOURCE_OBJ].x,
+            link[Graph.LINK_SOURCE_OBJ].y
+        );
+        ctx.lineTo(
+            link[Graph.LINK_TARGET_OBJ].x,
+            link[Graph.LINK_TARGET_OBJ].y
+        );
         ctx.strokeStyle = gradient;
         ctx.stroke();
 
-        // Only render strokes on last link
-        // var lastLink = graph.data[Graph.GRAPH_LINKS][graph.data[Graph.GRAPH_LINKS].length - 1];
-        // if (link === lastLink) {
-        //     ctx.stroke();
-        // }
-
         return undefined;
     }
 
diff --git a/editor/js/tools/deletetool.js b/editor/js/tools/deletetool.js
index ae347563a2a24abf0a1d72704b2bc81391db3769..f82dcbe7d6f8cceeb69bd50cb5421f30d4977ece 100644
--- a/editor/js/tools/deletetool.js
+++ b/editor/js/tools/deletetool.js
@@ -68,8 +68,8 @@ export default class DeleteTool extends Tool {
 
     onLinkClick(link) {
         graph.deleteLink(
-            link[Graph.LINK_SOURCE][Graph.NODE_ID],
-            link[Graph.LINK_TARGET][Graph.NODE_ID]
+            link[Graph.LINK_SOURCE_OBJ][Graph.NODE_ID],
+            link[Graph.LINK_TARGET_OBJ][Graph.NODE_ID]
         );
 
         if (state.selectedItem == link) {
diff --git a/editor/js/tools/menus/selectmenu.js b/editor/js/tools/menus/selectmenu.js
index e5d9478420b813d62cb2cc19f979e9af83614fdf..f0628b1f1646cb16785877bdb2c22a62c4b6ec23 100644
--- a/editor/js/tools/menus/selectmenu.js
+++ b/editor/js/tools/menus/selectmenu.js
@@ -55,12 +55,12 @@ export class SelectMenu extends ToolMenu {
         this.context = undefined;
         this.map = [
             { menu: NODE_NAME_ID, property: Graph.NODE_LABEL },
-            { menu: NODE_IMG_ID, property: Graph.NODE_IMAGE },
+            { menu: NODE_IMG_ID, property: Graph.NODE_ICON_IMG },
             { menu: NODE_DESC_ID, property: Graph.NODE_DESCRIPTION },
             { menu: NODE_TYPE_ID, property: Graph.NODE_TYPE },
             { menu: NODE_REF_ID, property: Graph.NODE_REFERENCES },
             { menu: NODE_VIDEO_ID, property: Graph.NODE_VIDEO },
-            { menu: NODE_DETAIL_IMG_ID, property: Graph.NODE_DETAIL_IMAGE },
+            { menu: NODE_DETAIL_IMG_ID, property: Graph.NODE_HEADER_IMG },
         ];
         this.hooked = false; // Can only hook menu events once, but have to do it later, when they are loaded
     }
@@ -158,11 +158,23 @@ export class SelectMenu extends ToolMenu {
     formatValue(propertyKey, rawValue) {
         var formattedValue = rawValue;
 
+        // Format references
         if (propertyKey === Graph.NODE_REFERENCES) {
             // Explode to list of url-lines
             formattedValue = rawValue
                 .split("\n") // Every line is it's own url
-                .filter((url) => url); // Remove empty entries
+                .filter((url) => url) // Remove empty entries
+                .map((url) => {
+                    return {
+                        node_id: this.values[SELECTION_KEY][Graph.NODE_ID],
+                        url: url,
+                    };
+                }); // Map to reference object
+
+            // Set created tag for every reference
+            formattedValue.forEach((reference) => {
+                reference[Graph.TAG_CREATED] = true;
+            });
         }
 
         return formattedValue;
@@ -239,7 +251,7 @@ export class SelectMenu extends ToolMenu {
 
             var formattedValue = undefined;
             if (propertyKey === Graph.NODE_REFERENCES && Array.isArray(value)) {
-                formattedValue = value.join("\n");
+                formattedValue = value.map((ref) => ref.url).join("\n");
             } else {
                 formattedValue = value;
             }