<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  
  <title>Peter Bryant</title>
  <subtitle>This is a longer description about your blog.</subtitle>
  <link href="https://ptrbrynt.com/feed.xml" rel="self" />
  <link href="https://ptrbrynt.com/" />
  <updated>2026-06-18T08:42:00Z</updated>
  <id>https://ptrbrynt.com/</id>
  <author>
    <name>Peter Bryant</name>
    <email>pb@ptrbrynt.com</email>
  </author>
  <entry>
    <title>Saying goodbye to my first car</title>
    <link href="https://ptrbrynt.com/posts/saying-goodbye-to-my-first-car/" />
    <updated>2026-06-18T08:42:00Z</updated>
    <id>https://ptrbrynt.com/posts/saying-goodbye-to-my-first-car/</id>
    <content type="html">&lt;p&gt;Today is an exciting day — I&#39;m picking up a new car! But of course that means giving up the old one. And this is a new experience for me.&lt;/p&gt;
&lt;p&gt;My current car was my very first. I learned to drive (finally) in 2023, and was extremely excited to pick up my little white Yaris after passing my test. 40,000 miles later, we&#39;ve been on so many adventures together — it drove me to my wedding, my father&#39;s funeral, and countless trips to airports, beaches, countryside walks, family visits, quartet rehearsals, and so much more.&lt;/p&gt;
&lt;p&gt;Through it all, the Yaris has been reliable and trustworthy. I drove it to Sheffield and back yesterday for my final journey, and I have to say I felt a tinge of sadness as I pulled the car into my driveway for the last time.&lt;/p&gt;
&lt;p&gt;I will own many cars in my lifetime, and they will all take me on lots of adventures. But my little white Yaris was, and always will be, my first car. And as excited as I am for my upgrade, I will miss the lil guy.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Could I really make something every day?</title>
    <link href="https://ptrbrynt.com/posts/could-i-really-make-something-every-day/" />
    <updated>2026-06-02T15:27:00Z</updated>
    <id>https://ptrbrynt.com/posts/could-i-really-make-something-every-day/</id>
    <content type="html">&lt;p&gt;Really enjoyed listening to Monday’s &lt;a href=&quot;https://www.theverge.com/podcast/941140/casey-neistat-daily-vergecast&quot;&gt;Vergecast&lt;/a&gt;, which is notable in that it’s the first episode of the new daily format. And it’s a super fun way to start this: David, our wonderful and perpetually self-doubting host, is asking the master of daily creativity, Casey Neistat, for advice.&lt;/p&gt;
&lt;p&gt;Casey has inspired me for years. I remember watching his daily vlogs back in the day, and I’m thrilled to see him posting more frequently again. And I think the reason I love watching Casey is that I find his style of filmmaking so impressive; that is, I can’t quite comprehend how it’s possible.&lt;/p&gt;
&lt;p&gt;I watch the videos and think, “Hang on, how did he get that shot? Did he literally get into the subway car, put his camera down, get off again, then film himself getting back on? What happens if the door closes and he loses his camera? What if someone takes it? How many takes did he need to do before he got the shot?”&lt;/p&gt;
&lt;p&gt;For one thing, Casey is braver than me. He’s not afraid to draw attention to himself in public. He’s not afraid to film his friends and family (within certain boundaries). And he’s not afraid of hard work.&lt;/p&gt;
&lt;p&gt;The primary emotion I feel when I watch Casey is jealousy. But in a good, healthy way! I really aspire to be more like him, and I was inspired hearing him talk about how his daily video schedule created a constraint that allowed him to thrive.&lt;/p&gt;
&lt;p&gt;There are so many creative projects — making videos, songwriting/arranging, podcasting, writing poetry — on my “someday/maybe” list, but I’m scared that I don’t have the tools or the skills or the talent. Maybe a commitment to making something — &lt;em&gt;anything&lt;/em&gt; — every single day could be helpful. But it also sounds stressful as hell.&lt;/p&gt;
&lt;p&gt;In situations like this — where I want to do something that someone else does — I have to step back and think about their privileges. Casey can make a video every day because &lt;em&gt;that is his job&lt;/em&gt; (or one of them, at least). I already have enough on my plate. But is that also an excuse.&lt;/p&gt;
&lt;p&gt;I don’t feel like I’ve come to any conclusions here. But it’s certainly fun to dream about.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Running update: I am a moron</title>
    <link href="https://ptrbrynt.com/posts/running-update-i-am-a-moron/" />
    <updated>2026-06-02T09:35:00Z</updated>
    <id>https://ptrbrynt.com/posts/running-update-i-am-a-moron/</id>
    <content type="html">&lt;p&gt;I &lt;a href=&quot;https://ptrbrynt.com/posts/running-might-not-be-for-me/&quot;&gt;recently wrote&lt;/a&gt; that running might not be for me. Well, I have discovered that I was just being a moron.&lt;/p&gt;
&lt;p&gt;My interest in running was piqued again when I heard folks online talking about Zone 2 training:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Zone 2 is a low- to moderate-intensity cardio effort, where you&#39;re working hard enough to raise your heart rate, but not so hard that you can&#39;t hold a conversation. It&#39;s roughly 60-70% of your maximum heart rate.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now, I&#39;m aware of &lt;a href=&quot;https://www.youtube.com/watch?v=--c3jT8R_VA&quot;&gt;the issues&lt;/a&gt; related to the online proliferation of Zone 2 training, but if you look past the hype, there are real benefits. It may not be the most physically optimal way to exercise, but it has helped a lot of regular folks stay more consistent, avoid injury, and enjoy exercise more.&lt;/p&gt;
&lt;p&gt;The other day, I decided to go out for a run and try to stick to Zone 2. I was &lt;em&gt;shocked&lt;/em&gt; at how difficult it was to run slowly enough to keep my heart rate down. It was a bit of a &amp;quot;eureka&amp;quot; moment for me: &lt;strong&gt;this whole time, I have been going way too fast and way too hard.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This morning, I ran just over 2km, trying again (and failing) to stick to Zone 2. But this approach is freeing: I now have permission to go slowly, at my own pace.&lt;/p&gt;
&lt;p&gt;I&#39;m happy about this, because for the longest time I have wanted to include running in my weekly routine. So this might be how it finally happens for me.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;In an effort to keep myself accountable, I&#39;ve started an &lt;a href=&quot;https://ptrbrynt.com/exercise-log/&quot;&gt;Exercise Log&lt;/a&gt; page where I will track my workouts.&lt;/em&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Behold the recursive number to Roman numeral converter</title>
    <link href="https://ptrbrynt.com/posts/behold-recursive-roman-numeral-converter/" />
    <updated>2026-05-14T16:05:00Z</updated>
    <id>https://ptrbrynt.com/posts/behold-recursive-roman-numeral-converter/</id>
    <content type="html">&lt;p&gt;I just read &lt;a href=&quot;https://sava.rocks/blog/behold-the-number-to-roman-numeral-converter/&quot;&gt;this post&lt;/a&gt; on how to convert a number to a Roman numeral. The post outlines an iterative method, which works and is very fun.&lt;/p&gt;
&lt;p&gt;It got me thinking though. I&#39;ve always had a strange interest in recursive algorithms. There is something very satisfying to me about writing a recursive method that works.&lt;/p&gt;
&lt;p&gt;If you don&#39;t know or need a reminder, a &lt;em&gt;recursive&lt;/em&gt; algorithm is one which &lt;em&gt;calls itself&lt;/em&gt;. A famous example is the Fibonacci sequence, which computes the value of the next number in the sequence by adding up the previous two. If you know the sequence starts with a pair of 1s, then it&#39;s pretty easy to write a recursive function which can compute the &lt;em&gt;n&lt;/em&gt;th value in the sequence:&lt;/p&gt;
&lt;pre class=&quot;language-dart&quot;&gt;&lt;code class=&quot;language-dart&quot;&gt;int &lt;span class=&quot;token function&quot;&gt;fib&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;int n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; n &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fib&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fib&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So I wondered whether it was possible to convert something to Roman numerals recursively. Turns out, it super is and I love it.&lt;/p&gt;
&lt;pre class=&quot;language-dart&quot;&gt;&lt;code class=&quot;language-dart&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; romanSymbols &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token generics&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;M&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token number&quot;&gt;900&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;CM&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;D&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token number&quot;&gt;400&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;CD&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;C&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token number&quot;&gt;90&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;XC&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;L&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token number&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;XL&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;X&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;IX&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;V&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;IV&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;I&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;RomanNumerals&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;on&lt;/span&gt; int &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; asRomanNumerals &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; value &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; romanSymbols&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keys&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; romanSymbols&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;asRomanNumerals&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You call this by doing &lt;code&gt;10.asRomanNumerals&lt;/code&gt;, and it works!&lt;/p&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Disclosure: I was struggling to write this walkthrough so I asked Claude for some help.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The code has two parts:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The symbol map&lt;/strong&gt; defines every meaningful Roman numeral value — not just the obvious ones like 1000 (M), 500 (D), 100 (C), etc., but also the subtractive combinations like 900 (CM), 400 (CD), and 9 (IX). These are the cases where a smaller symbol placed before a larger one means &amp;quot;subtract&amp;quot;, so rather than handling that as special logic, they&#39;re just baked directly into the map as their own entries. The map is ordered from largest to smallest, which is key to how the conversion works.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The extension&lt;/strong&gt; adds an &lt;code&gt;asRomanNumerals&lt;/code&gt; property to every integer in Dart, so you can call something like &lt;code&gt;2024.asRomanNumerals&lt;/code&gt; directly. When called, it walks through the map from largest value to smallest, and as soon as it finds a value that fits into the current number, it takes that Roman symbol and calls itself recursively on whatever is left over. For example, 14 is greater than 10, so it takes &amp;quot;X&amp;quot; and recurses on 4 — which matches &amp;quot;IV&amp;quot; — giving &amp;quot;XIV&amp;quot;. This repeats until the number has been fully accounted for and nothing remains.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I built this as a little command-line application — source code is &lt;a href=&quot;https://github.com/ptrbrynt/roman_numerals&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I love making silly things like this with code. It reminds me of why I got into it in the first place.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>What are your Top Three?</title>
    <link href="https://ptrbrynt.com/posts/what-are-your-top-three/" />
    <updated>2026-05-09T07:34:00Z</updated>
    <id>https://ptrbrynt.com/posts/what-are-your-top-three/</id>
    <content type="html">&lt;p&gt;I just read &lt;a href=&quot;https://www.vzqk50.com/blog/eating-its-nice/&quot;&gt;Eating: It’s Nice&lt;/a&gt; by Apis Necros, and there’s an excellent quote here:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The Top Three things you care about are where most of your attention is going to go, and you only have so much attention to give. So give yourself grace, and accept that some things may not be as important to you as you may think.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is &lt;em&gt;so smart&lt;/em&gt;. I see it as a slightly more concrete version of Oliver Burkeman’s &lt;a href=&quot;https://www.oliverburkeman.com/books&quot;&gt;&lt;em&gt;4000 Weeks&lt;/em&gt;&lt;/a&gt; message, which says that our time is even more finite than we like to think. As a result, we can’t just sacrifice stuff we &lt;em&gt;don’t&lt;/em&gt; want to do; we also have to compromise on some of the things we really &lt;em&gt;do&lt;/em&gt; want to do.&lt;/p&gt;
&lt;p&gt;At any given time, I can tell myself that I really care about any of the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Health&lt;/li&gt;
&lt;li&gt;Making music (choirs, quartets, coaching)&lt;/li&gt;
&lt;li&gt;Making time for friends &amp;amp; family&lt;/li&gt;
&lt;li&gt;My job&lt;/li&gt;
&lt;li&gt;Side projects&lt;/li&gt;
&lt;li&gt;Volunteering (primarily choir committee)&lt;/li&gt;
&lt;li&gt;Cooking&lt;/li&gt;
&lt;li&gt;Fitness&lt;/li&gt;
&lt;li&gt;Writing&lt;/li&gt;
&lt;li&gt;Mindfulness&lt;/li&gt;
&lt;li&gt;Reading&lt;/li&gt;
&lt;li&gt;Entertainment (games, TV, movies etc.)&lt;/li&gt;
&lt;li&gt;A million other interests that don’t come to mind right now&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It’s probably helpful to reflect every so often on what my Top Three areas of attention are at the moment, and whether that’s different from what I’d like them to be.&lt;/p&gt;
&lt;p&gt;Right now, I feel like I’m paying most attention to, in no particular order:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Making music&lt;/li&gt;
&lt;li&gt;Volunteering&lt;/li&gt;
&lt;li&gt;Entertainment&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Honestly, this probably changes at least every couple of weeks, but this is where I am right now, on 9th May 2026. And it feels about right to me for now.&lt;/p&gt;
&lt;p&gt;Do I wish I had more energy to focus on other things? Yes. In particular, I feel like I’m &lt;a href=&quot;https://ptrbrynt.com/posts/running-might-not-be-for-me/&quot;&gt;neglecting Fitness&lt;/a&gt; at the moment. But I can’t do everything all the time. Am I really prepared to sacrifice any of my current Top Three to make more time for Fitness? Probably not!&lt;/p&gt;
&lt;p&gt;It’s pretty hard to accept that I might not have the capacity for everything I want to do. And it’s the sort of thing I will need to remind myself about frequently. Perhaps I can build in a “Top Three” reflection into my weekly/monthly review rituals. If nothing else, it’s a great exercise in humility, and being kind to myself.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Running might not be for me, and that makes me sad</title>
    <link href="https://ptrbrynt.com/posts/running-might-not-be-for-me/" />
    <updated>2026-05-08T12:13:00Z</updated>
    <id>https://ptrbrynt.com/posts/running-might-not-be-for-me/</id>
    <content type="html">&lt;p&gt;We’ve just had the London Marathon here in the UK, and I was reminded that seeing people run really inspires me.&lt;/p&gt;
&lt;p&gt;It’s the kind of thing which can be done by literally anyone, anywhere, with no equipment save for a comfortable pair of trainers. And there’s something extremely romantic about the idea of doing a bunch of miles first thing in the morning, no matter where you happen to be in the world, Casey Neistat-style.&lt;/p&gt;
&lt;p&gt;Every so often, I get sufficiently inspired that I start to do morning runs. I get up, get dressed, and head out pretty much immediately. I’ve been able to keep this going for at most a few weeks, but I inevitably fall off the wagon. The habit is very fragile; it can easily be interrupted by travel, or simply by me deciding that I don’t feel like it on a particular day.&lt;/p&gt;
&lt;p&gt;This just happened again recently, and I’m starting to wonder whether it’s worth continuing to beat this horse. Maybe running just isn’t for me.&lt;/p&gt;
&lt;p&gt;I think this makes me sad, because I really want to reach the destination of this journey. I want to feel fitter and more energetic. I want to have exercise be a central part of my daily routine. I want to be able to run a few miles, every day, anywhere. I want to be a runner.&lt;/p&gt;
&lt;p&gt;The problem is that the journey is not sufficiently compelling for me. And no matter how desirable the destination is, you’ll never do the work to get there if you’re not motivated by the work itself.&lt;/p&gt;
&lt;p&gt;I actually don’t enjoy running. I always feel groggy and terrible first thing in the morning, and it takes huge mental effort to even talk myself into doing it. Then I do it, and I run for less than 15 minutes before I’ve had enough.&lt;/p&gt;
&lt;p&gt;Couple that with the weather where I live: more often than not it’s really cold outside in the morning. And it rains sometimes.&lt;/p&gt;
&lt;p&gt;All this — the fact that I find it hard to start, I’m not very good at it, and it’s overall an unpleasant experience — is frankly enough to make me wonder why I bother. Unlike Odysseus, I don’t care enough about the destination to endure the journey.&lt;/p&gt;
&lt;p&gt;“But Peter,” I hear you say. “Can’t you just run at a different time of day when you feel more up to it and the weather is better?” Sure. But then I have to take time out of my day to do that, and I’ve got enough on. Plus, I’m a morning shower person, but I have to shower after a run, so now do I shower twice a day? Or do I stop showering in the morning and feel gross? Trust me, dearest gentle reader, I have (over)thought this through.&lt;/p&gt;
&lt;p&gt;The thing is, I do need to do more cardio. I’m aware of the benefits. But I need to do something that works for me. I just don’t know what that is yet.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>I rebuilt my blog all by myself</title>
    <link href="https://ptrbrynt.com/posts/i-rebuilt-my-blog-all-by-myself/" />
    <updated>2026-05-01T09:10:00Z</updated>
    <id>https://ptrbrynt.com/posts/i-rebuilt-my-blog-all-by-myself/</id>
    <content type="html">&lt;p&gt;I&#39;m officially a self-built blogger.&lt;/p&gt;
