{"next_page": 2, "previous_page": null, "max_next_page": 10, "posts": [{"oid": "our-mill-year-in-review", "title": "Our Mill year in review", "pub_date": "2026-09-16T12:05:33.104Z", "comments": 0, "categories": [], "html": "<p>\"Mill Food Recycler\" is a machine we have in the kitchen where we put all food scraps. It produces highly nutritious fertilizer which I sprinkle on the grass and bushes about once every 1-2 months.</p>\n<p>It doesn't smell. It's very silent. And it feels kinda fun to use because of that feeling of making a small impact, one banana peel at a time.</p>", "url": "https://refer.mill.com/ashley776", "disallow_comments": false, "split": null, "is_photo": true}, {"oid": "beer-koozie-from-exactly-15-years-ago-today", "title": "Beer koozie from exactly 15 years ago today", "pub_date": "2026-09-10T11:33:44.732Z", "comments": 0, "categories": [], "html": "<p>Happy Anniversary to Ashley and me!</p>", "url": null, "disallow_comments": false, "split": null, "is_photo": true}, {"oid": "where-herman-melville-used-to-sit-when-he-went-to-bethal-in-new-bedford", "title": "Where Herman Melville used to sit when he went to Bethal in New Bedford", "pub_date": "2026-09-06T00:42:35.798Z", "comments": 0, "categories": [], "html": "", "url": null, "disallow_comments": false, "split": null, "is_photo": true}, {"oid": "hippos-in-boston", "title": "Hippos in Boston", "pub_date": "2026-09-04T20:54:57.142Z", "comments": 0, "categories": [], "html": "", "url": null, "disallow_comments": false, "split": null, "is_photo": true}, {"oid": "spicy-green-beans", "title": "Spicy Green Beans", "pub_date": "2026-09-03T02:50:21.270Z", "comments": 0, "categories": [], "html": "<p>Of all the yummy Chinese foods, spicy green beans are always my favorite.</p>", "url": null, "disallow_comments": false, "split": null, "is_photo": true}, {"oid": "bun-1.4.0-made-some-binaries-of-gg2-smaller", "title": "Bun 1.4.0 made some binaries of gg2 smaller", "pub_date": "2026-08-21T12:39:14.788Z", "comments": 0, "categories": ["Bun"], "html": "<p><a href=\"https://bun.com/blog/bun-v1.4\">Bun 1.4 came out yesterday</a>. It's an action-packed release.\nI created <a href=\"https://github.com/peterbe/gg2/pull/121\">a build matrix</a> that compares versions 1.3.14 and 1.4.0, and looked at the various sizes of the built binaries of <a href=\"https://github.com/peterbe/gg2\">github.com/peterbe/gg2</a>. The results are as follows:</p>\n<table>\n<thead>\n<tr>\n<th>Bun Version</th>\n<th>darwin-arm64</th>\n<th>darwin-x64</th>\n<th>windows-x64</th>\n<th>linux-arm64</th>\n<th>linux-x64</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>1.3.14</td>\n<td>65.4 MB</td>\n<td>70.8 MB</td>\n<td>98.8 MB</td>\n<td>94.2 MB</td>\n<td>95.0 MB</td>\n</tr>\n<tr>\n<td>1.4.0</td>\n<td>65.6 MB</td>\n<td>72.0 MB</td>\n<td>89.3 MB</td>\n<td>83.2 MB</td>\n<td>83.3 MB</td>\n</tr>\n<tr>\n<td>Delta</td>\n<td>+179.4Kb</td>\n<td>+1.2Mb</td>\n<td>-9.5MB</td>\n<td>-10.9Mb</td>\n<td>-11.8Mb</td>\n</tr>\n<tr>\n<td>Delta</td>\n<td>+0.3%</td>\n<td>+1.7%</td>\n<td>-9.6%</td>\n<td>-11.6%</td>\n<td>-12.4%</td>\n</tr>\n</tbody>\n</table>\n<p>It matches reasonably well with <a href=\"https://bun.com/blog/bun-v1.4#binary-size\">their 1.4 release blog post</a>.</p>\n<p>It's still small. What's amazing is that many of these builds take less than a second to create in this GitHub Action. You can <a href=\"https://github.com/peterbe/gg2/actions/runs/32481468178/job/96768570512\">see for yourself</a> by clicking the various nodes of the build matrix and looking at the time output of <code>time bun build src/index.ts --compile --minify --sourcemap --bytecode ...</code>.</p>", "url": "https://github.com/peterbe/gg2/pull/121", "disallow_comments": false, "split": null, "is_photo": false}, {"oid": "noise-level-crickets-back-porch", "title": "This is the noise level of the crickets on my back porch", "pub_date": "2026-08-15T13:26:01.004Z", "comments": 1, "categories": [], "html": "<p>It feels deafening when you're standing there. I measured it to compare with other noises, like a nearby mower.</p>\n<p>This is, by the way, inside the screened-in porch.</p>", "url": null, "disallow_comments": false, "split": null, "is_photo": true}, {"oid": "useslowtruth", "title": "useSlowTruth - React hook to throttle booleans", "pub_date": "2026-08-10T15:09:04.899Z", "comments": 0, "categories": ["React"], "html": "<p>I use this React hook to reduce the display of spinner animation icons in cases where a little patience means we don't really need to bother indicating that something is loading.</p>\n<h3 id=\"the-problem\"><a class=\"toclink\" href=\"#the-problem\">The problem</a></h3>\n<p>For example, you might have a TanStack Query that makes XHR requests to the backend, and that backend is generally fast. Many times, it finishes in tens or hundreds of milliseconds. If you prescriptively always show the loading spinner icon, or whatever you might have, <strong>it's going to flicker and cause confusion</strong>.</p>\n<p>For example, your use of <code>useQuery</code> might look like this:</p>\n<pre><code class=\"hljs\">\n<span class=\"hljs-keyword\">function</span> <span class=\"hljs-title function_\">MyComponent</span>(<span class=\"hljs-params\"></span>) {\n  <span class=\"hljs-keyword\">const</span> { data, isPending, error } = <span class=\"hljs-title function_\">useQuery</span>({\n    <span class=\"hljs-attr\">queryKey</span>: [<span class=\"hljs-string\">&quot;something&quot;</span>],\n    <span class=\"hljs-attr\">queryFn</span>: fetcher,\n  })\n\n  <span class=\"hljs-keyword\">return</span> <span class=\"language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div</span>&gt;</span>\n    {isPending &amp;&amp; <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Spinner</span>/&gt;</span>}\n    {error &amp;&amp; <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Alert</span> <span class=\"hljs-attr\">error</span>=<span class=\"hljs-string\">{error}/</span>&gt;</span>}\n    {data &amp;&amp; <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Tabular</span> <span class=\"hljs-attr\">data</span>=<span class=\"hljs-string\">{data}</span> /&gt;</span>}\n  <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">div</span>&gt;</span></span>\n}\n</code></pre>\n\n<p>The problem is that if <code>isPending</code> is only <code>true</code> for a very short time, you run the risk of displaying the <code>&lt;Spinner/&gt;</code> so briefly that it just becomes a flickering blur to the user.</p>\n<h3 id=\"the-solution\"><a class=\"toclink\" href=\"#the-solution\">The solution</a></h3>\n<p>The hook code looks like this:</p>\n<pre><code class=\"hljs\">\n<span class=\"hljs-keyword\">import</span> { useEffect, useState } <span class=\"hljs-keyword\">from</span> <span class=\"hljs-string\">&quot;react&quot;</span>;\n\n<span class=\"hljs-keyword\">type</span> <span class=\"hljs-title class_\">Options</span> = {\n  <span class=\"hljs-attr\">delay</span>?: <span class=\"hljs-built_in\">number</span>;\n};\n\n<span class=\"hljs-comment\">/**\n * A hook that throttles the truth. Useful when you want something to be true\n * only if it&#x27;s been true for a certain delay in milliseconds. Example use:\n *\n *   const stillLoading = useSlowTruth(isLoading);\n *\n * If the value of `isLoading` quickly changes from false, to true, to false;\n * the value of `stillLoading` will remain false the whole time.\n *\n * <span class=\"hljs-doctag\">@param</span> initialState boolean\n * <span class=\"hljs-doctag\">@param</span> <span class=\"hljs-variable\">options</span>\n * <span class=\"hljs-doctag\">@returns</span> a single boolean that is a delayed mirror of the input, if it&#x27;s true\n */</span>\n<span class=\"hljs-keyword\">export</span> <span class=\"hljs-keyword\">function</span> <span class=\"hljs-title function_\">useSlowTruth</span>(<span class=\"hljs-params\"><span class=\"hljs-attr\">initialState</span>: <span class=\"hljs-built_in\">boolean</span>, { delay = <span class=\"hljs-number\">1000</span> }: <span class=\"hljs-title class_\">Options</span></span>) {\n  <span class=\"hljs-keyword\">const</span> [isTrue, setIsTrue] = <span class=\"hljs-title function_\">useState</span>(initialState);\n  <span class=\"hljs-title function_\">useEffect</span>(<span class=\"hljs-function\">() =&gt;</span> {\n    <span class=\"hljs-keyword\">let</span> mounted = <span class=\"hljs-literal\">true</span>;\n    <span class=\"hljs-keyword\">let</span> <span class=\"hljs-attr\">timer</span>: <span class=\"hljs-built_in\">number</span> | <span class=\"hljs-literal\">null</span> = <span class=\"hljs-literal\">null</span>;\n    <span class=\"hljs-keyword\">if</span> (initialState) {\n      timer = <span class=\"hljs-variable language_\">window</span>.<span class=\"hljs-built_in\">setTimeout</span>(<span class=\"hljs-function\">() =&gt;</span> {\n        <span class=\"hljs-keyword\">if</span> (mounted) {\n          <span class=\"hljs-title function_\">setIsTrue</span>(<span class=\"hljs-literal\">true</span>);\n        }\n      }, delay);\n    } <span class=\"hljs-keyword\">else</span> {\n      <span class=\"hljs-keyword\">if</span> (timer !== <span class=\"hljs-literal\">null</span>) {\n        <span class=\"hljs-variable language_\">window</span>.<span class=\"hljs-built_in\">clearTimeout</span>(timer);\n      }\n      <span class=\"hljs-title function_\">setIsTrue</span>(<span class=\"hljs-literal\">false</span>);\n    }\n    <span class=\"hljs-keyword\">return</span> <span class=\"hljs-function\">() =&gt;</span> {\n      <span class=\"hljs-keyword\">if</span> (timer !== <span class=\"hljs-literal\">null</span>) {\n        <span class=\"hljs-variable language_\">window</span>.<span class=\"hljs-built_in\">clearTimeout</span>(timer);\n      }\n      mounted = <span class=\"hljs-literal\">false</span>;\n    };\n  }, [initialState, delay]);\n  <span class=\"hljs-keyword\">return</span> isTrue;\n}\n</code></pre>\n\n<p>I put together a demo app here: <a href=\"https://github.com/peterbe/use-slow-truth-demo\">https://github.com/peterbe/use-slow-truth-demo</a></p>\n<h3 id=\"the-usage\"><a class=\"toclink\" href=\"#the-usage\">The usage</a></h3>\n<p>This change</p>\n<pre><code class=\"hljs\">\n<span class=\"hljs-addition\">+import { useSlowTruth } from &quot;./useSlowTruth&quot;</span>\n<span class=\"hljs-addition\">+</span>\nfunction MyComponent() {\n  const { data, isPending, error } = useQuery({\n    queryKey: [&quot;something&quot;],\n    queryFn: fetcher,\n  })\n\n<span class=\"hljs-addition\">+ const isStillPending = useSlowTruth(isPending, { delay: 300 })</span>\n\n  return &lt;div&gt;\n<span class=\"hljs-deletion\">-   {isPending &amp;&amp; &lt;Spinner/&gt;}</span>\n<span class=\"hljs-addition\">+   {isStillPending &amp;&amp; &lt;Spinner/&gt;}</span>\n    {error &amp;&amp; &lt;Alert error={error}/&gt;}\n    {data &amp;&amp; &lt;Tabular data={data} /&gt;}\n  &lt;/div&gt;\n}\n</code></pre>\n\n<p>Now, <em>only</em> if the XHR query takes <em>longer than 300ms</em> does it show the <code>&lt;Spinner/&gt;</code> component.</p>", "url": "https://github.com/peterbe/use-slow-truth-demo", "disallow_comments": false, "split": null, "is_photo": false}, {"oid": "cart-path-bounce-is-my-jam", "title": "Cart path bounce is my jam", "pub_date": "2026-08-10T11:34:10.081Z", "comments": 0, "categories": [], "html": "<p>I'm a reasonably long hitter, but I can't get the driver beyond 300 yards without a lot of help from either a tailwind or, like this time, a bounce off the cart path.</p>", "url": null, "disallow_comments": false, "split": null, "is_photo": true}, {"oid": "cracked-my-callaway-driver", "title": "Cracked my Callaway driver", "pub_date": "2026-07-28T10:43:08.993Z", "comments": 0, "categories": [], "html": "<p>Heard something chip loose in it the other day. And now, on the range, it cracked open.</p>", "url": null, "disallow_comments": false, "split": null, "is_photo": true}]}