Week 18 of 2026

Development log of Better Tech Club website

7 items
  1. Upgrade TBB
  2. Spec: test horizontal overflow on Bussum page
  3. Use TBB delegation to compose spec scenarios
  4. Fix horizontal scroll on narrow viewports
  5. Larger text in the single-column layout of the Bussum page
  6. Write "The Netherlands" in full in the heading
  7. Rotate the Better Tech Club above Bussum a bit

Upgrade TBB

On by Tad Lispy

index f1c3398..f611911 100644
--- a/flake.lock
+++ b/flake.lock
@@ -114,11 +114,73 @@
=        ]
=      },
=      "locked": {
-        "lastModified": 1760971495,
-        "narHash": "sha256-IwnNtbNVrlZIHh7h4Wz6VP0Furxg9Hh0ycighvL5cZc=",
+        "lastModified": 1774017633,
+        "narHash": "sha256-CWhnwL2M83/ItapPVeJqCevRoQttesYxJ1h0Mo6ZCXs=",
=        "owner": "cachix",
=        "repo": "cachix",
-        "rev": "c5bfd933d1033672f51a863c47303fc0e093c2d2",
+        "rev": "e8be573b417f3daa3dd4cb9052178f848e0c9d1d",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "ref": "latest",
+        "repo": "cachix",
+        "type": "github"
+      }
+    },
+    "cachix_5": {
+      "inputs": {
+        "devenv": [
+          "tad-better-behavior",
+          "devenv",
+          "crate2nix"
+        ],
+        "flake-compat": [
+          "tad-better-behavior",
+          "devenv",
+          "crate2nix"
+        ],
+        "git-hooks": "git-hooks_4",
+        "nixpkgs": "nixpkgs_5"
+      },
+      "locked": {
+        "lastModified": 1767714506,
+        "narHash": "sha256-WaTs0t1CxhgxbIuvQ97OFhDTVUGd1HA+KzLZUZBhe0s=",
+        "owner": "cachix",
+        "repo": "cachix",
+        "rev": "894c649f0daaa38bbcfb21de64be47dfa7cd0ec9",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "ref": "latest",
+        "repo": "cachix",
+        "type": "github"
+      }
+    },
+    "cachix_6": {
+      "inputs": {
+        "devenv": [
+          "tad-better-behavior",
+          "devenv",
+          "crate2nix",
+          "crate2nix_stable"
+        ],
+        "flake-compat": [
+          "tad-better-behavior",
+          "devenv",
+          "crate2nix",
+          "crate2nix_stable"
+        ],
+        "git-hooks": "git-hooks_5",
+        "nixpkgs": "nixpkgs_6"
+      },
+      "locked": {
+        "lastModified": 1767714506,
+        "narHash": "sha256-WaTs0t1CxhgxbIuvQ97OFhDTVUGd1HA+KzLZUZBhe0s=",
+        "owner": "cachix",
+        "repo": "cachix",
+        "rev": "894c649f0daaa38bbcfb21de64be47dfa7cd0ec9",
=        "type": "github"
=      },
=      "original": {
@@ -157,6 +219,36 @@
=        "type": "github"
=      }
=    },
+    "crate2nix_2": {
+      "inputs": {
+        "cachix": "cachix_5",
+        "crate2nix_stable": "crate2nix_stable_2",
+        "devshell": "devshell_4",
+        "flake-compat": "flake-compat_5",
+        "flake-parts": "flake-parts_5",
+        "nix-test-runner": "nix-test-runner_4",
+        "nixpkgs": [
+          "tad-better-behavior",
+          "devenv",
+          "nixpkgs"
+        ],
+        "pre-commit-hooks": "pre-commit-hooks_4"
+      },
+      "locked": {
+        "lastModified": 1772186516,
+        "narHash": "sha256-8s28pzmQ6TOIUzznwFibtW1CMieMUl1rYJIxoQYor58=",
+        "owner": "rossng",
+        "repo": "crate2nix",
+        "rev": "ba5dd398e31ee422fbe021767eb83b0650303a6e",
+        "type": "github"
+      },
+      "original": {
+        "owner": "rossng",
+        "repo": "crate2nix",
+        "rev": "ba5dd398e31ee422fbe021767eb83b0650303a6e",
+        "type": "github"
+      }
+    },
=    "crate2nix_stable": {
=      "inputs": {
=        "cachix": "cachix_3",
@@ -187,6 +279,37 @@
=        "type": "github"
=      }
=    },
+    "crate2nix_stable_2": {
+      "inputs": {
+        "cachix": "cachix_6",
+        "crate2nix_stable": [
+          "tad-better-behavior",
+          "devenv",
+          "crate2nix",
+          "crate2nix_stable"
+        ],
+        "devshell": "devshell_3",
+        "flake-compat": "flake-compat_4",
+        "flake-parts": "flake-parts_4",
+        "nix-test-runner": "nix-test-runner_3",
+        "nixpkgs": "nixpkgs_7",
+        "pre-commit-hooks": "pre-commit-hooks_3"
+      },
+      "locked": {
+        "lastModified": 1769627083,
+        "narHash": "sha256-SUuruvw1/moNzCZosHaa60QMTL+L9huWdsCBN6XZIic=",
+        "owner": "nix-community",
+        "repo": "crate2nix",
+        "rev": "7c33e664668faecf7655fa53861d7a80c9e464a2",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "ref": "0.15.0",
+        "repo": "crate2nix",
+        "type": "github"
+      }
+    },
=    "devenv": {
=      "inputs": {
=        "cachix": "cachix",
@@ -218,21 +341,24 @@
=    "devenv_2": {
=      "inputs": {
=        "cachix": "cachix_4",
-        "flake-compat": "flake-compat_4",
-        "flake-parts": "flake-parts_4",
-        "git-hooks": "git-hooks_4",
+        "crate2nix": "crate2nix_2",
+        "flake-compat": "flake-compat_6",
+        "flake-parts": "flake-parts_6",
+        "git-hooks": "git-hooks_6",
=        "nix": "nix_2",
+        "nixd": "nixd_2",
=        "nixpkgs": [
=          "tad-better-behavior",
=          "nixpkgs"
-        ]
+        ],
+        "rust-overlay": "rust-overlay_2"
=      },
=      "locked": {
-        "lastModified": 1762889687,
-        "narHash": "sha256-oKvHfeYDZ0LfuHSaFLA0w/dfZ9R6C5W8pCGUjUWawGI=",
+        "lastModified": 1777040077,
+        "narHash": "sha256-21hK/8gia6FbcE2+R49WNCD24yd6Qf0VPpiYi1qEI3I=",
=        "owner": "cachix",
=        "repo": "devenv",
-        "rev": "3b4fb549962342c928aae1bbea3a13f0eeed2703",
+        "rev": "0b0246b7fed27e788d639cb82364c452b405970c",
=        "type": "github"
=      },
=      "original": {
@@ -286,6 +412,53 @@
=        "type": "github"
=      }
=    },
+    "devshell_3": {
+      "inputs": {
+        "nixpkgs": [
+          "tad-better-behavior",
+          "devenv",
+          "crate2nix",
+          "crate2nix_stable",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1768818222,
+        "narHash": "sha256-460jc0+CZfyaO8+w8JNtlClB2n4ui1RbHfPTLkpwhU8=",
+        "owner": "numtide",
+        "repo": "devshell",
+        "rev": "255a2b1725a20d060f566e4755dbf571bbbb5f76",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "devshell",
+        "type": "github"
+      }
+    },
+    "devshell_4": {
+      "inputs": {
+        "nixpkgs": [
+          "tad-better-behavior",
+          "devenv",
+          "crate2nix",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1768818222,
+        "narHash": "sha256-460jc0+CZfyaO8+w8JNtlClB2n4ui1RbHfPTLkpwhU8=",
+        "owner": "numtide",
+        "repo": "devshell",
+        "rev": "255a2b1725a20d060f566e4755dbf571bbbb5f76",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "devshell",
+        "type": "github"
+      }
+    },
=    "flake-compat": {
=      "locked": {
=        "lastModified": 1733328505,
@@ -331,13 +504,41 @@
=      }
=    },
=    "flake-compat_4": {
+      "locked": {
+        "lastModified": 1733328505,
+        "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=",
+        "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
+        "revCount": 69,
+        "type": "tarball",
+        "url": "https://api.flakehub.com/f/pinned/edolstra/flake-compat/1.1.0/01948eb7-9cba-704f-bbf3-3fa956735b52/source.tar.gz"
+      },
+      "original": {
+        "type": "tarball",
+        "url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz"
+      }
+    },
+    "flake-compat_5": {
+      "locked": {
+        "lastModified": 1733328505,
+        "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=",
+        "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
+        "revCount": 69,
+        "type": "tarball",
+        "url": "https://api.flakehub.com/f/pinned/edolstra/flake-compat/1.1.0/01948eb7-9cba-704f-bbf3-3fa956735b52/source.tar.gz"
+      },
+      "original": {
+        "type": "tarball",
+        "url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz"
+      }
+    },
+    "flake-compat_6": {
=      "flake": false,
=      "locked": {
-        "lastModified": 1761588595,
-        "narHash": "sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4=",
+        "lastModified": 1767039857,
+        "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=",
=        "owner": "edolstra",
=        "repo": "flake-compat",
-        "rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5",
+        "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
=        "type": "github"
=      },
=      "original": {
@@ -417,15 +618,62 @@
=        "nixpkgs-lib": [
=          "tad-better-behavior",
=          "devenv",
+          "crate2nix",
+          "crate2nix_stable",
=          "nixpkgs"
=        ]
=      },
=      "locked": {
-        "lastModified": 1760948891,
-        "narHash": "sha256-TmWcdiUUaWk8J4lpjzu4gCGxWY6/Ok7mOK4fIFfBuU4=",
+        "lastModified": 1768135262,
+        "narHash": "sha256-PVvu7OqHBGWN16zSi6tEmPwwHQ4rLPU9Plvs8/1TUBY=",
=        "owner": "hercules-ci",
=        "repo": "flake-parts",
-        "rev": "864599284fc7c0ba6357ed89ed5e2cd5040f0c04",
+        "rev": "80daad04eddbbf5a4d883996a73f3f542fa437ac",
+        "type": "github"
+      },
+      "original": {
+        "owner": "hercules-ci",
+        "repo": "flake-parts",
+        "type": "github"
+      }
+    },
+    "flake-parts_5": {
+      "inputs": {
+        "nixpkgs-lib": [
+          "tad-better-behavior",
+          "devenv",
+          "crate2nix",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1768135262,
+        "narHash": "sha256-PVvu7OqHBGWN16zSi6tEmPwwHQ4rLPU9Plvs8/1TUBY=",
+        "owner": "hercules-ci",
+        "repo": "flake-parts",
+        "rev": "80daad04eddbbf5a4d883996a73f3f542fa437ac",
+        "type": "github"
+      },
+      "original": {
+        "owner": "hercules-ci",
+        "repo": "flake-parts",
+        "type": "github"
+      }
+    },
+    "flake-parts_6": {
+      "inputs": {
+        "nixpkgs-lib": [
+          "tad-better-behavior",
+          "devenv",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1775087534,
+        "narHash": "sha256-91qqW8lhL7TLwgQWijoGBbiD4t7/q75KTi8NxjVmSmA=",
+        "owner": "hercules-ci",
+        "repo": "flake-parts",
+        "rev": "3107b77cd68437b9a76194f0f7f9c55f2329ca5b",
=        "type": "github"
=      },
=      "original": {
@@ -517,46 +765,207 @@
=        "type": "github"
=      },
=      "original": {
-        "owner": "cachix",
-        "repo": "git-hooks.nix",
+        "owner": "cachix",
+        "repo": "git-hooks.nix",
+        "type": "github"
+      }
+    },
+    "git-hooks_4": {
+      "inputs": {
+        "flake-compat": [
+          "tad-better-behavior",
+          "devenv",
+          "crate2nix",
+          "cachix",
+          "flake-compat"
+        ],
+        "gitignore": "gitignore_6",
+        "nixpkgs": [
+          "tad-better-behavior",
+          "devenv",
+          "crate2nix",
+          "cachix",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1765404074,
+        "narHash": "sha256-+ZDU2d+vzWkEJiqprvV5PR26DVFN2vgddwG5SnPZcUM=",
+        "owner": "cachix",
+        "repo": "git-hooks.nix",
+        "rev": "2d6f58930fbcd82f6f9fd59fb6d13e37684ca529",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "repo": "git-hooks.nix",
+        "type": "github"
+      }
+    },
+    "git-hooks_5": {
+      "inputs": {
+        "flake-compat": [
+          "tad-better-behavior",
+          "devenv",
+          "crate2nix",
+          "crate2nix_stable",
+          "cachix",
+          "flake-compat"
+        ],
+        "gitignore": "gitignore_7",
+        "nixpkgs": [
+          "tad-better-behavior",
+          "devenv",
+          "crate2nix",
+          "crate2nix_stable",
+          "cachix",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1765404074,
+        "narHash": "sha256-+ZDU2d+vzWkEJiqprvV5PR26DVFN2vgddwG5SnPZcUM=",
+        "owner": "cachix",
+        "repo": "git-hooks.nix",
+        "rev": "2d6f58930fbcd82f6f9fd59fb6d13e37684ca529",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "repo": "git-hooks.nix",
+        "type": "github"
+      }
+    },
+    "git-hooks_6": {
+      "inputs": {
+        "flake-compat": [
+          "tad-better-behavior",
+          "devenv",
+          "flake-compat"
+        ],
+        "gitignore": "gitignore_10",
+        "nixpkgs": [
+          "tad-better-behavior",
+          "devenv",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1775585728,
+        "narHash": "sha256-8Psjt+TWvE4thRKktJsXfR6PA/fWWsZ04DVaY6PUhr4=",
+        "owner": "cachix",
+        "repo": "git-hooks.nix",
+        "rev": "580633fa3fe5fc0379905986543fd7495481913d",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "repo": "git-hooks.nix",
+        "type": "github"
+      }
+    },
+    "gitignore": {
+      "inputs": {
+        "nixpkgs": [
+          "devenv",
+          "crate2nix",
+          "cachix",
+          "git-hooks",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1709087332,
+        "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
+        "owner": "hercules-ci",
+        "repo": "gitignore.nix",
+        "rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
+        "type": "github"
+      },
+      "original": {
+        "owner": "hercules-ci",
+        "repo": "gitignore.nix",
+        "type": "github"
+      }
+    },
+    "gitignore_10": {
+      "inputs": {
+        "nixpkgs": [
+          "tad-better-behavior",
+          "devenv",
+          "git-hooks",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1709087332,
+        "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
+        "owner": "hercules-ci",
+        "repo": "gitignore.nix",
+        "rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
+        "type": "github"
+      },
+      "original": {
+        "owner": "hercules-ci",
+        "repo": "gitignore.nix",
+        "type": "github"
+      }
+    },
+    "gitignore_2": {
+      "inputs": {
+        "nixpkgs": [
+          "devenv",
+          "crate2nix",
+          "crate2nix_stable",
+          "cachix",
+          "git-hooks",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1709087332,
+        "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
+        "owner": "hercules-ci",
+        "repo": "gitignore.nix",
+        "rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
+        "type": "github"
+      },
+      "original": {
+        "owner": "hercules-ci",
+        "repo": "gitignore.nix",
=        "type": "github"
=      }
=    },
-    "git-hooks_4": {
+    "gitignore_3": {
=      "inputs": {
-        "flake-compat": [
-          "tad-better-behavior",
-          "devenv",
-          "flake-compat"
-        ],
-        "gitignore": "gitignore_6",
=        "nixpkgs": [
-          "tad-better-behavior",
=          "devenv",
+          "crate2nix",
+          "crate2nix_stable",
+          "pre-commit-hooks",
=          "nixpkgs"
=        ]
=      },
=      "locked": {
-        "lastModified": 1760663237,
-        "narHash": "sha256-BflA6U4AM1bzuRMR8QqzPXqh8sWVCNDzOdsxXEguJIc=",
-        "owner": "cachix",
-        "repo": "git-hooks.nix",
-        "rev": "ca5b894d3e3e151ffc1db040b6ce4dcc75d31c37",
+        "lastModified": 1709087332,
+        "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
+        "owner": "hercules-ci",
+        "repo": "gitignore.nix",
+        "rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
=        "type": "github"
=      },
=      "original": {
-        "owner": "cachix",
-        "repo": "git-hooks.nix",
+        "owner": "hercules-ci",
+        "repo": "gitignore.nix",
=        "type": "github"
=      }
=    },
-    "gitignore": {
+    "gitignore_4": {
=      "inputs": {
=        "nixpkgs": [
=          "devenv",
=          "crate2nix",
-          "cachix",
-          "git-hooks",
+          "pre-commit-hooks",
=          "nixpkgs"
=        ]
=      },
@@ -574,13 +983,10 @@
=        "type": "github"
=      }
=    },
-    "gitignore_2": {
+    "gitignore_5": {
=      "inputs": {
=        "nixpkgs": [
=          "devenv",
-          "crate2nix",
-          "crate2nix_stable",
-          "cachix",
=          "git-hooks",
=          "nixpkgs"
=        ]
@@ -599,13 +1005,14 @@
=        "type": "github"
=      }
=    },
-    "gitignore_3": {
+    "gitignore_6": {
=      "inputs": {
=        "nixpkgs": [
+          "tad-better-behavior",
=          "devenv",
=          "crate2nix",
-          "crate2nix_stable",
-          "pre-commit-hooks",
+          "cachix",
+          "git-hooks",
=          "nixpkgs"
=        ]
=      },
@@ -623,12 +1030,15 @@
=        "type": "github"
=      }
=    },
-    "gitignore_4": {
+    "gitignore_7": {
=      "inputs": {
=        "nixpkgs": [
+          "tad-better-behavior",
=          "devenv",
=          "crate2nix",
-          "pre-commit-hooks",
+          "crate2nix_stable",
+          "cachix",
+          "git-hooks",
=          "nixpkgs"
=        ]
=      },
@@ -646,11 +1056,14 @@
=        "type": "github"
=      }
=    },
-    "gitignore_5": {
+    "gitignore_8": {
=      "inputs": {
=        "nixpkgs": [
+          "tad-better-behavior",
=          "devenv",
-          "git-hooks",
+          "crate2nix",
+          "crate2nix_stable",
+          "pre-commit-hooks",
=          "nixpkgs"
=        ]
=      },
@@ -668,12 +1081,13 @@
=        "type": "github"
=      }
=    },
-    "gitignore_6": {
+    "gitignore_9": {
=      "inputs": {
=        "nixpkgs": [
=          "tad-better-behavior",
=          "devenv",
-          "git-hooks",
+          "crate2nix",
+          "pre-commit-hooks",
=          "nixpkgs"
=        ]
=      },
@@ -763,6 +1177,38 @@
=        "type": "github"
=      }
=    },
+    "nix-test-runner_3": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1588761593,
+        "narHash": "sha256-FKJykltAN/g3eIceJl4SfDnnyuH2jHImhMrXS2KvGIs=",
+        "owner": "stoeffel",
+        "repo": "nix-test-runner",
+        "rev": "c45d45b11ecef3eb9d834c3b6304c05c49b06ca2",
+        "type": "github"
+      },
+      "original": {
+        "owner": "stoeffel",
+        "repo": "nix-test-runner",
+        "type": "github"
+      }
+    },
+    "nix-test-runner_4": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1588761593,
+        "narHash": "sha256-FKJykltAN/g3eIceJl4SfDnnyuH2jHImhMrXS2KvGIs=",
+        "owner": "stoeffel",
+        "repo": "nix-test-runner",
+        "rev": "c45d45b11ecef3eb9d834c3b6304c05c49b06ca2",
+        "type": "github"
+      },
+      "original": {
+        "owner": "stoeffel",
+        "repo": "nix-test-runner",
+        "type": "github"
+      }
+    },
=    "nix_2": {
=      "inputs": {
=        "flake-compat": [
@@ -795,16 +1241,16 @@
=        ]
=      },
=      "locked": {
-        "lastModified": 1761648602,
-        "narHash": "sha256-H97KSB/luq/aGobKRuHahOvT1r7C03BgB6D5HBZsbN8=",
+        "lastModified": 1776511668,
+        "narHash": "sha256-g2KEBuHpc3a56c+jPcg0+w6LSuIj6f+zzdztLCOyIhc=",
=        "owner": "cachix",
=        "repo": "nix",
-        "rev": "3e5644da6830ef65f0a2f7ec22830c46285bfff6",
+        "rev": "42d4b7de21c15f28c568410f4383fa06a8458a40",
=        "type": "github"
=      },
=      "original": {
=        "owner": "cachix",
-        "ref": "devenv-2.30.6",
+        "ref": "devenv-2.34",
=        "repo": "nix",
=        "type": "github"
=      }
@@ -835,6 +1281,30 @@
=        "type": "github"
=      }
=    },
+    "nixd_2": {
+      "inputs": {
+        "flake-parts": [
+          "tad-better-behavior",
+          "devenv",
+          "flake-parts"
+        ],
+        "nixpkgs": "nixpkgs_8",
+        "treefmt-nix": "treefmt-nix_2"
+      },
+      "locked": {
+        "lastModified": 1776341634,
+        "narHash": "sha256-L//ltP2o5+BnuK+KEulbi2gGeDpyyex6SkXLZcGQ/Ac=",
+        "owner": "nix-community",
+        "repo": "nixd",
+        "rev": "951e98e2025c47614f5249556ecf509b0ea35b51",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "nixd",
+        "type": "github"
+      }
+    },
=    "nixpkgs": {
=      "locked": {
=        "lastModified": 1765186076,
@@ -919,6 +1389,67 @@
=        "type": "github"
=      }
=    },
+    "nixpkgs_5": {
+      "locked": {
+        "lastModified": 1765186076,
+        "narHash": "sha256-hM20uyap1a0M9d344I692r+ik4gTMyj60cQWO+hAYP8=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "addf7cf5f383a3101ecfba091b98d0a1263dc9b8",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "ref": "nixos-unstable",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
+    "nixpkgs_6": {
+      "locked": {
+        "lastModified": 1765186076,
+        "narHash": "sha256-hM20uyap1a0M9d344I692r+ik4gTMyj60cQWO+hAYP8=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "addf7cf5f383a3101ecfba091b98d0a1263dc9b8",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "ref": "nixos-unstable",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
+    "nixpkgs_7": {
+      "locked": {
+        "lastModified": 1769433173,
+        "narHash": "sha256-Gf1dFYgD344WZ3q0LPlRoWaNdNQq8kSBDLEWulRQSEs=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "13b0f9e6ac78abbbb736c635d87845c4f4bee51b",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "ref": "nixpkgs-unstable",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
+    "nixpkgs_8": {
+      "locked": {
+        "lastModified": 1772963539,
+        "narHash": "sha256-G4+9cEu8XSqEWYUB6iRgDfrg53av6yyRwAKhSeKbUVw=",
+        "rev": "9dcb002ca1690658be4a04645215baea8b95f31d",
+        "type": "tarball",
+        "url": "https://releases.nixos.org/nixos/unstable/nixos-26.05pre960399.9dcb002ca169/nixexprs.tar.xz"
+      },
+      "original": {
+        "type": "tarball",
+        "url": "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz"
+      }
+    },
=    "pre-commit-hooks": {
=      "inputs": {
=        "flake-compat": [
@@ -977,6 +1508,68 @@
=        "type": "github"
=      }
=    },
+    "pre-commit-hooks_3": {
+      "inputs": {
+        "flake-compat": [
+          "tad-better-behavior",
+          "devenv",
+          "crate2nix",
+          "crate2nix_stable",
+          "flake-compat"
+        ],
+        "gitignore": "gitignore_8",
+        "nixpkgs": [
+          "tad-better-behavior",
+          "devenv",
+          "crate2nix",
+          "crate2nix_stable",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1769069492,
+        "narHash": "sha256-Efs3VUPelRduf3PpfPP2ovEB4CXT7vHf8W+xc49RL/U=",
+        "owner": "cachix",
+        "repo": "pre-commit-hooks.nix",
+        "rev": "a1ef738813b15cf8ec759bdff5761b027e3e1d23",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "repo": "pre-commit-hooks.nix",
+        "type": "github"
+      }
+    },
+    "pre-commit-hooks_4": {
+      "inputs": {
+        "flake-compat": [
+          "tad-better-behavior",
+          "devenv",
+          "crate2nix",
+          "flake-compat"
+        ],
+        "gitignore": "gitignore_9",
+        "nixpkgs": [
+          "tad-better-behavior",
+          "devenv",
+          "crate2nix",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1769069492,
+        "narHash": "sha256-Efs3VUPelRduf3PpfPP2ovEB4CXT7vHf8W+xc49RL/U=",
+        "owner": "cachix",
+        "repo": "pre-commit-hooks.nix",
+        "rev": "a1ef738813b15cf8ec759bdff5761b027e3e1d23",
+        "type": "github"
+      },
+      "original": {
+        "owner": "cachix",
+        "repo": "pre-commit-hooks.nix",
+        "type": "github"
+      }
+    },
=    "root": {
=      "inputs": {
=        "devenv": "devenv",
@@ -1006,6 +1599,28 @@
=        "type": "github"
=      }
=    },
+    "rust-overlay_2": {
+      "inputs": {
+        "nixpkgs": [
+          "tad-better-behavior",
+          "devenv",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1776741231,
+        "narHash": "sha256-k9G98qzn+7npROUaks8VqCFm7cFtEG8ulQLBBo5lItg=",
+        "owner": "oxalica",
+        "repo": "rust-overlay",
+        "rev": "02061303f7c4c964f7b4584dabd9e985b4cd442b",
+        "type": "github"
+      },
+      "original": {
+        "owner": "oxalica",
+        "repo": "rust-overlay",
+        "type": "github"
+      }
+    },
=    "systems": {
=      "locked": {
=        "lastModified": 1681028828,
@@ -1045,11 +1660,11 @@
=        "systems": "systems_2"
=      },
=      "locked": {
-        "lastModified": 1775133254,
-        "narHash": "sha256-orxwlnOwsWqRtZaYvt6Tu6l0Pdp9okpVZBaW/+gND2g=",
+        "lastModified": 1777445619,
+        "narHash": "sha256-HjHKZsgkNXvhPC22js+lEvhVBjP5delbuZ4jfsFw1sU=",
=        "ref": "refs/heads/main",
-        "rev": "fbf91ce2b8ebab992a7cbac5bf8ca91115985aea",
-        "revCount": 161,
+        "rev": "a5dc03a114f6284aa4e8e79a27d3846461d251ce",
+        "revCount": 186,
=        "type": "git",
=        "url": "http://codeberg.org/tad-lispy/tad-better-behavior"
=      },
@@ -1079,6 +1694,29 @@
=        "repo": "treefmt-nix",
=        "type": "github"
=      }
+    },
+    "treefmt-nix_2": {
+      "inputs": {
+        "nixpkgs": [
+          "tad-better-behavior",
+          "devenv",
+          "nixd",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1775636079,
+        "narHash": "sha256-pc20NRoMdiar8oPQceQT47UUZMBTiMdUuWrYu2obUP0=",
+        "owner": "numtide",
+        "repo": "treefmt-nix",
+        "rev": "790751ff7fd3801feeaf96d7dc416a8d581265ba",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "treefmt-nix",
+        "type": "github"
+      }
=    }
=  },
=  "root": "root",

Spec: test horizontal overflow on Bussum page

On by Tad Lispy

We know that on small screens the page overflows (has a horizontal scroll). Before we fix it, let's have a TBB scenario to test it.

For now only at 320px width. It is hardcoded. I intend to make it composable and parameterized. But let's take small steps.

index 3d85e45..22835e5 100644
--- a/spec/interpreters/web_automation.clj
+++ b/spec/interpreters/web_automation.clj
@@ -27,6 +27,12 @@
=       (slurp)
=       (tbb/send-text))))
=
+(tbb/implement-step
+ "Set the browser window size to {0} x {1}"
+ (fn [width height data]
+   (e/set-window-size @web-driver {:width (Integer/parseInt width)
+                                   :height (Integer/parseInt height)})))
+
=(tbb/implement-step
= "Navigate to {0}"
= (fn [url data]
@@ -65,4 +71,3 @@
=
=(when (= *file* (System/getProperty "babashka.file"))
=  (apply -main *command-line-args*))
-
index 4ddf9fa..b91450a 100644
--- a/spec/layout.md
+++ b/spec/layout.md
@@ -12,3 +12,13 @@ This scenario asserts that page content fits inside the viewport, i.e. there is
=  * Navigate to `http://localhost:1234/`
=  * The title should be `Better Tech Club`
=  * The content is not wider than the viewport
+
+## The Width of the Body Doesn't Exceed the Viewport on Bussum page
+
+This scenario asserts that page content fits inside the viewport, i.e. there is no need for horizontal scrolling
+
+  * Serve the `.` directory on port `1234`
+  * Set the browser window size to `320` x `480`
+  * Navigate to `http://localhost:1234/bussum.html`
+  * The title should be `Better Tech Club Bussum`
+  * The content is not wider than the viewport

Use TBB delegation to compose spec scenarios

On by Tad Lispy

There are now two main scenarios and two fixtures. The main scenarios are:

  1. All pages fit in a viewport
  2. All pages have correct titles

Each of them lists pages and delegates checking of each page to a specialized fixture scenario.

With this change, the main scenarios don't need to open browser windows. If they do, it looks weird with big empty windows hanging in the background, while action is happening in smaller windows from the fixtures. To facilitate an option to open a browser, there is now a step called "Open the ... browser" that starts a web driver with a chosen browser. Currently only Firefox is available, but in principle we can add other browsers via flake.nix.

I've also implemented the tbb/delegate function to facilitate delegation. There are two delegating steps, corresponding to the delegated scenarios:

  1. Test if page at {0} has title {1}
  2. Test if page at {0} fits in a viewport
index 1429264..beeeb30 100644
--- a/spec/interpreters/tbb.clj
+++ b/spec/interpreters/tbb.clj
@@ -68,6 +68,12 @@
=
=  (timbre/debug "Done reading from tbb."))
=
+(defn delegate [suite scenario parameters]
+  (println (json/generate-string {:type       "Delegate"
+                                  :suite      suite
+                                  :scenario   scenario
+                                  :parameters parameters})))
+
=(defn send-text [text]
=  (println (json/generate-string {:type   "Text"
=                                  :content text}))
index 22835e5..db80f45 100644
--- a/spec/interpreters/web_automation.clj
+++ b/spec/interpreters/web_automation.clj
@@ -27,6 +27,29 @@
=       (slurp)
=       (tbb/send-text))))
=
+(tbb/implement-step
+ "Test if page at {0} fits in a viewport"
+ (fn [url data]
+   (tbb/delegate "spec/layout.md"
+                 "The Width of the Body Doesn't Exceed the Viewport"
+                 {:url url})))
+
+(tbb/implement-step
+ "Test if page at {0} has title {1}"
+ (fn [url title _data]
+   (tbb/delegate "spec/layout.md"
+                 "The page title is correct"
+                 {:url url
+                  :title title})))
+
+(tbb/implement-step
+ "Open the {0} browser"
+ (fn [browser data]
+   (->> browser
+        keyword
+        e/boot-driver
+        (reset! web-driver))))
+
=(tbb/implement-step
= "Set the browser window size to {0} x {1}"
= (fn [width height data]
@@ -62,9 +85,9 @@
=
=(defn -main [& args]
=  (timbre/info "Interpreter start")
-  (reset! web-driver (e/firefox))
=  (tbb/ready)
-  (e/quit @web-driver)
+  (when-not (nil? @web-driver)
+    (e/quit @web-driver))
=  (when @miniserve-process
=    (destroy-tree @miniserve-process))
=  (timbre/info "Interpreter done"))
index b91450a..97a1a2f 100644
--- a/spec/layout.md
+++ b/spec/layout.md
@@ -4,21 +4,45 @@ interpreter: bb spec/interpreters/web_automation.clj
=
=# Basic Layout of the Page
=
+## All pages fit in a viewport
+
+  * Serve the `.` directory on port `1234`
+  * Test if page at `http://localhost:1234/` fits in a viewport
+  * Test if page at `http://localhost:1234/bussum.html` fits in a viewport
+
+
=## The Width of the Body Doesn't Exceed the Viewport
=
=This scenario asserts that page content fits inside the viewport, i.e. there is no need for horizontal scrolling
=
-  * Serve the `.` directory on port `1234`
+``` yaml tbb
+tags: [ fixture ]
+parameters:
+    url: http://localhost:1234/
+```
+
+  * Open the `firefox` browser
+  * Set the browser window size to `320` x `480`
=  * Navigate to `http://localhost:1234/`
-  * The title should be `Better Tech Club`
=  * The content is not wider than the viewport
=
-## The Width of the Body Doesn't Exceed the Viewport on Bussum page
=
-This scenario asserts that page content fits inside the viewport, i.e. there is no need for horizontal scrolling
+## All pages have correct titles
=
=  * Serve the `.` directory on port `1234`
-  * Set the browser window size to `320` x `480`
-  * Navigate to `http://localhost:1234/bussum.html`
-  * The title should be `Better Tech Club Bussum`
-  * The content is not wider than the viewport
+  * Test if page at `http://localhost:1234/` has title `Better Tech Club`
+  * Test if page at `http://localhost:1234/bussum.html` has title `Better Tech Club Bussum`
+
+
+## The page title is correct
+
+``` yaml tbb
+tags: [ fixture ]
+parameters:
+    url: http://localhost:1234/
+    title: Better Tech Club
+```
+
+  * Open the `firefox` browser
+  * Navigate to `http://localhost:1234/`
+  * The title should be `Better Tech Club`

Fix horizontal scroll on narrow viewports

On by Tad Lispy

In the header and main containers, include the padding in box size calculations.

index 15e11bb..7ea856e 100644
--- a/bussum.html
+++ b/bussum.html
@@ -154,6 +154,7 @@
=             width: 100%;
=             max-width: var(--content-width);
=             padding: 2rem;
+             box-sizing: border-box;
=         }
=
=         main {

Larger text in the single-column layout of the Bussum page

On by Tad Lispy

On very small viewports the main section collapses to a single column. In general, the font sizes are also smaller on smaller screens. Together it made the content crammed on the left side, with a lot of empty space on the right.

Now, when the grid collapses, the font is increased. For the headings to retain proportionality with the content, h2 is now scaled with em, not rem units.

I've also included a gap between the columns, so their content never gets too close together.

index 7ea856e..c98a9c4 100644
--- a/bussum.html
+++ b/bussum.html
@@ -83,10 +83,14 @@
=             main {
=                 display: grid;
=                 grid-template-columns: 1fr;
+                 gap: 2rem;
=                 align-items: start;
=
+                 font-size: 2rem;
+
=                 @media(width > 560px) {
=                     grid-template-columns: 1fr 1fr;
+                     font-size: 1rem;
=                 }
=             }
=
@@ -117,7 +121,7 @@
=         }
=
=         h2 {
-             font-size: 1.4rem;
+             font-size: 1.4em;
=             align-self: start;
=             color: var(--accent-color);
=             font-family: "Caveat";

Write "The Netherlands" in full in the heading

On by Tad Lispy

Instead of the abbreviated "NL", which looked weird.

index c98a9c4..58bd57b 100644
--- a/bussum.html
+++ b/bussum.html
@@ -149,6 +149,10 @@
=                     color: var(--accent-color);
=                     font-size: 1.5rem;
=                 }
+                 p {
+                     margin: -0.8rem 0px;
+                     font-weight: bold;
+                 }
=             }
=         }
=
@@ -257,7 +261,8 @@
=        <header>
=            <hgroup>
=                <small>Better Tech Club</small>
-                <h1> Bussum, NL</h1>
+                <h1> Bussum</h1>
+                <p>The Netherlands</p>
=            </hgroup>
=            <img
=                id="big-logo"

Rotate the Better Tech Club above Bussum a bit

On by Tad Lispy

For a more hand-written feeling.

index 58bd57b..e282566 100644
--- a/bussum.html
+++ b/bussum.html
@@ -144,10 +144,12 @@
=                     margin: 0
=                 }
=                 small {
+                     display: block;
=                     font-family: "Caveat";
=                     font-weight: bold;
=                     color: var(--accent-color);
=                     font-size: 1.5rem;
+                     rotate: -4deg;
=                 }
=                 p {
=                     margin: -0.8rem 0px;