diff --git a/source/RobotAPI/components/ArViz/CMakeLists.txt b/source/RobotAPI/components/ArViz/CMakeLists.txt
index 5a21a1cd4e02935799bdd4788aa7e2cac5ca12c8..d79d9a4ba4e3ee75d0860328997112e864c008d3 100644
--- a/source/RobotAPI/components/ArViz/CMakeLists.txt
+++ b/source/RobotAPI/components/ArViz/CMakeLists.txt
@@ -15,6 +15,7 @@ set(SOURCES
     Client/elements/Mesh.cpp
     Client/elements/Robot.cpp
     Client/elements/RobotHand.cpp
+    Client/drawer/ArVizDrawerBase.cpp
 
     Coin/ElementVisualizer.cpp
 
@@ -75,6 +76,8 @@ set(HEADERS
     Client/elements/Robot.h
     Client/elements/RobotHand.h
 
+    Client/drawer/ArVizDrawerBase.h
+
     Client/elements/point_cloud_type_traits.hpp
 
     Introspection/ElementJsonSerializers.h
diff --git a/source/RobotAPI/components/ArViz/Client/drawer/ArVizDrawerBase.cpp b/source/RobotAPI/components/ArViz/Client/drawer/ArVizDrawerBase.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a19032cd088ccdf49e16af5ea394d73a92b30878
--- /dev/null
+++ b/source/RobotAPI/components/ArViz/Client/drawer/ArVizDrawerBase.cpp
@@ -0,0 +1,29 @@
+#include "ArVizDrawerBase.h"
+
+#include "RobotAPI/components/ArViz/Client/Client.h"
+#include "RobotAPI/components/ArViz/Client/Layer.h"
+
+namespace armarx
+{
+
+    ArVizDrawerBase::ArVizDrawerBase(armarx::viz::Client &arviz) : arvizClient(arviz) {}
+
+    ArVizDrawerBase::~ArVizDrawerBase() = default;
+
+    viz::Client &ArVizDrawerBase::arviz() { return arvizClient; }
+
+    const viz::Client &ArVizDrawerBase::arviz() const { return arvizClient; }
+
+    void ArVizDrawerBase::commit(const viz::Layer &layer)
+    {
+        std::lock_guard guard{layerMtx};
+        arvizClient.commit(layer);
+    }
+
+    void ArVizDrawerBase::commit(const std::vector<viz::Layer> &layers)
+    {
+        std::lock_guard guard{layerMtx};
+        arvizClient.commit(layers);
+    }
+
+} // namespace armarx
diff --git a/source/RobotAPI/components/ArViz/Client/drawer/ArVizDrawerBase.h b/source/RobotAPI/components/ArViz/Client/drawer/ArVizDrawerBase.h
new file mode 100644
index 0000000000000000000000000000000000000000..f7c813be72283ec4899f402a1133c41ab5a381e2
--- /dev/null
+++ b/source/RobotAPI/components/ArViz/Client/drawer/ArVizDrawerBase.h
@@ -0,0 +1,62 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author     Fabian Reister ( fabian dot reister at kit dot edu )
+ * @date       2021
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <mutex>
+#include <vector>
+
+namespace armarx
+{
+    // forward declaration
+    namespace viz
+    {
+        class Client;
+        struct Layer;
+    } // namespace viz
+
+    /**
+     * @brief The ArVizDrawerBase class. Use this class to draw arbitrary objects.
+     *
+     * Instead of implementing arviz drawing in the component itself, this class helps to
+     * decouple drawing from "component / processing logic".
+     *
+     */
+    class ArVizDrawerBase
+    {
+      public:
+        ArVizDrawerBase(armarx::viz::Client &arviz);
+        virtual ~ArVizDrawerBase();
+
+      protected:
+        viz::Client &arviz();
+        const viz::Client &arviz() const;
+
+        void commit(const viz::Layer &layer);
+        void commit(const std::vector<viz::Layer> &layers);
+
+      private:
+        viz::Client &arvizClient;
+
+        std::mutex layerMtx;
+    };
+
+} // namespace armarx