diff --git a/Assets/Scripts/UI/InGame/WebViewController.cs b/Assets/Scripts/UI/InGame/WebViewController.cs
index c1cb33f3a370b56697153bf31e8e6efc9374f15a..8d247c58f70763c8843a3fa1d6b78a603fe603e2 100644
--- a/Assets/Scripts/UI/InGame/WebViewController.cs
+++ b/Assets/Scripts/UI/InGame/WebViewController.cs
@@ -12,6 +12,7 @@
 using System.Linq;
 using System.Text.RegularExpressions;
 using UnityEngine;
+using UnityEngine.UIElements;
 
 public class WebViewController : ScrollView
 {
@@ -35,9 +36,10 @@ private void OnWebViewComponentReady()
         SwitchScrollUI.activeScrollData.HintAvailableEvent.AddListener(OnHintAvailable);
         webViewComponent.tab.AddJSBinding("applyScroll", ApplyScrollHandler);
         webViewComponent.tab.AddJSBinding("getHint", GetHintHandler);
+        // webViewComponent.tab.AddJSBinding("updateAssignments", UpdateAssignmentsHandler); // The browser can just ask the MMTServer directly
         if (SwitchScrollUI.activeScrollData.Scroll is not null)
         {
-            SetScrollContent(SwitchScrollUI.activeScrollData.Scroll);
+            SetScrollContent(SwitchScrollUI.activeScrollData.RenderedScroll);
         }
         RegisterBrowserEventhandlers();
     }
@@ -76,42 +78,23 @@ private void DeRegisterBrowserEventhandlers()
     }
 
     /// <summary>
-    /// sets or updates the content of the scroll container dom element
+    /// <para>
+    /// Hand the ScrollView the labels (and potentially assignments) of all facts, so it can render the scroll content. (And then tell it to do so)
+    /// </para><para>
+    /// More precisely: Put a stringified and Json serialized Dictionary 
+    /// <see cref="OMS.uri"/> slotID  -> (<see cref="string"/> label, <see cref="Fact.Id"/> factId) <br/>
+    /// into the "data-assignments" attribute of the "assignments" node
+    /// </para>
     /// </summary>
     /// <param name="scroll"></param>
     private async void SetScrollContent(Scroll scroll)
     {
         // update scroll container content
         DomNodeWrapper document = await webViewComponent.tab.Document;
-        DomNodeWrapper scrollContainer = await document.querySelectorAsync("#scrollContainer");
+        DomNodeWrapper scrollContainer = await document.querySelectorAsync("#scrollContainer"); 
 
         var description = scroll.description;
-        if (Regex.IsMatch(description, ".*<scroll-description.*"))
-        {
-            // replace slot templates
-            description = Regex.Replace(description, "<scroll-slot([^>]*)>([^<]*)</scroll-slot>", match =>
-            {
-                var extraAttributes = match.Groups[1].Value;
-                var slotId = match.Groups[2].Value;
-                var assignment = SwitchScrollUI.activeScrollData.Assignments[slotId];
-                /** label of the assigned fact, or the slot label if nothing assigned */
-                var label = assignment.IsSet    ? assignment.fact.GetLabel(StageStatic.stage.factState) 
-                                                : scroll.requiredFacts.Find(fact => fact.@ref.uri == slotId).label;
-                /** id of the assigned fact. If nothing is assigned don't add the attribute */
-                var fact_id = assignment.IsSet  ? $"data-fact-id='{assignment.fact.Id}'" 
-                                                : "";
-                return $"<mi dropzone='copy' data-slot-id='{slotId}' {fact_id} {extraAttributes}>{label}</mi>";
-            });
-            // replace solution templates
-            description = Regex.Replace(description, "<scroll-solution([^>]*)>([^<]*)</scroll-solution>", match =>
-            {
-                var extraAttributes = match.Groups[1].Value;
-                var solutionId = match.Groups[2].Value;
-                var label = scroll.acquiredFacts.Find(fact => fact.@ref.uri == solutionId).label;
-                return $"<mi data-solution-id='{solutionId}' {extraAttributes}>{label}</mi>";
-            });
-        }
-        else
+        if (!Regex.IsMatch(description, ".*<scroll-description.*"))
         {
             // scroll is a legacy plain text scroll, generate html with slots for the required facts
             var factSlots = SwitchScrollUI.activeScrollData.Assignments
@@ -120,15 +103,67 @@ private async void SetScrollContent(Scroll scroll)
                     @$"<span class='legacySlot' dropzone='copy' data-slot-id='{pair.Key}' {(pair.Value.IsSet ? $"data-fact-id='{pair.Value.fact.Id}'" : "")}>
                         {(pair.Value.IsSet ?
                             pair.Value.fact.GetLabel(StageStatic.stage.factState) :
-                            scroll.requiredFacts.Find(fact => fact.@ref.uri == pair.Key).label )}
+                            scroll.requiredFacts.Find(fact => fact.@ref.uri == pair.Key).label)}
                     </span>");
 
             description = $"<scroll-description><p>{scroll.description}</p><div id='legacySlots'>{String.Join("", factSlots)}</div></scroll-description>";
