diff --git a/src/libRender/RadiumNBR/Gui/NodeEditor/include/nodes/internal/FlowScene.hpp b/src/libRender/RadiumNBR/Gui/NodeEditor/include/nodes/internal/FlowScene.hpp
index 184f7270d36bf2bc0d2f5d5030ec6721e187913d..cff22a3f506bca39201465dfc5b57f3c13684588 100644
--- a/src/libRender/RadiumNBR/Gui/NodeEditor/include/nodes/internal/FlowScene.hpp
+++ b/src/libRender/RadiumNBR/Gui/NodeEditor/include/nodes/internal/FlowScene.hpp
@@ -54,10 +54,17 @@ public:
 
   std::shared_ptr<Connection> restoreConnection(QJsonObject const &connectionJson);
 
+  void importConnection(const QString& fromNodeId,
+                        int fromNodePort,
+                        const QString& toNodeId,
+                        int toNodePort);
+
   void deleteConnection(Connection& connection);
 
   Node&createNode(std::unique_ptr<NodeDataModel> && dataModel);
 
+  Node&importNode(std::unique_ptr<NodeDataModel> && dataModel);
+
   Node&restoreNode(QJsonObject const& nodeJson);
 
   void removeNode(Node& node);
diff --git a/src/libRender/RadiumNBR/Gui/NodeEditor/include/nodes/internal/Node.hpp b/src/libRender/RadiumNBR/Gui/NodeEditor/include/nodes/internal/Node.hpp
index ada5a306651c356376ab197fe29ad1f85a3c4cd7..30742891940018124f127310b024638004ac7fd6 100644
--- a/src/libRender/RadiumNBR/Gui/NodeEditor/include/nodes/internal/Node.hpp
+++ b/src/libRender/RadiumNBR/Gui/NodeEditor/include/nodes/internal/Node.hpp
@@ -47,6 +47,9 @@ public:
   void
   restore(QJsonObject const &json) override;
 
+  void
+  import();
+
 public:
 
   QUuid
diff --git a/src/libRender/RadiumNBR/Gui/NodeEditor/include/nodes/internal/NodeDataModel.hpp b/src/libRender/RadiumNBR/Gui/NodeEditor/include/nodes/internal/NodeDataModel.hpp
index e13724860517c196dd98969386d3cc7ebc152cf0..9e2f887ec15aaac2657e5cbb5a024dcd919c41ed 100644
--- a/src/libRender/RadiumNBR/Gui/NodeEditor/include/nodes/internal/NodeDataModel.hpp
+++ b/src/libRender/RadiumNBR/Gui/NodeEditor/include/nodes/internal/NodeDataModel.hpp
@@ -66,6 +66,7 @@ public:
 
   virtual bool isDeletable() { return true; }
 
+  virtual void updateState() {}
 
 public:
 
diff --git a/src/libRender/RadiumNBR/Gui/NodeEditor/src/FlowScene.cpp b/src/libRender/RadiumNBR/Gui/NodeEditor/src/FlowScene.cpp
index a1c83883d0384960f1943c2b81ad5ed1be590d98..d5243236f2fc8c83a63477a9d908f0f964ca2f81 100644
--- a/src/libRender/RadiumNBR/Gui/NodeEditor/src/FlowScene.cpp
+++ b/src/libRender/RadiumNBR/Gui/NodeEditor/src/FlowScene.cpp
@@ -179,6 +179,37 @@ restoreConnection(QJsonObject const &connectionJson)
   return connection;
 }
 
+void
+FlowScene::
+importConnection(const QString& fromNodeId,
+                 int fromNodePort,
+                 const QString& toNodeId,
+                 int toNodePort)
+{
+    QUuid nodeInId  = QUuid(toNodeId);
+    QUuid nodeOutId = QUuid(fromNodeId);
+    auto nodeIn  = _nodes[nodeInId].get();
+    auto nodeOut = _nodes[nodeOutId].get();
+
+    auto connection =
+        std::make_shared<Connection>( *nodeIn,
+                                      toNodePort,
+                                      *nodeOut,
+                                      fromNodePort,
+                                      TypeConverter{} );
+
+    auto cgo = detail::make_unique<ConnectionGraphicsObject>(*this, *connection);
+
+    nodeIn->nodeState().setConnection(PortType::In, toNodePort, *connection);
+    nodeOut->nodeState().setConnection(PortType::Out, fromNodePort, *connection);
+
+    nodeIn->nodeDataModel()->updateState();
+
+    // after this function connection points are set to node port
+    connection->setGraphicsObject(std::move(cgo));
+
+    _connections[connection->id()] = connection;
+}
 
 void
 FlowScene::
