Ben’s Bloghttps://ben.prose.sh2022-07-05T20:17:01ZA blog for things I blog aboutbenTech debt → maintenance load2022-08-19T21:02:52Zhttps://ben.prose.sh/2022-08-19-technical-debt-to-maintenance-load<p>I came across this
<a href="https://chelseatroy.com/2021/01/14/quantifying-technical-debt/" rel="nofollow">incredible series about technical debt</a>
by <a href="https://chelseatroy.com/" rel="nofollow">Chelsea Troy</a>. (Her site is a treasure trove of
articles on topics I care about and I'll probably spend some time reading and
reflecting on them.)</p>
<p>In the first part of the series, she introduces a concept called <strong>maintenance
load</strong> to think about technical debt. That is,</p>
<blockquote>
<p>how much effort your development team spends to keep the existing features
running the same as before</p>
</blockquote>
<p>Maintenance load is a function of</p>
<ul>
<li>the age of the project</li>
<li>the practices used to build it</li>
</ul>
<p>She then gives some example scenarios where let's say you have a 10 y/o code
base (✓) where devs wrote some tests (✓), some cursory documentation but not
everything is documented (✓), and occasionally something got rethought or
removed (✓). In a code base like this, 4-5 devs are <em>just</em> on maintenance 🤔.</p>
<p>I feel seen 😅.</p>
<p>My ears perked because not only does this largely apply, but my team just began
to pilot a scheme I devised where we split our team into a <em>new feature</em> team
and a <em>maintenance</em> team. A big motivation was to allow some developers to focus
on building and avoid context switching. So in some ways, we have made explicit
the maintenance load on our team.</p>
<p>I still have yet to digest parts
<a href="https://chelseatroy.com/2021/01/18/avoiding-technical-debt/" rel="nofollow">two</a> and
<a href="https://chelseatroy.com/2021/01/21/reducing-technical-debt/" rel="nofollow">three</a> where she
describes how to avoid and reduce technical debt, but it feels good to
acknowledge and understand the issue more clearly.</p>
Intentional but reluctant2022-08-18T14:12:17Zhttps://ben.prose.sh/2022-08-18-intentional-but-reluctanct<p>A few weeks ago,
<a href="https://www.linkedin.com/posts/jeetupatel_we-live-in-a-world-where-we-are-in-an-illusion-activity-6955686436218028032-lkqo" rel="nofollow">the general manager of the Security and Collaboration business units at Cisco wrote</a>:</p>
<blockquote>
<p>We live in a world where we are in an illusion of being productive because we
are busy with activity.</p>
<p>In fact, our brains have gotten so conditioned to back to back meetings that
so many people tell me they feel lost when there is a break. People experience
guilt because it subconsciously feels like we are not working when we aren’t
in meetings.</p>
<p>Being intentional with our time is such an underrated superpower! I wish I did
it more.</p>
</blockquote>
<p>The idea that <strong>activity ≠ productivity</strong> is spot on. The message of "Be
intentional with your time—you don't have to be in meetings to be productive."
is also valid. But there are other reasons why we feel like we need to be in
meetings.
<a href="https://www.linkedin.com/feed/update/urn:li:activity:6955686436218028032?commentUrn=urn%3Ali%3Acomment%3A%28activity%3A6955686436218028032%2C6955724975865487360%29" rel="nofollow">I was compelled to respond</a>:</p>
<blockquote>
<p>I think a huge contributing factor to this behavior is a company culture that
rewards being in meetings!</p>
<p>If important decisions are only made in meetings, if exposure and clout are
accumulated primarily in meetings with important people, if critical business
context is only shared in meetings, then one's success hinges significantly on
being in more meetings.</p>
<p>My best idea for this is to instill a culture of writing (some examples that
come to mind are Amazon, Stripe, and HashiCorp). Writing clarifies thinking
and allows better ideas to shine rather than charisma. Making decisions
asynchronously through writing is more inclusive. It allows you to scale your
company's knowledge.</p>
<p>And this kind of change only works top-down ;)</p>
</blockquote>
<p>I know <a href="https://www.linkedin.com/in/jeetupatel" rel="nofollow">Jeetu</a> is speaking from his
personal perspective, and what can feel like a different world—a world inhabited
by VCs, executives, administrative assistants and contained in airplane lounges,
board rooms, and corner offices. At the same time, if there was ever a case when
I was in the same context as an executive of a Fortune 100 company, it's this
one!</p>
<p>Perhaps the first step on the path to less meetings begins with the leader being
intentional about not being in so many meetings. But if that "superpower" is to
be at all bestowed on the broader organization, there must be a subsequent
intentionality to foster a culture where people's careers are not so dependent
on being in meetings.</p>
<p>My idea to shift this power dynamic is through making information more
accessible. While understanding and embracing a company's vision is critical,
equally important is having the information and data to make the right
decisions. So often, that context is provided in meetings, as are decisions.</p>
<p>I've been enamored with company cultures that value writing. Some that I have
read and studied:</p>
<ul>
<li><a href="https://thehustle.co/02162021-amazon-writing/" rel="nofollow">Amazon's 6 pagers</a></li>
<li><a href="https://productify.substack.com/p/case-study-5-stripes-greatest-superpower" rel="nofollow">Stripe</a></li>
<li><a href="https://works.hashicorp.com/articles/writing-practices-and-culture" rel="nofollow">HashiCorp</a></li>
<li><a href="https://about.gitlab.com/handbook/handbook-usage/#why-handbook-first" rel="nofollow">GitLab's Handbooks</a></li>
</ul>
<p>Each of these companies approach it in a different way, but the one commonality
is the motivation to <strong>empower individuals and teams to do their best work.</strong></p>
<p>How does this culture change happen? I think it must be primarily top-down
because that's the direction the information and context needs to flow. Until
that happens, I will continue to attend meetings with intention and reluctance.</p>
Developers doing discovery2022-08-15T16:37:15Zhttps://ben.prose.sh/2022-08-15-developers-doing-discovery<p>I started a quest six months ago to bring a human-centered approach to how we
build product at work. I realized that no one on my team had seen a customer
user our product, let alone any feature we had implemented. So <strong>"connecting
engineers with customers"</strong> became my mantra. I looked for opportunities and
also asked the leaders in my organization.</p>
<p>But there was a disconnect.</p>
<p><em>We do have many opportunities for engineers to interact with customers</em>, I
heard. <em>We have a beta program. Sometimes we get pulled into support
escalations. Those are all times we can and should engage the customer.</em></p>
<p>That's when I realized I failed to be precise around what "connecting with
customers" meant, and how frequently the discovery and design phase of
development is foreign to Engineering. Our Scrum process does not adequately
support this kind of behavior.</p>
<p>A conversation with a seasoned engineering leader crystallized this for me. We
were talking about how we build empathy for the customer. He said that he had
done this developing relationships with customers through years of working with
them, presumably through escalations and other activities where he was
validating our solutions with them.</p>
<p>My response: Rather than having the goal of understanding customer goals and
needs as a side effect, let's be intentional about it! <strong>Engineering should
partner and participate in user research.</strong> This would be a more effective and
efficient way of building empathy and making sure we are solving the right
problems.</p>
Public Jrnl2022-08-09T21:15:35Zhttps://ben.prose.sh/2022-08-09-public-jrnl<p>I've connected together a few tools so I can quickly publish thoughts to a
website.</p>
<h3 id="jrnl"><a class="anchor" href="#jrnl" rel="nofollow">#</a> Jrnl</h3>
<p><a href="https://jrnl.sh" rel="nofollow">Jrnl</a> is a slick CLI tool for journaling. It stores data in a
single text file.</p>
<h3 id="lists"><a class="anchor" href="#lists" rel="nofollow">#</a> Lists</h3>
<p>Another tool in the <a href="https://pico.sh" rel="nofollow">picosphere</a>, <a href="https://lists.sh" rel="nofollow">Lists</a>
lets you easily publish a list-oriented text file to the web.</p>
<h3 id="raycast"><a class="anchor" href="#raycast" rel="nofollow">#</a> Raycast</h3>
<p>This is how I input my thoughts. I have a simple extension that calls <code>jrnl</code>,
then pipes the output into lists.sh:</p>
<pre><code>#!/bin/bash
# Required parameters:
# @raycast.schemaVersion 1
# @raycast.title jrnl-public
# @raycast.mode silent
# Optional parameters:
# @raycast.icon 📖
# @raycast.argument1 { "type": "text", "placeholder": "Entry" }
# @raycast.packageName JrnlPackage
# Documentation:
# @raycast.description Add a jrnl entry to public journal
# @raycast.author Ben Tsai
# @raycast.authorURL bentsai.org
jrnl public "$1"
jrnl public --short | tac | ssh lists.sh Jrnl.txt
</code></pre>
<h2 id="result"><a class="anchor" href="#result" rel="nofollow">#</a> Result</h2>
<p>A reverse-chronological list of items almost instantly published from my
fingertips:</p>
<p><a href="https://ben.lists.sh/Jrnl" rel="nofollow">https://ben.lists.sh/Jrnl</a></p>
🐦 Everyone does design2022-08-03T15:53:39Zhttps://ben.prose.sh/2022-08-03-everyone-does-design<blockquote class="twitter-tweet"><p lang="en" dir="ltr">I’d add that everyone *does* design, so let’s equip them with all the tools and support they (I) need <a href="https://t.co/Y53MUWwKDB" rel="nofollow">https://t.co/Y53MUWwKDB</a></p>— Ben Tsai (@bentsai) <a href="https://twitter.com/bentsai/status/1554814571944284161?ref_src=twsrc%5Etfw" rel="nofollow">August 3, 2022</a></blockquote>
Styling Prose2022-08-02T19:16:29Zhttps://ben.prose.sh/2022-08-02-prose-styles<p>I started using <a href="https://prose.sh/" rel="nofollow">prose.sh</a> as a mirror for my blog. Prose is
a cool project within the <a href="pico.sh" rel="nofollow">Pico</a> ecosystem that lets you blog with an
ssh-based workflow. Their vibe is to promote the smol web. Cool!</p>
<p>They recently <a href="https://todo.sr.ht/~erock/pico.sh/35" rel="nofollow">implemented custom CSS</a>,
based partially on my request in their IRC. So with that, I've made a few visual
tweaks to my blog which you're seeing now.</p>
<p>I'm happy about bumping up the font size on the headings, an unironic use of
Times New Roman with some tightening on the letter spacing.</p>
<p>The live file is <a href="https://ben.prose.sh/_styles.css" rel="nofollow">here</a>, while the current
state on publish is:</p>
<pre class="chroma"><code><span class="line"><span class="ln"> 1</span><span class="cl"><span class="nt">header</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"> <span class="k">margin</span><span class="p">:</span> <span class="mi">2</span><span class="kt">rem</span> <span class="kc">auto</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="nt">header</span> <span class="o">></span> <span class="p">.</span><span class="nc">text-2xl</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"> <span class="k">font-family</span><span class="p">:</span> <span class="s2">"Times New Roman"</span><span class="p">,</span> <span class="s2">"Droid Serif"</span><span class="p">,</span> <span class="n">Times</span><span class="p">,</span> <span class="s2">"Source Serif Pro"</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"> <span class="kc">serif</span><span class="p">,</span> <span class="s2">"Apple Color Emoji"</span><span class="p">,</span> <span class="s2">"Segoe UI Emoji"</span><span class="p">,</span> <span class="s2">"Segoe UI Symbol"</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"> <span class="k">font-size</span><span class="p">:</span> <span class="mf">2.5</span><span class="kt">rem</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"> <span class="k">letter-spacing</span><span class="p">:</span> <span class="mf">-0.05</span><span class="kt">rem</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"> <span class="k">line-height</span><span class="p">:</span> <span class="mf">2.25</span><span class="kt">rem</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"> <span class="k">text-align</span><span class="p">:</span> <span class="kc">center</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"> <span class="k">padding-top</span><span class="p">:</span> <span class="mi">1</span><span class="kt">rem</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="p">#</span><span class="nn">blog</span> <span class="nt">header</span> <span class="o">></span> <span class="p">.</span><span class="nc">text-2xl</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"> <span class="k">font-size</span><span class="p">:</span> <span class="mi">4</span><span class="kt">rem</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="nt">header</span> <span class="o">></span> <span class="nt">p</span><span class="p">.</span><span class="nc">font-bold</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl"> <span class="k">font-weight</span><span class="p">:</span> <span class="kc">normal</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl"> <span class="k">font-style</span><span class="p">:</span> <span class="kc">italic</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl"> <span class="k">letter-spacing</span><span class="p">:</span> <span class="mf">-0.05</span><span class="kt">rem</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl"> <span class="k">opacity</span><span class="p">:</span> <span class="mf">0.8</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl"> <span class="k">text-align</span><span class="p">:</span> <span class="kc">center</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl"> <span class="k">padding-top</span><span class="p">:</span> <span class="mf">0.5</span><span class="kt">rem</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">
</span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="nt">code</span><span class="o">,</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="nt">kbd</span><span class="o">,</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="nt">samp</span><span class="o">,</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="nt">pre</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl"> <span class="k">font-size</span><span class="p">:</span> <span class="mf">0.9</span><span class="kt">rem</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">
</span></span><span class="line"><span class="ln">34</span><span class="cl"><span class="p">.</span><span class="nc">post-date</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl"> <span class="k">font-family</span><span class="p">:</span> <span class="kc">monospace</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl"> <span class="k">font-style</span><span class="p">:</span> <span class="kc">normal</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl"> <span class="k">opacity</span><span class="p">:</span> <span class="mf">0.8</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl"> <span class="k">padding-top</span><span class="p">:</span> <span class="mf">0.2</span><span class="kt">rem</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl"> <span class="k">letter-spacing</span><span class="p">:</span> <span class="mf">-0.02</span><span class="kt">rem</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">40</span><span class="cl"> <span class="k">width</span><span class="p">:</span> <span class="mi">108</span><span class="kt">px</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">41</span><span class="cl"><span class="p">}</span>
</span></span></code></pre>
Arrange Kinopio cards2022-07-05T20:17:53Zhttps://ben.prose.sh/2022-06-29-arrange-kinopio-cards<p>I wrote a little <a href="https://deno.land" rel="nofollow">deno</a> script that arranges cards in a
Kinopio space in reverse-chronological order. This is a bud of an idea where I
could use Kinopio as a log with the most recent stuff on top. And this is all
automatically done.</p>
<p>For future:</p>
<ul>
<li>Abstract secrets</li>
<li>Put in repository</li>
<li>Experiment with grid layout</li>
<li>Comment cards are excluded</li>
<li>Comment cards that are connected move relatively with the card it is connected
to. This way I can annotate.</li>
</ul>
<pre class="chroma"><code><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kr">const</span> <span class="nx">jsonResponse</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">fetch</span><span class="p">(</span><span class="s2">"https://api.kinopio.club/space/<space ID>"</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kr">const</span> <span class="nx">spaceJson</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">jsonResponse</span><span class="p">.</span><span class="nx">json</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1">// console.log(spaceJson);
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="kr">const</span> <span class="nx">cards</span> <span class="o">=</span> <span class="nx">spaceJson</span><span class="p">.</span><span class="nx">cards</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="kr">const</span> <span class="nx">sortedCards</span> <span class="o">=</span> <span class="nx">cards</span><span class="p">.</span><span class="nx">sort</span><span class="p">((</span><span class="nx">a</span><span class="o">:</span> <span class="nx">any</span><span class="p">,</span> <span class="nx">b</span><span class="o">:</span> <span class="nx">any</span><span class="p">)</span> <span class="p">=></span> <span class="nx">a</span><span class="p">.</span><span class="nx">createdAt</span> <span class="o"><</span> <span class="nx">b</span><span class="p">.</span><span class="nx">createdAt</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">sortedCards</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="kr">const</span> <span class="nx">patchCard</span> <span class="o">=</span> <span class="kr">async</span> <span class="p">(</span><span class="nx">card</span><span class="o">:</span> <span class="nx">any</span><span class="p">)</span> <span class="p">=></span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"> <span class="kr">const</span> <span class="nx">headers</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Headers</span><span class="p">({</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"> <span class="s2">"Content-Type"</span><span class="o">:</span> <span class="s2">"application/json"</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"> <span class="s2">"Cache-Control"</span><span class="o">:</span> <span class="s2">"must-revalidate, no-store, no-cache, private"</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"> <span class="nx">Authorization</span><span class="o">:</span> <span class="s2">"<API KEY>"</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"> <span class="p">})</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl"> <span class="k">try</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl"> <span class="kr">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">fetch</span><span class="p">(</span><span class="s2">"https://api.kinopio.club/card"</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl"> <span class="nx">method</span><span class="o">:</span> <span class="s2">"PATCH"</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl"> <span class="nx">headers</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl"> <span class="nx">body</span><span class="o">:</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">card</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl"> <span class="p">})</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl"> <span class="kr">await</span> <span class="nx">response</span><span class="p">.</span><span class="nx">json</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl"> <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl"> <span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">error</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">
</span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="kd">let</span> <span class="nx">currentY</span> <span class="o">=</span> <span class="mi">200</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="kr">const</span> <span class="nx">PADDING</span> <span class="o">=</span> <span class="mi">24</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="k">for</span> <span class="p">(</span><span class="kr">const</span> <span class="nx">card</span> <span class="k">of</span> <span class="nx">sortedCards</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl"> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">card</span><span class="p">.</span><span class="nx">id</span><span class="p">,</span> <span class="nx">card</span><span class="p">.</span><span class="nx">y</span><span class="p">,</span> <span class="nx">currentY</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">card</span><span class="p">.</span><span class="nx">x</span> <span class="o">!==</span> <span class="mi">100</span> <span class="o">||</span> <span class="nx">card</span><span class="p">.</span><span class="nx">y</span> <span class="o">!==</span> <span class="nx">currentY</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl"> <span class="nx">patchCard</span><span class="p">({</span> <span class="p">...</span><span class="nx">card</span><span class="p">,</span> <span class="nx">x</span><span class="o">:</span> <span class="mi">100</span><span class="p">,</span> <span class="nx">y</span><span class="o">:</span> <span class="nx">currentY</span> <span class="p">})</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl"> <span class="nx">currentY</span> <span class="o">+=</span> <span class="nx">card</span><span class="p">.</span><span class="nx">height</span> <span class="o">+</span> <span class="nx">PADDING</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl"><span class="p">}</span>
</span></span></code></pre><p>Also here: <a href="https://gist.github.com/bentsai/5014dd575358e7e56d85146aac86a018" rel="nofollow">https://gist.github.com/bentsai/5014dd575358e7e56d85146aac86a018</a></p>
Bible at your fingertips with Raycast2022-07-05T20:17:53Zhttps://ben.prose.sh/2022-06-16-raycast-bible-script<p><a href="raycast.com" rel="nofollow">Raycast</a> is an extremely slick launcher for macOS. It's become a
must-install and handedly replaced Alfred for me.
<a href="https://www.raycast.com/changelog#1.36.0" rel="nofollow">In the past week, they released</a> the
last thing I was missing from Alfred—that is, customizable date snippets.</p>
<p>Combining this launcher with
<a href="https://github.com/covode/bible-fetch" rel="nofollow">bible fetch</a> gives me a powerful way to
retrieve any Bible passage on command, ready to be pasted into an app.</p>
<p><code>⌘-Space</code>, <code>bible<Tab>Ro 5:6-8<Enter></code></p>
<p><img src="/img/bible-fetch-raycast.png" alt=""></p>
<p><code>⌘-V</code></p>
<blockquote>
<p>You see, at just the right time, when we were still powerless, Christ died for
the ungodly. Very rarely will anyone die for a righteous person, though for a
good person someone might possibly dare to die. But God demonstrates his own
love for us in this: While we were still sinners, Christ died for us.</p>
</blockquote>
<p>This smooths out the workflow of having to visit Biblegateway, searching for the
passage, turning off verse numbers, selecting the text, invoking copy.</p>
<p>Here's the
<a href="https://raycastapp.notion.site/Script-Commands-771ff9351bc54ee88fa9c585b7782e22" rel="nofollow">Raycast script command</a>
I wrote that wraps the call to bible fetch and includes some metadata that
Raycast uses:</p>
<pre class="chroma"><code><span class="line"><span class="ln"> 1</span><span class="cl"><span class="cp">#!/bin/bash
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"># Required parameters:</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># @raycast.schemaVersion 1</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"># @raycast.title bible</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1"># @raycast.mode silent</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1"># Optional parameters:</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1"># @raycast.icon 📙</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"># @raycast.argument1 { "type": "text", "placeholder": "reference" }</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="c1"># @raycast.packageName Bible Fetch</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="c1"># Documentation:</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="c1"># @raycast.description Get passage</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="c1"># @raycast.author Ben Tsai</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="c1"># @raycast.authorURL bentsai.org</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl">~/Code/bible-fetch/bible <span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span> <span class="p">|</span> pbcopy
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="nb">echo</span> <span class="s2">"Bible passage copied"</span>
</span></span></code></pre>
New Mac New Stuff2022-07-05T20:17:53Zhttps://ben.prose.sh/2022-06-15-new-mac-new-stuff<p>The time finally came for my PC refresh at work, which meant I could ditch my
2018 13-inch MacBook Pro that was fraught with problems (primary display would
stop working upon sleep, terrible keyboard which I had to get replaced,
non-working TouchID sensor due to terrible keyboard replacement process). Now
I've got a shiny 16-inch M1 MacBook Pro.</p>
<p>Now that I've been a macOS user for 6 years, I've picked up some habits and
preferences. Here are the things I found myself immediately changing from
default settings.</p>
<h2 id="displays"><a class="anchor" href="#displays" rel="nofollow">#</a> Displays</h2>
<p>Crank up the resolution to moar space.</p>
<h2 id="trackpad-and-keyboard"><a class="anchor" href="#trackpad-and-keyboard" rel="nofollow">#</a> Trackpad and Keyboard</h2>
<h3 id="trackpad"><a class="anchor" href="#trackpad" rel="nofollow">#</a> Trackpad</h3>
<ul>
<li><strong>Tracking speed</strong>: One tick from fastest</li>
<li>☑ <strong>Tap to click</strong></li>
</ul>
<h3 id="keyboard"><a class="anchor" href="#keyboard" rel="nofollow">#</a> Keyboard</h3>
<ul>
<li><strong>Key Repeat</strong>: <em>Fast</em> (maximum)</li>
<li><strong>Delay Until Repeat</strong>: <em>Short</em> (shortest)</li>
</ul>
<h3 id="accessibility"><a class="anchor" href="#accessibility" rel="nofollow">#</a> Accessibility</h3>
<h4 id="pointer-control--trackpad-options"><a class="anchor" href="#pointer-control--trackpad-options" rel="nofollow">#</a> Pointer Control → Trackpad Options</h4>
<ul>
<li>☑ <strong>Enable dragging</strong>: three finger drag</li>
</ul>
FaceTime not a good experience2022-07-05T20:17:53Zhttps://ben.prose.sh/2022-06-04-video-calling-the-grandparents<pre><code>Using FaceTime, especially with young kids, is not a good experience. I'm not talking specifically about FaceTime, but
any video conferencing. The camera is not wide enough, so someone's gotta play cameraperson the whole time, or
you prop up the phone at a longer distance. But that is usually not practical, and even if you're sitting
down at a table or something, the screen is not big enough, nor the audio good enough, that keeps the kids engaged. Even with an iPad.
Maybe in the future, we have personal drones that are smart enough to play the camera part.
</code></pre>