+            
         }
-        // display the scroll description
-        dropzones = null;
+        //else // Is done by JS. How to render the scroll is the scrolls buisness
+        //{
+        //    // replace slot templates
+        //    description = Regex.Replace(description, "<scroll-slot([^>]*)>([^<]*)</scroll-slot>", match =>
+        //    {
+        //        var extraAttributes = match.Groups[1].Value;
+        //        var slotId = match.Groups[2].Value;
+        //        var assignment = SwitchScrollUI.activeScrollData.Assignments[slotId];
+        //        /** label of the assigned fact, or the slot label if nothing assigned */
+        //        var label = assignment.IsSet    ? assignment.fact.GetLabel(StageStatic.stage.factState) 
+        //                                        : scroll.requiredFacts.Find(fact => fact.@ref.uri == slotId).label;
+        //        /** id of the assigned fact. If nothing is assigned don't add the attribute */
+        //        var fact_id = assignment.IsSet  ? $"data-fact-id='{assignment.fact.Id}'" 
+        //                                        : "";
+        //        return $"<mi dropzone='copy' data-slot-id='{slotId}' {fact_id} {extraAttributes}>{label}</mi>";
+        //    });
+        //    // replace solution templates
+        //    description = Regex.Replace(description, "<scroll-solution([^>]*)>([^<]*)</scroll-solution>", match =>
+        //    {
+        //        var extraAttributes = match.Groups[1].Value;
+        //        var solutionId = match.Groups[2].Value;
+        //        var label = scroll.acquiredFacts.Find(fact => fact.@ref.uri == solutionId).label;
+        //        return $"<mi data-solution-id='{solutionId}' {extraAttributes}>{label}</mi>";
+        //    });
+        //}
+
+        // Display the scroll description.
         await scrollContainer.setOuterHtmlAsync($"<div id='scrollContainer'>{description}</div>");
 
+
+        DomNodeWrapper assignmentsNode = await document.querySelectorAsync("#assignments");
+        Dictionary<string, (string, string)> assignments = new();
+
+        foreach (MMTFact fact in scroll.requiredFacts)
+        {
+            string slotId = fact.@ref.uri;
+            ActiveScroll.SlotAssignment assignment = SwitchScrollUI.activeScrollData.Assignments[slotId];
+            if (assignment.IsSet)
+            {
+                assignments.Add(slotId, (assignment.fact.GetLabel(StageStatic.stage.factState), assignment.fact.Id));
+            }
+            else
+            {
+                assignments.Add(slotId, (fact.label, ""));
+            }
+        }
+        foreach (MMTFact fact in scroll.acquiredFacts)
+        {
+            assignments.Add(fact.@ref.uri, (fact.label, ""));
+        }
+        await assignmentsNode.setAttributeValue("data-assignments", JsonConvert.SerializeObject(assignments));
+        _ = webViewComponent.tab.Evaluate("RenderScroll()");
+
+        // Update the interactive components
+        dropzones = null;
         RegisterBrowserEventhandlers();
     }
 
@@ -194,6 +229,43 @@ private void GetHintHandler(string url)
         SwitchScrollUI.activeScrollData.ButtonClicked(new HintScrollButton(url));
     }
 