@@ -197,23 +228,39 @@ Node&
 FlowScene::
 createNode(std::unique_ptr<NodeDataModel> && dataModel)
 {
-  auto node = detail::make_unique<Node>(std::move(dataModel));
-  auto ngo  = detail::make_unique<NodeGraphicsObject>(*this, *node);
+    auto node = detail::make_unique<Node>(std::move(dataModel));
+    auto ngo  = detail::make_unique<NodeGraphicsObject>(*this, *node);
 
-  // generates the uuid of the node (delegated to nodeDataModel implementation)
-  node->_uid = QUuid(node->nodeDataModel()->uuid());
-  std::cout << "Generating an uuid for newly created node : " << node->_uid.toString().toStdString() << std::endl;
+    node->setGraphicsObject(std::move(ngo));
 
+    // generates the uuid of the node (delegated to nodeDataModel implementation)
+    node->_uid = QUuid(node->nodeDataModel()->uuid());
+
+    auto nodePtr = node.get();
+    _nodes[node->id()] = std::move(node);
+
+    nodeCreated(*nodePtr);
+    return *nodePtr;
+}
+
+Node&
+FlowScene::
+importNode(std::unique_ptr<NodeDataModel> && dataModel)
+{
+  auto node = detail::make_unique<Node>(std::move(dataModel));
+  auto ngo  = detail::make_unique<NodeGraphicsObject>(*this, *node);
   node->setGraphicsObject(std::move(ngo));
 
+  node->import();
+
   auto nodePtr = node.get();
   _nodes[node->id()] = std::move(node);
 
+  nodePlaced(*nodePtr);
   nodeCreated(*nodePtr);
   return *nodePtr;
 }
 
-// TODO MTHS -- Add a method that takes a datamodel and only create the node.
 Node&
 FlowScene::
 restoreNode(QJsonObject const& nodeJson)
diff --git a/src/libRender/RadiumNBR/Gui/NodeEditor/src/Node.cpp b/src/libRender/RadiumNBR/Gui/NodeEditor/src/Node.cpp
index 7a859f3249b2d5830e00246c2b14bc32445946a5..6739d8602f56d9dcec469fb527344d57375f66f1 100644
--- a/src/libRender/RadiumNBR/Gui/NodeEditor/src/Node.cpp
+++ b/src/libRender/RadiumNBR/Gui/NodeEditor/src/Node.cpp
@@ -72,6 +72,18 @@ save() const
 }
 
 
+void
+Node::
+import()
+{
+    QJsonObject json = _nodeDataModel->save();
+    _uid = QUuid(_nodeDataModel->uuid());
+    QJsonObject positionJson = json["position"].toObject();
+    QPointF     point(positionJson["x"].toDouble(),
+                   positionJson["y"].toDouble());
+    _nodeGraphicsObject->setPos(point);
+}
+
 void
 Node::
 restore(QJsonObject const& json)
