diff --git a/engine-proto/ganja-test/ganja-test.html b/engine-proto/ganja-test/ganja-test.html
new file mode 100644
index 0000000..f1ecf45
--- /dev/null
+++ b/engine-proto/ganja-test/ganja-test.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <style>
+    body {
+      background-color: #ffe0f0;
+    }
+    
+    /* needed to keep Ganja canvas from blowing up */
+    canvas {
+      min-width: 600px;
+      max-width: 600px;
+      min-height: 600px;
+      max-height: 600px;
+    }
+  </style>
+  <script src="https://unpkg.com/ganja.js"></script>
+</head>
+<body>
+  <script>
+  // the "points spheres plane" example from the Ganja coffee shop
+  //
+  //   https://enkimute.github.io/ganja.js/examples/coffeeshop.html#cga3d_points_spheres_planes
+  //
+  
+  // Create a Clifford Algebra with 4,1 metric for 3D CGA. 
+  Algebra(4,1,()=>{
+    // We start by defining a null basis, and upcasting for points
+    var ni = 1e4+1e5, no = .5e5-.5e4;
+    var up = (x)=> no + x + .5*x*x*ni;
+    
+    // Next we'll define 4 points
+    var p1 = up(1e1), p2 = up(1e2), p3 = up(-1e3), p4 = up(-1e2);
+    
+    // The outer product can be used to construct the sphere through
+    // any four points. 
+    var s = ()=>p1^p2^p3^p4;
+    
+    // The outer product between any three points and infinity is a plane.
+    var p = ()=>p1^p2^p3^ni;
+    
+    // Graph the items.  
+    document.body.appendChild(this.graph([
+      0x00FF0000, p1, "p1", p2, "p2", p3, "p3", p4, "p4", // points
+      0xE0008800, p, "p",                                 // plane
+      0xE00000FF, s, "s"                                  // sphere
+    ], {conformal: true, gl: true, grid: true}));
+  });
+  </script>
+</body>
+</html>
diff --git a/engine-proto/ganja-test/ganja-test.jl b/engine-proto/ganja-test/ganja-test.jl
new file mode 100644
index 0000000..ea8b334
--- /dev/null
+++ b/engine-proto/ganja-test/ganja-test.jl
@@ -0,0 +1,71 @@
+using Blink
+import Blink: JSString
+
+# === styling utility ===
+
+style!(w, stylesheet) = @js win begin
+  @var style = document.createElement("style");
+  style.appendChild(document.createTextNode($stylesheet));
+  document.head.appendChild(style);
+end
+
+# === page source ===
+
+stylesheet = """
+body {
+  background-color: #ffe0f0;
+}
+
+/* needed to keep Ganja canvas from blowing up */
+canvas {
+  min-width: 600px;
+  max-width: 600px;
+  min-height: 600px;
+  max-height: 600px;
+}
+"""
+
+# the "points spheres plane" example from the Ganja coffee shop
+#
+#   https://enkimute.github.io/ganja.js/examples/coffeeshop.html#cga3d_points_spheres_planes
+#
+sphere_example = """
+Algebra(4, 1, ()=>{
+  // We start by defining a null basis, and upcasting for points
+  var ni = 1e4+1e5, no = .5e5-.5e4;
+  var up = (x)=> no + x + .5*x*x*ni;
+  
+  // Next we'll define 4 points
+  var p1 = up(1e1), p2 = up(1e2), p3 = up(-1e3), p4 = up(-1e2);
+  
+  // The outer product can be used to construct the sphere through
+  // any four points. 
+  var s = ()=>p1^p2^p3^p4;
+  
+  // The outer product between any three points and infinity is a plane.
+  var p = ()=>p1^p2^p3^ni;
+  
+  // Graph the items.  
+  document.body.appendChild(this.graph([
+    0x00FF0000, p1, "p1", p2, "p2", p3, "p3", p4, "p4", // points
+    0xE0008800, p, "p",                                 // plane
+    0xE00000FF, s, "s"                                  // sphere
+  ], {conformal: true, gl: true, grid: true}));
+});
+"""
+
+# === page construction ===
+
+# create window and open developer console
+win = Window()
+opentools(win)
+
+# set stylesheet
+style!(win, stylesheet)
+
+# load Ganja.js
+loadjs!(win, "https://unpkg.com/ganja.js")
+
+# launch Ganja visualization
+body!(win, "", async=false)
+js(win, JSString(sphere_example))