+    /// <summary>
+    /// <para>
+    /// Hand the ScrollView the labels (and potentially assignments) of all facts, so it can render the scroll.
+    /// </para><para>
+    /// More precisely: Put a stringified and Json serialized Dictionary 
+    /// <see cref="OMS.uri"/> slotID  -> (<see cref="string"/> label, <see cref="Fact.Id"/> factId) <br/>
+    /// into the "data-assignments" attribute of the "assignments" node
+    /// </para>
+    /// </summary>
+    /// <param name="youHappyNowJS">Is ignored. JS bindings need to take a string argument, so here it is.</param>
+    [Obsolete("This data can be aquired directly from the MMTServer")]
+    private async void UpdateAssignmentsHandler(string youHappyNowJS = "")
+    {
+        DomNodeWrapper document = await webViewComponent.tab.Document;
+        DomNodeWrapper assignmentsNode = await document.querySelectorAsync("#assignments");
+        Scroll scroll = SwitchScrollUI.activeScrollData.RenderedScroll;
+        Dictionary<string, (string,string)> assignments = new();
+        foreach (var (slotId,assignment) in SwitchScrollUI.activeScrollData.Assignments)
+        {
+            string label = assignment.IsSet ? assignment.fact.GetLabel(StageStatic.stage.factState)
+                                                : scroll.requiredFacts.Find(fact => fact.@ref.uri == slotId).label;
+            /** id of the assigned fact. If nothing is assigned don't add the attribute */
+            string fact_id = assignment.IsSet ? assignment.fact.Id : "";
+            assignments.Add(slotId,(label,fact_id));
+        }
+        foreach(MMTFact fact in scroll.acquiredFacts)
+        {
+            string label = scroll.acquiredFacts.Find(f => fact.@ref.uri == f.@ref.uri).label;
+            Debug.Log(label);
+            Debug.Log(fact.label);
+            assignments.Add(fact.@ref.uri, (fact.label, ""));
+        }
+    
+
+        await assignmentsNode.setAttributeValue("data-assignments", JsonConvert.SerializeObject(assignments));
+    }
+
     public string[] GetFactAssignments()
     {
         return dropzones.Select(dropzone => dropzone.Node.attributes.GetValueOrDefault("data-fact-id", null)).ToArray();
diff --git a/Assets/StreamingAssets/StreamToDataPath_withHandler/scrollView.html b/Assets/StreamingAssets/StreamToDataPath_withHandler/scrollView.html
index fdbda223d648b86a920c896deeb72e30c8bfbc5e..3c96afb86e56c8cea7c751828b4cef3f8eeb0fd8 100644
--- a/Assets/StreamingAssets/StreamToDataPath_withHandler/scrollView.html
+++ b/Assets/StreamingAssets/StreamToDataPath_withHandler/scrollView.html
@@ -43,28 +43,28 @@
       <span>Given a triangle</span>
       <math>
           <mi>&xutri;<!-- △ --></mi>
-          <scroll-slot>http://mathhub.info/FrameIT/frameworld?TriangleProblem?A</scroll-slot>
-          <scroll-slot>http://mathhub.info/FrameIT/frameworld?TriangleProblem?B</scroll-slot>
-          <scroll-slot>http://mathhub.info/FrameIT/frameworld?TriangleProblem?C</scroll-slot>
+          <mi data-slot-id="http://mathhub.info/FrameIT/frameworld?TriangleProblem?A"></mi>
+          <mi data-slot-id="http://mathhub.info/FrameIT/frameworld?TriangleProblem?B"></mi>
+          <mi data-slot-id="http://mathhub.info/FrameIT/frameworld?TriangleProblem?C"></mi>
       </math>
       <span>right-angled at</span>
       <math>
           <!--<mi>&angrtvbd;</mi>--><!-- ⦝ -->
-          <scroll-slot>http://mathhub.info/FrameIT/frameworld?TriangleProblem_RightAngleAtC?rightAngleC</scroll-slot>
+          <mi data-slot-id="http://mathhub.info/FrameIT/frameworld?TriangleProblem_RightAngleAtC?rightAngleC"></mi>
       </math>,<br />
       <span>the opposite side has length</span>
       <math>
-          <scroll-solution>http://mathhub.info/FrameIT/frameworld?OppositeLen/Solution?deducedLineCA</scroll-solution>
+          <mi data-solution-id="http://mathhub.info/FrameIT/frameworld?OppositeLen/Solution?deducedLineCA"></mi>
           <mo>&equals;</mo>
           <mrow>
               <mi>tan</mi>
               <!--<mo>&#8289;</mo>-->
               <mo>(</mo>
-              <scroll-slot>http://mathhub.info/FrameIT/frameworld?TriangleProblem_AngleAtB?angleB</scroll-slot>
+              <mi data-slot-id="http://mathhub.info/FrameIT/frameworld?TriangleProblem_AngleAtB?angleB"></mi>
               <mo>)</mo>
           </mrow>
           <mo>&#8290;</mo>
-          <scroll-slot>http://mathhub.info/FrameIT/frameworld?OppositeLen/Problem?distanceBC</scroll-slot>
+          <mi data-slot-id="http://mathhub.info/FrameIT/frameworld?OppositeLen/Problem?distanceBC"></mi>
       </math>
       <span>.</span>
       <div>
@@ -109,7 +109,6 @@
                   y='67.117035'
                   id='pointB'
                   style='fill:#0000ff'
-                  dropzone='copy'
                   data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem?B'>${lverb B}</text>
               <text
                   xml:space='preserve'
@@ -117,7 +116,6 @@
                   y='68.080437'
                   id='pointC'
                   style='fill:#0000ff'
-                  dropzone='copy'
                   data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem?C'>${lverb C}</text>
               <text
                   xml:space='preserve'
@@ -125,7 +123,6 @@
                   y='6.551136'
                   id='pointA'
                   style='fill:#0000ff'
-                  dropzone='copy'
                   data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem?A'>${lverb A}</text>
               <text
                   xml:space='preserve'
@@ -133,7 +130,6 @@
                   y='62.492699'
                   id='angleAtB'
                   style='fill:#ffcc00'
-                  dropzone='copy'
                   data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem_AngleAtB?angleB'>${lverb angleB}</text>
               <text
                   xml:space='preserve'
@@ -141,7 +137,6 @@
                   y='60.951256'
                   id='rightAngleAtC'
                   style='fill:#ffcc00'
-                  dropzone='copy'
                   data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem_RightAngleAtC?rightAngleC'>${lverb rightAngleC}</text>
               <text
                   xml:space='preserve'
@@ -149,7 +144,6 @@
                   y='68.273117'
                   id='distanceBC'
                   style='fill:#008000'
-                  dropzone='copy'
                   data-slot-id='http://mathhub.info/FrameIT/frameworld?OppositeLen/Problem?distanceBC'>${lverb distanceBC}</text>
               <text
                   xml:space='preserve'
@@ -183,15 +177,10 @@
     }
 
     loadScript("./scroll_interaction/Drop_facts.js")
