@calebhailey.comhttps://calebhailey.com/2025-08-25T21:42:14ZCaleb Hailey (@calebhailey.com)https://calebhailey.com/posts/17561581340002025-08-25T21:42:14Z2025-08-25T21:42:14ZCaleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>Just wrapping up day 1 of a <a href="https://hypertemplates.net" data-hyper-mention>@hypertemplates.net</a> hack week with <a href="https://blog.thoward.me" data-hyper-mention>@blog.thoward.me</a>! ๐ฅ</p>
<p>Just wrapping up day 1 of a <a href="https://hypertemplates.net" data-hyper-mention>@hypertemplates.net</a> hack week with <a href="https://blog.thoward.me" data-hyper-mention>@blog.thoward.me</a>! ๐ฅ</p>
Caleb Hailey (@calebhailey.com)https://calebhailey.com/posts/17558880380002025-08-22T18:40:38Z2025-08-22T18:40:38ZCaleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>Been meaning to post about this. Google keeps promoting YouTube as a closed alternative to standards-based podcasting amid never-ending rumors about the death of podcasting. Meanwhile Apple continues to promote traditional podcasting!</p>
<p>Now if only Apple could wield its cultural influence (via the iPhone) by shifting Apple News more towards <a href="/tags/rss/" data-hyper-mention>#RSS</a>. Brand it as webcasting or <a href="https://textcasting.org" data-hyper-mention>@textcasting.org</a> if necessary.</p>
<p>Apple has the ability to make "Wherever you follow websites" a thingโข <a href="https://www.anildash.com/2024/02/06/wherever_you_get_podcasts/">like it did for podcasting</a>.</p>
<p>A boy can dream!</p>
<p>Been meaning to post about this. Google keeps promoting YouTube as a closed alternative to standards-based podcasting amid never-ending rumors about the death of podcasting. Meanwhile Apple continues to promote traditional podcasting!</p>
<p>Now if only Apple could wield its cultural influence (via the iPhone) by shifting Apple News more towards <a href="/tags/rss/" data-hyper-mention>#RSS</a>. Brand it as webcasting or <a href="https://textcasting.org" data-hyper-mention>@textcasting.org</a> if necessary.</p>
<p>Apple has the ability to make "Wherever you follow websites" a thingโข <a href="https://www.anildash.com/2024/02/06/wherever_you_get_podcasts/">like it did for podcasting</a>.</p>
<p>A boy can dream!</p>
Caleb Hailey (@calebhailey.com)https://calebhailey.com/posts/17522687310002025-07-11T21:18:51Z2025-07-11T21:18:51ZCaleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>I want so badly for this game to exist. The world needs a proper NBA Street Vol.2 successor! ๐</p>
<p>I want so badly for this game to exist. The world needs a proper NBA Street Vol.2 successor! ๐</p>
Caleb Hailey (@calebhailey.com)https://calebhailey.com/posts/17522676960002025-07-11T21:01:36Z2025-07-11T21:01:36ZCaleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>Finally ready to outsource bookkeeping for <a href="https://herd.works" data-hyper-mention>@herd.works</a> ๐</p>
<p><a href="/tags/startups/" data-hyper-mention>#startups</a> <a href="/tags/achievementunlocked/" data-hyper-mention>#AchievementUnlocked</a></p>
<p>Finally ready to outsource bookkeeping for <a href="https://herd.works" data-hyper-mention>@herd.works</a> ๐</p>
<p><a href="/tags/startups/" data-hyper-mention>#startups</a> <a href="/tags/achievementunlocked/" data-hyper-mention>#AchievementUnlocked</a></p>
Caleb Hailey (@calebhailey.com)https://calebhailey.com/posts/17521913680002025-07-10T23:49:28Z2025-07-10T23:49:28ZCaleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>Scored some sweet deals on the Prime Sale this year after mostly ignoring it for the past few years. I had my eye on this charger for a while and noticed it was $60 off, so I snagged one of these and massively simplified the device charging setup in my home office. This thing is an absolute beast.</p>
<p>PS - this is not an affiliate link. Iโm just sharing out of the goodness of my nerdy little heart. ๐ค</p>
<p>Scored some sweet deals on the Prime Sale this year after mostly ignoring it for the past few years. I had my eye on this charger for a while and noticed it was $60 off, so I snagged one of these and massively simplified the device charging setup in my home office. This thing is an absolute beast.</p>
<p>PS - this is not an affiliate link. Iโm just sharing out of the goodness of my nerdy little heart. ๐ค</p>
Caleb Hailey (@calebhailey.com)https://calebhailey.com/posts/17521906920002025-07-10T23:38:12Z2025-07-10T23:38:12ZCaleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>Is this thing on?!</p>
<p>Is this thing on?!</p>
Caleb Hailey (@calebhailey.com)https://calebhailey.com/posts/17467439390002025-05-08T22:38:59Z2025-05-08T22:38:59ZCaleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>I noticed my <a href="/?tab=Following">following</a> feed was broken earlier this week. It turns out it's been broken since the updated site went live at the beginning of the year. Whoops! ๐ </p>
<p>The issue was with my static site generator and how it was parsing OPML data files. With that fixed I can now drop a lightly modified OPML file (with paywalled <a href="/tags/rss/" data-hyper-mention>#RSS</a> feeds removed) into a data folder and get an auto-generated <a href="/?tab=Following">following</a> page. ๐ค๐ฝ</p>
<p>This whole idea was inspired by this <a href="https://anildash.com" data-hyper-mention>@anildash.com</a> blog post that I think about way too often.</p>
<p>I noticed my <a href="/?tab=Following">following</a> feed was broken earlier this week. It turns out it's been broken since the updated site went live at the beginning of the year. Whoops! ๐ </p>
<p>The issue was with my static site generator and how it was parsing OPML data files. With that fixed I can now drop a lightly modified OPML file (with paywalled <a href="/tags/rss/" data-hyper-mention>#RSS</a> feeds removed) into a data folder and get an auto-generated <a href="/?tab=Following">following</a> page. ๐ค๐ฝ</p>
<p>This whole idea was inspired by this <a href="https://anildash.com" data-hyper-mention>@anildash.com</a> blog post that I think about way too often.</p>
Caleb Hailey (@calebhailey.com)https://calebhailey.com/posts/17465124810002025-05-06T06:21:21Z2025-05-06T06:21:21ZCaleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>Office productivity is going to take a slight hit this week. โฝ๏ธ๐ ๐</p>
<p>Office productivity is going to take a slight hit this week. โฝ๏ธ๐ ๐</p>
Caleb Hailey (@calebhailey.com)https://calebhailey.com/posts/17463872560002025-05-04T19:34:16Z2025-05-04T19:47:16ZCaleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>The web needs more experimentation like this from <a href="https://eieio.games" data-hyper-mention>@eieio.games</a>. ๐๐๐</p>
<p>The web needs more experimentation like this from <a href="https://eieio.games" data-hyper-mention>@eieio.games</a>. ๐๐๐</p>
Steve Jobs' talk at the 1983 International Design Conference in Aspenhttps://calebhailey.com/links/steve-jobs-talk-at-the-1983-international-design-conference-in-aspen2025-05-04T18:50:52Z2025-05-04T18:50:52ZCaleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.comSteve Jobs Archivehttps://stevejobsarchive.com/@stevejobsarchive.comhttps://stevejobsarchive.com/apple-touch-icon.pngLink to https://stevejobsarchive.com/exhibits/objects-of-our-lifeCaleb Hailey (@calebhailey.com)https://calebhailey.com/posts/17462237840002025-05-02T22:09:44Z2025-05-02T22:09:44ZCaleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>Cool to see <a href="https://stripe.com" data-hyper-mention>@stripe.com</a> jump in! Competition for payments on iOS?!</p>
<p>The comments on <a href="https://x.com/AzianMike/status/1917830346332332329">this Twitter thread from Stripe Product Manager Michael Lou</a> are amazing. It reads like an FAQ, haha.</p>
<p>One <a href="https://x.com/ntelas_/status/1917934277557211168">comment</a> replies "But using Apple Pay makes purchasing something way more likely for me." Lou <a href="https://x.com/AzianMike/status/1917934617291796939">responds</a> "You can use Apple pay via Stripe!"</p>
<p>Another <a href="https://x.com/irishnick23/status/1918124789895516639">comment</a> asks "Do users return to the app automatically after successful completion or is an action required?" Lou <a href="https://x.com/AzianMike/status/1918127289596035231">responds</a> "They return automatically if [the developer has] Universal Links enabled".</p>
<p>๐ฟ</p>
<!-- Links -->
<p>Cool to see <a href="https://stripe.com" data-hyper-mention>@stripe.com</a> jump in! Competition for payments on iOS?!</p>
<p>The comments on <a href="https://x.com/AzianMike/status/1917830346332332329">this Twitter thread from Stripe Product Manager Michael Lou</a> are amazing. It reads like an FAQ, haha.</p>
<p>One <a href="https://x.com/ntelas_/status/1917934277557211168">comment</a> replies "But using Apple Pay makes purchasing something way more likely for me." Lou <a href="https://x.com/AzianMike/status/1917934617291796939">responds</a> "You can use Apple pay via Stripe!"</p>
<p>Another <a href="https://x.com/irishnick23/status/1918124789895516639">comment</a> asks "Do users return to the app automatically after successful completion or is an action required?" Lou <a href="https://x.com/AzianMike/status/1918127289596035231">responds</a> "They return automatically if [the developer has] Universal Links enabled".</p>
<p>๐ฟ</p>
<!-- Links -->
Caleb Hailey (@calebhailey.com)https://calebhailey.com/posts/17462178810002025-05-02T20:31:21Z2025-05-02T20:31:21ZCaleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>I knew today was gonna be an exceptional Daily Update on <a href="https://stratechery.com" data-hyper-mention>@stratechery.com</a> and I was not disappointed! ๐ฅ</p>
<p>I knew today was gonna be an exceptional Daily Update on <a href="https://stratechery.com" data-hyper-mention>@stratechery.com</a> and I was not disappointed! ๐ฅ</p>
Three meaningful changes to App Review guidelineshttps://calebhailey.com/posts/17461622180002025-05-02T05:03:38Z2025-05-02T05:03:38ZCaleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>These might be the three most meaningful paragraphs of policy/legal <a href="https://youtu.be/jIveQ4O9Tnw">mumbo jumbo</a> I've experienced in my professional career.</p>
<p>From an inconspicuously titled <a href="https://developer.apple.com/news/?id=9txfddzf">"Updated guidelines now available"</a> from <a href="https://developer.apple.com" data-hyper-mention>@developer.apple.com</a>:</p>
<blockquote>
<p>3.1.1(a): On the United States storefront, there is no prohibition on an app including buttons, external links, or other calls to action, and no entitlement is required to do so.</p>
<p>3.1.3: The prohibition on encouraging users to use a purchasing method other than in-app purchase does not apply on the United States storefront.</p>
<p>3.1.3(a): The External Link Account entitlement is not required for apps on the United States storefront to include buttons, external links, or other calls to action.</p>
</blockquote>
<p>The email opened with an acknowledgement of <a href="https://daringfireball.net/2025/04/gonzales_rogers_apple_app_store_ruling">this week's monumental legal mandate</a>:</p>
<blockquote>
<p>The App Review Guidelines have been updated for compliance with a United States court decision regarding buttons, external links, and other calls to action in apps. These changes affect apps distributed on the United States storefront of the App Store</p>
</blockquote>
<p>Three cheers for regulation?! ๐ฉโโ๏ธ</p>
<p>The most exciting thing about this to me personally is how <a href="https://apple.com" data-hyper-mention>@apple.com</a> itself might respond to these changes by <em>actually competing</em> for developers' business in an area where it hasn't had to in the past.</p>
<p>It's gonna be a fun <a href="/tags/wwdc/" data-hyper-mention>#WWDC</a> & summer! ๐๐ฝ</p>
<p>These might be the three most meaningful paragraphs of policy/legal <a href="https://youtu.be/jIveQ4O9Tnw">mumbo jumbo</a> I've experienced in my professional career.</p>
<p>From an inconspicuously titled <a href="https://developer.apple.com/news/?id=9txfddzf">"Updated guidelines now available"</a> from <a href="https://developer.apple.com" data-hyper-mention>@developer.apple.com</a>:</p>
<blockquote>
<p>3.1.1(a): On the United States storefront, there is no prohibition on an app including buttons, external links, or other calls to action, and no entitlement is required to do so.</p>
<p>3.1.3: The prohibition on encouraging users to use a purchasing method other than in-app purchase does not apply on the United States storefront.</p>
<p>3.1.3(a): The External Link Account entitlement is not required for apps on the United States storefront to include buttons, external links, or other calls to action.</p>
</blockquote>
<p>The email opened with an acknowledgement of <a href="https://daringfireball.net/2025/04/gonzales_rogers_apple_app_store_ruling">this week's monumental legal mandate</a>:</p>
<blockquote>
<p>The App Review Guidelines have been updated for compliance with a United States court decision regarding buttons, external links, and other calls to action in apps. These changes affect apps distributed on the United States storefront of the App Store</p>
</blockquote>
<p>Three cheers for regulation?! ๐ฉโโ๏ธ</p>
<p>The most exciting thing about this to me personally is how <a href="https://apple.com" data-hyper-mention>@apple.com</a> itself might respond to these changes by <em>actually competing</em> for developers' business in an area where it hasn't had to in the past.</p>
<p>It's gonna be a fun <a href="/tags/wwdc/" data-hyper-mention>#WWDC</a> & summer! ๐๐ฝ</p>
A Janky Experiencehttps://calebhailey.com/posts/a-janky-experience2025-04-22T23:30:08Z2025-04-22T23:30:08ZCaleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>While asking <a href="https://chatgpt.com" data-hyper-mention>@chatgpt.com</a> to help me debug a SwiftUI issue, it offered a solution and then said "but that results in a janky experience"!</p>
<p>The AI has become self-aware! ๐ </p>
<p>While asking <a href="https://chatgpt.com" data-hyper-mention>@chatgpt.com</a> to help me debug a SwiftUI issue, it offered a solution and then said "but that results in a janky experience"!</p>
<p>The AI has become self-aware! ๐ </p>
Caleb Hailey (@calebhailey.com)https://calebhailey.com/posts/17453510560002025-04-22T19:44:16Z2025-04-22T19:44:16ZCaleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>Looks like the <a href="https://gohugo.io" data-hyper-mention>@gohugo.io</a> website got a refresh. ๐</p>
<p>Looks like the <a href="https://gohugo.io" data-hyper-mention>@gohugo.io</a> website got a refresh. ๐</p>
Caleb Hailey (@calebhailey.com)https://calebhailey.com/links/17453494810002025-04-22T19:18:01Z2025-04-22T19:18:01ZCaleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>Markdown: this is the way. ๐ค</p>
<p>Markdown: this is the way. ๐ค</p>
Caleb Hailey (@calebhailey.com)https://calebhailey.com/links/17452810700002025-04-22T00:17:50Z2025-04-22T00:17:50ZCaleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>The web never rests. I love seeing stuff like this from <a href="https://webkit.org" data-hyper-mention>@webkit.org</a> in the roadmap! <a href="/tags/html/" data-hyper-mention>#HTML</a></p>
<p>The web never rests. I love seeing stuff like this from <a href="https://webkit.org" data-hyper-mention>@webkit.org</a> in the roadmap! <a href="/tags/html/" data-hyper-mention>#HTML</a></p>
Caleb Hailey (@calebhailey.com)https://calebhailey.com/posts/17437965780002025-04-04T19:56:18Z2025-04-04T19:56:18ZCaleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>Just got a Freshboi ๐</p>
<p>Just got a Freshboi ๐</p>
Caleb Hailey (@calebhailey.com)https://calebhailey.com/posts/17437885230002025-04-04T17:42:03Z2025-04-04T17:42:03ZCaleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>Setting up my HyperTextingโฆ ๐ค</p>
<p>Setting up my HyperTextingโฆ ๐ค</p>
Caleb Hailey (@calebhailey.com)https://calebhailey.com/posts/17436376860002025-04-02T23:48:06Z2025-04-02T23:48:06ZCaleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>is experimentingโฆ ๐จ๐ฝโ๐ฌ</p>
<p>is experimentingโฆ ๐จ๐ฝโ๐ฌ</p>
New pagehttps://calebhailey.com/posts/17430532921662025-03-26T22:28:12-07:002025-03-26T22:28:12-07:00Caleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>It's happening!! ๐ฑ</p>
<p>It's happening!! ๐ฑ</p>
New pagehttps://calebhailey.com/posts/17430518540582025-03-26T22:04:14-07:002025-03-26T22:04:14-07:00Caleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>Whoa! ๐คฏ</p>
<p>Whoa! ๐คฏ</p>
New pagehttps://calebhailey.com/posts/17430517756532025-03-26T22:02:55-07:002025-03-26T22:02:55-07:00Caleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>Test post from a new tool I've been working on. I hope this works!</p>
<p>Test post from a new tool I've been working on. I hope this works!</p>
customElements.apply()https://calebhailey.com/posts/customelements-apply2025-02-12T11:00:00-08:002025-02-12T11:00:00-08:00Caleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<h2 id="customelementsapply"><code>customElements.apply()</code></h2>
<p><strong>A (naive?) approach to workaround <code>customElements.define()</code> "same tag name" errors.</strong></p>
<p>Web components have completely changed the way I write vanilla JavaScript.
It turns out classes are quite useful for encapsulation (who knew?)!
Complementary approaches like <a href="https://adactio.com/journal/20618">HTML web components</a> (and <a href="https://hawkticehurst.com/2024/11/css-web-components-for-marketing-sites/">CSS web components</a>) have <em>reduced</em> the amount of JavaScript I'm writing by about 95%.
These ideas from <a href="https://adactio.com" data-hyper-mention>@adactio.com</a> and <a href="https://hawkticehurst.com" data-hyper-mention>@hawkticehurst.com</a> together with a steady stream of web component content from <a href="https://gomakethings.com" data-hyper-mention>@gomakethings.com</a> have revived my interest in modern web development.</p>
<p>But recently I started running into a little speed bump.
I've been exploring HTML templating workflows that enable me to compose sections and entire pages from a collection of layout "partials" (ala <a href="https://en.wikipedia.org/wiki/Server_Side_Includes">server side includes</a>).
This sometimes causes multiple <code><script></code> tags to be added for a given web component, resulting in redundant calls to <code>customElements.define()</code> and a <em>"cannot define multiple custom elements with the same tag name"</em> error.</p>
<alert-quote ht-element danger>
<p><strong>NotSupportedError:</strong> Cannot define multiple custom elements with the same tag name.</p>
</alert-quote>
<p>My initial reaction to this was to move all <code><script src></code> tags into the <code><head></code>, but this inevitably resulted in failing to load a component's JavaScript on certain pages (dependency management fail).
Then I read <a href="https://jakelazaroff.com" data-hyper-mention>@jakelazaroff.com</a>'s excellent <a href="https://til.jakelazaroff.com/html/define-a-custom-element/">Define a custom element</a> blog post and it opened my eyes to the many different approaches to managing custom elements.
But I also felt like my challenge might have been slightly different than the problem Jake was solving.
So I tried something different that has been working really well for me.</p>
<p>It started with reviewing the <a href="https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry"><code>CustomElementsRegistry</code></a> reference documentation and discovering that <a href="https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/get"><code>get()</code></a> and <a href="https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/getName"><code>getName()</code></a> methods already existed.
All that was needed was an idempotent method for registering custom elements.
It turns out this was trivial to implement.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="ln">1</span><span class="cl"><span class="nx">CustomElementRegistry</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">apply</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">component</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="p">(</span><span class="o">!!</span><span class="nx">component</span><span class="p">.</span><span class="nx">constructor</span> <span class="o">&&</span> <span class="nx">component</span><span class="p">.</span><span class="nx">toString</span><span class="p">().</span><span class="nx">substring</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">5</span><span class="p">)</span> <span class="o">==</span> <span class="s2">"class"</span><span class="p">))</span> <span class="p">{</span> <span class="k">return</span> <span class="p">};</span> <span class="c1">// guard
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">tag</span><span class="p">))</span> <span class="p">{</span> <span class="k">return</span> <span class="p">};</span> <span class="c1">// lookup by tag name
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">getName</span><span class="p">(</span><span class="nx">component</span><span class="p">))</span> <span class="p">{</span> <span class="k">return</span> <span class="p">};</span> <span class="c1">// lookup by component class
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"></span> <span class="k">try</span> <span class="p">{</span> <span class="k">this</span><span class="p">.</span><span class="nx">define</span><span class="p">(</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">component</span><span class="p">)</span> <span class="p">}</span> <span class="k">catch</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"> <span class="nx">console</span><span class="p">.</span><span class="nx">debug</span><span class="p">(</span><span class="sb">`component </span><span class="si">${</span><span class="nx">component</span><span class="p">.</span><span class="nx">name</span><span class="si">}</span><span class="sb"> already registered as <</span><span class="si">${</span><span class="nx">tag</span><span class="si">}</span><span class="sb">>`</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl"> <span class="p">};</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="p">};</span>
</span></span></code></pre><p>This is already working so well for me that it's just about the only JavaScript I keep in <code>main.js</code> for new projects.
I'm replacing calls to <code>customElements.define</code> with <code>customElements.apply</code> in all of my web component JavaScript.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="ln">1</span><span class="cl"><span class="nx">customElements</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="s2">"my-element"</span><span class="p">,</span> <span class="kr">class</span> <span class="nx">MyElement</span> <span class="kr">extends</span> <span class="nx">HTMLElement</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"> <span class="c1">// this is where the magic happens ๐ช
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"></span><span class="p">});</span>
</span></span></code></pre><p>In doing so, I can add <code><script src='/js/my-component.js'></code> tags in any layout partial without worrying about "same tag name" errors.</p>
<p>Do you find this helpful?
Or is this a horrible idea? 😅
Send me an email and let me know what you think: <strong>hello [at] calebhailey.com</strong></p>
<!-- Links -->
<h2 id="customelementsapply"><code>customElements.apply()</code></h2>
<p><strong>A (naive?) approach to workaround <code>customElements.define()</code> "same tag name" errors.</strong></p>
<p>Web components have completely changed the way I write vanilla JavaScript.
It turns out classes are quite useful for encapsulation (who knew?)!
Complementary approaches like <a href="https://adactio.com/journal/20618">HTML web components</a> (and <a href="https://hawkticehurst.com/2024/11/css-web-components-for-marketing-sites/">CSS web components</a>) have <em>reduced</em> the amount of JavaScript I'm writing by about 95%.
These ideas from <a href="https://adactio.com" data-hyper-mention>@adactio.com</a> and <a href="https://hawkticehurst.com" data-hyper-mention>@hawkticehurst.com</a> together with a steady stream of web component content from <a href="https://gomakethings.com" data-hyper-mention>@gomakethings.com</a> have revived my interest in modern web development.</p>
<p>But recently I started running into a little speed bump.
I've been exploring HTML templating workflows that enable me to compose sections and entire pages from a collection of layout "partials" (ala <a href="https://en.wikipedia.org/wiki/Server_Side_Includes">server side includes</a>).
This sometimes causes multiple <code><script></code> tags to be added for a given web component, resulting in redundant calls to <code>customElements.define()</code> and a <em>"cannot define multiple custom elements with the same tag name"</em> error.</p>
<alert-quote ht-element danger>
<p><strong>NotSupportedError:</strong> Cannot define multiple custom elements with the same tag name.</p>
</alert-quote>
<p>My initial reaction to this was to move all <code><script src></code> tags into the <code><head></code>, but this inevitably resulted in failing to load a component's JavaScript on certain pages (dependency management fail).
Then I read <a href="https://jakelazaroff.com" data-hyper-mention>@jakelazaroff.com</a>'s excellent <a href="https://til.jakelazaroff.com/html/define-a-custom-element/">Define a custom element</a> blog post and it opened my eyes to the many different approaches to managing custom elements.
But I also felt like my challenge might have been slightly different than the problem Jake was solving.
So I tried something different that has been working really well for me.</p>
<p>It started with reviewing the <a href="https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry"><code>CustomElementsRegistry</code></a> reference documentation and discovering that <a href="https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/get"><code>get()</code></a> and <a href="https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/getName"><code>getName()</code></a> methods already existed.
All that was needed was an idempotent method for registering custom elements.
It turns out this was trivial to implement.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="ln">1</span><span class="cl"><span class="nx">CustomElementRegistry</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">apply</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">component</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="p">(</span><span class="o">!!</span><span class="nx">component</span><span class="p">.</span><span class="nx">constructor</span> <span class="o">&&</span> <span class="nx">component</span><span class="p">.</span><span class="nx">toString</span><span class="p">().</span><span class="nx">substring</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">5</span><span class="p">)</span> <span class="o">==</span> <span class="s2">"class"</span><span class="p">))</span> <span class="p">{</span> <span class="k">return</span> <span class="p">};</span> <span class="c1">// guard
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">tag</span><span class="p">))</span> <span class="p">{</span> <span class="k">return</span> <span class="p">};</span> <span class="c1">// lookup by tag name
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">getName</span><span class="p">(</span><span class="nx">component</span><span class="p">))</span> <span class="p">{</span> <span class="k">return</span> <span class="p">};</span> <span class="c1">// lookup by component class
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"></span> <span class="k">try</span> <span class="p">{</span> <span class="k">this</span><span class="p">.</span><span class="nx">define</span><span class="p">(</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">component</span><span class="p">)</span> <span class="p">}</span> <span class="k">catch</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"> <span class="nx">console</span><span class="p">.</span><span class="nx">debug</span><span class="p">(</span><span class="sb">`component </span><span class="si">${</span><span class="nx">component</span><span class="p">.</span><span class="nx">name</span><span class="si">}</span><span class="sb"> already registered as <</span><span class="si">${</span><span class="nx">tag</span><span class="si">}</span><span class="sb">>`</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl"> <span class="p">};</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="p">};</span>
</span></span></code></pre><p>This is already working so well for me that it's just about the only JavaScript I keep in <code>main.js</code> for new projects.
I'm replacing calls to <code>customElements.define</code> with <code>customElements.apply</code> in all of my web component JavaScript.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="ln">1</span><span class="cl"><span class="nx">customElements</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="s2">"my-element"</span><span class="p">,</span> <span class="kr">class</span> <span class="nx">MyElement</span> <span class="kr">extends</span> <span class="nx">HTMLElement</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"> <span class="c1">// this is where the magic happens ๐ช
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"></span><span class="p">});</span>
</span></span></code></pre><p>In doing so, I can add <code><script src='/js/my-component.js'></code> tags in any layout partial without worrying about "same tag name" errors.</p>
<p>Do you find this helpful?
Or is this a horrible idea? 😅
Send me an email and let me know what you think: <strong>hello [at] calebhailey.com</strong></p>
<!-- Links -->
Caleb Hailey (@calebhailey.com)https://calebhailey.com/posts/the-only-intuitive-interface2025-01-24T09:05:27-08:002025-01-24T09:05:27-08:00Caleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.comiAhttps://ia.net/@ia.nethttps://calebhailey.com/img/ia.net/apple-touch-icon.png<p>This post by <a href="https://ia.net" data-hyper-mention>@ia.net</a> reminds me of a quote I used to have permanently written on the top of the whiteboard in my office:</p>
<blockquote>
<p>The only intuitive interface is the nipple.
Everything else is learned.</p>
<p><strong>โ Bruce "Tog" Tognazzini</strong></p>
</blockquote>
<!-- https://asktog.com/atc/about-bruce-tognazzini/ -->
<!-- https://en.wikipedia.org/wiki/Bruce_Tognazzini -->
<p>My favorite quote from the interview is:</p>
<pull-quote ht-element>
<p>Design requires a willingness to make a fool of yourself by asking outrageous and offensive questions and to be amazed at things that seem perfectly normal to other people.</p>
</pull-quote>
<p>This post by <a href="https://ia.net" data-hyper-mention>@ia.net</a> reminds me of a quote I used to have permanently written on the top of the whiteboard in my office:</p>
<blockquote>
<p>The only intuitive interface is the nipple.
Everything else is learned.</p>
<p><strong>โ Bruce "Tog" Tognazzini</strong></p>
</blockquote>
<!-- https://asktog.com/atc/about-bruce-tognazzini/ -->
<!-- https://en.wikipedia.org/wiki/Bruce_Tognazzini -->
<p>My favorite quote from the interview is:</p>
<pull-quote ht-element>
<p>Design requires a willingness to make a fool of yourself by asking outrageous and offensive questions and to be amazed at things that seem perfectly normal to other people.</p>
</pull-quote>
'Wherever you get your podcasts' is a radical statement.https://calebhailey.com/posts/17375860480962025-01-22T14:47:28-08:002025-01-22T14:47:28-08:00Caleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.comAnil Dashhttps://www.anildash.com/@anildash.comhttps://cdn.glitch.global/d45aff89-36ba-46db-8c7c-3da7c8a93931/microphone-pandelache.jpg?v=1706588470713<p>Speaking of <a href="/tags/rss/" data-hyper-mention>#RSS</a>, I love this piece by <a href="https://anildash.com" data-hyper-mention>@anildash.com</a>.</p>
<p>I've always wondered if one of the biggest differences <em>in adoption</em> between podcasts and text-based RSS feeds is that "podcast" has a catchy ring to it, and "really simple sindication" does not.
Neither does <a href="https://en.wikipedia.org/wiki/RSS">"RDF site summary"</a>.
It makes me further wonder if <a href="https://textcasting.org" data-hyper-mention>@textcasting.org</a> (by <a href="https://scripting.com" data-hyper-mention>@scripting.com</a>) is more important as (re-)branding for text-based RSS feeds than it is as an actual new standard.</p>
<p>Speaking of <a href="/tags/rss/" data-hyper-mention>#RSS</a>, I love this piece by <a href="https://anildash.com" data-hyper-mention>@anildash.com</a>.</p>
<p>I've always wondered if one of the biggest differences <em>in adoption</em> between podcasts and text-based RSS feeds is that "podcast" has a catchy ring to it, and "really simple sindication" does not.
Neither does <a href="https://en.wikipedia.org/wiki/RSS">"RDF site summary"</a>.
It makes me further wonder if <a href="https://textcasting.org" data-hyper-mention>@textcasting.org</a> (by <a href="https://scripting.com" data-hyper-mention>@scripting.com</a>) is more important as (re-)branding for text-based RSS feeds than it is as an actual new standard.</p>
Caleb Hailey (@calebhailey.com)https://calebhailey.com/posts/17374833140952025-01-21T10:15:14-08:002025-01-21T10:15:14-08:00Caleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.comAbout Feedshttps://aboutfeeds.com/@aboutfeeds.comhttps://aboutfeeds.com/favicon.ico<p>I've been looking for good resources to introduce people to <a href="/tags/rss/" data-hyper-mention>#RSS</a> and this looks like a great one by <a href="https://interconnected.org" data-hyper-mention>@interconnected.org</a>!</p>
<p>I've been looking for good resources to introduce people to <a href="/tags/rss/" data-hyper-mention>#RSS</a> and this looks like a great one by <a href="https://interconnected.org" data-hyper-mention>@interconnected.org</a>!</p>
How To Market A Game (@howtomarketagame.com)https://calebhailey.com/posts/17374832773702025-01-21T10:14:37-08:002025-01-21T10:14:37-08:00Caleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.comHow To Market A Gamehttps://howtomarketagame.com/@howtomarketagame.comhttps://howtomarketagame.com/wp-content/uploads/2020/01/cropped-small_logo512x512-1-180x180.pngTuesday, January 21, 2025Caleb Hailey (@calebhailey.com)https://calebhailey.com/posts/17369103384342025-01-14T19:05:38-08:002025-01-14T19:05:38-08:00Caleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.comSteph Angohttps://stephango.com/@stephango.comhttps://stephango.com/apple-touch-icon.png<p>I've thought about this <a href="https://stephango.com" data-hyper-mention>@stephango.com</a> blog post at least once per week for the last ~18 months.</p>
<p>Just added this to my <a href="/inspired-by">inspired by</a> hall of fame.</p>
<p>I've thought about this <a href="https://stephango.com" data-hyper-mention>@stephango.com</a> blog post at least once per week for the last ~18 months.</p>
<p>Just added this to my <a href="/inspired-by">inspired by</a> hall of fame.</p>
Daring Fireball (@daringfireball.net)https://calebhailey.com/posts/17364047435462025-01-08T22:39:03-08:002025-01-08T22:39:03-08:00Caleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.comDaring Fireballhttps://daringfireball.net/@daringfireball.nethttps://daringfireball.net/graphics/apple-touch-icon.pngWednesday, January 8, 2025Caleb Hailey (@calebhailey.com)https://calebhailey.com/posts/17362826283772025-01-07T12:43:48-08:002025-01-07T12:43:48-08:00Caleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>I still haven't used <a href="https://htmx.org" data-hyper-mention>@htmx.org</a>, but I've read the <a href="/tags/hypermedia/" data-hyper-mention>#HyperMedia</a> book and I'm a big fan of their ideas and where the project is headed overall. ๐</p>
<p><a href="/tags/html/" data-hyper-mention>#html</a> <a href="/tags/htmx/" data-hyper-mention>#htmx</a> <a href="/tags/javascript/" data-hyper-mention>#javascript</a></p>
<p>I still haven't used <a href="https://htmx.org" data-hyper-mention>@htmx.org</a>, but I've read the <a href="/tags/hypermedia/" data-hyper-mention>#HyperMedia</a> book and I'm a big fan of their ideas and where the project is headed overall. ๐</p>
<p><a href="/tags/html/" data-hyper-mention>#html</a> <a href="/tags/htmx/" data-hyper-mention>#htmx</a> <a href="/tags/javascript/" data-hyper-mention>#javascript</a></p>
Caleb Hailey (@calebhailey.com)https://calebhailey.com/posts/17359576971502025-01-03T18:28:17-08:002025-01-03T18:28:17-08:00Caleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.comThis is hands-down my favorite craft cocktail website. ๐น
This is hands-down my favorite craft cocktail website. ๐น
Caleb Hailey (@calebhailey.com)https://calebhailey.com/posts/17359440250632025-01-03T14:40:25-08:002025-01-03T14:40:25-08:00Caleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>I'm loving the new <a href="https://vw.com" data-hyper-mention>@vw.com</a> ID Buzz.</p>
<p>And my new scrolling image gallery. ๐</p>
<p>๐๐ฝ Swipe ๐๐ฝ</p>
<p>I'm loving the new <a href="https://vw.com" data-hyper-mention>@vw.com</a> ID Buzz.</p>
<p>And my new scrolling image gallery. ๐</p>
<p>๐๐ฝ Swipe ๐๐ฝ</p>
<!--more-->
<p>Pretty cool, right?!</p>
Caleb Hailey (@calebhailey.com)https://calebhailey.com/links/17358638205612025-01-02T16:23:40-08:002025-01-02T16:23:40-08:00Caleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.comMore like fast trashion, amirite? :sweat_smile:
More like fast trashion, amirite? :sweat_smile:
Caleb Hailey (@calebhailey.com)https://calebhailey.com/posts/17345649516072024-12-18T15:35:51-08:002024-12-18T15:35:51-08:00Caleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<h2 id="keep-it-on-the-markdown-low">Keep it on the markdown-low</h2>
<p>First post with my custom <a href="/tags/markdown/" data-hyper-mention>#markdown</a> parser.</p>
<p>Here's a little sample code block to show off the <code><code></code> syntax highlighting.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="ln"> 1</span><span class="cl"><span class="cp"><!DOCTYPE html></span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="p"><</span><span class="nt">html</span> <span class="na">lang</span><span class="o">=</span><span class="s">'en-US'</span><span class="p">></span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"> <span class="p"><</span><span class="nt">head</span><span class="p">></span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"> <span class="p"><</span><span class="nt">meta</span> <span class="na">ht-include</span><span class="o">=</span><span class="s">'partials/head.html'</span><span class="p">></span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"> <span class="p"><</span><span class="nt">meta</span> <span class="na">itemprop</span><span class="o">=</span><span class="s">'template.name'</span> <span class="na">content</span><span class="o">=</span><span class="s">'default'</span><span class="p">></span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"> <span class="c"><!-- Web Components --></span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"> <span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">'/js/components/relative-time.js'</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"> <span class="p"></</span><span class="nt">head</span><span class="p">></span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"> <span class="p"><</span><span class="nt">body</span><span class="p">></span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"> <span class="p"><</span><span class="nt">nav</span> <span class="na">ht-include</span><span class="o">=</span><span class="s">'partials/nav.html'</span><span class="p">></</span><span class="nt">nav</span><span class="p">></span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"> <span class="p"><</span><span class="nt">content-whitespace</span><span class="p">></</span><span class="nt">content-whitespace</span><span class="p">></span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"> <span class="p"><</span><span class="nt">section</span> <span class="na">id</span><span class="o">=</span><span class="s">'post'</span> <span class="na">data-color-scheme</span><span class="o">=</span><span class="s">'light'</span><span class="p">></span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"> <span class="p"><</span><span class="nt">article</span> <span class="na">ht-include</span><span class="o">=</span><span class="s">'partials/post-article'</span><span class="p">></</span><span class="nt">article</span><span class="p">></span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"> <span class="p"></</span><span class="nt">section</span><span class="p">></span>
</span></span><span class="line"><span class="ln">16</span><span class="cl"> <span class="p"><</span><span class="nt">content-whitespace</span><span class="p">></</span><span class="nt">content-whitespace</span><span class="p">></span>
</span></span><span class="line"><span class="ln">17</span><span class="cl"> <span class="p"><</span><span class="nt">footer</span> <span class="na">ht-include</span><span class="o">=</span><span class="s">'partials/footer.html'</span> <span class="na">data-color-scheme</span><span class="o">=</span><span class="s">'dark'</span><span class="p">></</span><span class="nt">footer</span><span class="p">></span>
</span></span><span class="line"><span class="ln">18</span><span class="cl"> <span class="p"><</span><span class="nt">section</span> <span class="na">ht-include</span><span class="o">=</span><span class="s">'partials/tail.html'</span><span class="p">></</span><span class="nt">section</span><span class="p">></span>
</span></span><span class="line"><span class="ln">19</span><span class="cl"> <span class="p"></</span><span class="nt">body</span><span class="p">></span>
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="p"></</span><span class="nt">html</span><span class="p">></span>
</span></span></code></pre><p>This is all table stakes stuff, but I'm pumped to get it all wired up!</p>
<h2 id="keep-it-on-the-markdown-low">Keep it on the markdown-low</h2>
<p>First post with my custom <a href="/tags/markdown/" data-hyper-mention>#markdown</a> parser.</p>
<p>Here's a little sample code block to show off the <code><code></code> syntax highlighting.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="ln"> 1</span><span class="cl"><span class="cp"><!DOCTYPE html></span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="p"><</span><span class="nt">html</span> <span class="na">lang</span><span class="o">=</span><span class="s">'en-US'</span><span class="p">></span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"> <span class="p"><</span><span class="nt">head</span><span class="p">></span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"> <span class="p"><</span><span class="nt">meta</span> <span class="na">ht-include</span><span class="o">=</span><span class="s">'partials/head.html'</span><span class="p">></span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"> <span class="p"><</span><span class="nt">meta</span> <span class="na">itemprop</span><span class="o">=</span><span class="s">'template.name'</span> <span class="na">content</span><span class="o">=</span><span class="s">'default'</span><span class="p">></span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"> <span class="c"><!-- Web Components --></span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"> <span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">'/js/components/relative-time.js'</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"> <span class="p"></</span><span class="nt">head</span><span class="p">></span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"> <span class="p"><</span><span class="nt">body</span><span class="p">></span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"> <span class="p"><</span><span class="nt">nav</span> <span class="na">ht-include</span><span class="o">=</span><span class="s">'partials/nav.html'</span><span class="p">></</span><span class="nt">nav</span><span class="p">></span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"> <span class="p"><</span><span class="nt">content-whitespace</span><span class="p">></</span><span class="nt">content-whitespace</span><span class="p">></span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"> <span class="p"><</span><span class="nt">section</span> <span class="na">id</span><span class="o">=</span><span class="s">'post'</span> <span class="na">data-color-scheme</span><span class="o">=</span><span class="s">'light'</span><span class="p">></span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"> <span class="p"><</span><span class="nt">article</span> <span class="na">ht-include</span><span class="o">=</span><span class="s">'partials/post-article'</span><span class="p">></</span><span class="nt">article</span><span class="p">></span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"> <span class="p"></</span><span class="nt">section</span><span class="p">></span>
</span></span><span class="line"><span class="ln">16</span><span class="cl"> <span class="p"><</span><span class="nt">content-whitespace</span><span class="p">></</span><span class="nt">content-whitespace</span><span class="p">></span>
</span></span><span class="line"><span class="ln">17</span><span class="cl"> <span class="p"><</span><span class="nt">footer</span> <span class="na">ht-include</span><span class="o">=</span><span class="s">'partials/footer.html'</span> <span class="na">data-color-scheme</span><span class="o">=</span><span class="s">'dark'</span><span class="p">></</span><span class="nt">footer</span><span class="p">></span>
</span></span><span class="line"><span class="ln">18</span><span class="cl"> <span class="p"><</span><span class="nt">section</span> <span class="na">ht-include</span><span class="o">=</span><span class="s">'partials/tail.html'</span><span class="p">></</span><span class="nt">section</span><span class="p">></span>
</span></span><span class="line"><span class="ln">19</span><span class="cl"> <span class="p"></</span><span class="nt">body</span><span class="p">></span>
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="p"></</span><span class="nt">html</span><span class="p">></span>
</span></span></code></pre><p>This is all table stakes stuff, but I'm pumped to get it all wired up!</p>
Caleb Hailey (@calebhailey.com)https://calebhailey.com/posts/17109643200002024-03-20T12:52:00-07:002024-03-20T12:52:00-07:00Caleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>Just started reading "Filterworld", by <a href="https://kylechayka.com" data-hyper-mention>@kylechayka.com</a>, and it starts with a picture from <a href="https://en.wikipedia.org/wiki/Mechanical_Turk">one of my favorite Wikipedia pages</a> of all time.
I think I'm gonna like this book!</p>
<p><a href="/tags/nowreading/" data-hyper-mention>#NowReading</a></p>
<p>Just started reading "Filterworld", by <a href="https://kylechayka.com" data-hyper-mention>@kylechayka.com</a>, and it starts with a picture from <a href="https://en.wikipedia.org/wiki/Mechanical_Turk">one of my favorite Wikipedia pages</a> of all time.
I think I'm gonna like this book!</p>
<p><a href="/tags/nowreading/" data-hyper-mention>#NowReading</a></p>
Caleb Hailey (@calebhailey.com)https://calebhailey.com/posts/17106256800002024-03-16T13:48:00-08:002024-03-16T13:48:00-08:00Caleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>TIL about the <a href="/tags/html/" data-hyper-mention>#HTML</a> <code><base></code> element!</p>
<p>TIL about the <a href="/tags/html/" data-hyper-mention>#HTML</a> <code><base></code> element!</p>
Herd Works (@herd.works)https://calebhailey.com/posts/16764084600002023-02-14T13:01:00-08:002023-02-14T13:01:00-08:00Caleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.comHerd Workshttps://herd.works/@herd.workshttps://herd.works/apple-touch-icon-57x57.png?v=1Tuesday, February 14, 2023The Best Chef in the Worldhttps://calebhailey.com/posts/sally-schmidt2022-10-08T14:30:00-07:002022-10-08T14:30:00-07:00Caleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.comYouTubehttps://www.youtube.com/@youtube.comhttps://www.youtube.com/s/desktop/648a021a/img/logos/favicon_144x144.png<blockquote>
<p>Originally posted on <a href="https://sheesh.blog" data-hyper-mention>@sheesh.blog</a>.</p>
</blockquote>
<p>As soon as you have 20 minutes to spare, I encourage you to go watch this short film about <a href="https://www.nytimes.com/2022/09/13/opinion/sally-schmitt-french-laundry.html">Sally Schmidt</a>, produced by Oscarยฎ award winning documentary filmmaker <a href="https://twitter.com/bgproudfoot">Ben Proudfoot</a>, for the <a href="https://nytimes.com" data-hyper-mention>@nytimes.com</a><sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.</p>
<p>Speaking of <a href="https://sheesh.blog/posts/popup-restaurant-theory">restaurants</a>, Sally started a little establishment you might have heard of called <a href="https://www.thomaskeller.com/early-history">The French Laundry</a>. 🤌</p>
<blockquote>
<p>Originally posted on <a href="https://sheesh.blog" data-hyper-mention>@sheesh.blog</a>.</p>
</blockquote>
<p>As soon as you have 20 minutes to spare, I encourage you to go watch this short film about <a href="https://www.nytimes.com/2022/09/13/opinion/sally-schmitt-french-laundry.html">Sally Schmidt</a>, produced by Oscarยฎ award winning documentary filmmaker <a href="https://twitter.com/bgproudfoot">Ben Proudfoot</a>, for the <a href="https://nytimes.com" data-hyper-mention>@nytimes.com</a><sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.</p>
<p>Speaking of <a href="https://sheesh.blog/posts/popup-restaurant-theory">restaurants</a>, Sally started a little establishment you might have heard of called <a href="https://www.thomaskeller.com/early-history">The French Laundry</a>. 🤌</p>
<!--more-->
<p>I particularly like this comment in the accompanying article:</p>
<pull-quote ht-element cite='Ben Proudfoot' href='https://www.nytimes.com/2022/09/13/opinion/sally-schmitt-french-laundry.html'>
<p>Talking to Ms. Schmitt that morning, I learned she held a different kind of wisdom: that success may have other definitions.</p>
</pull-quote>
<p>Now that's what I call <a href="https://sheesh.blog/posts/life-work-balance">life-work <em>balance</em></a>!</p>
<!-- Footnotes -->
<!-- Links -->
<div class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn:1">
<p><a href="https://www.nytimes.com/column/op-docs">Op-Docs</a> is a New York Times production of "Oscar-winning series of short documentaries by independent filmmakers".
This might be one of my new favorite places on the internet. <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
</ol>
</div>
Long time listener, first time callerhttps://calebhailey.com/posts/long-time-listener2022-04-24T20:26:18-07:002022-04-24T20:26:18-07:00Caleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<blockquote>
<p>Originally posted on <a href="https://sheesh.blog" data-hyper-mention>@sheesh.blog</a>.</p>
</blockquote>
<h2 id="long-time-listener-first-time-caller">Long time listener, first time caller</h2>
<p>I can't remember the last time I read a book from front to back<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>, but I am a voracious reader.
The thing is, I prefer to read "the internet" instead of books.</p>
<p>At some point early on in my internet journey I discovered <a href="/tags/rss/" data-hyper-mention>#RSS</a> and I immediately fell in love<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>.
My RSS feed became like my own personal newspaper, where I was the curator.
I could add and remove <del>columnists</del> blog feeds as my <a href="/about#interest-graph">interest graph</a> would change over time.
I was one of the many<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> who decried the death of Google Reader.
RSS lives on, but it's not as ubiquitious as it once was.</p>
<p>For some years my feed shifted from RSS to social media โ almost exclusively Twitter, and mostly via Twitter Lists โ but a few trends in recent years have brought me back to RSS:</p>
<ol>
<li>RSS services are great again<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup>.</li>
<li>RSS apps are <a href="https://www.macstories.net/reviews/netnewswire-review-the-mac-rss-client-rebooted-with-a-solid-foundation-for-the-future/">making</a> <a href="https://thesweetsetup.com/netnewswire-5-0-relaunches-as-an-open-source-rss-reader-for-the-mac/">a</a> <a href="https://daringfireball.net/linked/2019/08/29/netnewswire-5">comeback</a>!</li>
<li>"Doomscrolling" became a thingโข๏ธ, prompting a renewed need to curate my feed.</li>
</ol>
<p>With my newfound replacement for Google Reader's service (<a href="https://feedbin.com">Feedbin.com</a>), and my favorite old RSS reader app making a glorious (and <a href="https://github.com/Ranchero-Software/NetNewsWire">open source</a>!!) comeback, I decided to start the curation process from scratch.
I created folders for "News", "People", "Portland" (my local happenings), "Products", "Startups", and "Tech".</p>
<p>And then I started subscribing.
And I discovered that the very first feeds I added were the very same feeds I've been reading all along.
A combination of overlapping <a href="/about#interest-graph">interest graphs</a> (I'm assuming) and writing styles have kept me reading certain blogs for over a decade now.
These are the bloggers who's writing has both intimidated me โ because I hold them in high esteem โ and inspired me to start this blog.</p>
<p>I have feared that if I ever started a blog I would appear as a copy cat, a cheap imitation of these now-veterans who probably started like I am starting right now.
But I decided that instead of shying away from writing, I should lean into it.
Give credit where credit is due.
Start my blog, in my own voice (however heavily "inspired by" it may be), and acknowledge those who went before me.</p>
<p>Starting a blog is easy.
Buy a domain โ write an <a href="/about">/about</a> page โ write a <a href="https://sheesh.blog/posts/helloworld">"hello, world"</a> โ smash the publish button. ๐ฅ
But for me, I could not have started this blog without acknowledging who this blog was <a href="/inspired-by">inspired by</a>.</p>
<p>โ๏ธ</p>
<div class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn:1">
<p>I mean, I do remember the last book I read, but it's embarrasing. ๐  <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
<li id="fn:2">
<p>FUN FACT: fast forward many years later and I somehow had the privilege of working with <a href="https://www.linkedin.com/in/mshobe/">Matt Shobe</a> โ one of the co-founders of Feedburner (<a href="https://techcrunch.com/2007/05/23/100-million-payday-for-feedburner-this-deal-is-confirmed/">acquired by Google</a> in 2007).
And by "working with" I mean he became an angel investor in my first company, and a critical advisor in our early stages. <a href="#fnref:2" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
<li id="fn:3">
<p>Or <em>few</em>, I guess. Otherwise we would still have Google Reader? <a href="#fnref:3" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
<li id="fn:4">
<p>In the years following the death of Google Reader (RIP), I tried a handful of apps and services that built replacements for Google Reader โ from Feedly to Flipboard (powered by a carefully curated Twitter list) โ but nothing stuck.
Then a few years ago I tried Feedbin, and subsequently discovered its <a href="https://feedbin.com/blog/2016/02/03/subscribe-to-email-newsletters-in-feedbin/">support for Newsletters</a> (at a time when it seemed like everyone was starting a SubStack), and I almost forgot that Google Reader ever existed. <a href="#fnref:4" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
</ol>
</div>
<blockquote>
<p>Originally posted on <a href="https://sheesh.blog" data-hyper-mention>@sheesh.blog</a>.</p>
</blockquote>
<h2 id="long-time-listener-first-time-caller">Long time listener, first time caller</h2>
<p>I can't remember the last time I read a book from front to back<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>, but I am a voracious reader.
The thing is, I prefer to read "the internet" instead of books.</p>
<p>At some point early on in my internet journey I discovered <a href="/tags/rss/" data-hyper-mention>#RSS</a> and I immediately fell in love<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>.
My RSS feed became like my own personal newspaper, where I was the curator.
I could add and remove <del>columnists</del> blog feeds as my <a href="/about#interest-graph">interest graph</a> would change over time.
I was one of the many<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> who decried the death of Google Reader.
RSS lives on, but it's not as ubiquitious as it once was.</p>
<p>For some years my feed shifted from RSS to social media โ almost exclusively Twitter, and mostly via Twitter Lists โ but a few trends in recent years have brought me back to RSS:</p>
<ol>
<li>RSS services are great again<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup>.</li>
<li>RSS apps are <a href="https://www.macstories.net/reviews/netnewswire-review-the-mac-rss-client-rebooted-with-a-solid-foundation-for-the-future/">making</a> <a href="https://thesweetsetup.com/netnewswire-5-0-relaunches-as-an-open-source-rss-reader-for-the-mac/">a</a> <a href="https://daringfireball.net/linked/2019/08/29/netnewswire-5">comeback</a>!</li>
<li>"Doomscrolling" became a thingโข๏ธ, prompting a renewed need to curate my feed.</li>
</ol>
<p>With my newfound replacement for Google Reader's service (<a href="https://feedbin.com">Feedbin.com</a>), and my favorite old RSS reader app making a glorious (and <a href="https://github.com/Ranchero-Software/NetNewsWire">open source</a>!!) comeback, I decided to start the curation process from scratch.
I created folders for "News", "People", "Portland" (my local happenings), "Products", "Startups", and "Tech".</p>
<p>And then I started subscribing.
And I discovered that the very first feeds I added were the very same feeds I've been reading all along.
A combination of overlapping <a href="/about#interest-graph">interest graphs</a> (I'm assuming) and writing styles have kept me reading certain blogs for over a decade now.
These are the bloggers who's writing has both intimidated me โ because I hold them in high esteem โ and inspired me to start this blog.</p>
<p>I have feared that if I ever started a blog I would appear as a copy cat, a cheap imitation of these now-veterans who probably started like I am starting right now.
But I decided that instead of shying away from writing, I should lean into it.
Give credit where credit is due.
Start my blog, in my own voice (however heavily "inspired by" it may be), and acknowledge those who went before me.</p>
<p>Starting a blog is easy.
Buy a domain โ write an <a href="/about">/about</a> page โ write a <a href="https://sheesh.blog/posts/helloworld">"hello, world"</a> โ smash the publish button. ๐ฅ
But for me, I could not have started this blog without acknowledging who this blog was <a href="/inspired-by">inspired by</a>.</p>
<p>โ๏ธ</p>
<div class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn:1">
<p>I mean, I do remember the last book I read, but it's embarrasing. ๐  <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
<li id="fn:2">
<p>FUN FACT: fast forward many years later and I somehow had the privilege of working with <a href="https://www.linkedin.com/in/mshobe/">Matt Shobe</a> โ one of the co-founders of Feedburner (<a href="https://techcrunch.com/2007/05/23/100-million-payday-for-feedburner-this-deal-is-confirmed/">acquired by Google</a> in 2007).
And by "working with" I mean he became an angel investor in my first company, and a critical advisor in our early stages. <a href="#fnref:2" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
<li id="fn:3">
<p>Or <em>few</em>, I guess. Otherwise we would still have Google Reader? <a href="#fnref:3" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
<li id="fn:4">
<p>In the years following the death of Google Reader (RIP), I tried a handful of apps and services that built replacements for Google Reader โ from Feedly to Flipboard (powered by a carefully curated Twitter list) โ but nothing stuck.
Then a few years ago I tried Feedbin, and subsequently discovered its <a href="https://feedbin.com/blog/2016/02/03/subscribe-to-email-newsletters-in-feedbin/">support for Newsletters</a> (at a time when it seemed like everyone was starting a SubStack), and I almost forgot that Google Reader ever existed. <a href="#fnref:4" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
</ol>
</div>
Hello, worldhttps://calebhailey.com/posts/helloworld2022-04-23T18:15:55-07:002022-04-23T18:15:55-07:00Caleb Haileyhttps://calebhailey.com/@calebhailey.comhttps://calebhailey.com/favicon.jpeghello@calebhailey.com<p>Every new blog should start with an obligatory <a href="https://en.wikipedia.org/wiki/%22Hello,_World!%22_program#History">"hello, world"</a> โ so here I am doing just that.
My experience with blogging has generally rhymed with the experience a former co-worker of mine once shared:</p>
<blockquote>
<p>"Iโve started seven different blogs. Every one had one post."</p>
<p>โ <strong>Derek Newsom</strong></p>
</blockquote>
<p>Something feels different this time, but only time will tell.</p>
<p>โ๏ธ</p>
<p>Every new blog should start with an obligatory <a href="https://en.wikipedia.org/wiki/%22Hello,_World!%22_program#History">"hello, world"</a> โ so here I am doing just that.
My experience with blogging has generally rhymed with the experience a former co-worker of mine once shared:</p>
<blockquote>
<p>"Iโve started seven different blogs. Every one had one post."</p>
<p>โ <strong>Derek Newsom</strong></p>
</blockquote>
<p>Something feels different this time, but only time will tell.</p>
<p>โ๏ธ</p>