diff --git a/content/graph.html b/content/graph.md
similarity index 56%
rename from content/graph.html
rename to content/graph.md
index 1f36ed1..3b738be 100644
--- a/content/graph.html
+++ b/content/graph.md
@@ -1,22 +1,9 @@
---
title: "Content Graph"
+type: "graph"
---
-
-
-
-
-Here you can see a visualization of the posts on this blog using Vis.js.
+Here you can see a visualization of the posts on this blog using [Vis.js](https://visjs.org/).
In the below graph, each node is an article, and each edge between nodes is a reference from
one article to another. Each article is sized to be roughly proportional to its word count (file size
is used as a quick metric for this purpose). You can hover over a node to see the title of the article
it represents, and double-click to go to that article.
-
-
-
diff --git a/static/graph/graph.js b/static/graph/graph.js
deleted file mode 100644
index 3bc3a1b..0000000
--- a/static/graph/graph.js
+++ /dev/null
@@ -1,53 +0,0 @@
-import { nodes, edges } from "./graph.gen.js";
-
-var container = document.getElementById("graph-container");
-var options = {
- interaction: {
- hover: true
- },
- nodes: {
- shape: "dot",
- size: 16,
- },
- physics: {
- forceAtlas2Based: {
- gravitationalConstant: -10,
- centralGravity: 0.005,
- springLength: 230,
- springConstant: 0.18,
- },
- maxVelocity: 146,
- solver: "forceAtlas2Based",
- timestep: 0.35,
- stabilization: { iterations: 150 },
- },
-};
-
-var nodesDs = new vis.DataSet();
-nodesDs.add(nodes);
-var edgesDs = new vis.DataSet();
-edgesDs.add(edges);
-var network = new vis.Network(container, { nodes: nodesDs, edges: edgesDs }, options);
-
-network.on("doubleClick", function (params) {
- params.event = "[original event]";
- if (params.nodes.length !== 1) return;
- window.open(nodesDs.get(params.nodes[0]).url, "_blank")
-});
-network.on("hoverNode", function (params) {
- nodesDs.update({ id: params.node, label: nodesDs.get(params.node).name });
-});
-network.on("blurNode", function (params) {
- nodesDs.update({ id: params.node, label: undefined });
-});
-// network.on("selectNode", function (params) {
-// for (const node of params.nodes) {
-// nodesDs.update({ id: node, label: nodesDs.get(node).name });
-// }
-// });
-// network.on("deselectNode", function (params) {
-// for (const node of params.previousSelection.nodes) {
-// if (params.nodes.some(n => n === node)) continue;
-// nodesDs.update({ id: node, label: undefined });
-// }
-// });
diff --git a/themes/vanilla b/themes/vanilla
index 32738ce..84274f5 160000
--- a/themes/vanilla
+++ b/themes/vanilla
@@ -1 +1 @@
-Subproject commit 32738ce835858065abd19698657c57b8e4746952
+Subproject commit 84274f5c08a17d74752dafd04c376f757d2af97e