-
-    const container = document.getElementById('scrollContainer');
-    const tmp = document.createElement('div');
-    tmp.id='test'
-    tmp.innerText = 'test'
-    container.append(tmp);
+    loadScript("./scroll_interaction/SetScrollContent.js")
 
   </script>
-  <data id="assignments" hidden data-assignments="">hi</data>
+  <data id="assignments" hidden data-assignments="{&quot;http://mathhub.info/FrameIT/frameworld?TriangleProblem?A&quot;:{&quot;Item1&quot;:&quot;(C)&quot;,&quot;Item2&quot;:&quot;http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact310&quot;},&quot;http://mathhub.info/FrameIT/frameworld?TriangleProblem?B&quot;:{&quot;Item1&quot;:&quot;(B)&quot;,&quot;Item2&quot;:&quot;http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact309&quot;},&quot;http://mathhub.info/FrameIT/frameworld?TriangleProblem?C&quot;:{&quot;Item1&quot;:&quot;C&quot;,&quot;Item2&quot;:&quot;&quot;},&quot;http://mathhub.info/FrameIT/frameworld?TriangleProblem_RightAngleAtC?rightAngleC&quot;:{&quot;Item1&quot;:&quot;⊾C&quot;,&quot;Item2&quot;:&quot;&quot;},&quot;http://mathhub.info/FrameIT/frameworld?OppositeLen/Problem?distanceBC&quot;:{&quot;Item1&quot;:&quot;BC&quot;,&quot;Item2&quot;:&quot;&quot;},&quot;http://mathhub.info/FrameIT/frameworld?TriangleProblem_AngleAtB?angleB&quot;:{&quot;Item1&quot;:&quot;∠ABC&quot;,&quot;Item2&quot;:&quot;&quot;},&quot;http://mathhub.info/FrameIT/frameworld?OppositeLen/Solution?deducedLineCA&quot;:{&quot;Item1&quot;:&quot;CA&quot;,&quot;Item2&quot;:&quot;&quot;}}">hi</data>
   
   <!--<script src="visualiseCursor.mjs" defer type="module"></script>-->
   <!--<script>