&lt;p&gt;Previously, I was using &lt;a href=&quot;https://pika.page&quot;&gt;Pika&lt;/a&gt;, and I cannot overstate how awesome that product is. I really loved using it, and I found it hard to tear myself away. If you&#39;re starting an indie blog/newsletter in 2026, I would really urge you to consider Pika.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Having said that&lt;/em&gt;, I am a tinkerer at heart. And, having seen so many wonderful hand-built websites on the indie web, I had to scratch my itch.&lt;/p&gt;
&lt;p&gt;What you&#39;re now looking at is my brand-new, hand-built blog website.&lt;/p&gt;
&lt;h2 id=&quot;what-i-used&quot;&gt;What I used&lt;/h2&gt;
&lt;p&gt;The website is built using a static site generator called &lt;a href=&quot;https://11ty.dev&quot;&gt;Eleventy (11ty)&lt;/a&gt;. It&#39;s great, once you get over the learning curve. I love that I can write my blog posts and pages using Markdown &lt;em&gt;or&lt;/em&gt; HTML. It&#39;s super lightweight, and I&#39;m very happy with it so far.&lt;/p&gt;
&lt;p&gt;Continuing the lightweight theme, I used Pico CSS, which provides a very minimal set of components and styles to get you started. I&#39;ve customised it with a few layout choices of my own. Look at me writing CSS!&lt;/p&gt;
&lt;p&gt;This was my first time rolling my own RSS feed (thanks to &lt;a href=&quot;https://brandonrozek.com&quot;&gt;Brandon Rozek&lt;/a&gt; for a great tip on how to get RSS readers to easily discover my feed using a &lt;code&gt;link&lt;/code&gt; tag). Everything seems to have worked okay so far!&lt;/p&gt;
&lt;p&gt;If you discover any issues or bugs, please do &lt;a href=&quot;mailto:pb@ptrbrynt.com&quot;&gt;email me&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;In the meantime, I&#39;m very excited about the new version of my blog site. Again, huge thanks to the folks over at Pika for supporting me so well — I will miss you!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Re: Who knows that you blog?</title>
    <link href="https://ptrbrynt.com/posts/re-who-knows-that-you-blog/" />
    <updated>2026-04-30T09:01:00Z</updated>
    <id>https://ptrbrynt.com/posts/re-who-knows-that-you-blog/</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;https://forkingmad.blog/who-knows-that-you-blog/&quot;&gt;This post&lt;/a&gt; has sparked an interesting discussion online, and it happens to be something I think about a lot.&lt;/p&gt;
&lt;p&gt;When I joined Threads, something I didn’t really anticipate was that — thanks to its connection to Instagram — my real-life friends and family would follow me there. This was a new thing for a short-form micro-blogging platform. On other platforms like Twitter, Bluesky, Mastodon etc I felt a sense of insulation from my non-digital world. I had an internet identity which was distinct from my persona in “real life”.&lt;/p&gt;
&lt;p&gt;So, because I would often post links to new blog posts on Threads, my friends and family started talking to me about my blog. My mum read my posts. And I found this supremely uncomfortable. (If you are reading this, Mum, it’s fine! You can keep reading my blog.)&lt;/p&gt;
&lt;p&gt;I wonder how much of this is a generational thing. My relationship with the internet started when I was relatively young — let’s say in my early teens. When you’re that age, the real world is extremely complicated, challenging, and often upsetting. I used the internet as a refuge. And perhaps somewhere in my consciousness, that’s how I think about it still.&lt;/p&gt;
&lt;p&gt;Contrast that with someone younger than me, who grew up when the internet was already a part of mainstream life. For Gen Z, going online wasn’t an escape from the real world; it &lt;em&gt;was&lt;/em&gt; the real world. Equally, for someone older than me, they maybe didn’t start using the internet until they were into their adulthood, so it wasn’t an escape from reality for them either; they had found other ways to navigate the world as teens. I really wonder whether us Millennials are uniquely placed to have this experience.&lt;/p&gt;
&lt;p&gt;My “real world” life is, thankfully, much happier than it was when I was 12. But I do maintain a sense that “internet Peter” is actually a different person to “physical Peter”, and there’s a real discomfort in the idea that those two worlds might collide.&lt;/p&gt;
&lt;p&gt;I don’t fully understand the psychology behind all this, but it seems like my experience is not unique amongst bloggers. I’m utterly fascinated by it all.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>How I use my phone for good, not evil</title>
    <link href="https://ptrbrynt.com/posts/how-i-use-my-phone-for-good-not-evil/" />
    <updated>2026-04-27T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/how-i-use-my-phone-for-good-not-evil/</id>
    <content type="html">&lt;p&gt;Phones get a lot of bad press these days, and many people feel addicted to them. But it seems pretty clear to me that the phones aren&#39;t the problem; it&#39;s social media.&lt;/p&gt;
&lt;p&gt;It&#39;s perfectly possible to have a phone and use non-harmful software on it. For me, my phone is an extremely useful tool, as well as a source of entertainment and enrichment.&lt;/p&gt;
&lt;p&gt;Here are a few ways I use my phone to &lt;em&gt;improve&lt;/em&gt; my life.&lt;/p&gt;
&lt;h2 id=&quot;1-reading-independent-writing&quot;&gt;1. Reading independent writing&lt;/h2&gt;
&lt;p&gt;I&#39;m trying to be a more active participant in the &amp;quot;IndieWeb&amp;quot;. To this end, I use my phone to read blogs, primarily using RSS and the &lt;a href=&quot;https://netnewswire.com/&quot;&gt;NetNewsWire&lt;/a&gt; app. I also use &lt;a href=&quot;https://obsidian.md&quot;&gt;Obsidian&lt;/a&gt; to write posts, although I much prefer typing on my laptop.&lt;/p&gt;
&lt;p&gt;To me, independent websites are the best of the internet. I love connecting with other bloggers, and having a place to share my thoughts which is not beholden to any algorithms or advertising.&lt;/p&gt;
&lt;p&gt;A bunch of exciting tools and services are cropping up around this (such as &lt;a href=&quot;https://bubbles.town/&quot;&gt;Bubbles&lt;/a&gt;). I really do think blogs are back.&lt;/p&gt;
&lt;h2 id=&quot;2-tracking-nutrition&quot;&gt;2. Tracking nutrition&lt;/h2&gt;
&lt;p&gt;I struggle to manage my weight (thanks to Crohn&#39;s disease), but my current thesis is that if I arm myself with as much information as possible, I can attempt to make informed changes. That&#39;s where nutrition tracking comes in.&lt;/p&gt;
&lt;p&gt;I want to be very clear here — nutrition tracking is not for everyone, and I can absolutely see how it could lead to disordered eating or eating disorders (different things, a fact I recently learned from &lt;a href=&quot;https://www.theverge.com/features/907359/cgms-optimizing-metabolism-dexcom-abbott-wearables-health-tech#:~:text=disordered%20eating%20or%20eating%20disorders&quot;&gt;Victoria Song&lt;/a&gt; at &lt;em&gt;The Verge&lt;/em&gt;). &lt;/p&gt;
&lt;p&gt;But deployed with the right mindset, I am starting to see the benefits of tracking my nutrition after only a few weeks. My goals are to eat more mindfully, to develop a better intuition of how the food I eat impacts my health, and to learn how I can make better choices.&lt;/p&gt;
&lt;p&gt;I&#39;ve used a bunch of different services for this over the years including &lt;a href=&quot;https://foodnoms.com/&quot;&gt;FoodNoms&lt;/a&gt; and &lt;a href=&quot;https://lifesum.com/&quot;&gt;Lifesum&lt;/a&gt;, but the one I&#39;m using right now is &lt;a href=&quot;https://www.alma.food/&quot;&gt;Alma&lt;/a&gt;. This works great for me for the simple reason that it has the fastest data input method: I can literally take a photo of my food, and provide a very brief description, then let Alma&#39;s AI figure out the rest.&lt;/p&gt;
&lt;p&gt;Clearly this isn&#39;t going to be as accurate as other methods but, for me at least, anything that reduces friction is worth the tradeoff here so I can maintain the habit. Alma also has an AI diet coach which has provided some useful insights (but should be taken with a pinch of salt).&lt;/p&gt;
&lt;p&gt;Alma is pretty expensive, but I&#39;ve signed up for an annual subscription as an extra incentive to give it a really thorough try.&lt;/p&gt;
&lt;h2 id=&quot;3-doing-puzzles&quot;&gt;3. Doing puzzles&lt;/h2&gt;
&lt;p&gt;I &lt;em&gt;love&lt;/em&gt; doing the daily &lt;a href=&quot;https://www.nytimes.com/crosswords&quot;&gt;New York Times crosswords&lt;/a&gt;, and other puzzles. It&#39;s a great way to fill time, and it&#39;s impossible to get addicted because you can stop when you&#39;ve completed the day&#39;s puzzles.&lt;/p&gt;
&lt;p&gt;On it&#39;s face, my screen time has increased considerably since I started doing the crossword, but I do believe that not all screen time is created equal. I&#39;m pretty confident that 45-60 minutes a day spent doing brain puzzles is much better than the same amount of time mindlessly doomscrolling.&lt;/p&gt;
&lt;h2 id=&quot;4-podcasts&quot;&gt;4. Podcasts&lt;/h2&gt;
&lt;p&gt;I thought I&#39;d throw this one in here, partly as a shameless plug for my podcast app &lt;a href=&quot;https://crestpodcasts.com&quot;&gt;Crest&lt;/a&gt;, but also as a plug for podcasting in general. Although if you&#39;re reading this, it&#39;s unlikely that you need me to sell you on how awesome podcasts are (or you&#39;ve already decided they&#39;re not for you). If you want recommendations, my subscriptions are available on my &lt;a href=&quot;https://ptrbrynt.com/podroll&quot;&gt;Podroll&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;5-meditation&quot;&gt;5. Meditation&lt;/h2&gt;
&lt;p&gt;One of my quests for the Spring is to develop a consistent meditation habit. Previously, I think I&#39;ve been scuppered by the apps and services I&#39;ve been using. I&#39;ve tried all the usual suspects — Headspace, Apple Fitness+, Balance, (10 Percent) Happier etc. — but I&#39;ve found them all to be too burdensome. They&#39;re expensive, and they provide you with way too many options.&lt;/p&gt;
&lt;p&gt;I just want to open the app and start a session without having to make any decisions. I don&#39;t want sponsored content or brand deals, and I&#39;m not super interested in following a prescribed course.&lt;/p&gt;
&lt;p&gt;The app I&#39;ve found recently which works great is &lt;a href=&quot;https://meditofoundation.org/&quot;&gt;Medito&lt;/a&gt;. I like it for a few reasons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;It&#39;s non-profit, ad-free, supported by donations&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can open it, and tap a couple of buttons to start your daily session, without having to rifle through a massive catalog&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can customise the duration of each session, select from 3 excellent speakers, and customise the background sounds&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Overall, it&#39;s just as solid as any of the usual suspects, and you don&#39;t have to pay a penny.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;If you&#39;ve read this, I&#39;d love it if you &lt;a href=&quot;mailto:pb@ptrbrynt.com&quot;&gt;emailed me&lt;/a&gt; with more &amp;quot;phone for good, not evil&amp;quot; ideas and suggestions.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Privacy should not be a privilege</title>
    <link href="https://ptrbrynt.com/posts/privacy-should-not-be-a-privilege/" />
    <updated>2026-04-25T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/privacy-should-not-be-a-privilege/</id>
    <content type="html">&lt;p&gt;Loved reading &lt;a href=&quot;https://blog.avas.space/privacy-stuff/&quot;&gt;this post&lt;/a&gt; by Ava. It sums up really well how I feel about “privacy-focused” alternatives to popular software and services. It’s great that these alternatives exist, but we can’t think of them as a solution to the privacy problem.&lt;/p&gt;
&lt;p&gt;I also view it through the following lens: &lt;strong&gt;we currently live in a world in which your level of protection on the internet is a function of certain types of privilege&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;These include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Economic privilege, with which you are able to pay directly for services (or self-hosting) rather than relying on the mainstream ad-supported options&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Time privilege, with which you can set up and maintain the software you want to use. Much of it is higher-maintenance than the mainstream options, and you may end up switching more often as the services come and go&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Knowledge/skills privilege, with which you can overcome the technical barriers one faces when setting up and using a privacy-focused alternative&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Education privilege, with which you are able to understand the problem and know about the alternatives in the first place&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are probably others; this is just what comes to mind right now.&lt;/p&gt;
&lt;p&gt;I guess my point is that, if we want to &lt;em&gt;actually&lt;/em&gt; solve the privacy problems we have on the internet, we can’t just ask individual consumers to run away to alternative services. We have to address the problem at its root, by introducing practical and effective regulatory measures which shift the incentive structures for these companies. Right now, it’s more economically beneficial for these companies not to bother with proper privacy protection. Until the scales balance the other way, nothing will meaningfully change for the vast majority of internet users.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>I made a podcast app which doesn’t judge me</title>
    <link href="https://ptrbrynt.com/posts/i-made-a-podcast-app-which-doesnt-judge-me/" />
    <updated>2026-03-02T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/i-made-a-podcast-app-which-doesnt-judge-me/</id>
    <content type="html">&lt;p&gt;I hate that this was necessary. But I’m very pleased with the outcome.&lt;/p&gt;
&lt;p&gt;Let’s start here: &lt;strong&gt;I love podcasts.&lt;/strong&gt; I have listened to podcasts for as long as I have had access to them. I’ve even &lt;a href=&quot;https://open.spotify.com/show/0sYnIuLvXgCFhQ9Yek6bYR&quot;&gt;made&lt;/a&gt; a &lt;a href=&quot;https://www.fluttertwattle.com/&quot;&gt;few&lt;/a&gt; &lt;a href=&quot;https://www.singbarbershop.com/pages/podcast&quot;&gt;podcasts&lt;/a&gt;. Podcasts are awesome.&lt;/p&gt;
&lt;p&gt;But recently, I’ve had a niggling sense that I wasn’t enjoying them any more. They’d stopped being entertainment, and had turned into something else. Something less fun.&lt;/p&gt;
&lt;p&gt;A recent (and very good) &lt;a href=&quot;https://www.terrygodier.com/phantom-obligation&quot;&gt;essay&lt;/a&gt; by Terry Godier brought this feeling into sharp focus. The feeling I was experiencing was &lt;strong&gt;phantom obligation&lt;/strong&gt; : the sense that my podcast queue was constantly piling up in the background, and that I was a bad person if I failed to keep up.&lt;/p&gt;
&lt;p&gt;In the past, my solution to this has been to listen to fewer shows. And that sucks, because I love podcasts! I want a big library full of fun, interesting stuff. But I also don’t care if I miss an episode here or there. I’m interested in variety, not completionism.&lt;/p&gt;
&lt;p&gt;I wanted to find a piece of software which thinks about podcasts the way I do.&lt;/p&gt;
&lt;h2 id=&quot;the-existing-options&quot;&gt;The existing options&lt;/h2&gt;
&lt;p&gt;Apple Podcasts is shockingly bad at this. Here are a few issues I’ve discovered:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Opening the app presents you not only with your own queue, but an overwhelmingly infinite list of other things you haven’t listened to but definitely should because they’re popular&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;New episodes get added to the &lt;strong&gt;front&lt;/strong&gt; of your queue, meaning that episode you’ve been trying to get to for days keeps getting pushed further and further down&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you listen to one episode from a show — even if you don’t subscribe — it will start queueing new episodes of that show&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It’s impossible to keep track of what’s queued, what’s saved, or what’s downloaded&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As an Apple Podcasts user of many years, these realisations led me to rage-quit and look for alternatives.&lt;/p&gt;
&lt;p&gt;I tried Pocket Casts, which I used and enjoyed many years ago but whose vibe has become… odd since their acquisition. I just don’t &lt;em&gt;like&lt;/em&gt; using that app. Plus it’s kinda buggy (especially the macOS version) and has looked the same for a very long time.&lt;/p&gt;
&lt;p&gt;I also tried an indie app called Queue, which I actually really enjoyed until I realised that the queueing behaviour was weird (again, new stuff goes to the top for some reason), and the app was  buggy.&lt;/p&gt;
&lt;p&gt;Overcast is too fiddly and not very pretty. And the countless other podcast apps on the App Store seem dubious in various ways. Do I trust them with my data? Do I have to stare at ads while I use them? Do they just look kinda &lt;em&gt;bad&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;A few weeks ago, I came to the conslusion that if nobody was going to fix my problems for me, I should pick up the tools and very well fix them myself.&lt;/p&gt;
&lt;h2 id=&quot;how-i-approached-it&quot;&gt;How I approached it&lt;/h2&gt;
&lt;p&gt;Again, my inspiration for this app was very much inspired by Terry Godier’s essay, which eventually turned into an RSS reader called &lt;a href=&quot;https://www.terrygodier.com/current&quot;&gt;Current&lt;/a&gt;. Current uses very similar metaphors to my app, and I like it very much.&lt;/p&gt;
&lt;p&gt;Here’s what I was aiming for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;I never want to feel overwhelmed when I open the app&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I want to be able to open it and hit play, and not be surprised by what I hear&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I don’t want episodes to pile up like a to-do list; I want them to flow like a river. In other words, the app should be allowed to remove stale stuff from my queue without asking&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I want it to be private, non-predatory, and just generally good vibes&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-i-built&quot;&gt;What I built&lt;/h2&gt;
&lt;p&gt;So here it is. It’s called &lt;em&gt;Crest&lt;/em&gt;, and the first thing you see when you open it is the Now Playing screen.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/i-made-a-podcast-app-which-doesnt-judge-me/bKMSzxLdXB-1470.webp 1470w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/i-made-a-podcast-app-which-doesnt-judge-me/bKMSzxLdXB-1470.jpeg&quot; alt=&quot;The home screen of Crest, displaying an in-progress episode of The Vergecast.&quot; width=&quot;1470&quot; height=&quot;3000&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;This is very much &lt;em&gt;not&lt;/em&gt; an overwhelming welcome. You don’t get served with a massive queue, or any recommendations. Just the thing that’s relevant &lt;em&gt;right now&lt;/em&gt;: a big Play button.&lt;/p&gt;
&lt;h3 id=&quot;the-queue&quot;&gt;The Queue&lt;/h3&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/i-made-a-podcast-app-which-doesnt-judge-me/3V45rueItz-1470.webp 1470w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/i-made-a-podcast-app-which-doesnt-judge-me/3V45rueItz-1470.jpeg&quot; alt=&quot;A screenshot showing the Queue screen of the Crest app.&quot; width=&quot;1470&quot; height=&quot;3000&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;I’m proud of how this queue works, but it’s pretty complicated. My instinct when building software is to avoid complexity, particularly when it’s behaviour that happens automatically. But then I remembered that the whole point of this app was that it would do the queue management for me.&lt;/p&gt;
&lt;p&gt;So I decided that complexity is fine, as long as it’s transparent and understandable. To that end, I’ve included an entire screen which explains — in great detail — how the Queue works.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/i-made-a-podcast-app-which-doesnt-judge-me/SeDXp9Pgw1-1470.webp 1470w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/i-made-a-podcast-app-which-doesnt-judge-me/SeDXp9Pgw1-1470.jpeg&quot; alt=&quot;A screenshot showing the &amp;quot;How Queueing Works&amp;quot; screen of the Crest app.&quot; width=&quot;1470&quot; height=&quot;3000&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;In general, the automatic behaviour is designed to be set-and-forget. By default, each show is only allowed &lt;strong&gt;one spot&lt;/strong&gt; in the queue. If a new episode is released, it replaces any episodes of that show which are currently in the queue (unless it’s currently playing). Episodes also get added to the &lt;strong&gt;end&lt;/strong&gt; of the queue by default.&lt;/p&gt;
&lt;p&gt;Each show gets its own settings, so you can customise:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;How many episodes are allowed in the queue at once&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Whether new episodes get added to the start or end of the queue&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Whether to automatically expire episodes after a certain time limit (great for news shows which go out-of-date very quickly)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And, of course, you can manually manage your queue in a few ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Reorder episodes however you want&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Mark as Played&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Release — remove from the queue without marking as played&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a class=&quot;footnote-ref&quot; data-id=&quot;7fb759a6-1501-4eed-99ce-5aaa3832f7a9&quot; href=&quot;https://ptrbrynt.com/posts/i-made-a-podcast-app-which-doesnt-judge-me/#fn:1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Save — prevent the app from automatically removing&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Episodes of subscribed shows can also be manually added to the queue, but this won’t affect anything that happens in the future. The app won’t suddenly start queueing stuff up you didn’t ask for. Because &lt;em&gt;that would be insane.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;private-by-design&quot;&gt;Private by design&lt;/h3&gt;
&lt;p&gt;All your data is stored on your phone.&lt;/p&gt;
&lt;p&gt;That’s pretty much the entire privacy policy. The tradeoff is, of course, that you don’t get cross-device sync.&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a class=&quot;footnote-ref&quot; data-id=&quot;3dd52f31-4e39-4355-a48c-9ad0461849bb&quot; href=&quot;https://ptrbrynt.com/posts/i-made-a-podcast-app-which-doesnt-judge-me/#fn:2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; This was a hard decision but, for me at least, the pros outweight the cons. I do 95% of my podcast listening time on my phone, so moving the final 5% (which was on my Mac while working) won’t be too difficult. That’s what AirPlay and wireless headphones are for, I guess.&lt;/p&gt;
&lt;p&gt;There &lt;em&gt;is&lt;/em&gt; a small caveat, which is that I wanted product analytics. So when you start the app, I ask if you want to opt in. If so, I collect anonymous usage. If not, I’ll never bother you about it again (unless you want to go into Settings and turn it on).&lt;/p&gt;
&lt;p&gt;Why is there analytics? To be honest, I’m just curious to know whether I’m right about all of this. And if I’m &lt;em&gt;nearly&lt;/em&gt; right, I want to understand how I can improve things. And if I’m definitely not right, I want to know that too, so I can spend my time doing something more useful.&lt;/p&gt;
&lt;h2 id=&quot;wanna-try-it&quot;&gt;Wanna try it?&lt;/h2&gt;
&lt;p&gt;If this is vibing with you, I have a beta program open now for both iOS and Android. You can go to &lt;a href=&quot;https://crestpodcasts.com&quot;&gt;crestpodcasts.com&lt;/a&gt; for more info and a sign-up link. If you do, please know that you are awesome. And please tell me if Crest helps you enjoy podcasts more. That’s the whole point.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;This idea seems stupid; you can just mark it as played. But for me, I feel bad when software makes me lie. If I haven’t played it, I don’t want to tell the app that I have.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You do get backups though, via your phone’s automatic backup system.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
</content>
  </entry>
  <entry>
    <title>Meta disabled my account</title>
    <link href="https://ptrbrynt.com/posts/meta-disabled-my-account/" />
    <updated>2026-02-12T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/meta-disabled-my-account/</id>
    <content type="html">&lt;p&gt;Weird day. I’ve been in London for work, and I’ve just checked my emails for the first time today.&lt;/p&gt;
&lt;p&gt;I discovered that, at 11:37, I had an email from Meta saying they were suspending my account due to suspicious activity, and that I had the right to appeal. &lt;/p&gt;
&lt;p&gt;Less that 2 hours later, a second email came in saying that they had reviewed my account — apparently at my request — and decided that my account would be permanently disabled.&lt;/p&gt;
&lt;p&gt;Sure enough, I can no longer sign into Facebook, Messenger, or Instagram. I have no idea what caused this problem, and I appear to have missed the chance to put things right (despite the first email promising 180 days to appeal).&lt;/p&gt;
&lt;p&gt;I have super mixed feelings about this. On one hand, I have lost access to some pages/accounts for my choir, and the app I work on. I can also no longer participate in my singing-related Facebook communities, which is kind of a bummer. I have also lost access to all my conversations in Messenger; the impact of this will become clear as time goes on, but could be a reasonably huge problem. Thankfully, I still have WhatsApp.&lt;/p&gt;
&lt;p&gt;On the other hand, I have hated Meta and everything they do for quite some time. I have maintained my accounts for the purposes described above, but I guess this gives me a good excuse to stop using their products from now on. That will probably be a net positive for my life, even if it’s slightly unexpected and inconvenient in the short term.&lt;/p&gt;
&lt;p&gt;Weird day with a weird outcome. But there is a strange sense of relief, and I don’t find myself rushing to regain access to my accounts anytime soon.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Oh look, Spotify hates music fans</title>
    <link href="https://ptrbrynt.com/posts/oh-look-spotify-hates-music-fans/" />
    <updated>2025-12-23T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/oh-look-spotify-hates-music-fans/</id>
    <content type="html">&lt;p&gt;Sorry — it’s another post about how Spotify is a garbage company that doesn’t care about users or musicians.&lt;/p&gt;
&lt;p&gt;I am often sent Spotify links by friends. I’m fine with this — it’s easy enough to search Apple Music for the thing they sent me, or generate a cross-platform link using something like &lt;a href=&quot;https://www.tapelink.io&quot;&gt;Tapelink&lt;/a&gt; and open the music in my preferred service.&lt;/p&gt;
&lt;p&gt;But the other day, a friend sent me a &lt;a href=&quot;https://open.spotify.com/track/34sUWOEjFKrj8Rzk1HHicq?si=VWIuMu9tQ3i4qzQklh_fcg&quot;&gt;Spotify link&lt;/a&gt; to a new Fall Out Boy cover of &lt;em&gt;It Feels Like Christmas&lt;/em&gt; from The Muppet Christmas Carol. I was extremely excited about this — I listened to a lot of Fall Out Boy growing up, and The Muppet Christmas Carol is my absolute favourite Christmas film.&lt;/p&gt;
&lt;p&gt;So I did what I usually do in this situation — searched Apple Music for the track. But it came up empty.&lt;/p&gt;
&lt;p&gt;I quickly realised why: this track is a Spotify exclusive.&lt;/p&gt;
&lt;p&gt;The rage with which I am filled — about the idea that music should be exclusive to a particular streaming service — is palpable.&lt;/p&gt;
&lt;p&gt;I understand that, for other content like movies, TV shows, or games, platform exclusives are an industry standard, and that many households have multiple streaming service subscriptions because the stuff they want to enjoy exists across many platforms.&lt;/p&gt;
&lt;p&gt;But this is absolutely &lt;em&gt;not&lt;/em&gt; the case for music. Until recently, we have lived in a world in which music streaming platforms are largely interchangeable: you can switch from Spotify to another service and find exactly the same content. But almost everyone alive has only one music subscription, and their account contains a carefully curated library of playlists and albums. The idea of having more than one music service — in the same way that I have multiple TV streaming services — is insane to most people.&lt;/p&gt;
&lt;p&gt;But Spotify is breaking the one-service paradigm in an effort to get people to stay with Spotify, or switch away from their current service. Music fans lose out because they either need to switch, or have multiple subscriptions. And artists lose out because they can only get the revenue from one service. I would hope they are charging Spotify extra money for the exclusivity, but being beholden to one platform for your revenue is an uncomfortable place for any musician, artist, or content creator.&lt;/p&gt;
&lt;p&gt;I want to be very clear: &lt;strong&gt;exclusive music will not make me use Spotify; it will just piss me off and make me_ less_ likely to support their business.&lt;/strong&gt; This is just a big enshittification moment for music streaming services.&lt;/p&gt;
&lt;p&gt;I was able to listen to the song my friend sent me, by creating a temporary free Spotify account and using their web player. But I can’t add it to my library, or any of my Christmas playlists. I’ll probably never listen to it again.&lt;/p&gt;
&lt;p&gt;In conclusion — and I cannot emphasise this enough — fuck Spotify.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Talk to your friends about music</title>
    <link href="https://ptrbrynt.com/posts/talk-to-your-friends-about-music/" />
    <updated>2025-12-04T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/talk-to-your-friends-about-music/</id>
    <content type="html">&lt;p&gt;So Spotify Wrapped (and Apple Music Replay etc) is fun an all, but maybe we shouldn’t make this the only time in the whole year to share music with our friends?&lt;/p&gt;
&lt;p&gt;Possible 2026 resolution idea: when you hear a new album/artist/song, text a friend about it and see what they think. Have a conversation. Make a connection.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Grieving the career I never had</title>
    <link href="https://ptrbrynt.com/posts/grieving-the-career-i-never-had/" />
    <updated>2025-11-25T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/grieving-the-career-i-never-had/</id>
    <content type="html">&lt;p&gt;A big part of me always wanted to be a teacher.&lt;/p&gt;
&lt;p&gt;When thinking about work and careers, we’re often asked to focus on the things that we find easy but others find hard. For me, a few things come up:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;I enjoy speaking to groups&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I can communicate difficult concepts clearly&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I can read a room and know what the situation needs&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I don’t embarrass easily (any more)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I can talk to anyone&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I have found myself in the position of a teacher in a few unexpected ways in my life; primarily as a choir director. And I was &lt;em&gt;this close&lt;/em&gt; to actually taking the path of becoming a full-time teacher.&lt;/p&gt;
&lt;p&gt;But the more I spoke to my teacher friends about their experiences, the clearer it became that teaching involves some serious sacrifices, and rarely meets our expectations.&lt;/p&gt;
&lt;p&gt;There’s the rigid holiday schedule — sure, you get loads of holiday time, but no flexibility around &lt;em&gt;when&lt;/em&gt; you take your holiday. Then there’s the out-of-hours work: things like lesson planning and marking. This lack of flexibility around free time would preclude me from participating in the hobbies I treasure so much.&lt;/p&gt;
&lt;p&gt;Plus, there are huge systematic problems with the education system here in the UK which mean teachers are overworked and underpaid, because schools are understaffed and underfunded. Many management teams in schools are too busy trying to make ends meet to worry about professional development or career fulfilment for their teaching staff.&lt;/p&gt;
&lt;p&gt;Coupled with that, so many families are under huge pressure. This includes financial and economic challenges, and struggles with mental health. All of this adds up to kids who are set up to fail when they come into school; they’re under-nourished, under--stimulated, and under-nurtured.&lt;/p&gt;
&lt;p&gt;The reality of being a teacher became apparent to me very quickly as I was speaking to friends and family. It’s not about inspiring or mentoring young people. It’s often not even about teaching them; so many teachers just have to take one day at a time, and make it to home time incident-free.&lt;/p&gt;
&lt;p&gt;It’s bleak, and I wish the situation could change. I really think I  have something to offer as a teacher, and I spend a lot of time wondering what life would have been like if I had pursued this career. Could I have made the sacrifices so many teachers make every day, in the spirit of service to my community?&lt;/p&gt;
&lt;p&gt;In the end, I don’t regret the choices I made. But it makes me sad to think how many other great teachers never actually set foot in a classroom, because something scared them away. &lt;/p&gt;
&lt;p&gt;I believe that delivering good education is the most fundamental and important role of government. Without an educated population, all other problems are exacerbated. I don’t really know what the solution is, but I really hope someone finds one.&lt;/p&gt;
&lt;p&gt;And maybe teaching is still in my future.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Finally — a photo worthy of my desktop</title>
    <link href="https://ptrbrynt.com/posts/finally-a-photo-worthy-of-my-desktop/" />
    <updated>2025-11-21T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/finally-a-photo-worthy-of-my-desktop/</id>
    <content type="html">&lt;p&gt;I hit a milestone in my photography journey recently — I took a photo that I liked so much, I have set it as my desktop wallpaper.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/finally-a-photo-worthy-of-my-desktop/gk38-C2b8_-1280.webp 1280w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/finally-a-photo-worthy-of-my-desktop/gk38-C2b8_-1280.jpeg&quot; alt=&quot;A calm lake reflecting a range of softly rounded mountains under a bright, partly cloudy sky. The shoreline is lined with dense green and autumn-tinged trees, and a few small boats sit still on the water. The mountains in the background rise gently with patches of shadow and sunlight, creating a peaceful, expansive landscape.&quot; width=&quot;1280&quot; height=&quot;854&quot;&gt;&lt;/picture&gt;&lt;br&gt;
&lt;em&gt;My favourite landscape photo — taken from Castle Ross in County Kerry, Ireland.&lt;/em&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>I’m not sure I want to put my Apple Watch back on</title>
    <link href="https://ptrbrynt.com/posts/im-not-sure-i-want-to-put-my-apple-watch-back-on/" />
    <updated>2025-10-30T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/im-not-sure-i-want-to-put-my-apple-watch-back-on/</id>
    <content type="html">&lt;p&gt;Since upgrading to the Apple Watch Series 10, I’ve got a serious problem: contact dermatitis.&lt;/p&gt;
&lt;p&gt;Never happened with my Watch Ultra. Nor with the Series 5 before it. But this one? I’ll spare you the grisly details; suffice to say, every so often I have to stop wearing it for a few days, just to let the skin breathe and heal.&lt;/p&gt;
&lt;p&gt;My most recent break has been the longest yet: over a week. That’s when I started thinking — I can’t keep going like this without trying to fix it. I began hunting for protective film covers for the sensor array under the Watch. I was seconds from hitting “order”. Then I paused. And asked myself: do I &lt;em&gt;actually&lt;/em&gt; want to go back to wearing a smartwatch?&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;ten-years-of-feature-creep&quot;&gt;Ten years of feature creep&lt;/h3&gt;
&lt;p&gt;I’ve worn a smartwatch for nearly a decade.&lt;/p&gt;
&lt;p&gt;It started with a Pebble, then a Pebble Time. Then Android watches. In 2019 I switched to iPhone and naturally got an Apple Watch. Since then I’ve had one continuously.&lt;/p&gt;
&lt;p&gt;In 2013, the appeal of smartwatches was simple: notifications, music control, telling the time. Over time the watch evolved: I now leave my phone behind and can still get messages, calls, maps, podcasts, and even record workouts.&lt;/p&gt;
&lt;p&gt;That’s convenient, except somewhere along the way, I stopped asking whether I &lt;em&gt;wanted&lt;/em&gt; an internet-connected device strapped to my wrist &lt;em&gt;all the time&lt;/em&gt;. I always thought I loved the cellular independence of the Apple Watch as a way to disconnect from my phone — but looking back, that might be the crux of the issue: escape becomes impossible when you’ve got the internet on your body.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;apple-watch-or-apple-watch&quot;&gt;Apple Watch ⌚️ or Apple Watch 👀&lt;/h3&gt;
&lt;p&gt;The big selling point these days is health &amp;amp; fitness tracking. Wear it pretty much 24/7 and it learns everything about you: sleep, fitness, movement. It can tell you when your heart rate is elevated, whether you might have sleep apnea, and how fit you are.&lt;/p&gt;
&lt;p&gt;Here’s the thing: it’s great at measuring, awful at guiding.&lt;/p&gt;
&lt;p&gt;I’ve got six years of data in the Health app and I’ve learnt almost nothing useful from it. No sudden revelations; no helpful hints.&lt;/p&gt;
&lt;p&gt;I’m healthy enough. Sleep’s usually fine. If it’s not, I already know why — travel, wine, stress. But I’m not training for an Ironman. I go to the gym, walk the dog, go for a run sometimes.&lt;/p&gt;
&lt;p&gt;Without a coach interpreting the numbers, most of these stats are meaningless. If you’re broadly healthy, the watch becomes: “We’ll keep an eye on you” — which is okay… except that feedback without coaching just feels like judgement.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;what-i-actually-miss&quot;&gt;What I &lt;em&gt;actually&lt;/em&gt; miss&lt;/h3&gt;
&lt;p&gt;Going a week without the Watch has surfaced the few things I genuinely miss:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Checking the time quickly without fishing for my phone&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The gentle “tap” alarm on the wrist instead of a shouting ringtone&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Timers while cooking — using my phone for this is fiddly but it’s very easy with the Watch&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All fixable. A dumb watch, a £4 kitchen timer, and a good old alarm clock cover this ground. So I’m going back to basics for now.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;The watch isn’t evil. It’s clever. But clever doesn’t always mean &lt;em&gt;necessary&lt;/em&gt;. For me right now — a generally healthy person, not chasing extremes — it might be doing less than it promises, and more than I signed up for.&lt;/p&gt;
&lt;p&gt;So I’ll experiment with non-smart, low-tech alternatives. I’ll report back. If nothing else, my wrist will thank me — and maybe my brain too.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Can we let Tim Cook do his job?</title>
    <link href="https://ptrbrynt.com/posts/can-we-let-tim-cook-do-his-job/" />
    <updated>2025-10-24T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/can-we-let-tim-cook-do-his-job/</id>
    <content type="html">&lt;p&gt;Apple has once again &lt;a href=&quot;https://9to5mac.com/2025/10/23/apple-on-short-list-of-donors-to-trumps-white-house-demolition-ballroom-project/&quot;&gt;donated&lt;/a&gt; to the Trump administration.&lt;/p&gt;
&lt;p&gt;As a user and lover of Apple products, this sucks. I’m seeing lots of folks online becoming so outraged by this behaviour that they are swearing never to buy another Apple product again.&lt;/p&gt;
&lt;p&gt;I’m not quite that upset about it. To be absolutely clear: the Trump administration is utterly deplorable in every way. &lt;em&gt;However&lt;/em&gt;, it’s pretty clear what Apple’s motivation is for “bending the knee”.&lt;/p&gt;
&lt;p&gt;Fundamentally, Apple is a publicly traded company. That means it has one primary purpose: &lt;strong&gt;to deliver value to its shareholders&lt;/strong&gt;. &lt;em&gt;Everything&lt;/em&gt; it does serves that goal in one way or another.&lt;/p&gt;
&lt;p&gt;Being driven by shareholder value doesn’t exclude a company from being product- and customer-focused. In fact, Apple’s entire product strategy has been to make the best possible products in order to drive customer loyalty, which then leads to ongoing sales, which then leads to… increased shareholder value!&lt;/p&gt;
&lt;p&gt;Other companies have different strategies for driving shareholder value, but that’s Apple’s. &lt;/p&gt;
&lt;p&gt;In order to protect shareholder value, companies have to accept and work within their political and economic environment. The reality is that — in the current political climate — Apple’s shareholder value is directly tied to Donald Trump’s personal opinion of Tim Cook. If Trump decides one day that he doesn’t like Cook, he will impose tariffs on Apple’s supply chain such that the iPhone price could double. Then nobody would buy iPhones, and Apple’s stock price would tank. That is the world we live in.&lt;/p&gt;
&lt;p&gt;So I actually imagine that it was a very easy decision for Apple’s leadership to decide to “cosy up” to Trump. Morally reprehensible as it is, Apple’s job is not to signal virtue at the expense of their shareholders. That’s a great way to get a CEO fired. His job is to make decisions which benefit the shareholders. Those decisions in turn benefit customers, because Americans get to keep buying iPhones for $800 instead of $2,000.&lt;/p&gt;
&lt;p&gt;I really believe that Tim Cook is personally disgusted at the actions he is required to take. &lt;strong&gt;But this is his job&lt;/strong&gt;. So let’s focus on the real problem: the fact that Donald Trump has abused his power in order to create an environment in which this kind of sucking up is necessary. This is not how a capitalist society should work.&lt;/p&gt;
&lt;p&gt;If you want to boycott Apple, you are letting Donald Trump win. If we want Apple to continue making great products, the best thing we can do is keep buying them, and let Tim Cook do his job.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Removing analytics from my blog</title>
    <link href="https://ptrbrynt.com/posts/removing-analytics-from-my-blog/" />
    <updated>2025-10-23T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/removing-analytics-from-my-blog/</id>
    <content type="html">&lt;p&gt;I’ve had some lightweight analytics installed on my blog for the past few months. Not because I’m interested in optimising or growing (this is a hobby, not a business), but just because it kinda makes me feel good to know that people are reading my posts.&lt;/p&gt;
&lt;p&gt;But a recent feature update from my blogging platform &lt;a href=&quot;https://pika.page&quot;&gt;Pika&lt;/a&gt; made me think twice about whether I should have analytics on here.&lt;/p&gt;
&lt;p&gt;The new feature was email newsletters, and they have implemented the admin UI for this in a very interesting way.&lt;/p&gt;
&lt;p&gt;By default, they hide your subscribers list, and the UI makes you confirm whether or not you want to see it. This is because &amp;quot;we want you to write for yourself first!”&lt;/p&gt;
&lt;p&gt;This is one of many ways in which the folks who make Pika &lt;em&gt;really&lt;/em&gt; understand their target audience. We’re hobbyist bloggers, not professional publishers.  I like having a blog because I enjoy writing, and I want to escape the incentive structures behind social media platforms. I should actively avoid knowing how many people are reading my posts!&lt;/p&gt;
&lt;p&gt;So analytics is gone. I have no idea if you’re reading this (unless you &lt;a href=&quot;https://letterbird.co/ptrbrynt&quot;&gt;email me&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;This blog is for me.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>My terrible day</title>
    <link href="https://ptrbrynt.com/posts/my-terrible-day/" />
    <updated>2025-10-21T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/my-terrible-day/</id>
    <content type="html">&lt;p&gt;My terrible day started yesterday.&lt;/p&gt;
&lt;p&gt;I had woken up, feeling excited about starting the week. I had so much to catch up on after taking some time off sick last week. I was going to be a productivity &lt;em&gt;machine&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I packed my bag and marched into my wonderful co-working space. I had already ticked off so many &amp;quot;great day” boxes, and it was barely 9am!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;I ate breakfast, and it was healthy!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I didn’t look at Instagram &lt;em&gt;once&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I decided to have a mindful walk into town — no music or podcasts&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I treated myself to a nice coffee when I arrived&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sure enough, my morning was great. I smashed out some tasks, and attended some useful meetings. I was so locked in that I almost missed lunchtime rolling in.&lt;/p&gt;
&lt;p&gt;I went for a walk — via an excellent beef sandwich — to get some movement and fresh air before restarting for the afternoon. Everything was going great.&lt;/p&gt;
&lt;p&gt;Then, I sat back at my computer and looked for the next item on my to-do list.&lt;/p&gt;
&lt;p&gt;Blank.&lt;/p&gt;
&lt;p&gt;I hadn’t planned anything else for the day. No worries, I thought — I’ll just check the team kanban board; there’s bound to be something I can work on there.&lt;/p&gt;
&lt;p&gt;Nope.&lt;/p&gt;
&lt;p&gt;Everything was blocked by someone else. A pending meeting or decision. Or another developer.&lt;/p&gt;
&lt;p&gt;I could feel the productive momentum slipping from my grasp like sand. Being unsure of what to do next is my kryptonite. &lt;/p&gt;
&lt;p&gt;I sat in a state of paralysis for over an hour, waiting for something interesting to happen at work, or on the internet, or in my life. Eventually, I decided that I was wasting my time, and that I should just give up and go home.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Fast-forward to this morning. At 9am, I was still on the sofa. Because I knew that if I made it upstairs to my home office, I would just get myself stuck in the same paralysis, falling into a bottomless pit of boredom. And if I was going to be unproductive, I could at least do it productively by watching TV.&lt;/p&gt;
&lt;p&gt;It’s now nearly 4pm, and I’ve achieved very little today. I did eventually become bored enough to get my shoes on and walk the dog. But I feel as though my day has been an utter waste.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;What I’m experiencing is probably burnout. The brain’s defence mechanism against overextension and overwork.&lt;/p&gt;
&lt;p&gt;I’m absolutely sure that if I’d spent 10 minutes looking for something to work on, I would have found it. But that was not my destiny today. Truthfully, some days just get wasted. &lt;/p&gt;
&lt;p&gt;I’ve become fairly used to this since I started working from home 5 years ago. My motivation ebbs when there is nobody around me to keep it topped up when my internal reserves run dry.&lt;/p&gt;
&lt;p&gt;This is the reality of living with ADHD — my brain is on a rollercoaster, and sometimes it goes too fast and flies off the rails for a while. Sometimes it feels like it’s going alarmingly quickly, and it’s almost impossible to imagine it slowing down. And sometimes it feels like it’s crawling uphill, but it’s  just building momentum for an upcoming burst of speed.&lt;/p&gt;
&lt;p&gt;Today is a slow day. In the moment, I tell myself I’m an utter failure. But the bigger picture shows clear progress — albeit extremely unsteady and inconsistent.&lt;/p&gt;
&lt;p&gt;Today was terrible. That’s okay.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>I had to stop watching The Big Bang Theory</title>
    <link href="https://ptrbrynt.com/posts/i-had-to-stop-watching-the-big-bang-theory/" />
    <updated>2025-10-17T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/i-had-to-stop-watching-the-big-bang-theory/</id>
    <content type="html">&lt;p&gt;When I was growing up, &lt;em&gt;The Big Bang Theory&lt;/em&gt; seemed like a pretty cool show. As a member of the “nerd” group at school, I was happy to finally seem some characters to whom I could relate. &lt;/p&gt;
&lt;p&gt;That said, I actually never saw the end. Before the last 2 or 3 seasons, I moved away to university. My habits changed, my access to TV disappeared, and I never got around to finishing the show.&lt;/p&gt;
&lt;p&gt;At the time this didn’t bother me much, but I recently saw it recommended to me on Netflix and thought, “Okay, maybe it’s time to finish this.”&lt;/p&gt;
&lt;p&gt;So I started watching from the beginning. But I immediately started to struggle.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;In my opinion, &lt;em&gt;TBBT&lt;/em&gt; has aged more poorly than &lt;em&gt;Friends&lt;/em&gt;. And &lt;em&gt;Friends&lt;/em&gt; didn’t age particularly well.&lt;/p&gt;
&lt;p&gt;In my most recent watch-through, I realised that so much of the humour in &lt;em&gt;TBBT&lt;/em&gt; is centred around:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The neurodivergent traits of the male characters, particularly Sheldon&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Raj’s selective mutism&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Sheldon’s asexuality&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Penny’s apparent promiscuity&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Penny’s level of academic achievement in contrast with the male characters&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Mrs Wolowitz’s weight&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Raj’s Indian heritage and culture&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Howard’s Jewish heritage and culture&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Raj’s “metro” personality traits&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Howard and Raj’s apparently “homosexual” relationship&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the &lt;em&gt;first episode&lt;/em&gt;, there is a running joke about the “200 pound transvestite with a skin condition” who previously occupied Penny’s apartment.&lt;/p&gt;
&lt;p&gt;I have come to realise that almost every single joke in this show is poking some type of fun at a stereotype. In many cases, the fun is being poked at a marginalised group by engaging in sexism, racism, ableism, homophobia, body-shaming, and other forms of discrimination.&lt;/p&gt;
&lt;p&gt;In some cases, the discrimination &lt;em&gt;is&lt;/em&gt; the joke (e.g. Raj does sometimes call out the racism in the jokes made about him). But these are few and far between; most of the time, the jokes are plain discrimination.&lt;/p&gt;
&lt;p&gt;It’s pretty telling that a reviewer spotted this vibe after seeing the pilot episode. In TV Club, Scott Tobias &lt;a href=&quot;https://web.archive.org/web/20171203064613/https://tv.avclub.com/the-big-bang-theory-the-big-bang-theory-1798203099&quot;&gt;wrote&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Really bad television shows tend to pander to the mean: In affirming the superiority of Joe and Jane Average, they mock both the egregiously stupid (e.g. Kellie Pickler, Jay Leno’s man-on-the-street bozos, and other adults not smarter than a fifth grader) and the hyper-intelligent, who are struck down for the arrogant, unpardonable sin of… um… knowing stuff. The new CBS sitcom The Big Bang Theory is a broad example of this principle—really broad, like Amazon basin broad. It’s hard to believe that anyone’s even making a three-camera sitcom this mothballed; only an offhand mention of the word “blog” suggests that it takes place in the present-day.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I really am not usually the type of person who would stop watching a TV show based on language which could be seen as a product of it’s time. Do I cringe at old episodes of &lt;em&gt;Doctor Who&lt;/em&gt;? Absolutely. But I still glean enjoyment from old movies and TV shows.&lt;/p&gt;
&lt;p&gt;But I think the biggest disappointment with &lt;em&gt;TBBT&lt;/em&gt; is that, as a show which first aired in 2007 and ran all the way to 2019, it should have known better. I made it to Season 7 before I decided I could no longer look past these glaring issues; it’s simply unwatchable in 2025.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>You should turn off read receipts</title>
    <link href="https://ptrbrynt.com/posts/you-should-turn-off-read-receipts/" />
    <updated>2025-09-22T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/you-should-turn-off-read-receipts/</id>
    <content type="html">&lt;p&gt;I asked myself recently: how do read receipts in messaging apps actually serve me?&lt;/p&gt;
&lt;p&gt;The answer is that they don’t. The only function they seem to serve is making me anxious and guilty. I avoid opening messages because I know I’ll then be expected to reply. So I leave messages unread — often without knowing the full contents — and ruminate over what the message might say beyond the preview.&lt;/p&gt;
&lt;p&gt;On the other hand, when I send a message I find myself constantly checking to see if the recipient has read it. If they have, but don’t reply, I spiral into overthinking why they might not want to respond.&lt;/p&gt;
&lt;p&gt;The big realisation was this: I genuinely don’t understand the functional purpose of read receipts. They’re just another tool tech companies use to keep us engaged, at the expense of our mental health.&lt;/p&gt;
&lt;p&gt;So I turned them off.&lt;/p&gt;
&lt;h2 id=&quot;what-is-the-impact-of-read-receipts&quot;&gt;What is the impact of read receipts?&lt;/h2&gt;
&lt;p&gt;I wanted to know if my experience was unique, so I looked at the research. A number of studies show that users almost universally dislike features like this.&lt;/p&gt;
&lt;p&gt;A &lt;a href=&quot;https://tidsskrift.dk/mef-journal/article/view/28781&quot;&gt;2017 study&lt;/a&gt; by James Linden and Teis Rasmussen linked read receipts to:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;…an array of behaviours and emotional effects including avoidance strategies, increased app checking and feelings of anxiety as well as strong negative attitudes to the feature.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A &lt;a href=&quot;https://personales.upv.es/thinkmind/dl/conferences/achi/achi_2018/achi_2018_9_10_20029.pdf?utm_source=chatgpt.com&quot;&gt;2018 study&lt;/a&gt; (Kato et al.) found that “negative emotions” arise significantly faster when a sender knows the recipient has read the message. In other words, the little blue tick makes us much more impatient.&lt;/p&gt;
&lt;p&gt;In general, the research suggests that switching off read receipts — as well as other “status/awareness” features like typing indicators — reduces stress and anxiety, and improves well-being.&lt;/p&gt;
&lt;h2 id=&quot;who-should-turn-off-read-receipts&quot;&gt;Who should turn off read receipts?&lt;/h2&gt;
&lt;p&gt;In short: everyone. There are very few situations where they provide any meaningful benefit to users.&lt;/p&gt;
&lt;p&gt;If you want to go further, consider switching off other “presence” signals like typing indicators and “last seen” statuses. Essentially, anything that makes you feel watched by the people on the other end of the chat.&lt;/p&gt;
&lt;h2 id=&quot;what-apps-do-i-need-to-worry-about&quot;&gt;What apps do I need to worry about?&lt;/h2&gt;
&lt;p&gt;I was relieved to find that every app I use lets me switch off read receipts. These include WhatsApp, iMessage, and Messenger.&lt;/p&gt;
&lt;p&gt;WhatsApp and Messenger also allow you to disable their “Active Status” features, which I’ve done as well.&lt;/p&gt;
&lt;p&gt;So far I haven’t seen any downside. None of my friends or family seem to have noticed or cared — and I feel far better about my relationship with messaging apps.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Switching off read receipts is a no-brainer. Life’s too short to be haunted by blue ticks.&lt;/strong&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Let’s all raise a glass to the 11-inch MacBook Air</title>
    <link href="https://ptrbrynt.com/posts/lets-all-raise-a-glass-to-the-11-inch-macbook-air/" />
    <updated>2025-09-02T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/lets-all-raise-a-glass-to-the-11-inch-macbook-air/</id>
    <content type="html">&lt;p&gt;As &lt;a href=&quot;https://9to5mac.com/2025/09/01/end-of-an-era-as-the-last-11-inch-macbook-air-is-now-officially-obsolete/&quot;&gt;9to5Mac reported&lt;/a&gt;, the 11-inch MacBook Air is officially an obsolete product.&lt;/p&gt;
&lt;p&gt;My very first Mac was an 11-inch MacBook Air, which I bought for just £749 (imagine!) while I was at university. It was my gateway into the Apple ecosystem, and the best laptop I’d ever owned.&lt;/p&gt;
&lt;p&gt;I remember with fondness the many hours I spent in coffee shops, writing my dissertation and completing coursework on my 11-inch MacBook Air.&lt;/p&gt;
&lt;p&gt;The screen was terrible, the performance could be frustrating, and it did get hot every once in a while. But the tiny size and unbelievably light weight meant that I took this thing absolutely everywhere. It felt magical to be able to have a real computer in this minuscule package.&lt;/p&gt;
&lt;p&gt;Ultimately I ended up accidentally spilling tea on it, and the repair was deemed uneconomical; in other words, the parts and labour would have cost more than the laptop was worth. I was really very sad about it.&lt;/p&gt;
&lt;p&gt;And today I’m reminded of my relationship with this tiny computer. It could be frustrating, but it was useful and beautiful.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Spotify is adding DMs</title>
    <link href="https://ptrbrynt.com/posts/spotify-is-adding-dms/" />
    <updated>2025-08-26T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/spotify-is-adding-dms/</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;https://www.theverge.com/news/765771/spotify-messages-dms-audio-sharing-feature&quot;&gt;Spotify is adding DMs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In other news, Apple Music continues to be an excellent service, and invests in features which improve the experience of listening to music, including Lossless, Dolby Atmos (which is hit and miss but when it’s good it’s great) and SharePlay.&lt;/p&gt;
&lt;p&gt;I jumped ship on Spotify years ago — I really think we just have different ideas about what listening to music is supposed to look like. To me, music isn’t “content”, or fodder for Spotify to feed into their algorithm; it’s deeply personal, fuels real human connection, and encourages incredible creativity. It stands up on its own, and doesn’t need a recommendation engine (and yes, I’ve turned off Listening History on Apple Music for this reason).&lt;/p&gt;
&lt;p&gt;The music you listen to really shapes your life and your character. But it won’t if you just do what a megacorp tells you to do. Make your own choices, learn about your tastes, and listen outside the box.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>A day at the beach</title>
    <link href="https://ptrbrynt.com/posts/a-day-at-the-beach/" />
    <updated>2025-07-28T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/a-day-at-the-beach/</id>
    <content type="html">&lt;p&gt;We had an absolutely lovely family day out at Sandsend Beach this weekend. We walked on the beach for a couple of hours, and had lunch at the truly excellent Fish Cottage — I had a rack of tacos.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/a-day-at-the-beach/FfedV1Gch6-1280.webp 1280w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/a-day-at-the-beach/FfedV1Gch6-1280.jpeg&quot; alt=&quot;&quot; width=&quot;1280&quot; height=&quot;960&quot;&gt;&lt;/picture&gt; &lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/a-day-at-the-beach/mGnKGS1YOu-1280.webp 1280w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/a-day-at-the-beach/mGnKGS1YOu-1280.jpeg&quot; alt=&quot;&quot; width=&quot;1280&quot; height=&quot;854&quot;&gt;&lt;/picture&gt; &lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/a-day-at-the-beach/WX6EH-5-Dq-1280.webp 1280w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/a-day-at-the-beach/WX6EH-5-Dq-1280.jpeg&quot; alt=&quot;&quot; width=&quot;1280&quot; height=&quot;854&quot;&gt;&lt;/picture&gt; &lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/a-day-at-the-beach/ilHDIn6Byj-1280.webp 1280w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/a-day-at-the-beach/ilHDIn6Byj-1280.jpeg&quot; alt=&quot;&quot; width=&quot;1280&quot; height=&quot;854&quot;&gt;&lt;/picture&gt; &lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/a-day-at-the-beach/D0fHWffL8E-1280.webp 1280w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/a-day-at-the-beach/D0fHWffL8E-1280.jpeg&quot; alt=&quot;&quot; width=&quot;1280&quot; height=&quot;854&quot;&gt;&lt;/picture&gt; &lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/a-day-at-the-beach/x6oRGqEWp5-1280.webp 1280w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/a-day-at-the-beach/x6oRGqEWp5-1280.jpeg&quot; alt=&quot;&quot; width=&quot;1280&quot; height=&quot;854&quot;&gt;&lt;/picture&gt; &lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/a-day-at-the-beach/OIbIMXbgzK-1280.webp 1280w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/a-day-at-the-beach/OIbIMXbgzK-1280.jpeg&quot; alt=&quot;&quot; width=&quot;1280&quot; height=&quot;854&quot;&gt;&lt;/picture&gt; &lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/a-day-at-the-beach/jwSmJG4nuW-1280.webp 1280w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/a-day-at-the-beach/jwSmJG4nuW-1280.jpeg&quot; alt=&quot;&quot; width=&quot;1280&quot; height=&quot;854&quot;&gt;&lt;/picture&gt;
&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/a-day-at-the-beach/p36hZ-LFo8-854.webp 854w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/a-day-at-the-beach/p36hZ-LFo8-854.jpeg&quot; alt=&quot;&quot; width=&quot;854&quot; height=&quot;1280&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Date pickers are the worst</title>
    <link href="https://ptrbrynt.com/posts/date-pickers-are-the-worst/" />
    <updated>2025-06-06T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/date-pickers-are-the-worst/</id>
    <content type="html">&lt;p&gt;I hate date pickers.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/date-pickers-are-the-worst/DmUMOi-Yg4-1004.webp 1004w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/date-pickers-are-the-worst/DmUMOi-Yg4-1004.jpeg&quot; alt=&quot;Material Design date picker&quot; width=&quot;1004&quot; height=&quot;1250&quot;&gt;&lt;/picture&gt;&lt;br&gt;
&lt;em&gt;A date picker from Google’s Material Design system&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/date-pickers-are-the-worst/eOeBHuLq2y-748.webp 748w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/date-pickers-are-the-worst/eOeBHuLq2y-748.jpeg&quot; alt=&quot;iOS-style date picker&quot; width=&quot;748&quot; height=&quot;670&quot;&gt;&lt;/picture&gt;&lt;br&gt;
&lt;em&gt;A date picker from Apple’s iOS design system&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Why can’t we just tell the users what format we want, and let them type the date in? Maybe let them use a picker if they really want? It is &lt;em&gt;so much faster&lt;/em&gt; to type a date, particularly one that’s very far away like a date of birth.&lt;/p&gt;
&lt;p&gt;Sure, sometimes I need to see the calendar in order to know what date I need to pick (like setting a deadline for a task), but in those cases we can just let the user push a button to see the picker.&lt;/p&gt;
&lt;p&gt;But we should never, ever, make a picker the &lt;em&gt;only&lt;/em&gt; choice for date entry. Just let me type.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>I got married!</title>
    <link href="https://ptrbrynt.com/posts/i-got-married/" />
    <updated>2025-05-08T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/i-got-married/</id>
    <content type="html">&lt;p&gt;This is just a short post to record that 23rd April 2025 was the most special and magical day of my life. I am lucky enough to be the husband of the most amazing person I know. Here are some photos from the wonderful &lt;a href=&quot;https://instagram.com/chrismilnerphotography&quot;&gt;Chris Milner&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/i-got-married/3SS5GqcnIM-2304.webp 2304w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/i-got-married/3SS5GqcnIM-2304.jpeg&quot; alt=&quot;&quot; width=&quot;2304&quot; height=&quot;1536&quot;&gt;&lt;/picture&gt; &lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/i-got-married/lR0H1z9UZl-2304.webp 2304w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/i-got-married/lR0H1z9UZl-2304.jpeg&quot; alt=&quot;&quot; width=&quot;2304&quot; height=&quot;1536&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/i-got-married/oiUxNDfvu_-1536.webp 1536w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/i-got-married/oiUxNDfvu_-1536.jpeg&quot; alt=&quot;&quot; width=&quot;1536&quot; height=&quot;2304&quot;&gt;&lt;/picture&gt; &lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/i-got-married/FHAOO2siD9-1536.webp 1536w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/i-got-married/FHAOO2siD9-1536.jpeg&quot; alt=&quot;&quot; width=&quot;1536&quot; height=&quot;2304&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/i-got-married/dI2cd7hS9n-2304.webp 2304w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/i-got-married/dI2cd7hS9n-2304.jpeg&quot; alt=&quot;&quot; width=&quot;2304&quot; height=&quot;1536&quot;&gt;&lt;/picture&gt; &lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/i-got-married/36Ez5hvZv3-2304.webp 2304w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/i-got-married/36Ez5hvZv3-2304.jpeg&quot; alt=&quot;&quot; width=&quot;2304&quot; height=&quot;1536&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Endel is magic</title>
    <link href="https://ptrbrynt.com/posts/endel-is-magic/" />
    <updated>2025-02-08T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/endel-is-magic/</id>
    <content type="html">&lt;p&gt;A short post about a magical app called &lt;a href=&quot;https://endel.io/&quot;&gt;Endel&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you struggle with concentration, boredom, procrastination, or anxiety, you should try Endel. It seems to scratch an itch in my ADHD brain and really helps my executive function.&lt;/p&gt;
&lt;p&gt;In particular, I love the Autoplay function which syncs with my circadian rhythm, and also takes into account movement data from my Apple Watch, to provide a soundtrack to match my energy levels throughout the day.&lt;/p&gt;
&lt;p&gt;Give it a shot - I love it.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>I’ve been making espresso wrong for 5 years</title>
    <link href="https://ptrbrynt.com/posts/ive-been-making-espresso-wrong-for-5-years/" />
    <updated>2025-01-26T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/ive-been-making-espresso-wrong-for-5-years/</id>
    <content type="html">&lt;p&gt;Herein lies a very nerdy coffee-related confession.&lt;/p&gt;
&lt;p&gt;5 years ago, I bought a Sage/Breville Barista Express. It was a lockdown present to myself having become obsessed with making better coffee by the wonderful &lt;a href=&quot;https://www.jameshoffmann.co.uk/&quot;&gt;James Hoffmann&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The Barista Express is by no means an “endgame” coffee setup (although it is very lovely), but at the time I needed to save space. A major advantage here is that it comes with a built-in grinder, meaning I only need to have one appliance on my countertop rather than two.&lt;/p&gt;
&lt;p&gt;I’ve since spent the last 5 years honing my espresso making workflow. Something I realised very early on was that really smart coffee people seem to unanimously prefer “single-dose” grinder workflows, meaning you only weigh out the exact amount of beans you need, rather than storing all your beans in the hopper of the grinder.&lt;/p&gt;
&lt;p&gt;The Barista Express is designed for the latter workflow. Its hopper has space for around a 250g bag’s worth of unground beans, meaning the intention is for you to empty out a bunch of beans and then use the built-in grind timer function to produce roughly repeatable doses of ground coffee for each brew.&lt;/p&gt;
&lt;p&gt;But I didn’t want to use it that way. I wanted to weigh the beans going into the machine. And this was my mistake.&lt;/p&gt;
&lt;p&gt;See, what I’ve realised this morning is that the Barista Express has a weird design quirk. If you don’t have much coffee in the hopper, it will exhibit “popcorning” behaviour, whereby beans (or chunks of partially-ground beans) bounce out of the grinding mechanism and find themselves lost in the edges of the hopper/grinder area. This means that, if you use the single-dose technique, you are risking losing a pretty sizeable chunk of your dose to popcorning. And I had no idea this was happening.&lt;/p&gt;
&lt;p&gt;I was tipped off today while doing a deep-clean of my machine. I opened up the grinder and vacuumed out the beans that had bounced out. I finished the cleaning process and started making coffee again. But something wasn’t right. Suddenly my shots were pulling through much faster. So I opened up the grinder again and realised that it had already filled up with popcorned beans after just 2 shots of espresso.&lt;/p&gt;
&lt;p&gt;Essentially, the problem is that I was putting the right amount of coffee in, but not necessarily getting the same coffee out.&lt;/p&gt;
&lt;p&gt;This made me realise that using the Barista Express for single-dose grinding is actually hurting my coffee, not helping it. So my new technique involves using the machine as designed: filling the hopper, and measuring the coffee coming &lt;em&gt;out&lt;/em&gt; of the grinder rather than the coffee going in.&lt;/p&gt;
&lt;p&gt;The lesson: don’t try and outsmart your equipment. Work with it the way it was intended.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>What’s it like to have ADHD?</title>
    <link href="https://ptrbrynt.com/posts/whats-it-like-to-have-adhd/" />
    <updated>2025-01-23T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/whats-it-like-to-have-adhd/</id>
    <content type="html">&lt;p&gt;I recently started reading a book called &lt;a href=&quot;https://www.goodreads.com/book/show/203093731-the-adhd-advantage&quot;&gt;&lt;em&gt;The ADHD Advantage&lt;/em&gt;&lt;/a&gt; by Dr Anders Hansen. I’ve not finished it yet, but the first chapter does include an extremely helpful description of what ADHD is like.&lt;/p&gt;
&lt;p&gt;Hansen explains that ADHD brains have fewer, less effective dopamine receptors than neurotypical brains, so ADHDers find the world around the much more boring than others.&lt;/p&gt;
&lt;p&gt;This explains an awful lot of ADHD behaviours. In particular, it has helped me to understand why I am so distracted and impulsive: my brain is constantly bored and is desperately searching for quick hits of dopamine.&lt;/p&gt;
&lt;p&gt;It also explains hyperfocus: if my brain finds what it deems to be an endless source of dopamine - like a video game, a challenging piece of work, or something new and interesting to learn - it is highly motivated to keep doing that thing in order to avoid the boredom that would result from stopping.&lt;/p&gt;
&lt;p&gt;It’s the most helpful “root cause” explanation of ADHD I’ve heard so far, and certainly helps me to understand how I can control my attention. ADHDers can help ourselves by making the world less boring, using sound or other “background stimulation” to keep our brains occupied.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Why do we work?</title>
    <link href="https://ptrbrynt.com/posts/why-do-we-work/" />
    <updated>2025-01-13T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/why-do-we-work/</id>
    <content type="html">&lt;p&gt;&lt;em&gt;This post is part of a series called&lt;/em&gt; &lt;a href=&quot;https://ptrbrynt.com/tag/I-Finished-A-Book&quot;&gt;I Finished A Book&lt;/a&gt;&lt;em&gt;, in which I write about a book I’ve read recently. I don’t finish every book I start, so if I do manage to get to the end, that means I must have really liked it.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;For most people, work sucks. It always has, since the dawn of time, and it likely always will.&lt;/p&gt;
&lt;p&gt;But recently, influencers on the internet have been peddling the idea that enjoyable and meaningful work is within everyone’s grasp, if we only knew how to find it and were willing to take the necessary risks.&lt;/p&gt;
&lt;p&gt;The problem with that idea is that it’s snake oil. Most of us will spend our careers on pursuits which will seem futile, boring, and pointless to everyone around us.&lt;/p&gt;
&lt;p&gt;The internet would have us treat this as some kind of moral failure. If you find your job boring or unfulfilling, it must be &lt;em&gt;your&lt;/em&gt; fault. But this is nonsense.&lt;/p&gt;
&lt;p&gt;Nothing has shown this more plainly to me than Alain de Botton’s &lt;em&gt;The Pleasures and Sorrows of Work&lt;/em&gt;, in which he logs his experiences following a number of people doing their work. He spends time with manufacturers, artists, accountants, and product marketers. The book doesn’t offer an explicit conclustion, but I certainly took away an important insight: most work rarely matters to more than a very small number of people.&lt;/p&gt;
&lt;h2 id=&quot;the-invisible-work-of-others&quot;&gt;The invisible work of others&lt;/h2&gt;
&lt;p&gt;One chapter explores the aviation industry, through the lens of an aviation trade show. It exposes the inner workings of the unfathomably huge industry which makes planes.&lt;/p&gt;
&lt;p&gt;It’s clear that almost all of this work goes totally unnoticed by passengers. Have you ever thought about all the sales pitches, negotiations, entertainment and ass-kissing that leads to a particular upholstery being applied to your seat? Or the fierce bidding war to decide which company gets to fit the plastic window casing on your Boeing 747? It would be totally understandable if you hadn’t.&lt;/p&gt;
&lt;p&gt;Another chapter explores the inner workings of an accounting firm. An entire industry is built upon crunching numbers in business accounts, but this work never makes its way into anyone’s final product. Consumers are blissfully unaware of the office politics, late nights, procrastination, stress, and inordinate international travel which lie behind the incredibly complex tax affairs of the company which manufactures the biscuits they’re eating.&lt;/p&gt;
&lt;p&gt;But people aren’t leaving accountancy in droves, and engineering firms aren’t on the brink of collapse due to lack of recruitment opportunities. So there must be something other than external validation driving people to continue working in these industries.&lt;/p&gt;
&lt;h2 id=&quot;what-can-we-learn&quot;&gt;What can we learn?&lt;/h2&gt;
&lt;p&gt;This book gave me a helpful nudge for me to reset my expectations and shift my perspective. We are all told to search for work which has impact and meaning, but the reality is that all work is, on many levels, uninteresting to everyone else on the planet.&lt;/p&gt;
&lt;p&gt;So instead of looking for extrinsic motivation, we need to learn to appreciate the very act of doing the work. Accountants might enter that career based on an obsession with spreadsheets. Software developers (like me) end up writing code because they just love understanding how computers work, and hacking them into doing their bidding. Administrators may love the feeling of creating order from chaos. Salespeople might enjoy the thrill of the chase.&lt;/p&gt;
&lt;p&gt;I’ve struggled recently to feel motivated at work, and my instinct is to blame this on a missing sense of purpose or impact. But I’m realising that this sense of purpose or impact may never come from outside; I must start to look back at why I wanted to be a software developer in the first place.&lt;/p&gt;
&lt;p&gt;Looking for external validation for the work we do is futile; you will simply find yourself feeling under-appreciated, misunderstood, or simply unnoticed. Society tells us to find work that matters to others, but this book reminds us to focus on finding joy in the work itself.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>7 ways to use a notebook, inspired by history</title>
    <link href="https://ptrbrynt.com/posts/7-ways-to-use-a-notebook-inspired-by-history/" />
    <updated>2024-12-29T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/7-ways-to-use-a-notebook-inspired-by-history/</id>
    <content type="html">&lt;p&gt;&lt;em&gt;This post is the first in a series called&lt;/em&gt; &lt;a href=&quot;https://ptrbrynt.com/tag/I-Finished-A-Book&quot;&gt;I Finished A Book&lt;/a&gt;&lt;em&gt;, in which I write about a book I’ve read recently. I don’t finish every book I start, so if I do manage to get to the end, that means I must have really liked it.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I am a bit obsessed with notebooks. Every time I see them for sale in a shop, it takes several ounces of my willpower to stop myself from buying a new one. I buy them much faster than I finish them.&lt;/p&gt;
&lt;p&gt;This means I have a pile of blank and barely-used notebooks sitting in my office, and I’m constantly trying to find things to write in them. I recently read &lt;a href=&quot;https://www.google.co.uk/books/edition/The_Notebook/J8arEAAAQBAJ?hl=en&amp;amp;gbpv=0&amp;amp;kptab=getbook&quot;&gt;&lt;strong&gt;The Notebook: A History of Thinking on Paper&lt;/strong&gt;&lt;/a&gt; by Roland Allen, which gave me some really interesting and unusual ideas.&lt;/p&gt;
&lt;h2 id=&quot;1-zibaldone&quot;&gt;1. &lt;em&gt;Zibaldone&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/7-ways-to-use-a-notebook-inspired-by-history/YjRS3tleqz-4608.webp 4608w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/7-ways-to-use-a-notebook-inspired-by-history/YjRS3tleqz-4608.jpeg&quot; alt=&quot;An image with filename: mark-tegethoff-l-GmdF7Md0o-unsplash.jpg&quot; width=&quot;4608&quot; height=&quot;3456&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;The term &lt;em&gt;zibaldone&lt;/em&gt; (plural &lt;em&gt;zibaldoni&lt;/em&gt;)_ _first appeared in the middle of the 14th Century in Florence, Italy, but we’re not sure what the word originally meant. Someone records it as meaning “a salad of many herbs”, but it soon came into popular use to describe a particular use for a notebook.&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;zibalidone&lt;/em&gt; is essentially a miscellany or personal anthology. It was used as a way of collecting all kinds of information, including recipes, lists, and quotations. &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;What did people write in their &lt;em&gt;zibaldoni&lt;/em&gt;? In a word: everything. Poems in Latin, poems in Tuscan, prayers, excerpts from books, songs, recipes, lists, you name it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Essentially, it’s about collecting stuff you think you might find useful. Crucially, it doesn’t have to be neat or well-presented. I’ve started a &lt;em&gt;zibaldone&lt;/em&gt; in a blank, unruled pocket notebook. So far it’s just extracts from books; the first page is a list of tactics I want to try from Jake Knapp and John Zeratsky’s &lt;em&gt;Make Time&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;It might sound like a pain to handwrite this stuff. Why can’t we just save links or photos or paste things into notes apps? Well, as many of us know, there are lots of cognitive benefits to writing by hand. Slowing down the process encourages your brain to actually process the information you’re writing, leading to increased understanding and better memory. Just taking a picture of a page in a book involves zero cognition, so you’re less likely to actually understand the thing you’re trying to save.&lt;/p&gt;
&lt;h2 id=&quot;2-common-placing&quot;&gt;2. Common-placing&lt;/h2&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/7-ways-to-use-a-notebook-inspired-by-history/bYHiAr5gRa-4000.webp 4000w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/7-ways-to-use-a-notebook-inspired-by-history/bYHiAr5gRa-4000.jpeg&quot; alt=&quot;An image with filename: debby-hudson-asviIGR3CPE-unsplash.jpg&quot; width=&quot;4000&quot; height=&quot;2649&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;A common-place book feels a bit like a direct descendant of a &lt;em&gt;zibaldone&lt;/em&gt;. This is a practice that was very popular among academics and scholars, starting with Erasmus of Rotterdam around 1512. It fell out of favour gradually, but common-placing is still used by certain contemporary writers.&lt;/p&gt;
&lt;p&gt;A common-place book is essentially a place in which to collect quotes for later use in your own work. This is where it differs from a &lt;em&gt;zibaldone&lt;/em&gt;, which is intended as a personal reference.&lt;/p&gt;
&lt;p&gt;As a result of this more academic or scholarly purpose, common-place books tend to be more formal, with entries organised in indexed sections according to topics or themes.&lt;/p&gt;
&lt;p&gt;If you enjoy writing in any form, a common-place book might be a useful thing to keep around. Whenever you read something you might want to include or refer to in a piece of your own writing, make a note of it in a common-place notebook.&lt;/p&gt;
&lt;h2 id=&quot;3-waste-book&quot;&gt;3. Waste book&lt;/h2&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/7-ways-to-use-a-notebook-inspired-by-history/Kq6Xu356Hl-1776.webp 1776w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/7-ways-to-use-a-notebook-inspired-by-history/Kq6Xu356Hl-1776.jpeg&quot; alt=&quot;An image with filename: calum-macaulay-CxYHfBkC0vs-unsplash.jpg&quot; width=&quot;1776&quot; height=&quot;1184&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;The conclusion to &lt;em&gt;The Notebook&lt;/em&gt; is a wonderful exploration of our relationship to writing on paper. Recent philosophers have posited that a notebook, used in the right way, can actually be thought of as part of your mind, rather than merely a tool. They can aid in processing complex ideas, or act as an extension of your working and long-term memory.&lt;/p&gt;
&lt;p&gt;A waste book certainly ticks these boxes. Isaac Newton used one in order to support his mathematical study. Many of us have a little notebook on our desks to quickly jot down ideas, help us think through a problem, or simply remember something I want to say during a meeting or conversation.&lt;/p&gt;
&lt;p&gt;A waste book is intended as a temporary first home for thoughts. They are messy, unorganised, and not intended for consumption or use by anyone else. Later, relevant or important notes can be extracted and organised as needed. I used a waste book to write this post, by making notes as I was going through each chapter of &lt;em&gt;The Notebook&lt;/em&gt; to decide what I wanted to include.&lt;/p&gt;
&lt;h2 id=&quot;4-diary-or-journal&quot;&gt;4. Diary or journal&lt;/h2&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/7-ways-to-use-a-notebook-inspired-by-history/yBFUFLvQl0-7008.webp 7008w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/7-ways-to-use-a-notebook-inspired-by-history/yBFUFLvQl0-7008.jpeg&quot; alt=&quot;An image with filename: kelly-sikkema-ochM1ednBR4-unsplash.jpg&quot; width=&quot;7008&quot; height=&quot;4672&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;A diary or journal is simply a record of the stuff that has happened to you. Sometimes, it might include some writing about how it made you feel.&lt;/p&gt;
&lt;p&gt;This has been a popular use for notebooks for quite some time, particularly as literacy rates increased. But why is it useful?&lt;/p&gt;
&lt;p&gt;Often, writing in a diary about our experiences can be a comfort; a bit like confiding in a friend. Indeed, the opening lines of Anne Frank’s legendary and tragic diary read:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;I hope I will be able to confide everything to you, as I have never been able to confide in anyone, and I hope you will be a great source of comfort and support.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It is widely accepted that keeping a daily diary is beneficial to your emotional state, particularly during times of stress or anxiety. Externalising your experiences and feelings on paper is an important and helpful processing method.&lt;/p&gt;
&lt;h2 id=&quot;5-self-care-journal&quot;&gt;5. Self-care journal&lt;/h2&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/7-ways-to-use-a-notebook-inspired-by-history/1y2FwdCQw2-5616.webp 5616w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/7-ways-to-use-a-notebook-inspired-by-history/1y2FwdCQw2-5616.jpeg&quot; alt=&quot;An image with filename: thom-holmes-k-xKzowQRn8-unsplash.jpg&quot; width=&quot;5616&quot; height=&quot;3744&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;A slightly different form of journalling is known as “expressive writing”. This is a genre in which someone writes about an upsetting or traumatic experience.&lt;/p&gt;
&lt;p&gt;A large body of research shows that writing in this way leads to dramatic and unambiguous health benefits. People who perform expressive writing after experiencing trauma have been shown to experience:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Reduced blood pressure&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Lower risk of heart attack&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Improved response to vaccinations&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Faster healing of wounds&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Improved grades at school, college or university&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fewer sick days&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Lower risk of alcoholism after losing a job&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is a surprising list of &lt;em&gt;physical&lt;/em&gt; benefits, and the correlation is so strong that researchers have suggested prescribing this practice as a treatment for PTSD.&lt;/p&gt;
&lt;p&gt;You don’t have to use this method frequently, but if you do, it should go a long way towards helping you process difficult experiences.&lt;/p&gt;
&lt;h2 id=&quot;6-bullet-journal&quot;&gt;6. Bullet journal&lt;/h2&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/7-ways-to-use-a-notebook-inspired-by-history/V-RrzsIfif-2992.webp 2992w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/7-ways-to-use-a-notebook-inspired-by-history/V-RrzsIfif-2992.jpeg&quot; alt=&quot;An image with filename: estee-janssens-aQfhbxailCs-unsplash.jpg&quot; width=&quot;2992&quot; height=&quot;2000&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;Invented by Ryder Carrol as a way of managing his ADHD, &lt;a href=&quot;https://bulletjournal.com/&quot;&gt;Bullet Journalling&lt;/a&gt; has become a bit of a phenomenon. The internet is filled with influencers posting beautifully decorated BuJo pages, and YouTubers frequently share tips, tricks, and “plan with me” videos showing how they use their Bullet Journals.&lt;/p&gt;
&lt;p&gt;But the essence of a Bullet Journal is simple: keep a daily, monthly, and yearly log of to-dos, events, notes, and feelings. Engage in a reflection practice to stay organised and intentional.&lt;/p&gt;
&lt;p&gt;I have personally found a bullet journal incredibly useful in helping me to navigate everyday life. I have previously failed to resist the allure of cool productivity software and apps, but digital devices are riddled with distractions, and apps often impose limitations which don’t work with my brain. A bullet journal is a customisable, simple, low-maintenance, and distraction-free system which I have come to really love and rely on.&lt;/p&gt;
&lt;h2 id=&quot;7-friendship-book&quot;&gt;7. Friendship book&lt;/h2&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://ptrbrynt.com/posts/7-ways-to-use-a-notebook-inspired-by-history/obLe0G60yT-5472.webp 5472w&quot;&gt;&lt;img src=&quot;https://ptrbrynt.com/posts/7-ways-to-use-a-notebook-inspired-by-history/obLe0G60yT-5472.jpeg&quot; alt=&quot;An image with filename: helena-lopes-PGnqT0rXWLs-unsplash.jpg&quot; width=&quot;5472&quot; height=&quot;3648&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;This is a slightly left-field idea from early Dutch academic circles. Many of them kept &lt;em&gt;Stammbücher&lt;/em&gt;, which were notebooks in which friends would write autographs, draw sketches, and write messages.&lt;/p&gt;
&lt;p&gt;This feels a bit like an early precursor for Facebook, which was also originally intended as a way for students to stay connected. Many academics at the time would travel as part of their studies, and a friendship book was a great way to remember the people you had met. It also signalled your position in the social hierarchy.&lt;/p&gt;
&lt;p&gt;If you’re feeling brave, and meet enough new people, you too might consider keeping a friendship book, and inviting new acquaintances to sign it and write a message. There’s a particular romance about this idea which appeals to me somehow.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Notebooks are awesome, and &lt;em&gt;The Notebook&lt;/em&gt; has shown me just how awesome they have been for hundreds of years. In a constantly changing world, people keep coming back to pen and paper to help them stay organised, run their businesses, fuel their creativity, or help them process their experiences and emotions. A notebook is a beautiful, versatile, and incredibly important object, and I am excited to make more use of my growing collection.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Does remote work make me less creative?</title>
    <link href="https://ptrbrynt.com/posts/does-remote-work-make-me-less-creative/" />
    <updated>2024-12-16T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/does-remote-work-make-me-less-creative/</id>
    <content type="html">&lt;p&gt;This question is surprisingly charged, and your response often places you in a specific camp. Either you’re a manager who wants your team in the office, or you’re an “individual contributor” who instinctively protects your right to work remotely.&lt;/p&gt;
&lt;p&gt;My experience with remote work is complex. Before the pandemic, the idea didn’t really cross my mind. I enjoyed going into the office and spending time with my colleagues. I looked forward to meetings and felt enriched by lunch table conversations or quick pool games during coffee breaks. The daily walk to work kept me healthy and energised, and I had a clear separation between work and home.&lt;/p&gt;
&lt;p&gt;Then, remote work was forced upon me and my team. Initially, I expected it to be a temporary novelty, but nearly 5 years later, I haven’t returned to the office. The professional world I inhabit seems to have accepted remote work as a necessity. It’s now a standard requirement for job applicants, and if you don’t offer remote work, you’re missing out on a vast pool of exceptional talent.&lt;/p&gt;
&lt;p&gt;However, over the past few months, I’ve realised that I genuinely miss the days of working in an office. It’s no coincidence that my best work was produced before the pandemic. I thrive on the energy of others and process my ideas more effectively when I can articulate them aloud during collaborative conversations. Unfortunately, I’ve never been able to replicate this experience in an online meeting.&lt;/p&gt;
&lt;p&gt;Additionally, I feel much more focused when there are people around. This is a well-known phenomenon for individuals with ADHD, to the extent that “body doubling” is often recommended as a “focus hack” for distractible minds. In my home office, alone, there’s nothing that prevents me from wasting hours in YouTube rabbit holes. While I can implement systems to prevent this, they’re exhausting to maintain consistently. For me, remote work has led to frequent burnout and a sense of isolation.&lt;/p&gt;
&lt;p&gt;But this isn’t really a post about the advantages of working in an office. It’s more about a need to refocus the conversation. Any attempt to discuss this in a mature manner online invariably ends in a heated argument. I can acknowledge that, for most people, remote work offers significant benefits with minimal drawbacks. However, I believe it’s acceptable and appropriate to admit that this isn’t the case for everyone. For individuals like me, the proximity of an office within our daily commute is a substantial advantage. It could also be viewed as an important accommodation for individuals with ADHD.&lt;/p&gt;
&lt;p&gt;This isn’t about a conflict between management and workers. It’s about accommodating individual needs and preferences. If you’re fortunate enough to be part of the majority, let’s remember to protect the voices of those who may feel they’re “incorrect” for wanting to return to the office, and provide them with accommodations if possible. This approach might be one of the most effective ways to support their success.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Moving to Pika</title>
    <link href="https://ptrbrynt.com/posts/moving-to-pika/" />
    <updated>2024-12-03T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/moving-to-pika/</id>
    <content type="html">&lt;p&gt;I’ve just moved my blog from &lt;a href=&quot;https://ghost.org&quot;&gt;Ghost&lt;/a&gt; to &lt;a href=&quot;https://pika.page&quot;&gt;Pika&lt;/a&gt;. I have no problem with Ghost; I think it’s an amazing platform with a great philosophy, and it’s taking the web in a good direction. I’m rooting for them.&lt;/p&gt;
&lt;p&gt;That said, I’m not interested in turning my blog into a business, and the publishing tools provided by Ghost just aren’t for me. I recently discovered Pika, which is half the cost and much simpler. I also prefer the available themes, which support custom CSS without a higher-tier subscription plan.&lt;/p&gt;
&lt;p&gt;If, like me, you believe in personal blogging and want a little home on the internet, &lt;a href=&quot;https://pika.page&quot;&gt;Pika&lt;/a&gt; is a great option.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>How I manage my ADHD</title>
    <link href="https://ptrbrynt.com/posts/how-i-manage-my-adhd/" />
    <updated>2024-07-29T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/how-i-manage-my-adhd/</id>
    <content type="html">&lt;p&gt;I have undiagnosed ADHD. Without going into specifics, this means I have a lot of challenges around attention, memory, motivation, and executive function. I procrastinate a lot, struggle to focus on certain kinds of tasks, and forget about stuff.&lt;/p&gt;
&lt;p&gt;Because my ADHD is undiagnosed, and I&#39;m not able to get a diagnosis thanks to the state of mental healthcare in the UK, I have had to learn to manage it without medication.&lt;/p&gt;
&lt;p&gt;There is a lot of great advice online and in books for those of us with ADHD. I wanted to list some of the tools and techniques I have personally found helpful.&lt;/p&gt;
&lt;p&gt;ADHD is a deeply personal experience, so some of these ideas might not work for everyone. But everything is worth a try!&lt;/p&gt;
&lt;h2 id=&quot;capture-everything&quot;&gt;Capture everything&lt;/h2&gt;
&lt;p&gt;Getting Stuff Done with ADHD can be really hard, and having the right tools to support you is essential. I&#39;ve tried all sorts of systems, from bullet journalling to automated AI scheduling.&lt;/p&gt;
&lt;p&gt;The most important feature of any productivity system for ADHDers, though, is simplicity. It’s inevitable that you will drop it at some point, and it should be easy and frictionless to pick it back up again.&lt;/p&gt;
&lt;p&gt;For me, the “&lt;a href=&quot;https://gettingthingsdone.com&quot;&gt;Getting Things Done&lt;/a&gt;” method, using &lt;a href=&quot;https://culturedcode.com/things/&quot;&gt;Things 3&lt;/a&gt; as my software, works best for this. The best feature of this methodology and software for me has been the quick capture: having the ability to very quickly write down a task I think of, so that I don’t forget it or ruminate on it while I’m supposed to be focussed on something else.&lt;/p&gt;
&lt;h2 id=&quot;fidget&quot;&gt;Fidget&lt;/h2&gt;
&lt;p&gt;I have bitten my fingernails for literally longer than I can remember. This has been the main presentation of hyperactivity for me, and it’s not ideal. Eventually, I run out of fingernail to chew.&lt;/p&gt;
&lt;p&gt;This is where fidgets come in. I was an early adopter of the &lt;a href=&quot;https://www.antsylabs.com/products/fidget-cube-the-original-fidget-toy&quot;&gt;Fidget Cube&lt;/a&gt; when it first appeared, and I’m a little bit addicted to buying new fidgets. They’re everywhere in my house, and I even have &lt;a href=&quot;https://amzn.eu/d/0fsO1vu8&quot;&gt;one which fits in the little coin pocket of my jeans&lt;/a&gt;. I love them.&lt;/p&gt;
&lt;h2 id=&quot;have-nice-things&quot;&gt;Have nice things&lt;/h2&gt;
&lt;p&gt;Doing hard things is a little bit less hard when you enjoy using the tools you need to use. I think that’s why I’ve always been a bit obsessed with buying nice stuff for my desk, like a &lt;a href=&quot;https://www.lamy.com/en/lamy-swift/&quot;&gt;really nice pen&lt;/a&gt;, or a &lt;a href=&quot;https://www.keychron.com/products/keychron-k3-wireless-mechanical-keyboard&quot;&gt;mechanical keyboard&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For me, the quality is a necessity as much as it is a luxury: I’m more likely to sit down and do work if I can look forward to typing on my lovely keyboard, or if my code editor has a &lt;a href=&quot;https://draculatheme.com&quot;&gt;really nice colour scheme&lt;/a&gt; and font. (Yes, I have &lt;a href=&quot;https://philpl.gumroad.com/l/dank-mono&quot;&gt;paid&lt;/a&gt; &lt;a href=&quot;https://www.monolisa.dev&quot;&gt;money&lt;/a&gt; for programming fonts.) Spending a bit of extra money on my physical and digital tools is an investment in my future productivity. At least, that’s what I’m telling myself.&lt;/p&gt;
&lt;h2 id=&quot;use-timers&quot;&gt;Use timers&lt;/h2&gt;
&lt;p&gt;I’m a &lt;em&gt;huge&lt;/em&gt; fan of the &lt;a href=&quot;https://www.pomodorotechnique.com&quot;&gt;pomodoro technique&lt;/a&gt;. There is something magical about the act of starting a timer: it seems to kick my brain into gear and break down whatever wall is in the way of my executive function.&lt;/p&gt;
&lt;p&gt;I have a digital timer called &lt;a href=&quot;https://tomito.app&quot;&gt;Tomito&lt;/a&gt; installed on my Mac, which displays a little countdown in the corner of my display. I’ve hooked it up to &lt;a href=&quot;https://www.raycast.com&quot;&gt;Raycast&lt;/a&gt; and set up keyboard shortcuts, so starting a 25-minute timer is as easy as hitting ⌥ (Option) + Space.&lt;/p&gt;
&lt;p&gt;The other advantage of using timers is that it reminds me to take frequent breaks. This prevents unwanted &lt;a href=&quot;https://www.webmd.com/add-adhd/hyperfocus-flow&quot;&gt;hyperfocus&lt;/a&gt; and ensures I can work sustainably for longer each day.&lt;/p&gt;
&lt;h2 id=&quot;stay-active&quot;&gt;Stay active&lt;/h2&gt;
&lt;p&gt;It has taken me 29 years of living to finally accept the benefits of regular exercise, particularly for an ADHD brain. I have recently started running and swimming, and I really notice the difference if I don’t exercise in the morning. I feel less energetic, more bored, and less focused.&lt;/p&gt;
&lt;h2 id=&quot;sleep&quot;&gt;Sleep&lt;/h2&gt;
&lt;p&gt;I am incredibly lucky, because I don’t really have any problems with sleep. I know that this makes me very fortunate amongst my ADHD peers, many of whom struggle with insomnia.&lt;/p&gt;
&lt;p&gt;I have very healthy habits around sleep: I maintain a regular schedule, and I make sure I wake up with my alarm at the same time every morning. Yes, even on weekends.&lt;/p&gt;
&lt;p&gt;I recently came back from a trip to the US, and the jetlag I suffered upon my return rendered me basically useless for 6 straight days. It was an excellent reminder of the importance of good sleep.&lt;/p&gt;
&lt;h2 id=&quot;uninstall-social-media&quot;&gt;Uninstall social media&lt;/h2&gt;
&lt;p&gt;I’m planning a much more comprehensive post about this, but I cannot overstate the impact on my life that quitting social media has had.&lt;/p&gt;
&lt;p&gt;I no longer look at social media (including YouTube) or news websites for longer than 45 minutes a day. I use an app called &lt;a href=&quot;https://jomo.so&quot;&gt;Jomo&lt;/a&gt;, which blocks these distractions by default but allows me 3 “breaks” of up to 15 minutes each day.&lt;/p&gt;
&lt;p&gt;I have so much time back, and I am being much more deliberate in my decisions around how I spend my time. I have started listening to albums and podcasts as entertainment instead of background noise. I have found the time to watch movies and shows I’ve been meaning to look at for months. And I procrastinate less.&lt;/p&gt;
&lt;p&gt;There’s no easy way to say this: social media and YouTube are distracting, and are not worth the mediocre entertainment value they provide. Block yourself out.&lt;/p&gt;
&lt;h2 id=&quot;remember-why&quot;&gt;Remember why&lt;/h2&gt;
&lt;p&gt;ADHD brains really struggle with motivation. So I remind myself on the hardest days that there is a grander purpose behind my work: I am supporting my family, and funding the hobbies that bring me joy and fulfilment. Photos on my desk, and on my computer, serve to remind me what this is really all about.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>The floggings will continue until morale improves</title>
    <link href="https://ptrbrynt.com/posts/the-floggings-will-continue-until-morale-improves/" />
    <updated>2024-06-21T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/the-floggings-will-continue-until-morale-improves/</id>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;flogging&lt;/strong&gt; · &lt;em&gt;noun&lt;/em&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Infliction of punishment by dealing blows or whipping.&lt;/li&gt;
&lt;li&gt;Beating with a whip or strap or rope as a form of punishment. &lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Wiktionary, Creative Commons Attribution/Share-Alike License&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;The title of this post is a quote of &lt;a href=&quot;https://quoteinvestigator.com/2020/07/15/morale/#google_vignette&quot;&gt;unclear origin&lt;/a&gt;, which I spotted at the &lt;a href=&quot;https://www.beamish.org.uk&quot;&gt;Beamish Museum&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It&#39;s pretty silly on its face, but the reason I love it so much is because it reflects the way many of us treat ourselves. We punish ourselves when we are not as productive or successful as we want to be. The quote highlights how absurd this behaviour is.&lt;/p&gt;
&lt;p&gt;Management theory is absolutely full of advice about positive reinforcement and being compassionate. But we so rarely apply this to ourselves. Instead, we beat ourselves up because we think we will feel better if we work harder or do more.&lt;/p&gt;
&lt;p&gt;Instead, we need to do what a good manager would do: be compassionate and non-judgemental, and address the root cause of the problem.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Wix Studio is terrible</title>
    <link href="https://ptrbrynt.com/posts/wix-studio-is-terrible/" />
    <updated>2024-06-07T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/wix-studio-is-terrible/</id>
    <content type="html">&lt;p&gt;I had a task this week: to make a website for a friend.&lt;/p&gt;
&lt;p&gt;All he wanted was a few static pages, then one CMS-connected page displaying a list of items, with a couple of links and embedded media. He didn’t want to have to fiddle about with the website building tools; if he could just add the data to a table and have it populate his site, he would be happy.&lt;/p&gt;
&lt;p&gt;My first thought was, “This is exactly the kind of thing you should be able to do with a no-code site building tool.”&lt;/p&gt;
&lt;p&gt;Dearest reader, I was wrong.&lt;/p&gt;
&lt;h2 id=&quot;over-promise-and-under-deliver&quot;&gt;Over-promise and under-deliver&lt;/h2&gt;
&lt;p&gt;Wix Studio is the platform I decided to use. On its face, it has all the features I needed: a CMS feature with the ability to create your own data structures, and Repeaters allowing you to display data from your CMS tables.&lt;/p&gt;
&lt;p&gt;It even promises to use AI to make your website responsive across different screen sizes.&lt;/p&gt;
&lt;p&gt;The problem is that this might be the worst piece of software I have ever used. The CMS features are weirdly limited; for example, you can’t show or hide elements in a repeater based on a condition (e.g. if this field is empty, don’t display this button). You &lt;em&gt;can&lt;/em&gt; create a table which neatly displays the CMS data, but you can’t customise how any of the field are displayed; if a field contains a link, you can’t turn it into a button. It’s just a plaintext link that isn’t even clickable.&lt;/p&gt;
&lt;p&gt;Oh, and the responsive AI flat-out doesn’t work. I wanted to include an embedded audio file for each CMS entry, but the element is not resizeable at all, so it overflows on smaller screens. And the AI makes &lt;em&gt;terrible&lt;/em&gt; decisions about how to scale things for smaller screens.&lt;/p&gt;
&lt;p&gt;I would have provided a screenshot of this garbage, but in my rage I destroyed everything.&lt;/p&gt;
&lt;h2 id=&quot;the-only-other-option&quot;&gt;The only other option&lt;/h2&gt;
&lt;p&gt;There are plenty of amazing website building tools. I personally love Squarespace. But it doesn’t have the CMS features I need.&lt;/p&gt;
&lt;p&gt;That said, it turns out that I can build the site I want incredibly easily using &lt;a href=&quot;http://strapi.io/&quot;&gt;Strapi&lt;/a&gt; and &lt;a href=&quot;https://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt;. So that’s what I’m doing. And I’m enjoying it very much.&lt;/p&gt;
&lt;h2 id=&quot;who-is-wix-studio-for&quot;&gt;Who is Wix Studio for?&lt;/h2&gt;
&lt;p&gt;This then begs the question, who is the intended audience for Wix Studio? Even if it worked (which it doesn’t), the extremely complex tooling is apparently aimed at agencies making websites for clients. But if you need tools this complex, you probably need at least &lt;em&gt;some&lt;/em&gt; custom code, and so you’ll be hiring a developer. At which point, why not just build the site from scratch and have it completely bespoke?&lt;/p&gt;
&lt;p&gt;On the other end of the spectrum, if all you want is a simple website with some static pages, you are going to be so frustrated with Wix Studio’s cumbersome UX that you’ll give up and use something else.&lt;/p&gt;
&lt;p&gt;The conclusion: nobody should use Wix Studio. Code it from scratch, or use Squarespace.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>This budgeting app changed my life</title>
    <link href="https://ptrbrynt.com/posts/this-budgeting-app-changed-my-life/" />
    <updated>2024-05-29T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/this-budgeting-app-changed-my-life/</id>
    <content type="html">&lt;p&gt;This isn’t a typical “this app changed my life” post. Most of those seem to be written within a few days of someone trying a new app for the first time.&lt;/p&gt;
&lt;p&gt;This app recommendation comes off the back of over 2 years of continuous use. Without this app, my life would be substantially worse.&lt;/p&gt;
&lt;p&gt;The app is &lt;a href=&quot;https://ynab.com&quot;&gt;YNAB&lt;/a&gt;, which stands for “You Need A Budget”.&lt;/p&gt;
&lt;p&gt;This piece of software is remarkable in its ability to truly transform a person’s life. Before, I lived month-to-month and didn’t really save much. If a trip came along, I’d just pay for it all that month. I wasn’t prepared for emergency spending, but simultaneously my impulse purchasing was out of control (thanks, ADHD).&lt;/p&gt;
&lt;p&gt;Now I have YNAB, I feel financially prepared for pretty much anything. I save up over time for every trip I have planned. I have money set aside for emergency purchases. And I can see what I can afford to save up for big purchases. I’m setting aside &lt;em&gt;serious money&lt;/em&gt; for the first time in my life.&lt;/p&gt;
&lt;p&gt;This app has given me control over my money, and my life.&lt;/p&gt;
&lt;p&gt;Do you need to use this specific budgeting app? Possibly not. But I have tried a few, and this is the one that clicked for me. I was initially resistant because you need to change how you think about money and budgeting in order to make it work, but their &lt;a href=&quot;https://youtube.com/@ynabofficial?si=bytIlOBgYWs3y1w_&quot;&gt;YouTube channel&lt;/a&gt; has been extremely helpful - thanks Hannah!&lt;/p&gt;
&lt;p&gt;If you don’t have a solution for this already, I strongly encourage you to try YNAB. It’s been amazing, and it’s the one piece of software I genuinely don’t think I could live without.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>In the real world, refactoring is a software engineer’s secret weapon</title>
    <link href="https://ptrbrynt.com/posts/in-the-real-world-refactoring-is-a-software-engineers-secret-weapon/" />
    <updated>2023-11-14T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/in-the-real-world-refactoring-is-a-software-engineers-secret-weapon/</id>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Refactoring is a systematic process of improving code without creating new functionality that can transform mess into clean code and simple design.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you&#39;ve been doing software development for long enough, you probably know how to build a codebase from scratch using industry best practices. You can take that blank canvas and turn it into something beautifully crafted, thoroughly covered with tests, and maintainable for years to come.&lt;/p&gt;
&lt;p&gt;But, dear reader, I regret to inform you that if you develop software professionally, you will rarely need these skills.&lt;/p&gt;
&lt;p&gt;It is extremely uncommon to find a job which will let you start a codebase from scratch. Almost invariably, the first task at a new software job involves taking an existing codebase and learning to work within it.&lt;/p&gt;
&lt;p&gt;When I started my current role at &lt;a href=&quot;https://qured.com&quot;&gt;Qured&lt;/a&gt;, I came across this problem. I was to inherit a codebase which had been developed by a consultancy. And this codebase had &lt;em&gt;problems&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;But in my previous job, I had been spoiled. I previously worked for a development agency, where most of our projects were new builds. We had total control over the architectural decisions and day-to-day enforcement of code standards. We wrote some amazing code.&lt;/p&gt;
&lt;p&gt;So when I came into my new job, I saw this codebase and panicked. My first instinct was to say, &amp;quot;This thing needs rebuilding.&amp;quot; I couldn&#39;t face the idea of working with this codebase every day.&lt;/p&gt;
&lt;p&gt;But I realised that, in the real world, we can&#39;t just take 12 months out of a busy product pipeline to start an app from scratch. The code may not have been good, but the app was released and was being used by real people. It contained a lot of complex business logic, handling all kinds of edge cases that could only have been discovered by putting the app into the wild and letting real users break it.&lt;/p&gt;
&lt;p&gt;And it worked. So my job was to keep it working while improving our ability to maintain and iterate on the code.&lt;/p&gt;
&lt;p&gt;This is where refactoring comes in. Refactoring is a set of techniques which allows you to improve an existing codebase, making it more maintainable and easier to understand. Refactoring is a very important tool if you want to ensure your codebase is set up to support your product roadmap in the future.&lt;/p&gt;
&lt;h2 id=&quot;learning-to-refactor&quot;&gt;Learning to refactor&lt;/h2&gt;
&lt;p&gt;Refactoring is not the same as building a project from scratch. Being able to improve an existing codebase involves several skills:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Being able to explain the business case for refactoring, given that many of the changes you make won&#39;t affect the user experience or introduce any new functionality&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Being able to identify and prioritise the changes you want to make&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Assessing the risk of any changes you&#39;re making&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Being able to effectively verify you haven&#39;t broken anything in the process, which may or may not involve the use of automated tests&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Understanding what is wrong with the code, what the improved version looks like, and the steps required to get there&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Good version control skills&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;An amazing resource I discovered was &lt;a href=&quot;https://refactoring.guru/&quot;&gt;Refactoring Guru&lt;/a&gt;. This website lists various &amp;quot;code smells&amp;quot; and links them to refactoring techniques which can be used to fix them. It also includes a handy list of design patterns, which can be applied to your codebase to improve the architectural design.&lt;/p&gt;
&lt;h2 id=&quot;pitfalls&quot;&gt;Pitfalls&lt;/h2&gt;
&lt;p&gt;When refactoring, it&#39;s easy to &lt;em&gt;think&lt;/em&gt; you&#39;re helping when you actually may be introducing more complexity.&lt;/p&gt;
&lt;p&gt;For example, a common and perhaps obvious move would be to abstract the functionality of a third-party library using the &lt;a href=&quot;https://refactoring.guru/design-patterns/facade&quot;&gt;facade pattern&lt;/a&gt;. This pattern hides the implementation details of a piece of functionality from the classes which depend on it.&lt;/p&gt;
&lt;p&gt;But this pattern can often introduce additional complexity. In my experience, writing more code rarely leads to a simpler, more maintainable outcome.&lt;/p&gt;
&lt;h3 id=&quot;facade-pattern-example&quot;&gt;Facade Pattern example&lt;/h3&gt;
&lt;p&gt;Let&#39;s say we find this class in our codebase:&lt;/p&gt;
&lt;p&gt;class RegisterViewModel {
RegisterViewModel(this._auth);&lt;/p&gt;
&lt;p&gt;final FirebaseAuth _auth;&lt;/p&gt;
&lt;p&gt;Future&lt;void&gt; register({
required String email,
required String password,
}) async {
await _auth.registerWithEmailAndPassword(
email: email,
password: password,
);
await _auth.signIn(
email: email,
password: password,
);
}
}&lt;/void&gt;&lt;/p&gt;
&lt;p&gt;You might look at this and think, &amp;quot;I can refactor this so that the ViewModel doesn&#39;t have to directly depend on Firebase, which will allow me to switch to a different authentication system in the future.&amp;quot; This is a fair conclusion, so let&#39;s see what that might look like:&lt;/p&gt;
&lt;p&gt;class AuthRepository {
AuthRepository(this._auth);&lt;/p&gt;
&lt;p&gt;final FirebaseAuth _auth;&lt;/p&gt;
&lt;p&gt;Future&lt;void&gt; register({
required String email,
required String password,
}) async {
await _auth.registerWithEmailAndPassword(
email: email,
password: password,
);
await _auth.signIn(
email: email,
password: password,
);
}
}&lt;/void&gt;&lt;/p&gt;
&lt;p&gt;class RegisterViewModel {
RegisterViewModel(this._authRepository);&lt;/p&gt;
&lt;p&gt;final AuthRepository _authRepository;&lt;/p&gt;
&lt;p&gt;Future&lt;void&gt; register({
required String email,
required String password,
}) async {
await _authRepository.register(
email: email,
password: password,
);
}
}&lt;/void&gt;&lt;/p&gt;
&lt;p&gt;A legitimate argument could be made that our introduction of the facade pattern has improved the design of this code. But has our codebase truly benefitted from this change? The second, refactored version has more code than the first version. Additionally, the inner workings of the registration functionality are obscured from the ViewModel class; a developer working here may not realise that the &lt;code&gt;register&lt;/code&gt; method creates an account and signs in as part of the same method.&lt;/p&gt;
&lt;p&gt;Indeed, there is an argument to be made that this is an &amp;quot;anti-refactor&amp;quot;. There is a refactoring pattern known as &amp;quot;&lt;a href=&quot;https://refactoring.guru/remove-middle-man&quot;&gt;removing the middle man&lt;/a&gt;&amp;quot; which aims to avoid precisely the kind of structure we&#39;ve introduced here.&lt;/p&gt;
&lt;p&gt;The lesson here is to be cautious; don&#39;t just apply refactoring patterns because you see an opportunity. Take a step back and make sure the change you&#39;re making will &lt;em&gt;reduce&lt;/em&gt; complexity, not increase it.&lt;/p&gt;
&lt;h2 id=&quot;roll-your-sleeves-up&quot;&gt;Roll your sleeves up&lt;/h2&gt;
&lt;p&gt;As with many software skills, the best way to learn is to practice using real code. Here are some ideas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Find a personal project from a few years ago and bring it up-to-date&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use online training exercises like &lt;a href=&quot;https://understandlegacycode.com/blog/5-coding-exercises-to-practice-refactoring-legacy-code/&quot;&gt;these&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Study open-source projects on &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt; and make improvements. You could even submit your improvements as pull requests to get feedback!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you get very familiar with an open-source project, you can start contributing code reviews for other contributors&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And some important tips:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Learn and practice design patterns and common refactoring methods&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Take things in small steps&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Break down big refactoring tasks into smaller pieces of work&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Take the opportunity to incorporate test-driven development. Refactoring shouldn&#39;t change any functionality (unless you find a bug along the way), so writing a test before you start refactoring can improve confidence in the changes you&#39;re making, help to build another skillset, and improve overall test coverage.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Your IDE probably has tools available to help with refactoring, such as symbol renaming, method/class extraction, and other useful tricks.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Work in pairs and talk through your decisions with a colleague/friend.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;If you&#39;re more of a book person, Martin Fowler has written the canonical guide to refactoring - you can find out more&lt;/em&gt; &lt;a href=&quot;https://refactoring.com&quot;&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;wrap-up&quot;&gt;Wrap-up&lt;/h2&gt;
&lt;p&gt;Refactoring is a vital skill for software engineers, as it allows them to improve existing codebases without affecting functionality. But many of us undervalue these skills.&lt;/p&gt;
&lt;p&gt;By learning to identify code smells, prioritizing changes, and effectively applying design patterns and refactoring methods, developers can enhance the maintainability of software projects, making them fit for the future. While building a project from scratch may be ideal, refactoring is the secret weapon for tackling real-world challenges and ensuring long-term success.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Flutter needs to break free from Material</title>
    <link href="https://ptrbrynt.com/posts/flutter-needs-to-break-free-from-material/" />
    <updated>2023-05-16T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/flutter-needs-to-break-free-from-material/</id>
    <content type="html">&lt;p&gt;I&#39;ve been lucky to work on a large number of Flutter apps from scratch. Each time, we have done what we believed to be the right thing: started with a &lt;code&gt;MaterialApp&lt;/code&gt; and tweaked it to suit the style of our app.&lt;/p&gt;
&lt;p&gt;I think a lot of Flutter devs do the same thing. After all, what are our other options? It doesn&#39;t always make sense to start by building our own component library; that stuff takes time, and the Material library has a huge amount of functionality and customisability built-in. If you&#39;re trying to get a new project to market fast, you&#39;d be pretty daft not to use a pre-built component library. And right now, Material seems to be the only widely available and well-maintained option.&lt;/p&gt;
&lt;p&gt;Why is this a problem? Well, I think there are two issues. The first is that this behaviour is blurring the line between Flutter and Material. It seems like Flutter assumes most people will use Material, because functionality you would think is non-specific to Material sometimes ends up being Material-exclusive. For example, the Form API is only implemented for Material-specific &lt;code&gt;TextFormField&lt;/code&gt; widgets and doesn&#39;t support the generic &lt;code&gt;EditableText&lt;/code&gt; widget out-of-the-box.&lt;/p&gt;
&lt;p&gt;This then becomes a self-fulfilling prophecy; as the Material library gets more functionality that doesn&#39;t come with vanilla Flutter, more folks just use the Material library. And the more folks default to it, the more effort is spent on it rather than putting effort into improving the non-Material functionality in vanilla Flutter. So that leads to Material getting even more functionality, further locking in developers.&lt;/p&gt;
&lt;p&gt;However, as developers have felt more and more locked into Material, the more demand there has been for extra customisability. Everyone is essentially trying to shoehorn their own app designs to fit the opinionated Material design language. So the Material developers have been forced to add extra features and customisability options to the package (e.g. &lt;code&gt;ThemeExtensions&lt;/code&gt;). This is great, except that it&#39;s created a massive API surface for Material themes which is extremely difficult to understand and use. On the one hand you&#39;re forced into using a preset list of text styles (&lt;code&gt;headlineLarge&lt;/code&gt;, &lt;code&gt;bodyMedium&lt;/code&gt; and so on), but you&#39;re also given the option of changing the text style for individual Text widgets, breaking the whole typography system. If Material was true to its design language, you would be limited to only using text styles defined by the theme, but because this doesn&#39;t fit everyone&#39;s individual design needs, per-widget customisation had to be supported.&lt;/p&gt;
&lt;p&gt;At its core, I think this problem comes down to an identity crisis in the Material library. It&#39;s simultaneously trying to be an implementation of the very opinionated Material design system, while also supporting enough customisation for developers to be able to implement their own design systems using the tools provided by the Material library.&lt;/p&gt;
&lt;h2 id=&quot;the-solution&quot;&gt;&lt;strong&gt;The solution&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;I think the solution is for the community to start rolling out Material-free component libraries. These can be opinionated or not, but it&#39;s the first and most important step towards Flutter breaking free from Material. Not only will this make life better for Flutter developers (more choice is always better); it will also allow the Material library to become the best version of itself, potentially toning down some of its customisability options and doubling down on its opinionated design style.&lt;/p&gt;
&lt;p&gt;Ultimately, Material should be a choice and not something you just use by default. I&#39;d even go so far as to say that it should be unbundled from Flutter, and if you want to use it you would need to explicitly add it as a dependency. That would be a great signal to developers that Material isn&#39;t the only option, and you should go out and find the component library or design system that works best for you.&lt;/p&gt;
&lt;p&gt;I&#39;m happily getting the ball rolling by working on my own Material-free component library for Flutter. Catalyst UI will be an unopinionated component library, drawing plenty of inspiration from Tailwind UI. I&#39;m having lots of fun with it so far and I&#39;m excited for a future in which Flutter developers have more choice over the style of UI they want for their apps.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>How to actually do TDD in Flutter</title>
    <link href="https://ptrbrynt.com/posts/how-to-actually-do-tdd-in-flutter/" />
    <updated>2022-08-04T00:00:00Z</updated>
    <id>https://ptrbrynt.com/posts/how-to-actually-do-tdd-in-flutter/</id>
    <content type="html">&lt;p&gt;This post is the result of a months-long existential crisis about how to do testing in Flutter apps. There are &lt;em&gt;so many&lt;/em&gt; resources, tutorials, and opinions on how this should be done, but most of them give what is, in my opinion, bad advice.&lt;/p&gt;
&lt;p&gt;The aim of this post is to put forward a case for a change in direction. The Flutter community is barrelling towards a nightmare of unmaintainable test suites, and development practices which waste more time than they save. We need to look at the practices we&#39;re encouraging as a community and ensure that we are promoting good engineering that delivers &lt;strong&gt;value&lt;/strong&gt; to our customers.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A lot of the ideas in this post came from a fantastic talk by Ian Cooper at Devternity 2017 called &amp;quot;TDD: Where did it all go wrong?&amp;quot; It&#39;s worth watching that video first before trying to apply the ideas to Flutter. Here&#39;s the link:&lt;/em&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=EZ05e7EMOLM&quot;&gt;&lt;em&gt;🚀 TDD, Where Did It All Go Wrong (Ian Cooper)&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-problems-we-re-trying-to-solve&quot;&gt;The problems we&#39;re trying to solve&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Tests hold us hostage.&lt;/strong&gt; When we write over-specified tests, we couple them to our implementation details. This means that any changes we make to the implementation are likely to break a bunch of tests. This is extremely frustrating for a development team to have to deal with. It makes things difficult when they&#39;re supposed to be easy.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Achieving high coverage is hard.&lt;/strong&gt; When we test at class level - which most of the advice says we should - we can get fairly good test coverage without too much trouble. But the last 20% or so is usually extremely difficult to cover, and often gets left out. This means that there is loads of untested code in our project.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Writing tests takes too long.&lt;/strong&gt; We seem to spend most of our time writing fiddly tests to cover things that we know should just work.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Maintaining high coverage is hard.&lt;/strong&gt; The first three problems combined mean that over time, coverage slowly deteriorates as developers give up covering their changes with appropriate tests.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;some-rules-for-tdd&quot;&gt;Some rules for TDD&lt;/h2&gt;
&lt;p&gt;If we&#39;re going to solve the problems above and still have a well-tested app, we need to learn (or re-learn) some important principles. Some of these were totally new to me; some I knew but didn&#39;t understand properly.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;A unit is not a class.&lt;/strong&gt; Or a method, or a function. A &lt;em&gt;unit&lt;/em&gt; is an encapsulation of functionality, which could be implemented as lots of classes, or a single function, or an entire app. It&#39;s a super unhelpful word. I&#39;ve stopped using the phrase &amp;quot;unit tests&amp;quot;; I call them &amp;quot;developer tests&amp;quot; or &amp;quot;automated tests&amp;quot; now.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Test behaviour, not implementation.&lt;/strong&gt; You should write tests based on requirements like, &amp;quot;When I type in a valid email and password, then press the login button, I should be taken to the home screen.&amp;quot; &lt;strong&gt;Don&#39;t&lt;/strong&gt; write tests like this: &amp;quot;When I type in a valid email address and password, then press the login button, the &lt;code&gt;login&lt;/code&gt; method on the &lt;code&gt;AuthRepository&lt;/code&gt; class should be called with the correct parameters.&amp;quot;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;UI design is not behaviour.&lt;/strong&gt; It is totally impractical and unnecessary to test the design of your app using automated testing techniques such as golden testing. It holds your design hostage and means your tests break anytime you want to tweak something visual which doesn&#39;t actually change how the app works. The tooling is also horrible. This is precisely the purpose of human QA.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Tests must not drive code design decisions.&lt;/strong&gt; I&#39;ve seen some well-respected thought leaders in software engineering say that the design of your code should be informed or even dictated by your tests. But this breaks one of the fundamental rules of TDD, which is that tests should &lt;em&gt;not&lt;/em&gt; be coupled to the implementation of the behaviour under test. If your tests require you to design your code in a particular way, you&#39;ve written your tests wrong.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Don&#39;t mock your own code.&lt;/strong&gt; I&#39;ve often done this in order to isolate the class I&#39;m testing from its dependencies. It&#39;s unnecessary, as we&#39;ll discover.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Don&#39;t skip the refactoring step.&lt;/strong&gt; The red-green-refactor cycle is much more important for TDD than most developers realise.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;an-example&quot;&gt;An example&lt;/h2&gt;
&lt;p&gt;Let&#39;s build a very simple password reset screen. It has a field for you to enter a username, which can&#39;t be blank, and a button which submits the request. If the request fails, we want to show the error message. Otherwise, we want to go back to the login screen.&lt;/p&gt;
&lt;p&gt;In this example, the app uses Firebase Auth. Because this is an &lt;strong&gt;external&lt;/strong&gt; dependency, we&#39;re going to use a test double which mimics the behaviour of the real &lt;code&gt;FirebaseAuth&lt;/code&gt;implementation. If you were using a different authentication system which worked over HTTP requests, you could use something like &lt;code&gt;http_mock_adapter&lt;/code&gt; to fake your API responses.&lt;/p&gt;
&lt;p&gt;We&#39;re also using &lt;a href=&quot;https://riverpod.dev/&quot;&gt;Riverpod&lt;/a&gt; as our DI solution. These techniques obviously don&#39;t require Riverpod, but I&#39;ve found Riverpod to be the best DI/state management solution, so it&#39;s what I use.&lt;/p&gt;
&lt;h3 id=&quot;step-1-write-a-test-or-set-of-tests-that-fails&quot;&gt;&lt;strong&gt;Step 1: Write a test (or set of tests) that fails&lt;/strong&gt;&lt;/h3&gt;
&lt;pre class=&quot;language-dart&quot;&gt;&lt;code class=&quot;language-dart&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;reset password screen&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;testWidgets&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
          &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;&#39;&#39;goes to the login screen when a valid username is entered and the request succeeds&#39;&#39;&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tester&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; auth &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MockFirebaseAuth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;signedIn&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            
            &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; tester&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pumpWidget&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
              &lt;span class=&quot;token class-name&quot;&gt;ProviderScope&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
                overrides&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
                  firebaseAuthProvider&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;overrideWithValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;auth&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                child&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MyApp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
                  initialRoute&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/login/forgot-password&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            
            &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; tester&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;enterText&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
              find&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;byKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;forgot-password-username-field&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;username&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            
            &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; tester&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;tap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
              find&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;byKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;forgot-password-submit-button&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            
            &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; tester&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pumpAndSettle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            
            &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
              find&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;byType&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;LoginWidget&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
              findsOneWidget&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        
        &lt;span class=&quot;token function&quot;&gt;testWidgets&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
          &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;&#39;&#39;displays an error message in a snackbar when the user is not found&#39;&#39;&#39;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tester&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; auth &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MockFirebaseAuth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
              signedIn&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
              authExceptions&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AuthExceptions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
                sendPasswordResetEmail&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FirebaseAuthException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;code&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;auth/user-not-found&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            
            &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; tester&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pumpWidget&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
              &lt;span class=&quot;token class-name&quot;&gt;ProviderScope&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
                overrides&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
                  firebaseAuthProvider&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;overrideWithValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;auth&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                child&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MyApp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
                  initialRoute&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/login/forgot-password&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            
            &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; tester&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;enterText&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
              find&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;byKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;forgot-password-username-field&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;username&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            
            &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; tester&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;tap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
              find&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;byKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;forgot-password-submit-button&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            
            &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; tester&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pumpAndSettle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            
            &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
              find&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;User not found&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
              findsOneWidget&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        
        &lt;span class=&quot;token function&quot;&gt;testWidgets&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
          &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;&#39;&#39;shows a validation error when no username is entered&#39;&#39;&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tester&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; tester&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pumpWidget&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
              &lt;span class=&quot;token class-name&quot;&gt;ProviderScope&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
                child&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MyApp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
                  initialRoute&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/login/forgot-password&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            
            &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; tester&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;tap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
              find&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;byKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;forgot-password-submit-button&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            
            &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; tester&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pumpAndSettle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            
            &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
              find&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;descendant&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
                of&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; find&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;byKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;forgot-password-username-field&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                matching&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; find&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Please enter your username&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
              findsOneWidget&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Some important things to note about this test:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;We are running the whole app, rather than only pumping the widget under test. This is so we don&#39;t have to bother with any navigation mocking.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We always refer to widgets by keys, not by types. This is to ensure we can change the type of widget without the test breaking (e.g. if an &lt;code&gt;ElevatedButton&lt;/code&gt; becomes a &lt;code&gt;TextButton&lt;/code&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The exception to this rule is when we check that the &lt;code&gt;LoginWidget&lt;/code&gt; is visible. I think this is fine as the alternative would be wrangling to find the path of the current route or something.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We&#39;re not using any mock-style verifications to check that the correct method was called on the &lt;code&gt;FirebaseAuth&lt;/code&gt; class. This would couple our test to the implementation details, which we must not do.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Run the tests and, of course, they all fail. Let&#39;s make them pass.&lt;/p&gt;
&lt;h3 id=&quot;step-2-make-the-test-pass-by-making-a-mess&quot;&gt;Step 2: Make the test pass by making a mess&lt;/h3&gt;
&lt;p&gt;Here, we just need to write as little code as possible to make sure the test passes.&lt;/p&gt;
&lt;pre class=&quot;language-dart&quot;&gt;&lt;code class=&quot;language-dart&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ForgotPasswordWidget&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ConsumerStatefulWidget&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ForgotPasswordWidget&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      
      &lt;span class=&quot;token metadata function&quot;&gt;@override&lt;/span&gt;
      &lt;span class=&quot;token class-name&quot;&gt;ConsumerState&lt;/span&gt;&lt;span class=&quot;token generics&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ForgotPasswordWidget&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_ForgotPasswordWidgetState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; _ForgotPasswordWidgetState &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ConsumerState&lt;/span&gt;&lt;span class=&quot;token generics&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ForgotPasswordWidget&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; _formKey &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GlobalKey&lt;/span&gt;&lt;span class=&quot;token generics&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;FormState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; _usernameController &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;TextEditingController&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      
      &lt;span class=&quot;token metadata function&quot;&gt;@override&lt;/span&gt;
      &lt;span class=&quot;token class-name&quot;&gt;Widget&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;BuildContext&lt;/span&gt; context&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Scaffold&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
          body&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
            key&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _formKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            child&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Column&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
              children&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
                &lt;span class=&quot;token class-name&quot;&gt;TextFormField&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
                  key&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;forgot-password-username-field&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                  controller&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _usernameController&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                  validator&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isEmpty&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Please enter your username&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token class-name&quot;&gt;ElevatedButton&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
                  key&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;forgot-password-submit-button&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                  onPressed&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_formKey&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;currentState&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;validate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                      &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; auth &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ref&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;firebaseAuthProvider&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                      
                      &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; auth&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sendPasswordResetEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
                          email&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; _emailController&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;on&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FirebaseAuthException&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;code &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;auth/user-not-found&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                          &lt;span class=&quot;token class-name&quot;&gt;ScaffoldMessenger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;context&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;showSnackBar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
                            &lt;span class=&quot;token class-name&quot;&gt;SnackBar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;content&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;User not found&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                          &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                  child&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Submit&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;💡In a real app, you would also need to ensure you&#39;ve set your router up correctly.&lt;/p&gt;
&lt;p&gt;That&#39;s it! The code is sufficient to ensure all our tests pass. A couple of things to note:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;If we ran this app, it would look terrible. We haven&#39;t applied any UI design to it yet. That&#39;s okay.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Because it&#39;s a very simple example, the code looks okay. In a more complex widget, your code might be horrible and messy. That&#39;s okay too.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We can now move on to the final step.&lt;/p&gt;
&lt;h3 id=&quot;step-3-refactor-keeping-the-tests-green-all-the-way&quot;&gt;Step 3: Refactor, keeping the tests green all the way&lt;/h3&gt;
&lt;p&gt;We now come to the most important and useful step of TDD. We have a basic implementation which we can prove is working. Now we can begin refactoring: the process of changing the design of our code and/or the UI &lt;strong&gt;without&lt;/strong&gt; changing the behaviour and causing the tests to fail.&lt;/p&gt;
&lt;p&gt;Each time we make a change, we can run the tests again to make sure we haven&#39;t broken something.&lt;/p&gt;
&lt;p&gt;In terms of refactoring, if you&#39;re not sure where you might go from here there is a great resource at &lt;a href=&quot;http://refactoring.guru&quot;&gt;refactoring.guru&lt;/a&gt; which helps you identify opportunities to improve the design of your code. You could extract methods or classes to separate concerns; you could improve variable naming; you could generalise something to make it reusable. The important thing to remember is that &lt;strong&gt;anything you do from here should not change the way the screen behaves, and your tests should pass after every refactoring step.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is also the moment at which you apply the UI design. Add fancy animations, loading states, pretty pictures, and all the rest. But don&#39;t change the functionality required by your tests.&lt;/p&gt;
&lt;p&gt;By the end, you should find that you have &lt;strong&gt;well-designed code that is 100% covered by tests.&lt;/strong&gt; If your coverage is below 100%, that &lt;em&gt;must&lt;/em&gt; mean that you&#39;ve written some code that you didn&#39;t need to, or introduced new behaviour that isn&#39;t tested. &lt;strong&gt;Get rid of anything that you haven&#39;t written a test for, or write tests for the stuff you know you need.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Of course, any external dependencies you&#39;re mocking (like &lt;code&gt;FirebaseAuth&lt;/code&gt; in my example) won&#39;t be covered by tests. That&#39;s okay - if you&#39;re using Riverpod you can just exclude the providers from coverage reports:&lt;/p&gt;
&lt;pre class=&quot;language-dart&quot;&gt;&lt;code class=&quot;language-dart&quot;&gt;    &lt;span class=&quot;token comment&quot;&gt;// coverage:ignore-start&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; firebaseAuthProvider &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Provider&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FirebaseAuth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;instance&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// coverage:ignore-end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You&#39;ve made a deliberate and good decision never to use this dependency in a test, so ignoring it in coverage reports is totally appropriate and justified.&lt;/p&gt;
&lt;h3 id=&quot;the-results&quot;&gt;The results&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;We have a suite of tests which protects the &lt;strong&gt;behaviour&lt;/strong&gt; of our code without locking in its implementation. We can re-implement parts of this code without breaking the tests. We will only need to change the tests if we&#39;re changing the behaviour (e.g. if we wanted to disable the Submit button until the user has entered a username).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;High code coverage is easy to achieve this way. By not mocking our own code, we cover huge swathes of it with very few tests.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It was fast, and we got meaningful feedback at every step.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The burden of maintaining these tests will be low, and it&#39;s easy to keep coverage high.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Adopting this approach allows you to use your tests as a tool rather than a shackle. They give you confidence when refactoring by ensuring nothing more than that the behaviour of your code stays consistent. Tests should &lt;em&gt;never&lt;/em&gt; hold you to any particular implementation or design, and our tests don&#39;t.&lt;/p&gt;
&lt;p&gt;The other important aspect of this approach is that it&#39;s astonishingly easy. You write fewer tests, and those tests are a much lower maintenance burden.&lt;/p&gt;
&lt;p&gt;All this means you can provide value to your users and customers faster, while still having a well-tested codebase. Truly the best of both worlds.&lt;/p&gt;
</content>
  </entry>
</feed>