diff --git a/src/lib/components/textEditor/TextEditor.tsx b/src/lib/components/textEditor/TextEditor.tsx
index a603ffe35eece008556fa05438ccddf298c2f533..302215403085fb9c820a2f6a06b66c19358eec35 100644
--- a/src/lib/components/textEditor/TextEditor.tsx
+++ b/src/lib/components/textEditor/TextEditor.tsx
@@ -22,7 +22,7 @@ type TextEditorProps = {
   handleSave: (elements: SerializedEditorState, generateEmail: boolean) => void;
   saveDisabled: boolean;
   variableOptions: string[];
-  alarmMode: string;
+  insight: InsightModel;
 };
 
 function InitialStateLoader({ editorState }: { editorState: SerializedEditorState | null }) {
@@ -47,7 +47,7 @@ export function TextEditor({
   saveDisabled,
   children,
   variableOptions,
-  alarmMode,
+  insight,
 }: TextEditorProps) {
   const contentEditableRef = useRef<HTMLDivElement>(null);
   const updateTimeoutRef = useRef<NodeJS.Timeout | null>(null);
@@ -70,7 +70,7 @@ export function TextEditor({
   return (
     <LexicalComposer initialConfig={initialConfig}>
       <div className="editor-toolbar flex items-center bg-secondary-50 rounded mt-4 space-x-2" style={{ marginBottom: -8 }}>
-        <PreviewPlugin contentEditable={contentEditableRef} />
+        <PreviewPlugin contentEditable={contentEditableRef} insight={insight} />
         {showToolbar && <ToolbarPlugin />}
       </div>
       <div className="border p-2">
@@ -83,7 +83,7 @@ export function TextEditor({
         </div>
         <div className="preview min-h-24 p-3 hidden"></div>
       </div>
-      <InsertVariablesPlugin variableOptions={variableOptions} alarmMode={alarmMode} />
+      <InsertVariablesPlugin variableOptions={variableOptions} alarmMode={insight.alarmMode} />
       <InitialStateLoader editorState={editorState} />
 
       <div className="flex flex-row mt-3 justify-between">
diff --git a/src/lib/components/textEditor/plugins/PreviewPlugin.tsx b/src/lib/components/textEditor/plugins/PreviewPlugin.tsx
index fa40d7059035dbb0dd5ec7ac239eb0c97250df74..56e8c298e05e03597dd6d7fed965fe08748211f8 100644
--- a/src/lib/components/textEditor/plugins/PreviewPlugin.tsx
+++ b/src/lib/components/textEditor/plugins/PreviewPlugin.tsx
@@ -9,8 +9,15 @@ import { VisualizationSettingsType } from '@/lib/vis/common';
 
 // @ts-expect-error missing import
 import { newPlot, toImage } from 'plotly.js/dist/plotly';
+import { AppearanceMap, InsightModel } from 'ts-common';
+import { wsGetInsightAppearances, wsGetInsights, wsInsightAppearancesSubscription } from '@/lib/data-access/broker/wsInsightSharing';
 
-export function PreviewPlugin({ contentEditable }: { contentEditable: RefObject<HTMLDivElement | null> }): JSX.Element {
+interface PreviewPluginProps {
+  contentEditable: RefObject<HTMLDivElement | null>;
+  insight: InsightModel;
+}
+
+export function PreviewPlugin({ contentEditable, insight }: PreviewPluginProps): JSX.Element {
   const [editor] = useLexicalComposerContext();
 
   function updatePreview() {
@@ -19,7 +26,16 @@ export function PreviewPlugin({ contentEditable }: { contentEditable: RefObject<
       if (preview == null) return;
 
       const html = $generateHtmlFromNodes(editor as any); // any needed to avoid excessive ts error
-      preview.innerHTML = await populateTemplate(html);
+
+      if (insight.alarmMode == 'entityAppearances') {
+        wsInsightAppearancesSubscription(async nodeAppearances => {
+          if (nodeAppearances == null) return;
+          preview.innerHTML = await populateTemplate(html, nodeAppearances);
+        });
+        await wsGetInsightAppearances({ insightID: insight.id });
+      } else {
+        preview.innerHTML = await populateTemplate(html);
+      }
     });
   }
 
@@ -47,7 +63,7 @@ export function PreviewPlugin({ contentEditable }: { contentEditable: RefObject<
     return string.replace(regexp, () => replacements[i++]);
   }
 
-  async function populateTemplate(html: string) {
+  async function populateTemplate(html: string, nodeAppearance?: AppearanceMap) {
     const regex = / *?{\{ *?(\w*?):([\w •]*?) *?\}\} *?/gm;
 
     return replaceAllAsync(html, regex, async (_: string, _type: string, name: string) => {
@@ -63,6 +79,14 @@ export function PreviewPlugin({ contentEditable }: { contentEditable: RefObject<
           return ` ${value} `;
         }
 
+        case VariableType.list: {
+          if (nodeAppearance == null) {
+            throw new Error('No nodeAppearances available to populate tempate');
+          }
+          const headers = ['nodeID', 'count', 'queries']; // TODO: get headers from data
+          return generateList(nodeAppearance, headers);
+        }
+
         case VariableType.visualization: {
           const activeVisualization = vis.openVisualizationArray.find(x => x.name == name) as Vis1DProps & VisualizationSettingsType;
 
@@ -186,3 +210,70 @@ export function PreviewPlugin({ contentEditable }: { contentEditable: RefObject<
     </ul>
   );
 }
+
+export function generateTable(data: any[], headers: string[]): string {
+  if (!data || data.length === 0) {
+    return '<p>No data available</p>'; // Return a message if no data is provided
+  }
+
+  let tableHTML = `
+    <table border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse; width: 100%; margin-top: 20px;">
+      <thead>
+        <tr>
+  `;
+
+  // Generate table headers dynamically from the headers array
+  headers.forEach(header => {
+    tableHTML += `<th>${header}</th>`;
+  });
+
+  tableHTML += `</tr></thead><tbody>`;
+
+  // Generate rows for the table dynamically based on the data
+  data.forEach(row => {
+    tableHTML += `<tr>`;
+    headers.forEach(header => {
+      // For each header, grab the corresponding field in the data row
+      // If the field is an array (e.g. queries), convert it to a string for display
+      if (Array.isArray(row[header])) {
+        tableHTML += `<td>${row[header].join(', ')}</td>`;
+      } else {
+        tableHTML += `<td>${row[header] || ''}</td>`;
+      }
+    });
+    tableHTML += `</tr>`;
+  });
+
+  // Close table tags
+  tableHTML += `</tbody></table>`;
+
+  return tableHTML;
+}
+
+export function generateList(data: any[], headers: string[]): string {
+  if (!data || data.length === 0) {
+    return '<p>No data available</p>';
+  }
+
+  let listHTML = `<ul style="margin-top: 20px;">`;
+
+  data.forEach(row => {
+    listHTML += `<li><strong>${headers[0]}:</strong> ${row.nodeID || 'N/A'}`;
+
+    for (let i = 1; i < headers.length; i++) {
+      const key = headers[i];
+      let value = row[key];
+
+      if (Array.isArray(value)) {
+        value = value.join(', '); // Convert array to string
+      }
+
+      listHTML += `, <strong>${headers[i]}:</strong> ${value ?? 'N/A'}`;
+    }
+
+    listHTML += `</li>`;
+  });
+
+  listHTML += `</ul>`;
+  return listHTML;
+}
diff --git a/src/lib/data-access/broker/wsInsightSharing.ts b/src/lib/data-access/broker/wsInsightSharing.ts
index 42dbc5471e12820110869ff24b1bc329194d8d66..ddc57a7031b6338449724851a1f2ab12bd07f04a 100644
--- a/src/lib/data-access/broker/wsInsightSharing.ts
+++ b/src/lib/data-access/broker/wsInsightSharing.ts
@@ -78,6 +78,23 @@ export const wsDeleteInsight: WsFrontendCall<{ id: number }, wsReturnKey.insight
   );
 };
 
+export const wsGetInsightAppearances: WsFrontendCall<{ insightID: number }, wsReturnKey.insightAppearance> = (params, callback) => {
+  Broker.instance().sendMessage(
+    {
+      key: wsKeys.insight,
+      subKey: wsSubKeys.getAppearances,
+      body: { insightID: params.insightID },
+    },
+    callback,
+  );
+};
+export function wsInsightAppearancesSubscription(callback: ResponseCallback<wsReturnKey.insightAppearance>) {
+  const id = Broker.instance().subscribe(callback, wsReturnKey.insightAppearance);
+  return () => {
+    Broker.instance().unSubscribe(wsReturnKey.insightAppearance, id);
+  };
+}
+
 export function wsInsightSubscription(callback: ResponseCallback<wsReturnKey.insightResult>) {
   const id = Broker.instance().subscribe(callback, wsReturnKey.insightResult);
   return () => {
diff --git a/src/lib/insight-sharing/FormInsight.tsx b/src/lib/insight-sharing/FormInsight.tsx
index 59e2f87e5523350cd83c18231f97013b89aab255..b13a422d5b37191b4edda4c3b271458c397c66dd 100644
--- a/src/lib/insight-sharing/FormInsight.tsx
+++ b/src/lib/insight-sharing/FormInsight.tsx
@@ -453,7 +453,7 @@ export function FormInsight(props: Props) {
             handleSave={handleSave}
             saveDisabled={!valid}
             variableOptions={selectedQueryID.entities}
-            alarmMode={localInsight.alarmMode}
+            insight={localInsight}
           >
             <Button
               label="Delete"