diff --git a/Assets/StreamingAssets/StreamToDataPath_withHandler/scroll_interaction/SetScrollContent.js b/Assets/StreamingAssets/StreamToDataPath_withHandler/scroll_interaction/SetScrollContent.js
new file mode 100644
index 0000000000000000000000000000000000000000..f206f4fec4b38428ac25f1a8db2b0cf0f83f994d
--- /dev/null
+++ b/Assets/StreamingAssets/StreamToDataPath_withHandler/scroll_interaction/SetScrollContent.js
@@ -0,0 +1,67 @@
+
+function RenderScroll() {
+    const scrollContainer = document.querySelector("#scrollContainer");
+    const description = scrollContainer.textContent;
+    const assignments = JSON.parse(document.querySelector("#assignments").dataset.assignments)
+    console.log(assignments);
+
+    //everything that has a slotID is a scroll slot
+    scrollContainer.querySelectorAll("[data-slot-id]").forEach(element => {
+        //console.log(element);
+        let slotId = element.dataset.slotId;
+        let fact_assignment = assignments[slotId];
+
+        element.setAttribute("dropzone", "copy");
+        element.textContent = fact_assignment.Item1;
+
+        if (fact_assignment.Item2 != "") {
+            element.dataset.factId = fact_assignment.Item2;
+        }
+    });
+
+    //everything that has a solutionID is a scroll solution
+    scrollContainer.querySelectorAll("[data-solution-id]").forEach(element => {
+        element.textContent = assignments[element.dataset.solutionId].Item1;
+    })
+    console.log('Scroll rendered')
+}
+RenderScroll()
+// if (Regex.IsMatch(description, ".*<scroll-description.*"))
+// {
+//     // replace slot templates
+//     description = Regex.Replace(description, "<scroll-slot([^>]*)>([^<]*)</scroll-slot>", match =>
+//     {
+//         var extraAttributes = match.Groups[1].Value;
+//         var slotId = match.Groups[2].Value;
+//         var assignment = SwitchScrollUI.activeScrollData.Assignments[slotId];
+//         /** label of the assigned fact, or the slot label if nothing assigned */
+//         var label = assignment.IsSet    ? assignment.fact.GetLabel(StageStatic.stage.factState)
+//                                         : scroll.requiredFacts.Find(fact => fact.@ref.uri == slotId).label;
+//         /** id of the assigned fact. If nothing is assigned don't add the attribute */
+//         var fact_id = assignment.IsSet  ? $"data-fact-id='{assignment.fact.Id}'"
+//                                         : "";
+//         return $"<mi dropzone='copy' data-slot-id='{slotId}' {fact_id} {extraAttributes}>{label}</mi>";
+//     });
+//     // replace solution templates
+//     description = Regex.Replace(description, "<scroll-solution([^>]*)>([^<]*)</scroll-solution>", match =>
+//     {
+//         var extraAttributes = match.Groups[1].Value;
+//         var solutionId = match.Groups[2].Value;
+//         var label = scroll.acquiredFacts.Find(fact => fact.@ref.uri == solutionId).label;
+//         return $"<mi data-solution-id='{solutionId}' {extraAttributes}>{label}</mi>";
+//     });
+// }
+// else
+// {
+//     // scroll is a legacy plain text scroll, generate html with slots for the required facts
+//     var factSlots = SwitchScrollUI.activeScrollData.Assignments
+//         .Where(pair => pair.Value.IsVisible)
+//         .Select(pair =>
+//             @$"<span class='legacySlot' dropzone='copy' data-slot-id='{pair.Key}' {(pair.Value.IsSet ? $"data-fact-id='{pair.Value.fact.Id}'" : "")}>
+//                 {(pair.Value.IsSet ?
+//                     pair.Value.fact.GetLabel(StageStatic.stage.factState) :
+//                     scroll.requiredFacts.Find(fact => fact.@ref.uri == pair.Key).label )}
+//             </span>");
+
+//     description = $"<scroll-description><p>{scroll.description}</p><div id='legacySlots'>{String.Join("", factSlots)}</div></scroll-description>";
+// }
\ No newline at end of file
diff --git a/Assets/StreamingAssets/StreamToDataPath_withHandler/scroll_interaction/SetScrollContent.js.meta b/Assets/StreamingAssets/StreamToDataPath_withHandler/scroll_interaction/SetScrollContent.js.meta
new file mode 100644
index 0000000000000000000000000000000000000000..cedf0ac5485748bf9bf7e22d808882c9b48c5327
--- /dev/null
+++ b/Assets/StreamingAssets/StreamToDataPath_withHandler/scroll_interaction/SetScrollContent.js.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 215e6162e17215b4a9118b3db2f4944f
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: