diff --git a/libs/shared/lib/vis/visualizations/nodelinkvis/components/NLPixi.tsx b/libs/shared/lib/vis/visualizations/nodelinkvis/components/NLPixi.tsx
index 52b711cb7119615fa60c67152377a45204193da3..c0434d43d0742a0a13353527284cc8f97b17d082 100644
--- a/libs/shared/lib/vis/visualizations/nodelinkvis/components/NLPixi.tsx
+++ b/libs/shared/lib/vis/visualizations/nodelinkvis/components/NLPixi.tsx
@@ -1,6 +1,6 @@
 import { GraphType, GraphTypeD3, LinkType, LinkTypeD3, NodeType, NodeTypeD3 } from '../types';
 import { dataColors, visualizationColors } from 'config';
-import { useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
+import { useEffect, useImperativeHandle, useMemo, useRef, useState, forwardRef } from 'react';
 import {
   Application,
   Color,
@@ -47,7 +47,7 @@ type LayoutState = 'reset' | 'running' | 'paused';
 // MAIN COMPONENT
 //////////////////
 
-export const NLPixi = (props: Props) => {
+export const NLPixi = forwardRef((props: Props, refExternal) => {
   const [quickPopup, setQuickPopup] = useState<{ node: NodeType; pos: IPointData } | undefined>();
   const [popups, setPopups] = useState<{ node: NodeTypeD3; pos: IPointData }[]>([]);
 
@@ -334,6 +334,67 @@ export const NLPixi = (props: Props) => {
     },
   }));
 
+  useImperativeHandle(refExternal, () => ({
+    exportImage() {
+      const captureImage = () => {
+        const canvas = ref.current?.querySelector('canvas') as HTMLCanvasElement;
+        if (canvas) {
+          canvas.toBlob((blob) => {
+            if (blob) {
+              const imageUrl = URL.createObjectURL(blob);
+              const whiteCanvas = document.createElement('canvas');
+              whiteCanvas.width = canvas.width;
+              whiteCanvas.height = canvas.height;
+              const ctx = whiteCanvas.getContext('2d');
+              if (ctx) {
+                // Draw a white background
+                ctx.fillStyle = 'white';
+                ctx.fillRect(0, 0, whiteCanvas.width, whiteCanvas.height);
+
+                // Draw the original canvas image on top
+                const img = new Image();
+                img.src = imageUrl;
+                img.onload = () => {
+                  ctx.drawImage(img, 0, 0);
+
+                  // Now export the combined image
+                  const finalImage = whiteCanvas.toDataURL('image/png');
+
+                  const link = document.createElement('a');
+                  link.href = finalImage;
+                  link.download = 'nodelinkvis.png';
+                  document.body.appendChild(link);
+                  link.click();
+                  document.body.removeChild(link);
+
+                  // Revoke the object URL to free up memory
+                  URL.revokeObjectURL(imageUrl);
+                };
+                img.onerror = (err) => {
+                  console.error('Failed to load image', err);
+                };
+              } else {
+                console.error('2D context not found on the new canvas');
+              }
+            } else {
+              console.error('Failed to convert canvas to Blob');
+            }
+          }, 'image/png');
+        } else {
+          console.error('Canvas element not found');
+        }
+      };
+
+      const renderCanvas = () => {
+        requestAnimationFrame(() => {
+          captureImage();
+        });
+      };
+
+      renderCanvas();
+    },
+  }));
+
   function resize() {
     const width = ref?.current?.clientWidth || 1000;
     const height = ref?.current?.clientHeight || 1000;
@@ -903,6 +964,8 @@ export const NLPixi = (props: Props) => {
     layoutAlgorithm.current.layout(graphologyGraph, boundingBox);
   };
 
+  // export image
+
   return (
     <>
       {popups.map((popup) => (
@@ -937,4 +1000,4 @@ export const NLPixi = (props: Props) => {
       ></div>
     </>
   );
-};
+});
diff --git a/libs/shared/lib/vis/visualizations/nodelinkvis/nodelinkvis.tsx b/libs/shared/lib/vis/visualizations/nodelinkvis/nodelinkvis.tsx
index 4679606a36acc47be8a7812c07244a63d67bf78b..5c4c23202d91fe43e4e678d5c7d7a725668668b7 100644
--- a/libs/shared/lib/vis/visualizations/nodelinkvis/nodelinkvis.tsx
+++ b/libs/shared/lib/vis/visualizations/nodelinkvis/nodelinkvis.tsx
@@ -1,4 +1,4 @@
-import React, { useEffect, useRef, useState } from 'react';
+import React, { useEffect, useRef, useState, forwardRef, useImperativeHandle } from 'react';
 import { GraphType, LinkType, NodeType, NodeTypeD3 } from './types';
 import { NLPixi } from './components/NLPixi';
 import { parseQueryResult } from './components/query2NL';
@@ -14,6 +14,10 @@ import { Node } from '@graphpolaris/shared/lib/data-access/store/graphQueryResul
 import { IPointData } from 'pixi.js';
 import { VisualizationPropTypes, VISComponentType, VisualizationSettingsPropTypes } from '../../common';
 
+export interface NodeLinkVisHandle {
+  exportImageInternal: () => void;
+}
+
 export interface NodelinkVisProps {
   id: string;
   name: string;
@@ -49,78 +53,91 @@ const settings: NodelinkVisProps = {
   nodeList: [],
 };
 
-export const NodeLinkVis = React.memo(({ data, ml, dispatch, settings, handleSelect }: VisualizationPropTypes<NodelinkVisProps>) => {
-  const ref = useRef<HTMLDivElement>(null);
-  const [graph, setGraph] = useImmer<GraphType | undefined>(undefined);
-  const [highlightNodes, setHighlightNodes] = useState<NodeType[]>([]);
-  const [highlightedLinks, setHighlightedLinks] = useState<LinkType[]>([]);
-
-  useEffect(() => {
-    if (data) {
-      setGraph(
-        parseQueryResult(data, ml, {
-          defaultX: (ref.current?.clientWidth || 1000) / 2,
-          defaultY: (ref.current?.clientHeight || 1000) / 2,
-        }),
-      );
-    }
-  }, [data, ml]);
-
-  const onClickedNode = (event?: { node: NodeTypeD3; pos: IPointData }, ml?: ML) => {
-    if (graph) {
-      if (!event?.node) {
-        handleSelect();
-        return;
+const NodeLinkVis = forwardRef<NodeLinkVisHandle, VisualizationPropTypes<NodelinkVisProps>>(
+  ({ data, ml, dispatch, settings, handleSelect }, refExternal) => {
+    const ref = useRef<HTMLDivElement>(null);
+    const nlPixiRef = useRef<any>(null);
+    const [graph, setGraph] = useImmer<GraphType | undefined>(undefined);
+    const [highlightNodes, setHighlightNodes] = useState<NodeType[]>([]);
+    const [highlightedLinks, setHighlightedLinks] = useState<LinkType[]>([]);
+
+    useEffect(() => {
+      if (data) {
+        setGraph(
+          parseQueryResult(data, ml, {
+            defaultX: (ref.current?.clientWidth || 1000) / 2,
+            defaultY: (ref.current?.clientHeight || 1000) / 2,
+          }),
+        );
       }
-
-      const node = event.node;
-      const nodeMeta = graph.nodes[node._id];
-      handleSelect({ nodes: [nodeMeta as Node] });
-
-      if (ml && ml.shortestPath.enabled) {
-        setGraph((draft) => {
-          let _node = draft?.nodes[node._id];
-          if (!_node) return draft;
-
-          if (!ml.shortestPath.srcNode) {
-            _node.isShortestPathSource = true;
-            dispatch(setShortestPathSource(node._id));
-          } else if (ml.shortestPath.srcNode === node._id) {
-            _node.isShortestPathSource = false;
-            dispatch(setShortestPathSource(undefined));
-          } else if (!ml.shortestPath.trtNode) {
-            _node.isShortestPathTarget = true;
-            dispatch(setShortestPathTarget(node._id));
-          } else if (ml.shortestPath.trtNode === node._id) {
-            _node.isShortestPathTarget = false;
-            dispatch(setShortestPathTarget(undefined));
-          } else {
-            _node.isShortestPathSource = true;
-            _node.isShortestPathTarget = false;
-            dispatch(setShortestPathSource(node._id));
-            dispatch(setShortestPathTarget(undefined));
-          }
-          return draft;
-        });
+    }, [data, ml]);
+
+    const onClickedNode = (event?: { node: NodeTypeD3; pos: IPointData }, ml?: ML) => {
+      if (graph) {
+        if (!event?.node) {
+          handleSelect();
+          return;
+        }
+
+        const node = event.node;
+        const nodeMeta = graph.nodes[node._id];
+        handleSelect({ nodes: [nodeMeta as Node] });
+
+        if (ml && ml.shortestPath.enabled) {
+          setGraph((draft) => {
+            let _node = draft?.nodes[node._id];
+            if (!_node) return draft;
+
+            if (!ml.shortestPath.srcNode) {
+              _node.isShortestPathSource = true;
+              dispatch(setShortestPathSource(node._id));
+            } else if (ml.shortestPath.srcNode === node._id) {
+              _node.isShortestPathSource = false;
+              dispatch(setShortestPathSource(undefined));
+            } else if (!ml.shortestPath.trtNode) {
+              _node.isShortestPathTarget = true;
+              dispatch(setShortestPathTarget(node._id));
+            } else if (ml.shortestPath.trtNode === node._id) {
+              _node.isShortestPathTarget = false;
+              dispatch(setShortestPathTarget(undefined));
+            } else {
+              _node.isShortestPathSource = true;
+              _node.isShortestPathTarget = false;
+              dispatch(setShortestPathSource(node._id));
+              dispatch(setShortestPathTarget(undefined));
+            }
+            return draft;
+          });
+        }
       }
-    }
-  };
+    };
 
-  if (!graph) return null;
-  return (
-    <NLPixi
-      graph={graph}
-      configuration={settings}
-      highlightNodes={highlightNodes}
-      highlightedLinks={highlightedLinks}
-      onClick={(event) => {
-        onClickedNode(event, ml);
-      }}
-      layoutAlgorithm={settings.layout}
-      showPopupsOnHover={settings.showPopUpOnHover}
-    />
-  );
-});
+    const exportImageInternal = () => {
+      nlPixiRef.current.exportImage();
+    };
+
+    useImperativeHandle(refExternal, () => ({
+      exportImageInternal,
+    }));
+
+    if (!graph) return null;
+
+    return (
+      <NLPixi
+        ref={nlPixiRef}
+        graph={graph}
+        configuration={settings}
+        highlightNodes={highlightNodes}
+        highlightedLinks={highlightedLinks}
+        onClick={(event) => {
+          onClickedNode(event, ml);
+        }}
+        layoutAlgorithm={settings.layout}
+        showPopupsOnHover={settings.showPopUpOnHover}
+      />
+    );
+  },
+);
 
 const NodelinkSettings = ({ settings, graphMetadata, updateSettings }: VisualizationSettingsPropTypes<NodelinkVisProps>) => {
   useEffect(() => {
@@ -216,15 +233,20 @@ const NodelinkSettings = ({ settings, graphMetadata, updateSettings }: Visualiza
     </SettingsContainer>
   );
 };
+const nodeLinkVisRef = React.createRef<{ exportImageInternal: () => void }>();
 
 export const NodeLinkComponent: VISComponentType<NodelinkVisProps> = {
   displayName: 'NodeLinkVis',
   description: 'General Patterns and Connections',
-  component: NodeLinkVis,
+  component: React.forwardRef((props: VisualizationPropTypes<NodelinkVisProps>, ref) => <NodeLinkVis {...props} ref={nodeLinkVisRef} />),
   settingsComponent: NodelinkSettings,
   settings: settings,
   exportImage: () => {
-    alert('Not yet supported');
+    if (nodeLinkVisRef.current) {
+      nodeLinkVisRef.current.exportImageInternal();
+    } else {
+      console.error('NodeLink reference is not set.');
+    }
   },
 };