diff --git a/debug.html b/debug.html
new file mode 100644
index 0000000..c79ae55
--- /dev/null
+++ b/debug.html
@@ -0,0 +1,11 @@
+<html>
+  <head>
+    <title>Misc. Infrastructure POCs</title>
+  </head>
+  <body>
+    <script src="js/debug.js"></script>
+    <script>
+      document.body.append(...TickDebug());
+    </script>
+  </body>
+</html>
diff --git a/debug.ts b/debug.ts
new file mode 100644
index 0000000..19908a0
--- /dev/null
+++ b/debug.ts
@@ -0,0 +1,3 @@
+import { TickDebug } from "./debug/tick";
+
+Object.assign(globalThis, { TickDebug });
diff --git a/debug/tick.ts b/debug/tick.ts
new file mode 100644
index 0000000..320d249
--- /dev/null
+++ b/debug/tick.ts
@@ -0,0 +1,36 @@
+import { h } from "../lib/html";
+import { Cancel } from "../lib/source";
+import { tick } from "../lib/tick";
+
+export function TickDebug() {
+  const output = h("pre", {});
+
+  const tickSource = tick(30);
+  let cancel: Cancel;
+
+  const begin = () => {
+    // reset / init
+    cancel?.();
+    output.innerHTML = "";
+    // subscribe to source, stash cancellation func
+    cancel = tickSource((tick) => {
+      switch (tick[0]) {
+        case "physics":
+          output.append(`${new Date().toISOString()}: Physics\n`);
+          break;
+        case "render":
+          output.append(
+            `${new Date().toISOString()}: Render (dt=${tick[1]})\n`
+          );
+          break;
+      }
+    });
+  };
+
+  const end = () => cancel?.();
+
+  const start = h("button", { onclick: begin }, "Begin");
+  const stop = h("button", { onclick: end }, "Cease");
+
+  return [h("h1", {}, "Tick Event Demo"), start, stop, output, h("hr")];
+}