diff --git a/src/libRender/RadiumNBR/Gui/NodeGraphControllerGui.cpp b/src/libRender/RadiumNBR/Gui/NodeGraphControllerGui.cpp
index 3f10f8acc49b61dfe77617b51ed6f8b9a6f49da9..ac51bd3c274fe12725fd2d53da454fd755921964 100644
--- a/src/libRender/RadiumNBR/Gui/NodeGraphControllerGui.cpp
+++ b/src/libRender/RadiumNBR/Gui/NodeGraphControllerGui.cpp
@@ -24,15 +24,11 @@ buildNodeGraphControllerGui( NodeBasedRenderer* renderer,
     nodeEditor->setGraph( renderer->getRenderGraph() );
 
 
-    // TODO: find a way to refresh the main window when a widget gets updated instead of
-    // when the mouse moves
+    // TODO: find a way to refresh the main window when a widget gets updated instead of relying on nodeHoverLeft event
 
-    /*
-    nodeEditor->connections.push_back(
-        QObject::connect( nodeEditor, &RenderGraphEditorView::needUpdate, appUpdateCallback ) );
-    */
     QObject::connect( nodeEditor, &RenderGraphEditorView::needUpdate, appUpdateCallback );
 
+    // TODO : change this to use the loadFromJson method on the graph
     auto loadGraph = [nodeEditor, renderer, appUpdateCallback]() {
         QString fileName = QFileDialog::getOpenFileName(
             nullptr, "Open Flow Scene", QDir::homePath(), "Flow Scene Files (*.flow)" );
@@ -58,11 +54,10 @@ buildNodeGraphControllerGui( NodeBasedRenderer* renderer,
         }
     };
 
-    auto saveGraphToFile = []( const std::string& filename, FlowScene* scene ) {
+    auto saveGraphToFile = []( const std::string& filename, RenderGraph* graph ) {
         if ( !filename.empty() && QFileInfo::exists( filename.c_str() ) )
         {
-            QFile file( filename.c_str() );
-            if ( file.open( QIODevice::WriteOnly ) ) { file.write( scene->saveToMemory() ); }
+            graph->saveToJson( filename );
             return filename;
         }
         else
@@ -73,19 +68,18 @@ buildNodeGraphControllerGui( NodeBasedRenderer* renderer,
             {
                 if ( !newFileName.endsWith( "flow", Qt::CaseInsensitive ) ) newFileName += ".flow";
 
-                QFile file( newFileName );
-                if ( file.open( QIODevice::WriteOnly ) ) { file.write( scene->saveToMemory() ); }
+                graph->saveToJson( newFileName.toStdString() );
             }
             return newFileName.toStdString();
         }
     };
 
-    auto saveGraph = [nodeEditor, renderer, saveGraphToFile]() {
-        saveGraphToFile( renderer->getJsonFilePath(), nodeEditor->scene );
+    auto saveGraph = [renderer, saveGraphToFile]() {
+        saveGraphToFile( renderer->getJsonFilePath(), renderer->getRenderGraph() );
     };
 
     auto saveGraphAs = [nodeEditor, renderer, saveGraphToFile]() {
-        auto filename = saveGraphToFile( "", nodeEditor->scene );
+        auto filename = saveGraphToFile( "", renderer->getRenderGraph() );
         renderer->setJsonFilePath( filename );
         nodeEditor->setWindowTitle( std::string( "RenderGraph Node Editor - " +
                                                  renderer->getRendererName() + " - " + filename )
@@ -102,19 +96,7 @@ buildNodeGraphControllerGui( NodeBasedRenderer* renderer,
         renderer->setJsonFilePath( "" );
         appUpdateCallback();
     };
-    /*
-        nodeEditor->connections.push_back(
-            QObject::connect( nodeEditor->openAction, &QAction::triggered, loadGraph ) );
 
-        nodeEditor->connections.push_back(
-            QObject::connect( nodeEditor->saveAsAction, &QAction::triggered, saveGraphAs ) );
-
-        nodeEditor->connections.push_back(
-            QObject::connect( nodeEditor->saveAction, &QAction::triggered, saveGraph ) );
-
-        nodeEditor->connections.push_back(
-            QObject::connect( nodeEditor->newAction, &QAction::triggered, newGraph ) );
-    */
     QObject::connect( nodeEditor->openAction, &QAction::triggered, loadGraph );
     QObject::connect( nodeEditor->saveAsAction, &QAction::triggered, saveGraphAs );
     QObject::connect( nodeEditor->saveAction, &QAction::triggered, saveGraph );
@@ -124,11 +106,12 @@ buildNodeGraphControllerGui( NodeBasedRenderer* renderer,
         if ( !nodeEditor->isVisible() )
         {
             // Fill the flowscene in the editor with the current graph if any
+            // TODO change this detection method. Instead of the file name, set a flag on the graph that indicates it is available
             if ( renderer->getJsonFilePath() != "" )
             {
                 // Fill the editor with the current graph ...
                 // TODO modify the editor to reflect exactly the same graph than in the renderer
-                // (e.g. if adding a node programatically, update the flowscene
+                // (e.g. if adding a node programmatically, update the flowscene
                 if ( nodeEditor->scene->getSceneName().compare(
                          renderer->getJsonFilePath().c_str() ) != 0 )
                 {
@@ -140,10 +123,9 @@ buildNodeGraphControllerGui( NodeBasedRenderer* renderer,
                             std::cerr << "Loading nodegraph " << renderer->getJsonFilePath()
                                       << " in the editor." << std::endl;
                             nodeEditor->disconnectAll();
+                            // nothing to do, the setGraph method of the editor will do that.
                             nodeEditor->scene->clearScene();
-                            renderer->getRenderGraph()->clearNodes();
-                            QByteArray wholeFile = file.readAll();
-                            nodeEditor->scene->loadFromMemory( wholeFile );
+                            nodeEditor->editGraph();
                             nodeEditor->scene->setSceneName( renderer->getJsonFilePath().c_str() );
                             nodeEditor->setWindowTitle( std::string( "RenderGraph Node Editor - " +
                                                                      renderer->getRendererName() +
@@ -155,7 +137,6 @@ buildNodeGraphControllerGui( NodeBasedRenderer* renderer,
                     }
                 }
             }
-
             nodeEditor->resize( 800, 600 );
             nodeEditor->show();
         }
diff --git a/src/libRender/RadiumNBR/Gui/RenderGraphEditor/NodeAdapterModel.cpp b/src/libRender/RadiumNBR/Gui/RenderGraphEditor/NodeAdapterModel.cpp
index 52c5bd360e1ec65bfe8b083813088d31da472a64..a4573019ed50a9ae68d14b814f7ff3ade0367128 100644
--- a/src/libRender/RadiumNBR/Gui/RenderGraphEditor/NodeAdapterModel.cpp
+++ b/src/libRender/RadiumNBR/Gui/RenderGraphEditor/NodeAdapterModel.cpp
@@ -93,7 +93,7 @@ void QJsonEntryToNlohmannEntry( const QString& key, const QJsonValue& value, nlo
     }
 }
 
-void NlohmannEntryQJsonEntry( const nlohmann::json& data, QJsonValue& value ) {
+void NlohmannEntryToQJsonEntry( const nlohmann::json& data, QJsonValue& value ) {
     switch ( data.type() )
     {
     case nlohmann::detail::value_t::boolean: {
@@ -122,11 +122,10 @@ void NlohmannEntryQJsonEntry( const nlohmann::json& data, QJsonValue& value ) {
     }
     break;
     case nlohmann::detail::value_t::array: {
-        std::cerr << "Saving an array : \n\t" << data << std::endl;
         QJsonArray a;
         QJsonValue v;
         for( auto& x : data.items() ) {
-            NlohmannEntryQJsonEntry(x.value(), v);
+            NlohmannEntryToQJsonEntry( x.value(), v );
             a.append( v );
         }
         value = a;
@@ -155,7 +154,6 @@ void QJsonObjectToNlohmannObject( const QJsonObject& p, nlohmann::json& data ) {
 
 void NlohmannObjectToQJsonObject(const nlohmann::json& data, QJsonObject& p) {
     for (const auto& [key, value] : data.items()) {
-        std::cout << key << " : " << value << "\n";
         if ( value.is_object() ) {
             QJsonObject o;
             NlohmannObjectToQJsonObject( data[key], o);
@@ -163,7 +161,7 @@ void NlohmannObjectToQJsonObject(const nlohmann::json& data, QJsonObject& p) {
         }
         else {
             QJsonValue v;
-            NlohmannEntryQJsonEntry(value, v);
+            NlohmannEntryToQJsonEntry( value, v );
             p.insert(key.c_str(), v);
         }
     }
diff --git a/src/libRender/RadiumNBR/Gui/RenderGraphEditor/NodeAdapterModel.hpp b/src/libRender/RadiumNBR/Gui/RenderGraphEditor/NodeAdapterModel.hpp
index 2cf10da0ee14cc4a2b0a228b84226ae51418bea6..8eb83f20a2c67dac72fb0847491f97c7d8dd6d62 100644
--- a/src/libRender/RadiumNBR/Gui/RenderGraphEditor/NodeAdapterModel.hpp
+++ b/src/libRender/RadiumNBR/Gui/RenderGraphEditor/NodeAdapterModel.hpp
@@ -36,8 +36,17 @@ class NodeAdapterModel : public QtNodes::NodeDataModel
         m_renderGraph->m_recompile = true;
     }
 
+    void adapt(T* n) {
+        m_node = n;
+        m_inputsConnected.resize( m_node->getInputs().size() );
+        m_widget = NodeDataModelTools::getWidget( m_node );
+        NodeDataModelTools::updateWidget( m_node, m_widget );
+        checkConnections();
+    }
+
   public:
     explicit NodeAdapterModel( RenderGraph* renderGraph ) : m_renderGraph( renderGraph ) { init(); }
+    explicit NodeAdapterModel( RenderGraph* renderGraph, T* n ) : m_renderGraph( renderGraph ) { adapt(n); }
     NodeAdapterModel()                          = delete;
     NodeAdapterModel( const NodeAdapterModel& ) = delete;
     NodeAdapterModel( NodeAdapterModel&& )      = default;
@@ -58,6 +67,17 @@ class NodeAdapterModel : public QtNodes::NodeDataModel
 
     bool isDeletable() override { return m_node->isDeletable(); }
 
+    void updateState() override {
+        int i = 0;
+        for( const auto& in : m_node->getInputs() ) {
+            if( in->isLinked() ) {
+                m_inputsConnected[i] = true;
+            }
+            i++;
+        }
+        checkConnections();
+        }
+
   private:
     QtNodes::NodeDataType IOToDataType( size_t hashType, const std::string& ioName ) const {
         return QtNodes::NodeDataType{ std::to_string( hashType ).c_str(), ioName.c_str() };
diff --git a/src/libRender/RadiumNBR/Gui/RenderGraphEditor/RenderGraphEditorView.cpp b/src/libRender/RadiumNBR/Gui/RenderGraphEditor/RenderGraphEditorView.cpp
index 48cdc9dedb539b8d45751df0342ba9b1dcac818c..26b17a316a744e8078a8e60889229e3fbb8981d3 100644
--- a/src/libRender/RadiumNBR/Gui/RenderGraphEditor/RenderGraphEditorView.cpp
+++ b/src/libRender/RadiumNBR/Gui/RenderGraphEditor/RenderGraphEditorView.cpp
@@ -111,28 +111,97 @@ void RenderGraphEditorView::connectAll() {
         } ) );
 }
 
+
+
 void RenderGraphEditorView::setGraph( RenderGraph* rg) {
     currentGraph = rg;
-    auto editorRegistry = NodeGraphQtEditor::initializeNodeRegistry( currentGraph );
-    scene->setRegistry( editorRegistry );
+    // Replace this by a transformation of the currentGraph NodeSet (how to access ??) instead of a hard building of the registry
+    m_editorRegistry = NodeGraphQtEditor::initializeNodeRegistry( currentGraph );
+    scene->setRegistry( m_editorRegistry );
+
+
 }
 
-#if 0
-// TODO : understand why this is problematic with gcc (and not with clang)
-// Moved here from NodeAdapterModel.cpp
-template <>
-void NodeAdapterModel<DisplaySinkNode>::init() {
-    m_node = m_renderGraph->getDisplayNode();
-    m_inputsConnected.resize( m_node->getInputs().size() );
-    checkConnections();
+void RenderGraphEditorView::editGraph() {
+    // TODO, check if pointer are valid ? They have to ...
+    const auto& nodes = *(currentGraph->getNodes());
+    // inserting nodes
+    for(const auto& n : nodes) {
+        scene->importNode( NodeGraphQtEditor::getAdaptedNode( n.get() ) );
+
+    }
+    // inserting connections
+    for(const auto& n : nodes) {
+        int numPort=0;
+        for( const auto & input : n->getInputs() ) {
+            if( input->isLinked() ) {
+                auto portOut = input->getLink();
+                auto nodeOut = portOut->getNode();
+                int outPortIndex = 0;
+                for( const auto& p : nodeOut->getOutputs() ) {
+                    if ( p.get() == portOut ) {
+                        break;
+                    }
+                    outPortIndex++;
+                }
+                scene->importConnection( nodeOut->getUuid().c_str(), outPortIndex,
+                                         n->getUuid().c_str(), numPort);
+            }
+            numPort++;
+        }
+    }
 }
 
-template <>
-void NodeAdapterModel<DisplaySinkNode>::destroy() {}
-#endif
 
 namespace NodeGraphQtEditor {
 
+/** NodeDataModelBuilder to convert an existing graph to its editor representation */
+
+using DataModelAdapter = std::function<std::unique_ptr<QtNodes::NodeDataModel>(Node*)>;
+
+template <typename T>
+class NodeDataModelAdapter
+{
+  public:
+    explicit NodeDataModelAdapter( RenderGraph* renderGraph ) : m_renderGraph( renderGraph ) {}
+
+    std::unique_ptr<QtNodes::NodeDataModel> operator()(Node* n) {
+        return std::make_unique<NodeAdapterModel<T>>( m_renderGraph, static_cast<T*>(n) );
+    }
+
+  private:
+    RenderGraph* m_renderGraph;
+};
+
+using DataModelAdapters = std::unordered_map<std::string, DataModelAdapter>;
+DataModelAdapters dataModelAdapters;
+
+void registerNodeModelAdapterInternal( std::string nodeType,
+                                       DataModelAdapter adapter) {
+    if ( dataModelAdapters.find( nodeType ) == dataModelAdapters.end() )
+    { dataModelAdapters[nodeType] = std::move( adapter ); }
+    else
+    {
+        std::cerr << "registerNodeModelCreatorInternal: trying to add an already existing node adapter for type "
+                  << nodeType << "." << std::endl;
+    }
+}
+
+template <typename T>
+void registerNodeModelAdapter( DataModelAdapter nodeAdapter ) {
+    registerNodeModelAdapterInternal( T::getTypename(), std::move( nodeAdapter ) );
+}
+
+
+std::unique_ptr<QtNodes::NodeDataModel> getAdaptedNode( Node* n ) {
+    auto it = dataModelAdapters.find( n->getTypeName() );
+    if (  it != dataModelAdapters.end() ) {
+        return it->second(n);
+    }
+    return nullptr;
+}
+
+/** Editor registry associated to the editor so that it ca create a node */
 template <typename T>
 class NodeCreator
 {
@@ -148,8 +217,64 @@ class NodeCreator
 };
 
 using namespace QtNodes;
+
+template<typename T>
+void addNodeTypeToEditor( RenderGraph* renderGraph,
+                          std::shared_ptr<DataModelRegistry>& creators,
+                          /*DataModelAdapters& adapters, */
+                          std::string category ) {
+
+    creators->registerModel<NodeAdapterModel<T>>(
+        NodeCreator<NodeAdapterModel<T>>( renderGraph ), "Data" );
+
+    registerNodeModelAdapter<T>( NodeDataModelAdapter<T>(renderGraph) );
+}
+
+
 std::shared_ptr<DataModelRegistry> initializeNodeRegistry( RenderGraph* renderGraph ) {
     auto ret = std::make_shared<DataModelRegistry>();
+#if 1
+    addNodeTypeToEditor<DataNode<NodeTypeRenderObject>>(renderGraph, ret, "Data");
+    addNodeTypeToEditor<DataNode<NodeTypeLight>>(renderGraph, ret, "Data");
+    addNodeTypeToEditor<DataNode<NodeTypeCamera>>(renderGraph, ret, "Data");
+
+    addNodeTypeToEditor<DisplaySinkNode>(renderGraph, ret, "Sinks");
+
+    addNodeTypeToEditor<FilterROByTypeNode>(renderGraph, ret, "Filters");
+    addNodeTypeToEditor<FilterROByNameNode>(renderGraph, ret, "Filters");
+
+    addNodeTypeToEditor<ClearColorNode>(renderGraph, ret, "RenderPasses");
+    addNodeTypeToEditor<ZGeomPrepassNode>(renderGraph, ret, "RenderPasses");
+    addNodeTypeToEditor<AccessibilityBufferNode>(renderGraph, ret, "RenderPasses");
+    addNodeTypeToEditor<EnvLightNode>(renderGraph, ret, "RenderPasses");
+    addNodeTypeToEditor<LocalLightNode>(renderGraph, ret, "RenderPasses");
+    addNodeTypeToEditor<EmissivityNode>(renderGraph, ret, "RenderPasses");
+    addNodeTypeToEditor<TransparencyNode>(renderGraph, ret, "RenderPasses");
+    addNodeTypeToEditor<VolumeNode>(renderGraph, ret, "RenderPasses");
+    addNodeTypeToEditor<VolumeVizualisationNode>(renderGraph, ret, "RenderPasses");
+    addNodeTypeToEditor<UINode>(renderGraph, ret, "RenderPasses");
+    addNodeTypeToEditor<WireframeNode>(renderGraph, ret, "RenderPasses");
+    addNodeTypeToEditor<SimpleNode>(renderGraph, ret, "RenderPasses");
+
+    addNodeTypeToEditor<ColorSourceNode>(renderGraph, ret, "Sources");
+    addNodeTypeToEditor<BooleanValueSource>(renderGraph, ret, "Sources");
+    addNodeTypeToEditor<ScalarValueSource>(renderGraph, ret, "Sources");
+    addNodeTypeToEditor<EnvMapTextureSource>(renderGraph, ret, "Sources");
+    addNodeTypeToEditor<ColorTextureNode>(renderGraph, ret, "Sources");
+    addNodeTypeToEditor<DepthTextureNode>(renderGraph, ret, "Sources");
+
+    addNodeTypeToEditor<DifferenceNode>(renderGraph, ret, "Compositing");
+    addNodeTypeToEditor<SumNode>(renderGraph, ret, "Compositing");
+    addNodeTypeToEditor<MultiplyNode>(renderGraph, ret, "Compositing");
+    addNodeTypeToEditor<OneMinusNode>(renderGraph, ret, "Compositing");
+    addNodeTypeToEditor<MaxNode>(renderGraph, ret, "Compositing");
+    addNodeTypeToEditor<MinNode>(renderGraph, ret, "Compositing");
+    addNodeTypeToEditor<MoreThanThresholdNode>(renderGraph, ret, "Compositing");
+    addNodeTypeToEditor<LessThanThresholdNode>(renderGraph, ret, "Compositing");
+
+    addNodeTypeToEditor<FXAANode>(renderGraph, ret, "Anti Aliasing");
+
+#else
     ret->registerModel<NodeAdapterModel<DataNode<NodeTypeRenderObject>>>(
         NodeCreator<NodeAdapterModel<DataNode<NodeTypeRenderObject>>>( renderGraph ), "Data" );
     ret->registerModel<NodeAdapterModel<DataNode<NodeTypeLight>>>(
@@ -223,7 +348,7 @@ std::shared_ptr<DataModelRegistry> initializeNodeRegistry( RenderGraph* renderGr
 
     ret->registerModel<NodeAdapterModel<FXAANode>>(
         NodeCreator<NodeAdapterModel<FXAANode>>( renderGraph ), "Anti Aliasing" );
-
+#endif
     return ret;
 }
 } // namespace NodeGraphQtEditor
diff --git a/src/libRender/RadiumNBR/Gui/RenderGraphEditor/RenderGraphEditorView.hpp b/src/libRender/RadiumNBR/Gui/RenderGraphEditor/RenderGraphEditorView.hpp
index 4f859017d370dc701db011328e10fb38c73ff38a..7c4b28ee4edd9ca598ed099aa1ef5dbbe8914af3 100644
--- a/src/libRender/RadiumNBR/Gui/RenderGraphEditor/RenderGraphEditorView.hpp
+++ b/src/libRender/RadiumNBR/Gui/RenderGraphEditor/RenderGraphEditorView.hpp
@@ -14,9 +14,11 @@ class NodeBasedRenderer;
 
 // TODO, why is this class outside of any namespace ?
 class RenderGraph;
+class Node;
 
 namespace NodeGraphQtEditor {
 std::shared_ptr<QtNodes::DataModelRegistry> initializeNodeRegistry( RenderGraph* renderGraph );
+std::unique_ptr<QtNodes::NodeDataModel> getAdaptedNode( Node* n );
 }
 
 class NodeBasedRenderer_LIBRARY_API RenderGraphEditorView : public QWidget
@@ -30,6 +32,8 @@ class NodeBasedRenderer_LIBRARY_API RenderGraphEditorView : public QWidget
 
     void setGraph( RenderGraph* rg);
 
+    void editGraph();
+
   public slots:
     bool eventFilter( QObject* object, QEvent* event ) {
         if ( event->type() == QEvent::MouseMove || event->type() == QEvent::KeyPress )
@@ -57,4 +61,6 @@ class NodeBasedRenderer_LIBRARY_API RenderGraphEditorView : public QWidget
 
   private:
     RenderGraph* currentGraph{ nullptr };
+
+    std::shared_ptr<QtNodes::DataModelRegistry> m_editorRegistry;
 };
diff --git a/src/libRender/RadiumNBR/NodeGraph/Node.hpp b/src/libRender/RadiumNBR/NodeGraph/Node.hpp
index 2dfe18d787ce63fc5f8380d81cec7c9fd7287aa7..4cd36160d53005381bc2f25709f6f27e54d6f51e 100644
--- a/src/libRender/RadiumNBR/NodeGraph/Node.hpp
+++ b/src/libRender/RadiumNBR/NodeGraph/Node.hpp
@@ -243,4 +243,9 @@ class NodeBasedRenderer_LIBRARY_API Node
     static bool s_uuidGeneratorInitialized;
     static uuids::uuid_random_generator* s_uidGenerator;
     static void createUuidGenerator();
+
+  public:
+    static const std::string getTypename() {
+        return "Node";
+    }
 };
diff --git a/src/libRender/RadiumNBR/NodeGraph/NodeFactory.hpp b/src/libRender/RadiumNBR/NodeGraph/NodeFactory.hpp
index 53583f1abb691d2e89f220db5e7a29ddd01f0246..14be5f39eba88608f18463437e1aad82874b9534 100644
--- a/src/libRender/RadiumNBR/NodeGraph/NodeFactory.hpp
+++ b/src/libRender/RadiumNBR/NodeGraph/NodeFactory.hpp
@@ -6,12 +6,14 @@
 #include <iostream>
 #include <unordered_map>
 
+#include <any>
+
 namespace NodeFactory {
 NodeBasedRenderer_LIBRARY_API Node* createNode( std::string& nodeType, const nlohmann::json& data );
 
 NodeBasedRenderer_LIBRARY_API void
 registerNodeInternal( std::string nodeType,
-                      std::function<Node*( const nlohmann::json& data )> nodeCreator );
+                      std::function<Node*( const nlohmann::json& data )> nodeCreator);
 
 template <typename T>
 void registerNode( std::function<Node*( const nlohmann::json& data )> nodeCreator ) {
diff --git a/src/libRender/RadiumNBR/NodeGraph/RenderGraph.cpp b/src/libRender/RadiumNBR/NodeGraph/RenderGraph.cpp
index 84706e514102db668e233e9e9f5241b7c9961034..1f143978524de04f9107f93ee6f9d5e2473a9909 100644
--- a/src/libRender/RadiumNBR/NodeGraph/RenderGraph.cpp
+++ b/src/libRender/RadiumNBR/NodeGraph/RenderGraph.cpp
@@ -212,6 +212,7 @@ void RenderGraph::loadFromJson( const std::string& jsonFilePath ) {
 }
 
 void RenderGraph::saveToJson( const std::string& jsonFilePath ) {
+    std::cout << "RenderGraph::saveToJson : saving graph to " << jsonFilePath << "\n";
     nlohmann::json nodes = nlohmann::json::array();
     nlohmann::json connections = nlohmann::json::array();
     for(const auto&n : m_nodes) {
diff --git a/src/libRender/RadiumNBR/Renderer/NodeGraphController.cpp b/src/libRender/RadiumNBR/Renderer/NodeGraphController.cpp
index fb9a4e2a5c6dd47ea32028fcf711daba440c3683..6cabb08f0ef46a051b47015d6de592fcd4b0d38f 100644
--- a/src/libRender/RadiumNBR/Renderer/NodeGraphController.cpp
+++ b/src/libRender/RadiumNBR/Renderer/NodeGraphController.cpp
@@ -40,128 +40,16 @@ void NodeGraphController::configure( RadiumNBR::NodeBasedRenderer* renderer, int
         LOG( Ra::Core::Utils::logERROR ) << "Unable to find resources for MultiPassRenderer!";
         return;
     }
-    auto renderGraph = renderer->getRenderGraph();
     auto resourcesPath{ *resourcesCheck };
     auto shaderManager = Ra::Engine::RadiumEngine::getInstance()->getShaderProgramManager();
+    //! [Caching some helpers and data from the Engine and the renderer]
 
+    //! [Access to the rendering node graph and parameterize it]
+    auto renderGraph = renderer->getRenderGraph();
     renderGraph->setResourcesDir( resourcesPath );
     renderGraph->setShaderProgramManager( shaderManager );
 
-    //! [Caching some helpers and data from the Engine and the renderer]
-
-    // Build render graph
-
-    // renderer->loadFromJson(resourcesPath + "RenderGraphs/fullfeaturerenderer.flow");
-
-    /*Ra::Engine::Data::TextureParameters texParams;
-    texParams.width  = w;
-    texParams.height = h;
-    texParams.target = gl45core::GL_TEXTURE_2D;
-    texParams.internalFormat = gl45core::GL_RGBA32F;
-    texParams.format         = gl45core::GL_RGBA;
-    texParams.type           = gl45core::GL_FLOAT;
-    texParams.minFilter      = gl45core::GL_LINEAR;
-    texParams.magFilter      = gl45core::GL_LINEAR;
-    texParams.name           = "Linear RGB";
-
-    auto color = new TextureNode("swapchain", texParams);
-    renderGraph->addNode(color);
-
-    auto clearColor = new ClearColorNode("clearColor");
-    renderGraph->addNode(clearColor);
-
-    auto clearColorColor = new SourceNode<NodeTypeColor>("clearColorColor",
-    NodeTypeColor::fromRGB(NodeTypeColor::Red().rgb())); renderGraph->addNode(clearColorColor);
-
-    auto zGeomPrepass = new ZGeomPrepassNode("zGeomPrepass");
-    renderGraph->addNode(zGeomPrepass);
-
-    auto envLight = new EnvLightNode("envLight");
-    renderGraph->addNode(envLight);
-
-    auto AO = new AccessibilityBufferNode("aoPass");
-    renderGraph->addNode(AO);
-
-    auto emissivity = new EmissivityNode("emissivity");
-    renderGraph->addNode(emissivity);
-
-    auto localLight = new LocalLightNode("localLight");
-    renderGraph->addNode(localLight);
-
-    auto transparency = new TransparencyNode("transparency");
-    renderGraph->addNode(transparency);
-
-    auto filterROTransparent = new FilterNode<NodeTypeRenderObject>("filterTransparent", [] (const
-    NodeTypeRenderObject& ro) { return ro->isTransparent(); });
-    renderGraph->addNode(filterROTransparent);
-
-    auto volume = new VolumeNode("volume");
-    renderGraph->addNode(volume);
-
-    auto filterROVolume = new FilterNode<NodeTypeRenderObject>("filterVolume", [] (const
-    NodeTypeRenderObject& ro) { auto material = ro->getMaterial(); return material &&
-    material->getMaterialAspect() == Ra::Engine::Data::Material::MaterialAspect::MAT_DENSITY;
-    });
-    renderGraph->addNode(filterROVolume);
-
-    auto wireframe = new WireframeNode("wireframe");
-    renderGraph->addNode(wireframe);
-
-    auto wireframeActivated = new SourceNode<bool>("wireframeActivated", false);
-    renderGraph->addNode(wireframeActivated);
-
-    auto displayNode = new DisplaySinkNode("displayNode");
-    renderGraph->addNode(displayNode);
-
-    renderGraph->addLink(color, "to", clearColor, "inColor");
-    renderGraph->addLink(clearColorColor, "to", clearColor, "inClearColor");
-    renderGraph->addLink(wireframeActivated, "to", wireframe, "inActivate");
-    renderGraph->addLink(clearColor, "outColor", emissivity, "inColor");
-    renderGraph->addLink(renderGraph->getRenderObjectNode(), "outData", localLight, "inRO");
-    renderGraph->addLink(renderGraph->getRenderObjectNode(), "outData", zGeomPrepass, "inRO");
-    renderGraph->addLink(renderGraph->getRenderObjectNode(), "outData", emissivity, "inRO");
-    renderGraph->addLink(renderGraph->getRenderObjectNode(), "outData", envLight, "inRO");
-    renderGraph->addLink(renderGraph->getRenderObjectNode(), "outData", filterROTransparent, "in");
-    renderGraph->addLink(renderGraph->getRenderObjectNode(), "outData", wireframe, "inRO");
-    renderGraph->addLink(filterROTransparent, "out", transparency, "inRO");
-    renderGraph->addLink(renderGraph->getRenderObjectNode(), "outData", filterROVolume, "in");
-    renderGraph->addLink(filterROVolume, "out", volume, "inRO");
-    renderGraph->addLink(renderGraph->getLightNode(), "outData", localLight, "inL");
-    renderGraph->addLink(renderGraph->getLightNode(), "outData", transparency, "inL");
-    renderGraph->addLink(renderGraph->getLightNode(), "outData", volume, "inL");
-    renderGraph->addLink(renderGraph->getCameraNode(), "outData", localLight, "inC");
-    renderGraph->addLink(renderGraph->getCameraNode(), "outData", zGeomPrepass, "inC");
-    renderGraph->addLink(renderGraph->getCameraNode(), "outData", AO, "inC");
-    renderGraph->addLink(renderGraph->getCameraNode(), "outData", emissivity, "inC");
-    renderGraph->addLink(renderGraph->getCameraNode(), "outData", envLight, "inC");
-    renderGraph->addLink(renderGraph->getCameraNode(), "outData", transparency, "inC");
-    renderGraph->addLink(renderGraph->getCameraNode(), "outData", volume, "inC");
-    renderGraph->addLink(renderGraph->getCameraNode(), "outData", wireframe, "inC");
-    renderGraph->addLink(zGeomPrepass, "outDepth", localLight, "inDepth");
-    renderGraph->addLink(zGeomPrepass, "outDepth", emissivity, "inDepth");
-    renderGraph->addLink(zGeomPrepass, "outDepth", envLight, "inDepth");
-    renderGraph->addLink(zGeomPrepass, "outDepth", transparency, "inDepth");
-    renderGraph->addLink(zGeomPrepass, "outDepth", volume, "inDepth");
-    renderGraph->addLink(zGeomPrepass, "outDepth", wireframe, "inDepth");
-    renderGraph->addLink(zGeomPrepass, "outDepth", displayNode, "in4");
-    renderGraph->addLink(zGeomPrepass, "outPosInWorld", AO, "inPos");
-    renderGraph->addLink(zGeomPrepass, "outPosInWorld", displayNode, "in1");
-    renderGraph->addLink(zGeomPrepass, "outNormalInWorld", AO, "inNormal");
-    renderGraph->addLink(zGeomPrepass, "outNormalInWorld", displayNode, "in2");
-    renderGraph->addLink(AO, "outAO", localLight, "inAO");
-    renderGraph->addLink(AO, "outAO", emissivity, "inAO");
-    renderGraph->addLink(AO, "outAO", envLight, "inAO");
-    renderGraph->addLink(AO, "outAO", displayNode, "in3");
-    renderGraph->addLink(emissivity, "outColor", envLight, "inColor");
-    renderGraph->addLink(envLight, "outColor", localLight, "inColor");
-    renderGraph->addLink(localLight, "outColor", transparency, "inColor");
-    renderGraph->addLink(transparency, "outColor", volume, "inColor");
-    renderGraph->addLink(volume, "outColor", wireframe, "inColor");
-    renderGraph->addLink(wireframe, "outColor", displayNode, "in0");
-
-    renderGraph->init();
-
-    renderer->setDisplayNode(displayNode);*/
+    //! [Access to the rendering node graph and parameterize it]
 }
 
 void NodeGraphController::update( const Ra::Engine::Data::ViewingParameters& ){