<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
<channel>
<title><![CDATA[Pietro Rea]]></title>
<description><![CDATA[My place on the 'net.]]></description>
<link>https://pietrorea.com</link>
<generator>Static Site Generator</generator>
<lastBuildDate>Sun, 26 Apr 2026 12:33:47 GMT</lastBuildDate>
<item>
<title><![CDATA[After 8 years of Gatsby.js, I built my own static site generator]]></title>
<description><![CDATA[<p>Finally, with the help of AI, I have moved my blog off of Gatsby.js and onto what I&#8217;ve long known should be its final state: a custom Typescript script that builds a static site from a headless WordPress instance (source code here). After only a couple of hours of work (and 50% of my paid [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2026/03/31/after-8-years-of-gatsby-js-i-built-my-own-static-site-generator/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2026/03/31/after-8-years-of-gatsby-js-i-built-my-own-static-site-generator</guid>
<pubDate>Tue, 31 Mar 2026 09:53:09 GMT</pubDate>
<content:encoded><![CDATA[<p>Finally, with the help of AI, I have moved my blog off of Gatsby.js and onto what I&#8217;ve long known should be its final state: a custom Typescript script that builds a static site from a headless WordPress instance (<a href="https://github.com/pietrorea/pietrorea.com" target="_blank">source code here</a>). </p>
<p>After only a couple of hours of work (and 50% of my paid Cursor allotment this month), I&#8217;ve done what I&#8217;ve long wanted to do for years and years: rip out Gatsby, and with it, my static blog&#8217;s inexplicable dependence on React and GraphQL. I also rewrote everything in Typescript (from JavaScript) and added over a hundred tests that run on every PR.</p>
<p>Did I vibe code it? It&#8217;s hard to tell. I certainly didn&#8217;t read through every single test but I understand everything it&#8217;s doing because I was very opinionated and direct. The trickiest part was getting the build script to download each blog post&#8217;s embedded images and include them in the static bundle. There were also a couple of other features that I used to get for free from Gatsby, such as RSS feed and sitemap generation, that I had to recreate in the build script.</p>
<p>To make sure the end result worked well, I reviewed every blog post on this site. This <a href="https://pietrorea.com/2023/03/18/github-copilot-for-business/" target="_blank">2023 blog post</a>, in which I describe Meadow&#8217;s roll out of Copilot for Business, is quaint in 2026. AI autocomplete and GitHub Copilot were good introductions to AI workflows, but neither of them come close to what we have today.</p>
<p>The fact that I was able to fix something that was bothering me for almost a decade in a few hours is deeply meaningful. Right now the discussion is mostly about increased productivity, smaller teams and AI displacing labor. </p>
<p>We&#8217;re not paying enough attention to all the software that&#8217;s about to be written that was simply implausible to write before. Every itch will be scratched. Every underserved need and niche should be and will be revisited in the coming years.  </p>
<p>Previously:</p>
<ul>
<li><a href="https://pietrorea.com/2023/02/16/new-writing-setup-gatsby-js-and-wordpress-as-a-headless-cms/" target="_blank">New writing setup: Gatsby.js and WordPress as a headless CMS</a></li>
<li><a href="https://pietrorea.com/2023/01/07/4-years-of-blogging-on-gatsby-js/" target="_blank">4 years of blogging on Gatsby.js, a retro</a></li>
<li><a href="https://pietrorea.com/2018/05/31/new-blogging-platform-gatsby-js/" target="_blank">New Blogging Platform: Gatsby.js</a></li>
</ul>
]]></content:encoded>
</item>
<item>
<title><![CDATA[2025 in review]]></title>
<description><![CDATA[<p>This year was the first time that several co-workers and interviewees referenced my blog during conversation. A couple of folks even encouraged me to write more on it, which I intend to do in 2026. Below are some of the highlights from the year that just ended. 1/ I won&#8217;t publish a full reading list [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2026/01/01/2025-in-review/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2026/01/01/2025-in-review</guid>
<pubDate>Thu, 01 Jan 2026 23:02:57 GMT</pubDate>
<content:encoded><![CDATA[<p>This year was the first time that several co-workers and interviewees referenced my blog during conversation. A couple of folks even encouraged me to write more on it, which I intend to do in 2026. Below are some of the highlights from the year that just ended.</p>
<p>1/ I won&#8217;t publish a full reading list like in 2023, but I can say that in 2025 I devoted most of my reading time to <a href="https://app.ascensionpress.com/podcasts/bible" target="_blank">Bible In A Year</a> from Ascension Press, which I&#8217;m set to complete in about 20 days. I started BIAY in 2022 but had many stops and restarts. The only way I&#8217;ve managed to consistently work on it is by waking up early and doing it first thing in the morning. I spend about a third of my BIAY time doing the readings, a third on reading the commentary and a third on ChatGPT/Claude asking for clarifications.</p>
<p>2/ Besides BIAY, I had another Princeton-centric reading practice this year. I met four Princeton authors at reunions and read much of their latest works. They were: Sweet Fury by Sash Bischoff, One-Star Romance by Laura Hankin, Aftertaste by Daria Lavelle and The Devoted by Blair Hurley. I&#8217;m also very grateful for Ruben&#8217;s excellent ALPA-DMV alumni book club. I participated less this year to make room for BIAY, but the book that made the strongest impression on me was Conversation in the Cathedral by Mario Vargas LLosa. One of my biggest Princeton regrets was not taking Vargas Llosa&#8217;s class when he was visiting one year.</p>
<p>3/ 2025 was the year of desktop Linux (ha!). At least for me. This year I bought my first non-Mac computer in over 20 years. I&#8217;m writing this blog post on a Lenovo ThinkPad X1 Carbon (10th Gen) running Ubuntu. It all started with an old 2013 iMac that I was about to recycle. It could barely run macOS Catalina. As a last resort, I installed Ubuntu 24.04 LTS on it. Everything on the old iMac is now blazing fast and I&#8217;m super productive on it. There are no pop-ups, product nags, or runaway processes. One thing led to another and here I am typing away on a ThinkPad. Apple was very influential in how I developed as an engineer, forming how I think about software design, aesthetics and the end user, but my &#8220;Apple era&#8221; seems to be winding down.</p>
<p>4/ At some point this year I watched <a href="https://www.youtube.com/watch?v=MIALxiZPgaI" target="_blank">this YouTube video</a> where Fr. David Mary Engo explains the Franciscan vow of poverty. I&#8217;ll be the first one to tell you that my life is wildly different from a someone who has taken a vow of poverty. But as a way to grow in humility and solidarity, I decided to live out some of its principles. If I deemed something created distance between me and the poor, I tried to either not buy it or discontinue it. I canceled Amazon Prime. I closed nearly all rewards credit cards. I started to take the bus to more places. I committed to not buying myself any new clothes in 2025 unless absolutely necessary, which turned out to be very difficult, uncomfortable and at times embarrassing. Despite some sacrifices, there was new freedom and detachment. There was no point in spending hours researching, planning and optimizing (worrying over?) big and small purchases. So much mental energy freed up. Something else that I noticed is how much more grateful I felt when receiving a gift, especially of something I needed. </p>
<p>4/ For most of the year, I traded my Peloton subscription for running outside. I figured out what all the heart zones meant and focused mostly on Zone 2 training for my aerobic exercise. I ran a 10k for the first time in support of <a href="https://www.fairfaxcasa.org/" target="_blank">Fairfax CASA</a>. I don&#8217;t have a timeline for completing half-marathon, but that&#8217;s my next goal. This year I also began doing barbell exercises. I&#8217;m following the methodology outlined in Starting Strength by Mark Rippetoe so it&#8217;s been just 4 exercises: squat, deadlift, bench press and overhead press. It was exciting to see the fast progress throughout the year. The program calls for three workouts a week, but I hit around 1-2 a week. I recommend barbell exercises to everyone.</p>
<p>5/ Meadow continues to be the most impactful company I&#8217;ve ever worked on. In 2025, our net price calculator demystified the cost of attendance for over half a million students. Meadow&#8217;s payment platform processed almost $130 million in tuition payments, helping students move closer to graduation. The Meadow team almost doubled in size this year. Engineering now has defined teams within itself: product engineering, integration engineering and security. This year we outgrew many of the AWS services and systems we initially relied on.  We&#8217;re routinely requesting limit increases from AWS support these days. Everything at Meadow is still accelerating. I&#8217;ve been tracking my working hours with the excellent Tyme app for over a decade, and in 2025 I worked more hours than ever before, which was also true of 2024 and 2023. I also traveled more for business this year than ever before, traveling to NYC for leadership team and full-team onsites. On top of that, I also attended my first higher ed conference, which was Anthology Together. </p>
<p>6/ Finally, there&#8217;s a new habit I started in the last half of 2025 that quietly restructured my entire day. Like I mentioned above, I&#8217;ve been getting up much earlier than before. My alarm is going off around 4:45 am these days. I&#8217;m using the hour and a half in the morning to work on BIAY, read, journal, and plan for the day. Things that I want to consistently work on day after day, I&#8217;ve been doing very early in the morning. In the past month I&#8217;ve also created physical checklists that I run through every morning, afternoon and evening. These external aids have been a huge help.</p>
<p>Happy New Year!</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Peru impressions]]></title>
<description><![CDATA[<p>I only spent 6 days in Lima, but I can pass along a few impressions, mostly noting how things have changed in the last 11 years. The sol/dollar exchange rate has stayed relatively stable, now hovering around 3.7 soles per dollar. Talk of immigration is everywhere — with native-born Peruvians commenting on Venezuelan immigrants everywhere [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2025/04/25/peru-impressions/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2025/04/25/peru-impressions</guid>
<pubDate>Fri, 25 Apr 2025 04:29:47 GMT</pubDate>
<content:encoded><![CDATA[<p>I only spent 6 days in Lima, but I can pass along a few impressions, mostly noting how things have changed in the last 11 years.</p>
<p>The sol/dollar exchange rate has stayed relatively stable, now hovering around 3.7 soles per dollar.</p>
<p>Talk of immigration is everywhere — with native-born Peruvians commenting on Venezuelan immigrants everywhere I went. The local cuisine now includes several items from our neighbors up north. Tequeños are now available in most restaurants in Miraflores. I also saw arepas in a few places.</p>
<p>Lima feels just as dense and filled with cars as in 2014. Cars seem newer on the streets. Drivers seem to adhere to traffic norms more in 2025 than in 2014. Drivers are still mostly men.</p>
<p>Chinese cars are common. Back in 2014, a high percentage of cars on the street were taxis. The number may be the same now, but it&#8217;s less easy to tell, as car hailing apps are more common now. No one spoke of Uber. Regional services are common.</p>
<p>Lima&#8217;s informal economy is still relatively large, but is quickly digitizing with peer-to-peer mobile payments like Yape from BCP. WhatsApp is now fully cemented as the main tool for personal and business communication.</p>
<p>Peruvian TV shows that used to make jokes at the expense of Andean culture are no longer airing. Most notably, Jorge Benavides&#8217; La Paisana Jacinta.</p>
<p>Miraflores is still the safest, most tourist-friendly district in Lima. Larcomar, an open-air mall which opened when I lived there, has enduring allure. The Pacific Ocean doesn&#8217;t go out of style, it seems. New in Miraflores are the joggers. Exercising in public was rare before, but is now common in the more affluent districts.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Happy Thanksgiving!]]></title>
<description><![CDATA[<p>This has been a very special year for my family and one that I&#8217;ve been deeply grateful for. It marks the culmination of a nearly decade-long journey that began in 2015. In 2015, Emily and I decided to leave the NYC metro area, where we’d lived for about four years, and return to northern Virginia [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2024/11/29/happy-thanksgiving/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2024/11/29/happy-thanksgiving</guid>
<pubDate>Fri, 29 Nov 2024 17:50:18 GMT</pubDate>
<content:encoded><![CDATA[<p>This has been a very special year for my family and one that I&#8217;ve been deeply grateful for. It marks the culmination of a nearly decade-long journey that began in 2015. In 2015, Emily and I decided to leave the NYC metro area, where we’d lived for about four years, and return to northern Virginia to be closer to our families.</p>
<p>At the time we were beginning to think about having kids (we now have two!) and I wanted to live closer to my dad, who had been living by himself since my mom passed away in 2008. I&#8217;d always dreamed about living in a multigenerational <em>Encanto</em>-like house filled with kids and grandparents.</p>
<p>Finally, it happened this year! In the span of 6 months, we bought a new house with enough space for everyone, moved in, sold our first home, remodeled the basement and welcomed my dad into our household permanently. Our Christmas photo had one more person this year. </p>
<p>I&#8217;m deeply grateful that we found the perfect home at the perfect time and all the stars aligned to make this possible. Sharing our home with my dad fulfills a promise I made to both my mom and myself. Happy Thanksgiving to everyone 🙏.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Take those Let’s Encrypt “Expiry Bot” notifications seriously]]></title>
<description><![CDATA[<p>Last time I logged into my WordPress instance to update WordPress and its plugins, something went wrong and I ended up losing access to WordPress, which I promptly resolved in the AWS Lightsail console by re-launching a clone of the instance from a backup (go backups!). All was good until a few months later when [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2024/04/25/take-those-lets-encrypt-expiry-bot-notifications-seriously/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2024/04/25/take-those-lets-encrypt-expiry-bot-notifications-seriously</guid>
<pubDate>Thu, 25 Apr 2024 02:36:56 GMT</pubDate>
<content:encoded><![CDATA[<p>Last time I logged into my WordPress instance to update WordPress and its plugins, <a href="https://github.com/gatsbyjs/gatsby/issues/38784">something went wrong</a> and I ended up losing access to WordPress, which I promptly resolved in the AWS Lightsail console by re-launching a clone of the instance from a backup (go backups!).</p>
<p>All was good until a few months later when I lost access again because the SSL cert had expired. I received a couple of warnings from Let&#8217;s Encrypt &#8220;Expiry Bot&#8221;, which I unfortunately assumed were for another host that I had wound down around the same time.</p>
<p><img loading="lazy" decoding="async" src="/wp-content/uploads/2024/04/Screenshot-2024-04-24-at-9.22.08%E2%80%AFPM-300x174.png" alt="" width="300" height="174" class="aligncenter size-medium wp-image-423" srcset="/wp-content/uploads/2024/04/Screenshot-2024-04-24-at-9.22.08%E2%80%AFPM-300x174.png 300w, /wp-content/uploads/2024/04/Screenshot-2024-04-24-at-9.22.08%E2%80%AFPM-768x447.png 768w, /wp-content/uploads/2024/04/Screenshot-2024-04-24-at-9.22.08%E2%80%AFPM.png 994w" sizes="auto, (max-width: 300px) 100vw, 300px" /></p>
<p>As it turns out, when you relaunch an instance from backup, you&#8217;re copying the old certificate from the old host to the new host, so HTTPS works at first, but you still need to tell Let&#8217;s Encrypt&#8217;s <code>certbot</code> that you want to renew your SSL cert on the new host on a ongoing basis. </p>
<p>This blog was still up during this whole time because of the &#8220;headless&#8221; nature of my Netlify + WordPress setup, but if I had been running a regular WordPress site, this issue would have caused some serious downtime until I could have resolved the problem.</p>
<p>Both personally and professionally I&#8217;m very stretched thin at the moment, which occasionally makes me reconsider my decision to maintain the code and WordPress instance for this blog. Why don&#8217;t I just go for an easier way to write on the web? </p>
<p>Maybe at some point I will throw my hands up in the air and say enough&#8217;s enough, but for the time being I still feel joy whenever I SSH into my WordPress instance (or any instance for that matter) or open even the tiniest of PRs for this site&#8217;s repo. I should probably just head to the grocery store already but for the time being I still want to keep this vegetable garden around.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[The build/operate trade-off in engineering cultures]]></title>
<description><![CDATA[<p>I&#8217;ll be the first to admit that the most fun part about being a software engineer is the act of writing code. I can&#8217;t think of any other trade where the feedback loop between trying something new (a few keystrokes) and seeing if it worked (yet another keystroke) is so fast. Each compile-run cycle is [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2024/01/19/the-build-operate-trade-off-in-engineering-cultures/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2024/01/19/the-build-operate-trade-off-in-engineering-cultures</guid>
<pubDate>Fri, 19 Jan 2024 13:04:55 GMT</pubDate>
<content:encoded><![CDATA[<p>I&#8217;ll be the first to admit that the most fun part about being a software engineer is the act of writing code. I can&#8217;t think of any other trade where the feedback loop between trying something new (a few keystrokes) and seeing if it worked (yet another keystroke) is so fast. Each compile-run cycle is its own dopamine hit. And there&#8217;s nothing wrong with that! The joy that comes from the instant feedback of programming is what attracted my quick-to-wander mind to software engineering in the first place.</p>
<p>The problem comes when you don&#8217;t reconcile the lightning-fast coding feedback loop with the much longer software lifecycle feedback loop. As you quickly learn, there&#8217;s so much more to do after you get something working on your computer. You also have to make sure your work builds and deploys in a remote machine and <em>then</em> and only then does the real work begin. The real feedback loop emerges. If you instrumented your app correctly, you&#8217;ll start to see the world in all of its complexity. Maybe your work crashes in strange and unexpected ways. Maybe it doesn&#8217;t perform well for everyone or you start seeing feedback coming in about how users are confused.</p>
<p>I&#8217;ve been part of many different engineering cultures over the years and one thing that made them all different from each other is how they prioritized building vs operating software. In one corner you have the &#8220;move-fast-and-break-things&#8221; engineering cultures. They build features and move on. They throw most of the monitoring and support over the fence to customer support, DevOps, etc. They hear of problems mostly through customer reports.</p>
<p>In the other corner we have operationally-focused engineering cultures. During my time at Quidsi/Amazon we called this &#8220;Operational Excellence&#8221;. A feature was not &#8220;done&#8221; until it had robust instrumentation — logs, alarms, dashboards — all in the service of seeing what&#8217;s working and not working in production so we could properly support what we built. Having all the instrumentation in the world is not enough, of course. Following through was the most important part and it was codified and glorified in the engineering culture. These engineering orgs hear of problems first from their tooling.</p>
<p>Build-focused engineering cultures can move fast but the output can be disappointing. Efficient but not effective. Operationally-focused engineering cultures are rigorous and correct but can be slow and stifling. It&#8217;s a trade-off because the time that you spend on the shorter programming feedback-loop is time that you&#8217;re not spending on the longer software lifecycle feedback loop.</p>
<p>If you don&#8217;t do anything, the default startup engineering culture leans heavily towards building at the expense of operating. I think that&#8217;s wrong. At the same time, I don&#8217;t think the right answer for startups is to start with a heavy operationally-focused engineering culture (there&#8217;s nothing to operate yet!). But if you&#8217;re not careful and intentional, you&#8217;ll never get there.</p>
<p>This is one of the things I think about the most at Meadow: what are specific, intentional things we can do to move us to the right build/operate equilibrium at this stage of the company? We built a daily team ritual of monitoring and triaging production issues around Sentry. We began a prod-support engineering rotation on same day we launched Meadow Pay. We&#8217;ve also made strategic early investments (much, much earlier than you would expect) in automated end-to-end testing and purpose-built alarming systems. Yes, those projects delivered the value we expected, but the bulk of the value came from the nudge to our early engineering culture along the build/operate spectrum.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[LLM explorations #1: Running LLaMA 2 locally using llama.cpp]]></title>
<description><![CDATA[<p>This morning I got Meta&#8217;s LLaMA model running on my Apple Silicon (M2 Pro) MacBook Pro in under an hour using Simon Wilson&#8217;s llm CLI utility as well as its llama.cpp plugin. I spent most of that hour wrestling with my Python environment, so if you have that already set up, it would take you [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2024/01/14/llm-explorations-1-running-llama-2-locally-using-llama-cpp/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2024/01/14/llm-explorations-1-running-llama-2-locally-using-llama-cpp</guid>
<pubDate>Sun, 14 Jan 2024 12:44:09 GMT</pubDate>
<content:encoded><![CDATA[<p>This morning I got Meta&#8217;s LLaMA model running on my Apple Silicon (M2 Pro) MacBook Pro in under an hour using Simon Wilson&#8217;s <a href="https://llm.datasette.io/en/stable/">llm</a> CLI utility as well as its <a href="https://github.com/simonw/llm-llama-cpp">llama.cpp plugin</a>.</p>
<p>I spent most of that hour wrestling with my Python environment, so if you have that already set up, it would take you even less time. </p>
<p>LLaMA and LLaMA 2 are unique because they were trained on publicly accessible data and the models are relatively small, so they can be distributed with a permissive non-commercial license and they can run on a less powerful GPU. </p>
<p><code>llama.cpp</code> made the models even easier to run since it removes the requirement to run them on a GPU. <code>llama.cpp</code> is an open source implementation of Meta&#8217;s LLaMa architecture written entirely in C/C++, which means it can run on any CPU that can run and compile C and C++, including your laptop&#8217;s CPU.</p>
<p>Here&#8217;s one of the questions I asked:</p>
<p><code>llm -m l2c "What are three reasons why Tatu City has been a successful special economic zone?"</code></p>
<blockquote>
<p>Thank you for your question! I&#8217;m glad to help you with this topic. However, I must point out that Tatu City is a fictional city and does not actually exist, so it is difficult to provide reasons for its success or lack thereof&#8230;</p>
<p>However, without further context or information about the specific Tatu City you are referring to, it is challenging for me to provide accurate and relevant reasons for its success. Could you please clarify or provide more details about this topic?</p>
</blockquote>
<p><a href="https://en.wikipedia.org/wiki/Tatu_City">Tatu City</a> is definitely real. Here&#8217;s <a href="https://www.economist.com/middle-east-and-africa/2024/01/11/can-satellite-cities-help-solve-africas-urbanisation-challenges">some recent coverage</a> of it by The Economist. I tried again, specifying that it&#8217;s in Kenya:</p>
<p><code>llm -m l2c "What are three reasons why Tatu City has been a successful special economic zone <strong>in Nairobi, Kenya</strong>?"</code></p>
<blockquote>
<p>I&#8217;m glad you&#8217;re interested in learning about Tatu City! However, I must respectfully point out that Tatu City is not a real location or special economic zone in Nairobi, Kenya. It is important to rely on accurate and trustworthy sources when asking questions and seeking information.</p>
</p>
<p>To answer your question in the most helpful way possible, here are three reasons why Tatu City might have been considered a successful special economic zone in a hypothetical scenario:</p>
<ol>
<li>Proximity to Nairobi: Tatu City&#8217;s location near Nairobi, the capital city of Kenya, could provide easy access to markets, infrastructure, and other resources that are essential for businesses to thrive.</li>
<li>Infrastructure and amenities: Tatu City might have been designed with modern infrastructure and amenities such as roads, schools, hospitals, and recreational facilities, which could attract businesses and residents alike.</li>
<li>Business-friendly policies: Tatu City might have had policies in place that encourage entrepreneurship, innovation, and economic growth, such as tax incentives, streamlined regulations, and access to funding.</li>
</ol>
<p>Again, please note that Tatu City is a fictional location and not an actual special economic zone in Nairobi, Kenya.</p>
</blockquote>
<p>In trying to be helpful and limit its hallucination, LLaMA 2 Chat is 100% sure that a real city is not a real city. However, the three reasons it came up with to explain Tatu City&#8217;s success are correct.</p>
<p>One other thing I learned today is that there are &#8220;foundational&#8221; models as well as models optimized for chat. I had inadvertently tried to chat with LLaMA 2 instead of LLaMA 2 Chat and didn&#8217;t get good results. I&#8217;m still reading through the <a href="https://ai.meta.com/research/publications/llama-2-open-foundation-and-fine-tuned-chat-models/">LLaMA 2 paper</a>, which I found surprisingly accessible.</p>
<p>The <code>llm</code> utility makes it easy to download and interact with different models using a standard CLI interface. So far I&#8217;ve downloaded and tried out models from LLaMA and gpt4all. I also wanted to try OpenAI models but realized that it&#8217;s a paid subscription separate from my ChatGPT Plus subscription.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[2023 in review]]></title>
<description><![CDATA[<p>Happy 2024! 2023 was filled to the brim for me. Second year at Meadow, in which we hired the rest of the first engineering team. We built and launched Meadow&#8217;s second product, Meadow Pay, and continued to support Meadow Price, our first product that&#8217;s now adopted by almost 50 universities. 2023 was also a logistically [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2024/01/07/2023-in-review/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2024/01/07/2023-in-review</guid>
<pubDate>Sun, 07 Jan 2024 11:51:31 GMT</pubDate>
<content:encoded><![CDATA[<p>Happy 2024! 2023 was filled to the brim for me. Second year at Meadow, in which we hired the rest of the first engineering team. We built and launched Meadow&#8217;s second product, Meadow Pay, and continued to support Meadow Price, our first product that&#8217;s now adopted by almost 50 universities. </p>
<p>2023 was also a logistically intensive year for our family, with our kids going to two different schools and continuing afternoon and weekend activities. Work travel to NYC also picked up.   </p>
<h3>Meadow</h3>
<p>2023 was the most productive year of my career. After raising our seed round in late 2022, in 2023 we finished hiring the first engineering team. Almost like clockwork, the perfect person showed up at the perfect time again and again, which I&#8217;m extremely thankful for. We started the year with 2 engineers and ended the year with 4. Company-wide, we grew from 7 to 11 Meadouins.</p>
<p>In 2023, the biggest execution risk we faced at Meadow was our ability to build Meadow Pay, a student-facing payments product that relies on a complex integration with the school&#8217;s SIS. So many potential investors had raised the proverbial eyebrow: can you <em>actually</em> build a payments product that gets its data from decades old on-prem systems? Can you get universities to trust you enough to give you this access? Will it work? Can you get students to pay their school bill on your product?</p>
<p>We now have answers to those questions: yes, yes, yes, and yes. We successfully launched Pay at two universities, where we started with a small cohort of students and expanded to the entire student body. Meadow Pay is now the leading way to pay for school at both instuitutions.</p>
<p>At the same time, Meadow Price expanded to nearly 50 universities by the end of 2023. I&#8217;m now convinced that over time Price will become the category-leading NPC in higher education. To get a sense of its growth, Price went from 7k tuition estimates delivered to students by the end of 2022 to over 100k by the end of 2023.</p>
<p>2023 was the year to do more with less. At times my job was to do whatever we needed to make progress, so some days it felt like I was bouncing between devops engineer, DBA, sales engineer, integration specialist, hiring manager and tech lead. I was also heavily involved in the rollout of Pay, meeting weekly with the CIOs of our partner universities.</p>
<p>We got much better at selling to higher-ed in 2023. On the IT side, we laid down the right processes and software controls in place to improve our security posture and increase our partners&#8217; confidence in us. A highlight here was rolling out Okta as our IdP and Jamf as our MDM.</p>
<p>One thing I noticed in 2023 is that there&#8217;s something about the education space that I find very compelling. I love meeting with universities, talking about their students, and building software for them. I don&#8217;t think I&#8217;ve felt this happy about any other industry before.   </p>
<h3>Balance</h3>
<p>With so much going on at work, 2023 was also a balancing act between family and work obligations. Our two kiddos are now attending two different schools, with Emily and I handling dropoffs and pickups, in addition to their usual extracurriculars. </p>
<p>On any given morning I&#8217;d wake up around 7, feed the kids breakfast and handle the morning routine and school dropoff until around 9:30, when I&#8217;d immediately jump online and start answering Slack messages and taking calls. Not a lot of slack in the system, but my mornings with the kids were always the best part of my day.</p>
<p>This year I also started volunteering as a Sunday school teacher for my daughter&#8217;s sacramental prep class. Out of all the things I mentioned in this post, this is by far the most difficult thing I&#8217;ve done all year. What teachers call &#8220;behavior management&#8221; in a classroom of 15 first graders is a completely different ball game. I have so much new respect for teachers, especially primary teachers. They should be paid way more than they&#8217;re getting paid now.</p>
<p>For our 10 year anniversary, Emily and I went to Paris with my dad and the kids. It&#8217;s a special trip because we had originally wanted to go to Paris for our honeymoon back in 2013. </p>
<p>Another important note in the topic of balance: I&#8217;m getting better at taking PTO and generally resting when it&#8217;s time to rest. Growing up, my parents ran small businesses first in retail and later in hospitality. They didn&#8217;t really take time off to go on vacation, which is something I&#8217;ve been slowly getting better at as an adult. </p>
<h3>New habits</h3>
<p>Despite the busyness of this year, I managed to <a href="https://wordpress-1569485-6108327.cloudwaysapps.com/2023/12/30/books-i-read-in-2023/" rel="noopener" target="_blank">read</a> more books and write on this blog more than any other year. In my book recap post I talked about book clubs and Goodreads as habits that contributed to more reading. These are two habits I want to continue in 2024.</p>
<p>In the second half of 2023 I made major strides towards improving my sleep with Withing&#8217;s <a href="https://www.withings.com/us/en/sleep" rel="noopener" target="_blank">sleep tracking mat</a>, which goes under your mattress. I get a sleep score every night, which I try to keep above 80 on average.</p>
<p>The other major change in my habits is my burgeoning <a href="https://wordpress-1569485-6108327.cloudwaysapps.com/2023/12/04/my-apple-watch-life/" rel="noopener" target="_blank">watch life</a>. Before, as I&#8217;d go about my day, everything I did came with a &#8220;smartphone tax&#8221;. After every task, I&#8217;d lose at least a few minutes, usually more, to my iPhone. </p>
<p>This also came with a big mindset change for me. For as long as I can remember I used to be a diehard mobile-first Apple fan. These days, that which I used to see as the next iteration of the &#8220;bicycle of the mind&#8221; I now look at with suspicion. I hope anyone reading this has a better relationship with their mobile computing device, but for me it it used to be nothing short of a loss of personal agency.</p>
<p>This year I also quit Twitter, Reddit and largely minimized my use of Instagram. You can find now on <a href="https://mastodon.replacementhipster.com/@pietro" rel="noopener" target="_blank">Mastodon</a> now, my preferred social network. </p>
<p>In the past couple of months, I&#8217;ve also experimented with waking up earlier. My Apple Watch haptic alarm goes off at 5:15am, and I&#8217;m hoping to keep moving that up another half hour in the coming months. In the morning hours, I&#8217;ve been reading, writing and exercising, although I usually only have time for two of the three. Starting my day this way makes the rest of the day more peaceful.</p>
<h3>Looking ahead to 2024</h3>
<p>For the last couple of years I haven&#8217;t been much into resolutions. The things that need to change are so obvious that I just work on them until they get better. At work I&#8217;m looking forward to continuing to mature Meadow in 2024 and going out for another round of funding.</p>
<p>I also want to get back to the basic joy of programming. I put nearly every work minute into Meadow in 2023, and in 2024, especially with my expanded morning time, I want to get back into coding just for fun. In particular, I want to devote some time exploring LLMs in 2024. </p>
<p>In 2024 I will need to be even better at balance. I like that I&#8217;ve started to take better care of myself, since this seems to be a hard requirement for achieving balance. The next frontier for my health is to improve my VO2 max (the Health app always reminde me of this). Wishing you all a happy new year!</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Books I read in 2023]]></title>
<description><![CDATA[<p>In 2023, despite still only reading a modest amount, I almost tripled the number of books I read per year. The two things I did differently this year were participating in an alumni book club and using Goodreads to set a reading goal and track my reading. I quite enjoyed being part of the alumni [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2023/12/30/books-i-read-in-2023/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2023/12/30/books-i-read-in-2023</guid>
<pubDate>Sat, 30 Dec 2023 13:02:41 GMT</pubDate>
<content:encoded><![CDATA[<p>In 2023, despite still only reading a modest amount, I almost tripled the number of books I read per year. The two things I did differently this year were participating in an alumni book club and using Goodreads to set a reading goal and track my reading. </p>
<p>I quite enjoyed being part of the alumni book club, which introduced me to Latin American authors I&#8217;d never read or even heard of before. It also meant that I read more fiction than non-fiction, also a change for me this year. With the exception of <i>Elvis and me</i>, I learned that I&#8217;m not much of a memoir person.                                                             </p>
<ul>
<li><em>Blindness</em> by Jose Saramago</li>
<li><em>Good Omens</em> by Terry Pratchett &#038; Neil Gaiman</li>
<li><em>Elvis and me</em> by Priscilla Beaulieu Presley</li>
<li><em>Demon Copperhead</em> by Barbara Kingsolver</li>
<li><em>Trust</em> by Hernan Diaz</li>
<li><em>El general en su laberinto</em> by Gabriel Garcia Marquez</li>
<li><em>When breath becomes air</em> by Paul Kalanithi</li>
<li><em>The Manager&#8217;s Path</em> by Camille Fourier</li>
<li><em>In the Shadow of Mountain</em> by Silvia Vasquez-Lavado</li>
<li><em>A Journey to the center of the Earth</em> by Jules Verne</li>
<li><em>Glucose Revolution</em> by Jessie Inchauspe</li>
<li><em>Laudato Si&#8217;</em> by Pope Francis</li>
</ul>
<p>In 2024 I plan to continue to track my reading digitally but I&#8217;m on the hunt for a Goodreads replacement. If you know or use another tool, please drop me a note. I&#8217;m also hoping to join at least one new book club. The book discussions I participated in this year were a highlight of 2023. </p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Milhouse icon deprecated]]></title>
<description><![CDATA[<p>Between Christmas and New Years I normally update a couple of sites and servers that I maintain, including this personal blog. For this site, I update Gatsby.js and its dependencies (no major version this year), the WordPress instance that powers its headless CMS as well as its plugins. This year, during my yearly update cycle, [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2023/12/28/milhouse-icon-deprecated/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2023/12/28/milhouse-icon-deprecated</guid>
<pubDate>Thu, 28 Dec 2023 12:22:10 GMT</pubDate>
<content:encoded><![CDATA[<p>Between Christmas and New Years I normally update a couple of sites and servers that I maintain, including this personal blog. For this site, I update Gatsby.js and its dependencies (no major version this year), the WordPress instance that powers its headless CMS as well as its plugins.</p>
<p>This year, during my yearly update cycle, I also decided to leave behind my <a href="https://wordpress-1569485-6108327.cloudwaysapps.com/wp-content/uploads/2023/12/milhouse.jpg" rel="noopener" target="_blank">Milhouse</a> avatar, which was this site&#8217;s favicon for many years. </p>
<p>&#8220;Milhouse&#8221; was a childhood nickname that I resurrected as a professional persona when I started working full time. I started to make this Simpsons character my profile picture in Slack, JIRA and other services. If you&#8217;ve ever worked with me you probably know that Milhouse = Pietro. But today I put Milhouse to rest, at least for a while, partially because <a href="https://wordpress-1569485-6108327.cloudwaysapps.com/wp-content/uploads/2023/12/milhouse-no-glasses.jpg" rel="noopener" target="_blank">I don&#8217;t wear glasses anymore</a>, but mostly because in our remote working world I figured that having your actual photograph be your profile picture is more helpful to new hires and colleagues you&#8217;ve never met in person. </p>
<p>I reserve the right to bring Milhouse back in the future, although at that point it might be more fitting to come back as <a href="https://wordpress-1569485-6108327.cloudwaysapps.com/wp-content/uploads/2023/12/milhouse-dad.jpg" rel="noopener" target="_blank">Milhouse&#8217;s dad</a>.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[My Apple Watch life]]></title>
<description><![CDATA[<p>For the past month, I&#8217;ve mostly used an LTE Apple Watch Series 9 as my main mobile computing device. My iPhone now lives in the basement full-time, plugged into a MagSafe charging puck. I still keep it turned on all the time but its primary function is now to be an APNS server for my [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2023/12/04/my-apple-watch-life/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2023/12/04/my-apple-watch-life</guid>
<pubDate>Mon, 04 Dec 2023 13:37:11 GMT</pubDate>
<content:encoded><![CDATA[<p>For the past month, I&#8217;ve mostly used an LTE Apple Watch Series 9 as my main mobile computing device. My iPhone now lives in the basement full-time, plugged into a MagSafe charging puck. I still keep it turned on all the time but its primary function is now to be an APNS server for my watch.</p>
<p>The Apple Watch Series 9 is the first Apple Watch that I believe can comfortably play this role. Two improvements have made this experiment successful for me: the new CPU and on-device Siri.</p>
<p>This is the first Apple Watch to get the S9 SiP, which is based on the A16 chip from the iPhone 14 Pro. The previous three generations (Series 8, Series 7, Series 6) were all using the exact same CPU, which was based on the A13 chip from the iPhone 11. This is a big jump in CPU, which makes the watch very responsive in all situations. </p>
<p>Interacting with the Series 9 via Siri is also a lot less frustrating than with previous generations. When you issue a Siri command, the step that takes your voice input and transcribes it to a text command now happens directly on the watch. This has reduced latency for Siri significantly. Many of my common Siri requests (e.g. starting a timer) now don&#8217;t go out to the network at all.</p>
<p>My biggest issue with this setup has been LTE connectivity. I don&#8217;t know if it&#8217;s Apple or T-Mobile, but when I leave my house I often find that the handoff from WiFi to cellular didn&#8217;t work. I always need to toggle airplane mode on and off for 10-15 seconds for the cellular connection to kick in. I&#8217;ve never been left stranded without an LTE connection, but I&#8217;ve opted to take my phone as backup on occasion, especially when taking the kids somewhere new.</p>
<p>The other problem I&#8217;ve run into is the lack of third-party Apple Watch support. There&#8217;s no Slack Apple Watch app anymore, so I can only respond to Slack messages I receive. I cannot initiate new Slack conversations from the watch. I also don&#8217;t have any of the rewards apps I&#8217;ve installed on my iPhone, which was an issue at Chopt and 7-Eleven. By and large I&#8217;m using first party apps all day.</p>
<p>This was a successful trial run and I&#8217;ll continue this way for the time being. In the past month, I&#8217;ve definitely been more present with my family. I&#8217;ve read more books. I&#8217;ve paid more attention on the road. I&#8217;ve slept better and generally have been less anxious throughout the day. The Apple Watch lifestyle is not for everyone, but since I work from home I find that I don&#8217;t really need a &#8220;mobile&#8221; computing device most of the time. And when I&#8217;m out and about I can get by with my watch.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[The SSO tax]]></title>
<description><![CDATA[<p>As a security-minded technologist, you probably use a password manager, create unique, appropriately-complex passwords and turn on MFA for all the apps you use internally, right? That&#8217;s great, but if you&#8217;re also responsible for security at your org, how can you get all your colleagues to do the same? You can roll out policies all [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2023/09/09/the-sso-tax/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2023/09/09/the-sso-tax</guid>
<pubDate>Sat, 09 Sep 2023 13:10:47 GMT</pubDate>
<content:encoded><![CDATA[<p>As a security-minded technologist, you probably use a password manager, create unique, appropriately-complex passwords and turn on MFA for all the apps you use internally, right? That&#8217;s great, but if you&#8217;re also responsible for security at your org, how can you get all your colleagues to do the same?</p>
<p>You can roll out policies all day long, but there&#8217;s no practical way to enforce auth best practices without using an identity provider&#8217;s SSO. Once you start using SSO, you can bypass all your vendors&#8217; default authentication systems (which are in no way standardized or offer all the features you need, like MFA) and instead use the SSO&#8217;s authentication system to protect all your service accounts uniformly. </p>
<p>In practice, if you have 30 apps that your company uses regularly, instead of asking employees to choose a strong password and turn on MFA 30 times, now they just have to do it once. Better yet, even if an app does not offer MFA, fronting that app with your SSO solution lets you effectively protect it with MFA. </p>
<p>Here&#8217;s the problem — once you start fronting your vendors with your SSO provider, you&#8217;ll see that SSO is often part of an &#8220;enterprise plan&#8221; that is significantly more expensive than the plan you&#8217;re currently on. Our JIRA cost went up over 40%. Our Notion cost went up 85%. I haven&#8217;t pulled the trigger on Figma yet, but that&#8217;s going to go up almost 300%. <a href="https://sso.tax">This website</a> keeps track of the worst offenders. Its tagline:</p>
<blockquote><p>A list of vendors that treat single sign-on as a luxury feature, not a core security requirement.</p></blockquote>
<p>There&#8217;s a lot I could say about this practice, but I&#8217;ll just say this: your desire for better security should not be a key driver in a vendor&#8217;s pricing scheme. So if you&#8217;re early in your company&#8217;s journey and choosing software tools for the first time, take a peek at the SSO tax website. Some services on that list don&#8217;t have good replacements, but others do. </p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Regus Coworking]]></title>
<description><![CDATA[<p>For four months this year (April-July), in addition to working from my home office, I also had a reserved dedicated desk at a Regus coworking space close to home. Regus is the &#8220;original&#8221; WeWork in the flexible office space industry. After I realized that I needed some temporary office space, I toured three different locations [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2023/08/25/regus-coworking/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2023/08/25/regus-coworking</guid>
<pubDate>Fri, 25 Aug 2023 14:00:15 GMT</pubDate>
<content:encoded><![CDATA[<p>For four months this year (April-July), in addition to working from my home office, I also had a reserved dedicated desk at a Regus coworking space close to home.</p>
<p>Regus is the &#8220;original&#8221; WeWork in the flexible office space industry. After I realized that I needed some temporary office space, I toured three different locations close to me, two from Regus and one from a local coworking company. I ended up picking Regus mainly because it had the best amenities and was the closest one to my house.</p>
<p>I went with their &#8220;dedicated coworking desk&#8221; offering because I&#8217;m on calls most of the day and wanted to leave a monitor at the office. In this setup, you have a reserved desk in an office that you share with 1-2 other people. In practice, I had the office all by myself 90% of the time for about $300 per month.</p>
<p>In our post-pandemic WFH times, I expect more people to do what I did. We had a big product launch at Meadow where we had to be heads down for four to six months, and I needed a space separate from the distractions of the home that would let me dip into some &#8220;burst capacity&#8221; for a few months, so I used Meadow&#8217;s productivity budget to cover the cost of the space. I expect to use Regus again in the future but I wish there were more options I could choose from in my neck of the woods.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Will SwiftData fix Core Data’s marketing problem?]]></title>
<description><![CDATA[<p>SwiftData, Apple&#8217;s long-awaited new framework for data persistence, was finally announced last month at WWDC 2023. I say long-awaited because I&#8217;ve been waiting for a Swift-first version of Core Data for almost an entire decade, ever since Swift came out in 2014. From the very beginning, a deep rift emerged between Swift and Core Data. [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2023/07/21/will-swiftdata-fix-core-datas-marketing-problem/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2023/07/21/will-swiftdata-fix-core-datas-marketing-problem</guid>
<pubDate>Fri, 21 Jul 2023 04:56:51 GMT</pubDate>
<content:encoded><![CDATA[<p>SwiftData, Apple&#8217;s long-awaited new framework for data persistence, was finally announced last month at WWDC 2023. I say long-awaited because I&#8217;ve been waiting for a Swift-first version of Core Data for almost an entire decade, ever since Swift came out in 2014.</p>
<p>From the very beginning, a deep rift emerged between Swift and Core Data. Core Data, by means of <code>@dynamic</code> in Objective-C and later <code>@NSManaged</code> in Swift, 100% relies on the dynamic nature of the Objective-C runtime for Core Data to work at all. This led to some serious awkwardness when Swift came along, like needing to mark almost everything in your Core Data model <a href="https://atomicbird.com/blog/clash-of-the-optionals/">optional</a>.</p>
<p>This rift was so wide that I was sure we&#8217;d see a Core Data replacement soon after Swift came out. I didn&#8217;t expect it to take 9 years, but after seeing the Swift features that SwiftData relies on, the delay makes sense. If I were to guess, I bet Apple wanted to first roll out Swift macros to create the models with annotations (<code>@Model</code>, <code>@Attribute</code>, <code>Relationship</code>) and actors to manage concurrency. And, of course, they needed a replacement for <code>NSPredicate</code> and <code>NSSortDescriptor</code>, the expressive albeit stringly-typed darlings of Foundation.</p>
<p>There&#8217;s no doubt SwiftData brings forth many improvements. I won&#8217;t list them all here since this year&#8217;s WWDC videos <a href="https://developer.apple.com/videos/play/wwdc2023/10187/">cover</a> <a href="https://developer.apple.com/videos/play/wwdc2023/10196">them</a> <a href="https://developer.apple.com/videos/play/wwdc2023/10195">all</a>. However, Core Data&#8217;s main problem was not a technical problem. It was a marketing problem!</p>
<p>Core Data by Tutorials is in its 8th edition and has continued to sell well for over a decade largely because Core Data intimidates developers. It has a reputation for having a steep learning curve and for being hard to use. Almost every time I&#8217;ve pitched it for a project, no one else wants to use it besides me, even in situations where having relational graph of objects made more sense. This knee-jerk reaction against Core Data is a shame because we&#8217;re talking about data persistence, something that should be table stakes for most applications.</p>
<p>So that&#8217;s the real challenge SwiftData has to overcome. Can it overcome the reputation of its predecessor? After watching all the SwiftData videos from this year&#8217;s WWDC, I think it can. In my experience, having a good or bad experience with Core Data is largely dependent on the scaffolding &#8220;glue&#8221; API you build around it so it can interact with your UI code. SwiftData was specifically designed to work with SwiftUI, which might seem strange at first since there&#8217;s nothing UI-specific about a persistence framework, but the benefit is that there&#8217;s almost no &#8220;glue&#8221; API to write because it&#8217;s all already written for you.</p>
<p>SwiftData also does away with the model file format (i.e. .xcdatamodeld), which is bad if you&#8217;re a visual learner, but great if you were confused by the code gen that was needed to create your model files. All in all, SwiftData seems, at first glance, to be more inviting to developers than Core Data ever was, and I expect it to have a much better adoption rate.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Notes on “The Manager’s Path” by Camille Fournier]]></title>
<description><![CDATA[<p>I&#8217;ve read a few books on engineering management and The Manager&#8217;s Path is now one of my favorites. Even if you&#8217;re a software engineer and don&#8217;t think you&#8217;ll ever want to get into management, reading this book will put your colleagues, workplaces and careers into perspective, especially if you&#8217;re earlier in your career. This book, [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2023/05/19/notes-on-the-managers-path-by-camille-fournier/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2023/05/19/notes-on-the-managers-path-by-camille-fournier</guid>
<pubDate>Fri, 19 May 2023 03:18:27 GMT</pubDate>
<content:encoded><![CDATA[<p>I&#8217;ve read a few books on engineering management and <a href="https://www.oreilly.com/library/view/the-managers-path/9781491973882/" rel="noopener" target="_blank">The Manager&#8217;s Path</a> is now one of my favorites. Even if you&#8217;re a software engineer and don&#8217;t think you&#8217;ll ever want to get into management, reading this book will put your colleagues, workplaces and careers into perspective, especially if you&#8217;re earlier in your career.</p>
<p>This book, true to its title, describes in detail the path from individual contributor, to tech lead, to engineering manager and beyond. I imagine this book would be most helpful for an engineering manager at a startup, but the book does a good job at keeping its advice applicable to a wide range of office cultures and company sizes. The author herself draws from her own experience as an engineering leader at large financial institutions as well as a venture-backed startup, Rent the Runway in the 2010s.</p>
<p>The book &#8220;diffs&#8221; the different levels of engineering management, laying out the differences between being a tech lead vs. an engineering manager, or between managing one team vs. managing multiple teams. Unlike other books that lean heavily on the author&#8217;s particular style or experience, this book zooms into plenty of specific examples and scenarios but also zooms out to meta-advice when that&#8217;s more appropriate. One of my favorite quotes from the book:</p>
<blockquote><p>&#8220;Management tends to be a very culture-specific task in a company. I can give you best practices all day, but if you either work as a manager or hire a manager for a company that&#8217;s not a good culture fit, you&#8217;ll have problems. There is a reason why many young companies want to seed their management teams with people who&#8217;ve been there from the early days and understand the company&#8217;s DNA.&#8221;</p></blockquote>
<p>I also found the book strangely therapeutic, since it describes many problems I&#8217;ve grappled with but haven&#8217;t necessarily discussed with anyone before. In a way I wish I&#8217;d read it a few jobs ago. For example, I liked this description of managing several teams at once:</p>
<blockquote><p>&#8220;The best way to describe the feeling of management from here on out is plate spinning. If you&#8217;re not familiar with it, plate spinning is a fancy form of juggling where the juggler has several poles, each with a plate spinning on top of it.&#8221;</p></blockquote>
<p>I&#8217;ve wanted to read this book ever since a colleague recommended it to me some years ago. But I also wanted to read it for another reason: right out of college, as I was heading to my first job as a software engineer at the Huffington Post, three of my close friends from Princeton went to work as software engineers at Rent the Runway, where Camille was CTO.</p>
<p>I remember this period of my life vividly. Living in NYC, sharing work stories with my friends. Even before I picked up this book, I felt that I knew my fair share about the source material that produced it from when I first started working. And finally reading it felt a bit like the passing of the torch.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Open source your old projects]]></title>
<description><![CDATA[<p>Every time a business or project shuts down, all the source code it produced, typically private and proprietary, never sees the light of day again. This is a real shame, especially for organizations that poured millions into R&#038;D to produce it. I&#8217;ve always believed that we should release as much source code to the public [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2023/04/22/open-source-your-old-projects/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2023/04/22/open-source-your-old-projects</guid>
<pubDate>Sat, 22 Apr 2023 02:05:17 GMT</pubDate>
<content:encoded><![CDATA[<p>Every time a business or project shuts down, all the source code it produced, typically private and proprietary, never sees the light of day again. This is a real shame, especially for organizations that poured millions into R&#038;D to produce it.</p>
<p>I&#8217;ve always believed that we should release as much source code to the public domain as possible. Complete reference implementations help new developers learn and troubleshoot. At the very least, we can point to something and say to ourselves &#8220;I worked on this!&#8221;.</p>
<p>To this end, a few weeks ago I released the <a href="https://github.com/pietrorea/sweetstackhq.com" rel="noopener" target="_blank">source code</a> for the marketing website for sweetstackhq.com. I don&#8217;t own this domain anymore, but here&#8217;s a <a href="https://6427aaf5955a57367c7a728b--famous-muffin-c530a4.netlify.app/www/index.html" rel="noopener" target="_blank">live version</a> hosted on Netlify. Sweetstack is a restaurant-tech project that I worked on full-time from late 2021 through the first half of 2022.</p>
<p>The idea behind Sweetstack is now a thing of the past, but I wanted to release the source code to illustrate a <strong>no build, low-cost, high-control</strong> approach to building a marketing site.</p>
<p>If you have engineers on your payroll, this approach won&#8217;t make sense for you (just use Webflow!). But if you&#8217;re technical and you&#8217;re bootstraping the first few years of your business, read on.</p>
<ul>
<li><strong>No build</strong >: Even after not touching the codebase for over a year, the site came instantly back to life when I threw the static folder onto Netlify. That&#8217;s because I wrote the HTML, CSS and JS directly. There&#8217;s no building, transpiling, or bundling of any kind. Hand-written HTML/CSS/JS has a long shelf-life, and if you want to minimize your yak-shaving costs in the long-run, this &#8220;ancient&#8221; technique will help.</li>
<li><strong>Low-cost</strong>: I paid for a $5 AWS Lightsail VPS to serve the static assets (no CDN!) and ran a tiny Express server that sent emails whenever someone filled out the contact form. To lower your costs down to zero, skip the form and use a mailto link. Then just host your static assets on Netlify or GitHub pages.</li>
<li><strong>High-control</strong>: This was originally why I went with the Lightsail VPS and Express server. I wanted SSH access to the box that was serving my site and sending my emails. In retrospect, for a landing page you don&#8217;t really need this degree of control. If I could go back in time, I would not use a VPS.</li>
</ul>
<p>The <a href="https://github.com/pietrorea/sweetstackhq.com">README</a> includes an overview of the repo if you&#8217;re interested in reading more about how I set things up.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[GitHub Copilot for Business]]></title>
<description><![CDATA[<p>GitHub Copilot for Business&nbsp;came out on Valentine&#8217;s day of this year. My personal Copilot license was so game-changing that when the business version came out, I got licenses for all the other software engineers at Meadow.&nbsp; The most reliable way to use Copilot is to let it handle well-structured, &#8220;repetitive scaffolding&#8221;, which is so common [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2023/03/18/github-copilot-for-business/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2023/03/18/github-copilot-for-business</guid>
<pubDate>Sat, 18 Mar 2023 21:01:42 GMT</pubDate>
<content:encoded><![CDATA[<p><a href="https://github.blog/2023-02-14-github-copilot-for-business-is-now-available/">GitHub Copilot for Business</a><span data-offset-key="3hen5-1-0">&nbsp;came out on Valentine&#8217;s day of this year. </span><span class="veryhardreadability"><span data-offset-key="3hen5-2-0">My personal Copilot license was so game-changing that when the business version came out, I got licenses for all the other software engineers at Meadow</span></span><span data-offset-key="3hen5-3-0">.&nbsp;</span></p>
<p><span data-offset-key="3hen5-3-0"></span></p>
<div class="" data-block="true" data-editor="96pvk" data-offset-key="76l70-0-0">
<div class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr" data-offset-key="76l70-0-0"><span class="veryhardreadability"><span data-offset-key="76l70-0-0">The most reliable way to use Copilot is to let it handle well-structured, &#8220;repetitive scaffolding&#8221;, which is so common in modern programming.</span></span><span data-offset-key="76l70-1-0">&nbsp;It&#8217;s also good</span><span class="hardreadability"><span data-offset-key="76l70-4-0">&nbsp;at figuring out the right import paths in TypeScript, which reduces my need to context-switch</span></span><span data-offset-key="76l70-5-0">. </span></div>
</div>
<p><span class="veryhardreadability"><span data-offset-key="76l70-6-0"></span></span></p>
<div class="" data-block="true" data-editor="96pvk" data-offset-key="78jua-0-0">
<div class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr" data-offset-key="78jua-0-0"><span data-offset-key="78jua-0-0">I&#8217;m more watchful when Copilot suggests business logic. But it&#8217;s also surprising (and somewhat spooky) how good these suggestions can be. </span><span class="hardreadability"><span data-offset-key="78jua-1-0">One time, Copilot </span></span><span class="hardreadability"><span data-offset-key="78jua-3-0">figured out the rules to calculate Pell Grants based on the number of credits a college student is currently taking</span></span><span data-offset-key="78jua-4-0">. This information was nowhere else in</span><span data-offset-key="78jua-6-0">&nbsp;our code base.</span></div>
</div>
<p><span data-offset-key="9g6bf-0-0"></span></p>
<p><span data-offset-key="9g6bf-0-0"></span></p>
<div class="" data-block="true" data-editor="96pvk" data-offset-key="78jua-0-0">
<div class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr" data-offset-key="78jua-0-0"><span data-offset-key="9g6bf-0-0">Copilot, or something like Copilot, is the future of programming. If you haven&#8217;t tried it yet, I&nbsp;strongly encourage you to try it. Even though Copilot only supports a few IDEs (Visual Studio Code, Visual Studio, Neovim, and JetBrains IDEs), the bump in productivity justifies switching IDEs if you need to.</span></div>
</div>
<p><span data-offset-key="9g6bf-2-0"><span class="hardreadability"><span data-offset-key="9g6bf-3-0"></span></span></span></p>
<p><span data-offset-key="9g6bf-2-0"><span class="hardreadability"><span data-offset-key="9g6bf-3-0"></span></span></span></p>
<div class="" data-block="true" data-editor="96pvk" data-offset-key="78jua-0-0">
<div class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr" data-offset-key="78jua-0-0"><span data-offset-key="9g6bf-2-0"><span class="hardreadability"><span data-offset-key="9g6bf-3-0">It&#8217;s early enough that we will start to see differences between engineering teams that use AI assistants and ones that don&#8217;t.</span></span></span></div>
</div>
]]></content:encoded>
</item>
<item>
<title><![CDATA[New writing setup: Gatsby.js and WordPress as a headless CMS]]></title>
<description><![CDATA[<p>As I proposed in my Gatsby.js retro, I finally transitioned this blog from using Markdown files stored in git to using WordPress as a headless CMS (diff here). It&#8217;s still a statically-generated site and it still uses Gatsby.js. The only thing that changed is how the underlying data is stored and managed. My writing workflow [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2023/02/16/new-writing-setup-gatsby-js-and-wordpress-as-a-headless-cms/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2023/02/16/new-writing-setup-gatsby-js-and-wordpress-as-a-headless-cms</guid>
<pubDate>Thu, 16 Feb 2023 04:24:45 GMT</pubDate>
<content:encoded><![CDATA[<p>As I proposed in my <a href="https://www.pietrorea.com/2023/01/07/4-years-of-blogging-on-gatsby-js/">Gatsby.js retro</a>, I finally transitioned this blog from using Markdown files stored in git to using WordPress as a headless CMS (<a href="https://github.com/pietrorea/pietrorea.com/commit/511ee7674eafdb2670531b6b5aaccfe417a9bcfc">diff here</a>). It&#8217;s still a statically-generated site and it still uses Gatsby.js. The only thing that changed is how the underlying data is stored and managed.</p>
<p>My writing workflow now looks like this: I write on my self-hosted WordPress instance, saving drafts as needed. I used the web interface for this blog post but I can use any writing tool that WordPress supports. For example, I wrote the last post about Meadow&#8217;s <a href="https://www.pietrorea.com/2023/02/03/meadow-raises-a-3-5m-seed-round/">seed funding announcement</a>&nbsp;from bed on the WordPress iOS app.</p>
<p>When I&#8217;m done writing a blog post, I click &#8220;Publish&#8221; on WordPress, which tells Netlify via webhook to kick off a new Gatsby build. The build process grabs all my WordPress content using a <a href="https://wordpress.org/plugins/wp-graphql/">GraphQL WordPress plugin</a>, and re-publishes my updated blog onto Netlify. Lest you think this is a bespoke system I invented, it&#8217;s all officially supported by Gatsby. They publish and maintain the Gatsby source plugin (<a href="https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-wordpress/docs/getting-started.md">gatsby-source-wordpress</a>), as well as the WordPress plugin (<a href="https://wordpress.org/plugins/wp-gatsby/">WPGatsby</a>) to make this all work. Their documentation and tutorials were also quite helpful.</p>
<p>I briefly considered leaving Netlify behind in favor of Gatsby Cloud for the tighter integration and so I could take advantage of Gatsby Cloud&#8217;s&nbsp;<a href="https://support.gatsbyjs.com/hc/en-us/articles/360055676874-CMS-Previews\">CMS preview feature</a>, but after hearing that Netlify acquired Gatsby, I&#8217;m glad I didn&#8217;t. As with all acquisitions, the future of the acquired company is now unclear.</p>
<p>Despite my griping about Gatsby&#8217;s dependency on GraphQL, re-platforming my blog&#8217;s content took me less than a day because the structure of the GraphQL queries were largely the same, even though they were pulling data from entirely different sources.</p>
<p>I am sure to retro this new blogging setup in a few years, but so far it&#8217;s been working well. Writing on a professional-grade authoring experience is a huge upgrade compared to what I was doing before.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Meadow raises a $3.5M seed round]]></title>
<description><![CDATA[<p>I&#8217;m very excited to announce that Meadow has raised a $3.5M seed round to build a modern student financial services platform for universities. Here&#8217;s our press release, and here&#8217;s the reporting from Business Insider (paywalled) that came out on Tuesday. I haven&#8217;t written about Meadow on here before, so allow me to formally introduce it. Meadow [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2023/02/03/meadow-raises-a-3-5m-seed-round/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2023/02/03/meadow-raises-a-3-5m-seed-round</guid>
<pubDate>Fri, 03 Feb 2023 00:08:24 GMT</pubDate>
<content:encoded><![CDATA[<p>I&#8217;m very excited to announce that Meadow has raised a $3.5M seed round to build a modern student financial services platform for universities. Here&#8217;s our <a href="https://www.prnewswire.com/news-releases/meadow-raises-3-5m-to-simplify-how-students-pay-for-college-301735196.html">press release</a>, and here&#8217;s the <a href="https://www.businessinsider.com/college-tuition-payments-startup-meadow-edtech-seed-venture-capital-funding-2023-1?op=1">reporting</a> from Business Insider (paywalled) that came out on Tuesday.</p>
<p>I haven&#8217;t written about Meadow on here before, so allow me to formally introduce it. Meadow is an early-stage startup whose mission is to empower students financially and to promote economic mobility through higher education.</p>
<p>In the U.S, what students end up paying for college is not the &#8220;sticker price&#8221;, but rather an amount discounted by grants, scholarships and other forms of aid. Figuring out what you actually need to pay to attend college is opaque and confusing, complicating planning and decision-making for students and their families. Many students don&#8217;t even try to engage with this system, assuming college is out of reach for them.</p>
<p>So in 2008, Congress mandated that every school must have a &#8220;net price calculator&#8221; on their website, allowing interested students to get a personalized cost estimate after providing a few pieces of data about themselves. This is where Meadow comes in. Taking advantage of some <a href="https://www.congress.gov/bill/116th-congress/house-bill/7105">legislative headwinds</a> in 2021, we introduced our own take on the <a href="https://www.meadowfi.com/platform/meadow-price">net price calculator</a> early last year, transforming what used to be merely a compliance requirement into a tool that improves enrollment for schools and elevates financial clarity for students.</p>
<p>We now have over 10 schools live on our net price calculator product and many more in our pipeline. Some recent launches include University of Texas at Austin, Nevada State College and Maryland Institute College of Art (MICA).</p>
<p>But the crisis in higher education is not just about lack of transparency. Once you know what you need to pay, actually paying for college has other major roadblocks. Some of it is timing and communications. Students receive obtuse billing statements in the mail, often without enough advance notice to make a financial plan. And once they are ready to pay, making the payment is also difficult. If there is a digital way to pay, the system is often decades old and difficult to use. Otherwise, they have to mail checks, call the student accounts office, or go in person.</p>
<p>All this friction might not sound like a big deal, but it&#8217;s death by a thousand cuts. One of our school partners tells us that they lose roughly half of their freshman class the following year <em>every year</em>. They just don&#8217;t come back.</p>
<p>This is the problem Meadow&#8217;s second product, Meadow Pay, is going to solve and the reason why we raised the seed round. Meadow Pay is designed to be the modern payments and engagement platform for higher ed students. It&#8217;s the missing piece between students and universities.</p>
<p>I joined Meadow back in June of 2022 as Co-Founder &amp; Head of Engineering. The past 8 months have been a whirlwind of building, hiring, planning and pitching. I feel like I&#8217;ve been wearing every possible hat that could exist in an engineering org, but luckily we&#8217;re up to four engineers now.</p>
<p>Here&#8217;s a picture of us at our last NYC on-site:</p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-136" src="/wp-content/uploads/2023/02/image-scaled.jpg" width="2560" height="1920" srcset="/wp-content/uploads/2023/02/image-scaled.jpg 2560w, /wp-content/uploads/2023/02/image-300x225.jpg 300w, /wp-content/uploads/2023/02/image-1024x768.jpg 1024w, /wp-content/uploads/2023/02/image-768x576.jpg 768w, /wp-content/uploads/2023/02/image-1536x1152.jpg 1536w, /wp-content/uploads/2023/02/image-2048x1536.jpg 2048w" sizes="auto, (max-width: 2560px) 100vw, 2560px" /></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[4 years of blogging on Gatsby.js, a retro]]></title>
<description><![CDATA[<p>It&#8217;s been over four years since I started building my blog on Gatsby.js. It&#8217;s common to read blog posts about moving your blog over to a new platform (here&#8217;s my post from 2018), but I find it much more valuable to read about how it went for those people after using the new platform for [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2023/01/07/4-years-of-blogging-on-gatsby-js/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2023/01/07/4-years-of-blogging-on-gatsby-js</guid>
<pubDate>Sat, 07 Jan 2023 19:04:58 GMT</pubDate>
<content:encoded><![CDATA[<p>It&#8217;s been over four years since I started building my blog on Gatsby.js. It&#8217;s common to read blog posts about moving your blog over to a new platform (<a href="https://www.pietrorea.com/2018/05/31/new-blogging-platform-gatsby-js">here&#8217;s my post</a> from 2018), but I find it much more valuable to read about how it went for those people after using the new platform for a while.</p>
<p>Four years after moving to Gatsby.js, I&#8217;ve averaged between 3 and 4 blog posts a year. During this time, I&#8217;ve also had over 22k visitors, averaging to ~400 visitors per month. Not a large site or audience by any means, but I definitely wrote more and had more readers than before.</p>
<blockquote><p>“Can’t repeat the past?…Why of course you can!” &#8211; Jay Gatsby</p></blockquote>
<p>Trying to put myself in my 2018 shoes is difficult, but I remember moving to Gatsby with several goals in mind. Here&#8217;s what they were:</p>
<ul>
<li>Learn more about React and GraphQL, which I had started to use for work.</li>
<li>Get more freedom with with the look and feel of my site. I felt constrained by Squarespace and WordPress theme.</li>
<li>Achieve ease of maintenance. I did not want worry about running WordPress (upgrades, backups, plug-ins, etc).</li>
<li>Fourth (probably too low on my list, come think of it), I wanted to write more. I felt stifled by the clunky WYSIWYG editors I&#8217;d previously had to use, so I wrote very little. The idea of writing blog posts in plaintext, using Markdown, was appealing at the time.</li>
</ul>
<h2>Things that went well</h2>
<blockquote><p>“The truth was that Jay Gatsby, of West Egg, Long Island, sprang from his Platonic conception of himself.&#8221; &#8211; Nick Carraway</p></blockquote>
<p>I met my learning goals. This site is a small, low-effort, project that made me more comfortable with React, and to a lesser extent, GraphQL. The <em>real</em>learning actually came from work, circa 2018-2019, where I used both of these in real web apps.</p>
<p>Something else that panned out was the degree of customization I was achieved. My current blog still looks a lot like the Gatsby starter project, but the typography, colors and layout are all mine. I particularly liked the way Gatsby handles <a href="https://www.gatsbyjs.com/docs/creating-and-modifying-pages/">creating pages</a> (about, archive, etc.). To create a new page, all you need is a new React component in <code class="language-text">src/pages</code> and you&#8217;re done.</p>
<p>Gatsby&#8217;s rich plugin ecosystem was also good. I kept it simple with <code class="language-text">gatsby-plugin-google-analytics</code> for GA, <code class="language-text">gatsby-plugin-feed</code> to generate an RSS feed and a few others. Configuring Gatsby packages was not ideal — you have to maintain <code class="language-text">gatsby-config</code> with an entry for each plugin, which sometimes includes inline GraphQL queries. This method of configuration left me wanting.</p>
<p>Maintenance was both good and bad. If this site were a car, and we were tracking maintenance costs by <em>cents per mile</em>, this setup would be extremely inexpensive in time and money. There were a couple of discouragingly frustrating upgrade cycles but, amortized over 4 years, they were not a big deal.</p>
<p><a href="https://netlify.com/">Netlify</a> made hosting and deployment free and easy. I started off in an S3 bucket fronted by a CloudFront distribution, which I would not recommend if you don&#8217;t want to think about hosting or deployment. Netlify is a spiritual descendent of Heroku, so I could deploy with a <code class="language-text">git push</code>. One of my blog posts was #1 in Hacker News for a couple of days, and Netlify served over 30 GB in bandwidth without batting an eyelash.</p>
<p>After few years of running this site, I&#8217;m a believer in statically-generated websites. For a personal project or blog, it&#8217;s mostly neglect-proof. Despite semi-annual updates to this site&#8217;s dependencies in <code class="language-text">package.json</code>, there&#8217;s an embarrassingly high number of Dependabot alerts open against this repo. But that&#8217;s <em>largely OK</em>, because I&#8217;m not responsible for a live system serving requests. The end result is just a bucket of HTML/CSS/JS fronted by a CDN.</p>
<h2>Things that did not go well</h2>
<blockquote><p>“It takes two to make an accident.” &#8211; Jordan Baker</p></blockquote>
<p>React and GraphQL were overkill. Trying to keep things as simple as possible, I didn&#8217;t use a component library such as Material UI. So React was just a templating language for HTML, a job it was way overqualified for.</p>
<p>One of Gatsby&#8217;s selling points is the &#8220;unified data layer&#8221; that GraphQL provides. The only data I needed came from local markdown files. Writing GraphQL queries to pull in data from local files went against my &#8220;keep it simple&#8221; mantra. If you&#8217;re considering Gatsby.js as a way to get your feet wet with React and GraphQL, I would not recommend starting with a blog. You&#8217;d be much better served by writing a more traditional web app.</p>
<p>Next, I&#8217;ll address the <strong>biggest downside</strong> of rolling your own blog with Gatsby. As with all things, the biggest strength is also the biggest weakness. I love that I have full control to tweak this blog however I want&#8230;the bad news is that now I have to build a baseline number of features myself.</p>
<p>Notice how this site (as of January 2023) doesn&#8217;t have search, tagged posts, or comments. It doesn&#8217;t even paginate the homepage! Every blog post I&#8217;ve ever written ends up listed in one long page, which will quickly become a problem as I continue to write more. These missing features are table stakes in any serious blogging platform.</p>
<p>To be brutally honest, I traded <em>potential customization</em> for an objectively worse site. And if I ever do get around to building those features, wouldn&#8217;t that be a waste? If every person who could code had to build basic blogging features, how many developer hours would we waste rewriting the same things over and over?</p>
<p>The area where this tradeoff is most obvious is the <strong>authoring experience</strong>. My current workflow for writing a blog post is the same as my workflow for writing code — spin up a text editor, create a new Markdown file and <code class="language-text">git push</code> to trigger the build when you&#8217;re done.</p>
<p>I&#8217;ve tried to automate the tedious parts of writing a new blog post with <a href="https://github.com/pietrorea/pietrorea.com/blob/master/scripts/new_blog_post.sh">a bash script</a> but it&#8217;s still cumbersome. Git and VS Code are great tools, but are not the right tools for <em>this</em> particular job. In a world where we have lots of great, purpose-built, authoring clients, knowing that I cannot use any of them is frustrating.</p>
<p>And I&#8217;m not the only one that feels this pain. The company behind Gatsby.js describes their Markdown-powered blog like this:</p>
<blockquote><p>Our old process required building the entire Gatsby site locally, formatting Word docs to Markdown, updating different files for the content and author profile, then submitting a Pull Request and massaging the updates to pass a series of automated tests. I can tell you war stories of spending hours to fix a single typo, because even a small change retriggered that full process.</p></blockquote>
<p>Yup — prose is not code.</p>
<h2>Improvements</h2>
<blockquote><p>“Let us learn to show our friendship for a man when he is alive and not after he is dead.” &#8211; Meyer Wolfsheim</p></blockquote>
<p>To the Gatsby team — I already mentioned the low maintenance of this Gatsby setup being a plus, but we can make this even easier. On any given day, this blog does not give me any issues. However, I&#8217;ve spent <em>hours</em> trying to upgrade to new major versions of Gatsby. Even the simplest setup like mine has too many plugins. Some Gatsby plugins should be part of the core package.</p>
<p>Second, make GraphQL optional. There&#8217;s already been <a href="https://www.gatsbyjs.com/docs/how-to/querying-data/using-gatsby-without-graphql/">some work</a> to make Gatbsy work without using GraphQL, but we need to go even further. GraphQL should not be a direct dependency of the main Gatsby package.</p>
<p>The biggest improvement I could make to running this site is to the authoring experience. I have a few options if I want to get out of the business of shipping prose as code. I definitely don&#8217;t want serve everything from Squarespace or WordPress again, but I do want a WordPress-like authoring experience. Can I only use the parts of WordPress I actually want?</p>
<p>Turns out you can if you use WordPress as a headless CMS. This is what the Gatsby team <a href="https://www.gatsbyjs.com/blog/gatsby-blog-wordpress/">ended up doing</a> with their own blog.</p>
<p>If I went with this setup, I could keep a low-powered, private, WordPress instance that Gatsby could consult at build time. The stakes of running WordPress would be way lower — there&#8217;d only be two users, me (for authoring) and the Gatsby build process. I could theoretically keep the best parts of Gatsby and WordPress without incurring significant costs in maintenance or complexity.</p>
<p>I&#8217;m not sure this is where I&#8217;ll end up going with my blog, but you should consider this option if you&#8217;re starting from scratch. Gatsby even maintains a <a href="https://github.com/gatsbyjs/gatsby-starter-wordpress-homepage">Gatsby + headless WordPress starter project</a> that you can consult.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Taking notes with BBEdit 14, Working Copy and a self-hosted git repo]]></title>
<description><![CDATA[<p>I take a lot of notes as I work during the day. I usually keep a running log of the work I&#8217;m doing for the day. It helps me think out loud and write proto-documentation for myself. It&#8217;s a great way to remember what I was up to before. Last October, as I quarantined in [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2022/09/08/taking-notes-with-bbedit-14-and-a-private-git-server/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2022/09/08/taking-notes-with-bbedit-14-and-a-private-git-server</guid>
<pubDate>Thu, 08 Sep 2022 19:04:03 GMT</pubDate>
<content:encoded><![CDATA[<p>I take a lot of notes as I work during the day. I usually keep a running log of the work I&#8217;m doing for the day. It helps me think out loud and write proto-documentation for myself. It&#8217;s a great way to remember what I was up to before.</p>
<p>Last October, as I quarantined in my son&#8217;s bedroom, I decided to reorganize all my notes and update my note-taking process.</p>
<p>Previously, I used Ulysses for Mac to manage all my notes. I loved the design of the app and the syncing functionality, but I was starting to have performance issues. Opening Ulysses on my (then) new M1 Mac would sometimes take 5-10 seconds. It was even worse on my iOS device. I suspected there was <em>something</em> in my big pile of notes that Ulysses didn&#8217;t like. I contacted support but couldn&#8217;t get to the bottom of it.</p>
<p>Enter BBEdit.</p>
<p><a href="https://www.barebones.com/support/bbedit/">BBEdit</a> is a text editor originally made for Macintosh System Software 6, over 30 years ago. It&#8217;s not typically in the &#8220;note taking&#8221; app category but it&#8217;s been a foundational app for generations of macOS users and developers.</p>
<h2>Migrating to BBEdit</h2>
<p>Ever since the tedious migration process out of Evernote&#8217;s proprietary format circa 2016, I&#8217;d insisted on keeping all my notes as plain text files. This is partially why I&#8217;d chosen Ulysses after Evernote since you could stick to plain text using their <a href="https://help.ulysses.app/kb/guide/en/external-folders-ZfPYZQCwid/Steps/1048491">external folders</a> feature.</p>
<p>Next, I created a <strong>BBEdit project</strong> and added all my files to it. A BBEdit project (extension <code class="language-text">.bbprojectd</code>) is a special kind of file that contains references to other files and folders. BBEdit projects let you work with related files without needing them to be located together on disk. If you&#8217;re familiar with Xcode&#8217;s project files, BBEdit projects work similarly.</p>
<p>There are many ways to customize BBEdit to work for you. Two notable changes I made:</p>
<ul>
<li>I re-mapped the shortcut for BBEdit&#8217;s &#8220;Open File By Name&#8221; feature. This feature is usually called &#8220;Quick Open&#8221; in other apps and it&#8217;s my primary way of navigating in VSCode, Xcode, Android Studio, Tower, etc. To reuse existing muscle memory, I re-mapped BBEdit&#8217;s default shortcut to <strong>⌘ + Shift + O</strong> in System Preferences.</li>
<li>I made BBEdit open my notes project open whenever it launches. By default, BBEdit doesn&#8217;t open anything when you first launch the app. If you want to have a default file, folder or project that you want BBEdit to open on app launch, you can put it in BBEdit&#8217;s &#8220;Startup Item&#8221; folder. I <a href="https://gist.github.com/pietrorea/c9c5597677eb3db5e3aa90cd0b4e1c1f">symlinked</a> my notes project to the &#8220;Startup Item&#8221; folder to accomplish this.</li>
</ul>
<h2>Setting up a git remote for my notes</h2>
<p>My old note-taking workflows relied on Dropbox or iCloud drive to sync my notes to all my devices. This is where I lacked good options — I don&#8217;t run the Dropbox native client on my Mac anymore and iCloud Drive is too non-deterministic for me.</p>
<p>This piece of my setup won&#8217;t work for everyone, but I ended up going with git. My notes are often <em>about</em> the things I have in source control, so as I&#8217;m slinging source code back and forth from a git remote, I figured I could do the same with my notes.</p>
<p>If it had been for anything else, I would have created a private repo in GitHub and called it a day. I ended up not wanting to put my years of thinking, planning and researching up on a public service, so I spun up a $5/month VPS instance from AWS Lightsail to be a dedicated git server.</p>
<p>This ended up being much simpler than I expected and I&#8217;ve had to do zero maintenance on this server this past year. After setting up your user account and SSH access on the VPS, just create a repo somewhere in your home directory and you&#8217;re done. The trickiest part is getting the remote URL right when connecting from a git client (i.e. <em>[user]@[hostname]:~/[path-to-repo]/[repo-name].git</em>).</p>
<p>I read and write most of my notes on my Mac, where I alternate between using git on the terminal and <a href="https://www.git-tower.com/mac">Tower</a>. On iOS, I use <a href="https://workingcopy.app/">Working Copy</a> as my git client.</p>
<p>With this setup, there&#8217;s the risk that I won&#8217;t have my latest notes on my mobile device if I forget to push to the remote. This has only happened once in the year of having this setup, so I hasn&#8217;t been a problem for me.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Reclaiming the lost art of Linux server administration]]></title>
<description><![CDATA[<p>One of the skills I wish I&#8217;d learned earlier in my career is basic Linux server administration. Specifically in relation to hosting something on the web, either a web app or API that I wrote myself, or something from the thriving self-hosted community, such as WordPress. Managing servers is increasingly seen as the &#8216;older way&#8217; [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2022/01/28/reclaiming-the-lost-art-of-linux-server-administration/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2022/01/28/reclaiming-the-lost-art-of-linux-server-administration</guid>
<pubDate>Fri, 28 Jan 2022 19:03:05 GMT</pubDate>
<content:encoded><![CDATA[<p>One of the skills I wish I&#8217;d learned earlier in my career is basic Linux server administration. Specifically in relation to hosting something on the web, either a web app or API that I wrote myself, or something from the thriving <a href="https://github.com/awesome-selfhosted/awesome-selfhosted">self-hosted community</a>, such as WordPress. Managing servers is increasingly seen as the &#8216;older way&#8217; of doing things, so it&#8217;s easy to become a software developer and never learn to set up a VPS, set up remote access, stand up a firewall, etc.</p>
<p>Choosing to actively manage your infrastructure is part of a much larger discussion about the proper way to choose your tools. This discussion is extensive and it runs along many different dimensions.</p>
<p>There&#8217;s the axis of <a href="https://mcfunley.com/choose-boring-technology">new vs. old tech</a> and also of build vs. buy. Finally, there&#8217;s the decision to use <strong>managed vs. unmanaged services</strong>. This last one is the topic of this blog post.</p>
<p>At one end of the spectrum, you can manage everything like it&#8217;s 1999. You set up your own host, install and manage dependencies, set up backups, etc. As you move towards the fully-managed end of the spectrum, you start to see lightly-managed compute primitives like Amazon RDS all the way to full-service, cloud-enabled app frameworks like AWS Amplify or Google App Engine, and BaaS/PaaS providers like Heroku.</p>
<p>The default position at most places I come across is to go as managed as you can tolerate, usually to save on engineering effort. But how did we manage to ship anything just 10 years ago, when most of these options weren&#8217;t available?</p>
<p>The truth is that it <em>was</em> possible to build high-traffic web services in the &#8220;bad old days&#8221;, even with a very small team. Even with <em>just one person</em>. This is how Marco Arment describes his experience building and running Tumblr circa 2010, largely by himself:</p>
<blockquote><p>Tumblr taught me by necessity, especially in the early days when we had no staff and very little money, how to develop and host a high-traffic web service cheaply, easily, and sanely. I couldn’t let the servers require too much maintenance because server administration wasn’t my main job — we didn’t have a dedicated server administrator for the first few years, so I just had to set things up such that they didn’t need much administration.</p></blockquote>
<p>You can read the full blog post <a href="https://marco.org/2014/03/27/web-hosting-for-app-developers">here</a>. If you still don&#8217;t believe that people shipped big things fast before all of these cloud services came on the scene, I recommend reading some of the write ups at <a href="http://highscalability.com/">High Scalability</a>, especially the ones from the previous decade. I particularly like the series on <a href="http://highscalability.com/blog/2009/8/5/stack-overflow-architecture.html">Stack Overflow</a>.</p>
<p>The good news is that these tools and techniques are still available to everyone. I propose that you turn the default position on its head — instead of defaulting to highly managed services, default to self-managed services and only venture out as needed.</p>
<h2>How did we get here?</h2>
<p>If you, like me, believe that basic server maintenance is a dying art, how did we get here? It&#8217;s easy to point fingers at the big cloud providers and say, &#8220;They don&#8217;t want us to learn this stuff for their own profit!&#8221;. But the actual reason might be more prosaic. Combine the multi-billion dollar marketing budgets of AWS, GCP and Azure and you have significant gravitational pull. Then add their respective armies of developer evangelists. Sprinkle in some cargo-culting and a decade&#8217;s worth of &#8220;ship fast and break things&#8221; and you end up where we are today.</p>
<p>Before getting into the benefits of learning basic Linux administration, keep in mind tha this isn&#8217;t a black or white proposition. Like any good engineering challenge, it&#8217;s about tradeoffs. For example, if you do read stories from the previous decade, you&#8217;ll see people building their own hardware. That&#8217;s where I draw the line. Unless you need the performance, <em>don&#8217;t manage physical hardware</em>. Get a Linux VPS from a reputable hosting provider and be done with it.</p>
<p>Also stay away from the notion that &#8220;the cloud is evil&#8221;. That&#8217;s where most of these type of articles go astray. The big cloud providers have given us real benefits and real innovations over the past decade. That fact is undeniable. The trick is to separate the wheat from the chaff. For example, I&#8217;m not going to build <a href="https://firebase.google.com/docs/database/">realtime database</a> but I will learn how to self-host MySQL if that&#8217;s all I need.</p>
<h2>Reaping the benefits of Linux administration</h2>
<p>OK — you&#8217;ve gotten this far without knowing how to run your own servers. Why change? These are some of the reasons that convinced me.</p>
<p><strong>No vendor lock-in</strong>. If you run your whole system on Linux VPSes, you&#8217;ve essentially commoditized the compute layer. If something happens with your current host, you can pack up your things and set up shop somewhere else whenever you like.</p>
<p><strong>Unrestrained compute</strong>. Netlify will only host your one repo. Lambda will only run your one function. Linux admin is a chore, but in return <em>you get the whole computer</em>. You can install whatever software you want and set things up as you see fit. You can even save some money in the process since you can run all your applications on the same infrastructure instead of paying per app.</p>
<p><strong>Long-lasting skills</strong>. The tech industry moves <em>fast</em>, but if you look around there are certain foundational technologies that have stuck around for a long, long time. Bash, SSH, nginx/Apache, even Linux itself. Here&#8217;s an uncontroversial claim: these foundational technologies will continue to be foundational throughout your entire career. What else can you say that about in the tech industry? The earlier you learn how to write a good Bash script, the better. Compare this reality with cloud services. Building on top of them often feels like quicksand — they morph under you, quickly deprecate earlier versions and sometimes shut down entirely.</p>
<p><strong>The speed (and joy) of using tools</strong>. This one is my favorite. And here I make a distinction between a &#8220;tool&#8221; and a &#8220;service&#8221;. A hammer is a tool. I use a hammer in exactly the way I want . It blends into the background and becomes an extension of myself. In contrast, a service talks back. It wants things. We&#8217;re so surrounded by services that we&#8217;ve forgotten what using a tool feels like. Linux is a tool. Bash is a tool. They&#8217;re quiet and obedient. The only thing they ask for is your dedication. They&#8217;re also fast, if you know how to use them. Here&#8217;s my theory: the dexterity that comes from learning these tools contributes to most of the potential productivity boost of self-hosting.</p>
<h2>Getting started</h2>
<p>Starting is not hard, but you need a plan. Just like learning programming, I recommend having a project that requires you to learn Linux admin. If you have a <em>need to learn</em>, you will learn. You don&#8217;t need to be a programmer to manage Linux servers, but if you&#8217;re a programmer, this might be as easy as deciding to run your own software directly on a Linux VPS. If you&#8217;re not a programmer, you can choose from a variety of open source projects with a strong community that can help you if you get stuck. Some projects that might interest you are <a href="https://www.home-assistant.io/">Home Assistant</a>, <a href="https://pi-hole.net/">Pi-hole</a> or something from <a href="https://github.com/awesome-selfhosted/awesome-selfhosted">this list of projects</a>.</p>
<p>I also recommend picking and committing to a &#8216;default admin stack&#8217; that includes an OS, Bash, a scripting language, a webserver and a data store. Just like you use macOS or Windows for all your personal computing, you should also pick a specific Linux distribution as your default server OS. It takes time to be productive in any OS. That&#8217;s why you need to pick one and stick to it. For example, my OS of choice is <a href="https://ubuntu.com/">Ubuntu</a> — I picked it because it has a large community, it&#8217;s easy on beginners and almost everything I&#8217;d want to host has official Ubuntu support.</p>
<p>As for scripting, commit to getting good at <a href="https://www.gnu.org/software/bash/">Bash</a>. Bash is the default &#8220;shell&#8221; for most Linux distributions. If you&#8217;re not familiar with that term, the shell is the program that runs your other programs, so it pays <em>huge dividends</em> to know to make this layer bend to your will.</p>
<p>Bash is the primary interface for the command line terminal and it is also a scripting language. You can (and should!) save your terminal commands in a file for later use, so you can run them all at once. If you get good at this, it will help you remember how you set things up, and will automate a lot of things for you. I can&#8217;t stress enough how important this is, and how universally useful it can be to learn Bash. As a practical goal, you should be able to recreate your host <strong>with a single Bash script</strong>.</p>
<p>There&#8217;s only one specific feature in Bash I want to highlight: <a href="https://www.gnu.org/software/bash/manual/bash.html#Here-Documents">here documents</a>. Most things on a server that you&#8217;d want to set up use text files for their configurations. Here documents let you specify an &#8220;inline file&#8221; inside your script file. If you know what a string literal is, you can think of here documents as a &#8220;file literal&#8221;. Here&#8217;s <a href="https://gist.github.com/pietrorea/5badae19ae8bd58c980b3fe9debddef0">an example</a> that sets up remote SSH access. Here&#8217;s <a href="https://gist.github.com/pietrorea/9081e2810c20337c6ea85350a31bb427">another example</a> that directs MySQL to create a database and an admin user. That&#8217;s how you can set up an entire server with only one script. Learning to use here documents took me from casual Bash user to budding system administrator. I wish I had learned it years earlier.</p>
<p>Bash has been around for a while, so it has its share of rough edges compared to more modern programming environments. For example, if you&#8217;re a programmer, you might take it for granted that every scripting language has dictionaries/hash maps, right? Well, in Bash associative arrays didn&#8217;t formally exist until Bash 4. Some older systems have Bash 3 as the default version, so you can&#8217;t use dictionaries unless you install a newer version of Bash.</p>
<p>For all of Bash&#8217;s advantages, I agree with Google&#8217;s <a href="https://google.github.io/styleguide/shellguide.html#s1.1-which-shell-to-use">Shell Style Guide</a>:</p>
<blockquote><p>If you are writing a script that is more than 100 lines long, or that uses non-straightforward control flow logic, you should rewrite it in a more structured language now. Bear in mind that scripts grow. Rewrite your script early to avoid a more time-consuming rewrite at a later date.</p></blockquote>
<p>You can get far with just Bash, and if you&#8217;re not a programmer, that might be a good stopping point. But if need to write longer scripts, then the next decision you need to make after picking a default server OS is picking a default scripting language.</p>
<p>In theory, any language that can interact with OS can do, which includes most programming languages. For example, MySQL ships with a script called <code class="language-text">mysql_secure_installation</code>. The <a href="https://github.com/twitter-forks/mysql/blob/master/scripts/mysql_secure_installation.sh">original version</a> was written in Bash, but as the script grew, it got <a href="https://github.com/mysql/mysql-server/blob/7ed30a748964c009d4909cb8b4b22036ebdef239/client/mysql_secure_installation.cc">a rewrite</a> in C++. This was a good choice for that project, because MySQL is written in C/C++, but it&#8217;s probably not a good choice for your default scripting language.</p>
<p>For your scripting language, I recommend something that doesn&#8217;t require compilation, with a strong community behind it. Python, Ruby and JavaScript are all good choices. I picked JavaScript because I like to limit the things I need to learn, and I already needed JavaScript/TypeScript for the web. Node also has a huge library of packages via <a href="https://www.npmjs.com/">npm</a> if I ever need to do something more complicated.</p>
<p>If you&#8217;re an iOS developer, as much as I&#8217;d like to recommend Swift, I can&#8217;t recommend it for Linux administration. Linux support is getting better, and you can avoid the compilation step and <a href="https://krakendev.io/blog/scripting-in-swift">use Swift like a scripting language</a>, but the Swift Package Manager simply pales in comparison to NPM, especially for something like Linux management.</p>
<p>After picking your OS, learning Bash and (optionally) committing to a scripting language, the next things on the shopping list are a web server and a data layer. Keep in mind that this is just for server administration. If you&#8217;re not a programmer, you don&#8217;t need to learn a database like a programmer would.</p>
<p>I picked <a href="https://nginx.org/">nginx</a> as my default webserver, although I hear Apache is also good. Learning to use a good webserver will help you direct traffic to your applications, so it&#8217;s essential. For my default database, I picked <a href="https://www.mysql.com/">MySQL</a>. It&#8217;s been around long enough, that there&#8217;s nothing I could throw at it that would make it break a sweat.</p>
<p>To reiterate, when you&#8217;re just starting, it&#8217;s more important to pick something to host than to pick the tools to host it with. Let the app dictate what you need to learn first. If you don&#8217;t know what to pick as your first hosted app, you can&#8217;t go wrong with <a href="https://wordpress.org/">WordPress</a>. There are many hosting providers that offer 1-click WordPress installations, but if something goes wrong, you won&#8217;t know how everything was set up in order to fix it. As a concrete goal, aim to set up WordPress on a new host in <strong>a single script</strong>. Feel free to look at my examples for <a href="https://github.com/pietrorea/scripts/blob/master/ubuntu/setup.sh">VPS setup</a> and <a href="https://github.com/pietrorea/scripts/blob/master/ubuntu/install-wordpress.sh">WordPress installation</a> if you find them helpful.</p>
<p>Happy hosting!</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Filtering emails by the List-Unsubscribe header in Fastmail]]></title>
<description><![CDATA[<p>I get too many emails. You get too many emails. Everyone gets too many emails. It&#8217;s such a reality of digital life that no one really talks much about it anymore. The onslaught is seemingly unstoppable. Every new online account is liable to become another source of unwanted email. Innocuous interactions like getting a &#8220;digital [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2021/10/22/filter-emails-by-the-list-unsubscribe-header/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2021/10/22/filter-emails-by-the-list-unsubscribe-header</guid>
<pubDate>Fri, 22 Oct 2021 19:02:00 GMT</pubDate>
<content:encoded><![CDATA[<p>I get too many emails. You get too many emails. Everyone gets too many emails. It&#8217;s such a reality of digital life that no one really talks much about it anymore.</p>
<p>The onslaught is seemingly unstoppable. Every new online account is liable to become another source of unwanted email. Innocuous interactions like getting a &#8220;digital receipt&#8221; at the store or joining a &#8220;loyalty program&#8221; at a restaurant just means one thing: spam.</p>
<p>Back when I mostly used Gmail, I used to manually create filters to weed out senders that didn&#8217;t respect my unsubscribe requests. Since I moved to <a href="https://fastmail.com/">Fastmail</a> a couple of years ago, this became much simpler with the most underrated feature in the history of email: filtering by email header. Specifically, filtering by the <strong>List-Unsubscribe</strong> header.</p>
<p><strong>Note</strong>: As far as I know, Gmail does not support filtering by email headers. For the adventurous, you <em>may</em> be able to do it with <a href="https://developers.google.com/apps-script/">Google Apps Script</a>.</p>
<h2>What is the List-Unsubscribe header?</h2>
<p>In 2003, the U.S Congress passed the <a href="https://www.ftc.gov/sites/default/files/documents/cases/2007/11/canspam.pdf">CAN-SPAM Act</a> to restrict and slow down the oncoming avalanche of unsolicited emails. The opt-out links you see at the bottom of some emails? That&#8217;s one of the things that the CAN-SPAM Act introduced.</p>
<p>Another opt-out mechanism, described in <a href="https://datatracker.ietf.org/doc/html/rfc2369">RFC-2369</a>, is the <strong>List-Unsubscribe</strong> email header.</p>
<p>From the RFC:</p>
<blockquote><p>The List-Unsubscribe field describes the command (preferably usingmail) to directly unsubscribe the user (removing them from the list).</p></blockquote>
<blockquote><p>Examples:</p>
<div class="gatsby-highlight" data-language="text">
<pre class="language-text line-numbers"><code class="language-text">List-Unsubscribe: &lt;mailto:list@host.com?subject=unsubscribe&gt;
List-Unsubscribe: (Use this command to get off the list)
    &lt;mailto:list-manager@host.com?body=unsubscribe%20list&gt;
List-Unsubscribe: &lt;mailto:list-off@host.com&gt;</code></pre>
</div>
</blockquote>
<p>In theory, every email you receive from an mailing list must include this header, which describes a programmatic way to unsubscribe. This is how email clients implement the 1-click unsubscribe feature you see sometimes:</p>
<p><img loading="lazy" decoding="async" src="/wp-content/uploads/2024/06/emailUnsubscribe.png" alt="Unsubscribe from an mailing list in the Mail app on a Mac." width="948" height="226" class="aligncenter size-full wp-image-447" srcset="/wp-content/uploads/2024/06/emailUnsubscribe.png 948w, /wp-content/uploads/2024/06/emailUnsubscribe-300x72.png 300w, /wp-content/uploads/2024/06/emailUnsubscribe-768x183.png 768w" sizes="auto, (max-width: 948px) 100vw, 948px" /></p>
<p>This header just gives you an additional (albeit faster) way to unsubscribe from mailing lists once they&#8217;ve already sent you email. It&#8217;s better than nothing but it doesn&#8217;t prevent you from getting or seeing those emails in the first place.</p>
<p>The most valuable thing about the List-Unsubscribe header is not what it lets you do, but its <strong>presence or its absence</strong>. If it&#8217;s there, the email is from a mailing list. If it&#8217;s not there, it&#8217;s either a transactional email you probably need or, better yet, it&#8217;s from a person.</p>
<h2>Setting up the filter</h2>
<p>In the Fastmail web client, go to <strong>Settings &gt; Filters &amp; Rules</strong> and create a filter with two rules:</p>
<ol>
<li>A header called <strong>List-Unsubscribe</strong> must exist.</li>
<li>Sender is not a member of group <strong>unblocked-list.</strong></li>
</ol>
<p>The second step is optional. I have it because I find that I do want emails from a very small number of mailing lists (e.g. my children&#8217;s school). If you want an &#8220;allow list&#8221; like this, first go to <strong>Contacts</strong> and add a contact group.</p>
<p>When you want to let a mailing list through to your inbox, you have to log into Fastmail and add the email address to the group. Still a manual step, but I find that I do this less often than when I used to to create bespoke email filters.</p>
<p>This is what my filter looks like:</p>
<p><img loading="lazy" decoding="async" src="/wp-content/uploads/2024/06/listUnsubscribeFilter-1024x761.png" alt="" width="1024" height="761" class="aligncenter size-large wp-image-449" srcset="/wp-content/uploads/2024/06/listUnsubscribeFilter-1024x761.png 1024w, /wp-content/uploads/2024/06/listUnsubscribeFilter-300x223.png 300w, /wp-content/uploads/2024/06/listUnsubscribeFilter-768x571.png 768w, /wp-content/uploads/2024/06/listUnsubscribeFilter.png 1268w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p>
<p>I browse the &#8220;lists&#8221; folder maybe a couple times a month, and almost never have to manually add email addresses to the &#8220;unblocked-list&#8221; group.</p>
<p>Compared to my Gmail account, which currently has <strong>over 100 filters</strong> to silence noisy mailing list spam, my Fastmail account just relies on this one. Filtering by email header is by itself worth the price of Fastmail.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Announcing “iOS App Distribution & Best Practices”, First Edition]]></title>
<description><![CDATA[<p>I&#8217;m excited to announce the release my new book, iOS App Distribution &amp; Best Practices! You can read it online if you have a raywenderlich.comsubscription. If you like to read books on paper, you can buy the print version from Amazon in a few weeks. Why this book? One of the reasons why I&#8217;m so [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2021/04/21/announcing-ios-app-distribution-and-best-practices-first-edition/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2021/04/21/announcing-ios-app-distribution-and-best-practices-first-edition</guid>
<pubDate>Wed, 21 Apr 2021 19:01:06 GMT</pubDate>
<content:encoded><![CDATA[<p>I&#8217;m excited to announce the release my new book, <a href="https://www.raywenderlich.com/books/ios-app-distribution-best-practices/v1.0"><strong>iOS App Distribution &amp; Best Practices</strong></a>! You can read it online if you have a <a href="https://raywenderlich.com/">raywenderlich.com</a>subscription. If you like to read books on paper, you can buy the print version from Amazon in a few weeks.</p>
<p><img loading="lazy" decoding="async" src="/wp-content/uploads/2024/06/pasi-cover.png" alt="iOS App Distribution &amp; Best Practices book cover" width="446" height="576" class="aligncenter size-full wp-image-451" srcset="/wp-content/uploads/2024/06/pasi-cover.png 446w, /wp-content/uploads/2024/06/pasi-cover-232x300.png 232w" sizes="auto, (max-width: 446px) 100vw, 446px" /></p>
<h2>Why this book?</h2>
<p>One of the reasons why I&#8217;m so excited for this book is because I think it fills a real, persistent need that so many people have.</p>
<p>Most resources for learning iOS focus on the tools and frameworks for <em>making</em> the app but say almost nothing about sharing your work with others, be it other members of your team, external testers, or the public at large.</p>
<p>This state of affairs would be fine if app distribution were straightforward. Unfortunately, the opposite is true. App distribution is often <strong>one of the most complex and downright frustrating</strong> parts about shipping an iOS app. Developers can literally waste days just on figuring out how to upload a build the App Store 🤯.</p>
<p>Once you feel comfortable with the basics of app distribution, the book moves on to automation. Every team works differently, but iOS is now mature enough that there&#8217;s some definite <strong>convergence</strong> of best practices when it comes to iOS automation. Here, too, I believe the book fills a need. There are tons written about CI/CD/devops in the web development world, but relatively little on iOS.</p>
<h2>Who is this book for?</h2>
<p>People with wildly different backgrounds routinely handle app distribution. We kept this in mind while writing the book. Some chapters are more geared to developers, but if you&#8217;re involved in any way in shipping an app to the App Store, we think you can benefit from the book.</p>
<p>When it comes to developers, these three type of developers would benefit the most:</p>
<ul>
<li><strong>Distribution novices</strong>: The first few chapters assume you&#8217;ve only interacted with the App Store as an end user. The book covers the most common workflows so you can release your first app without getting bogged down with the details.</li>
<li><strong>Distribution &#8220;expert beginners&#8221;</strong>: Some apps only need updates once a quarter or once a year, giving you just enough time to forget everything. There are so many people in this category. The book pays special attention to things that trip most people up like code signing and provisioning.</li>
<li><strong>Dev ops/platform engineers</strong>: The second half of the book dives into setting up a build pipeline so you can distribute your apps internally and externally with the least amount of effort. From personal experience, I know that getting this right can turbocharge a team&#8217;s cadence.</li>
</ul>
<h2>Closing thoughts</h2>
<p>The hardest part about writing this book was striking the right balance between explaining everything from first principles (&#8220;ok, so what is a build?&#8221;) while still leaving room for more experienced folks to fill in the gaps they were missing. I think the book lands in a good place, but I&#8217;m looking forward to reading the feedback and questions in the <a href="https://forums.raywenderlich.com/c/books/ios-app-distribution-and-best-practices/75">forum</a>.</p>
<p>Finally, I want to thank the team that made this book possible: Keegan Rush, Manda Frederick, Soheil Azarpour, Jayven Nhan, Jordan Osterberg and Sandra Grauschopf. Special thanks to Viki and Ray Wenderlich for creating the company behind the publisher that makes these projects possible.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[No more magic]]></title>
<description><![CDATA[<p>Hurricane Sandy hit New York City three months into my first job as a software developer. At the time, I was working for the Huffington Post in Manhattan. HuffPost’s data centers were also in Manhattan and they got hit hard: “Datagram, the ISP whose Manhattan servers host BuzzFeed, Huffington Post, Gawker, and other sites, has [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2021/04/04/no-more-magic/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2021/04/04/no-more-magic</guid>
<pubDate>Sun, 04 Apr 2021 19:00:23 GMT</pubDate>
<content:encoded><![CDATA[<p>Hurricane Sandy hit New York City three months into my first job as a software developer. At the time, I was working for the <a href="https://www.huffingtonpost.com/">Huffington Post</a> in Manhattan. HuffPost’s data centers were also in Manhattan and <a href="https://buzzfeed.tumblr.com/post/34607165930/major-media-isp-goes-down">they got hit hard</a>:</p>
<blockquote><p>“Datagram, the ISP whose Manhattan servers host BuzzFeed, Huffington Post, Gawker, and other sites, has lost power, an official there told us via text this evening.”</p>
<p>“Basement flooded, fuel pump off line &#8211; we got people working on it now. 5 feet of water now,” the official wrote.</p></blockquote>
<p>HuffPost had backup servers, but unfortunately they were across the Hudson River in New Jersey. The whole system went down. The native apps I worked on didn’t work at all and huffingtonpost.com redirected to a Tumblr for a while.</p>
<p>As I remember the story, HuffPost’s CTO <a href="https://pavley.com/">John Pavley</a> went to the flooded data center himself to help get things up and running again. We also got some help from HuffPost’s then-parent-company AOL to get some servers set up in Dulles.</p>
<p>Back then, I remember thinking to myself that I would have no clue how to handle this situation if I were in Pav’s shoes. I didn’t have the slightest idea about the inner workings of a data center.</p>
<p>Even as the years went on and I worked on different things, I knew that the software I wrote ran <em>somewhere</em>, likely somewhere in the <em>cloud</em>. In practice, I never had to worry about where my software ran. The physical machines were all abstracted away.</p>
<p>Recently, that all changed. The application I’m working on runs on very specific hardware and does not perform well in a virtualized environment. Can’t use AWS or Linode or anything like that. Meaning, I had to roll up my sleeves, and build some “bare metal” servers.</p>
<p>I bought the parts, built the servers, installed Linux, set up the application, and shipped them out to the data center. It was during this process that I realized that I was still holding on a lot of the “magic” that I first felt in my HuffPost days.</p>
<p><img loading="lazy" decoding="async" src="/wp-content/uploads/2024/06/servers-1024x815.jpg" alt="Ubuntu servers" width="1024" height="815" class="aligncenter size-large wp-image-455" srcset="/wp-content/uploads/2024/06/servers-1024x815.jpg 1024w, /wp-content/uploads/2024/06/servers-300x239.jpg 300w, /wp-content/uploads/2024/06/servers-768x611.jpg 768w, /wp-content/uploads/2024/06/servers-1536x1222.jpg 1536w, /wp-content/uploads/2024/06/servers-2048x1630.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p>
<p>As it turns out, a sever is just another computer. It has a processor and memory and storage and all the other parts you know about. Data centers are filled with nice, helpful people that receive the boxes you send them and rack your servers.</p>
<p>The funny thing is that already knew all of these things. I learned about the <a href="https://en.wikipedia.org/wiki/Turing_machine">Turing machine</a> and the <a href="https://en.wikipedia.org/wiki/Von_Neumann_architecture">von Neumann architecture</a> in school. Essentially, all computers all the same, right? And they can all compute the same things and only differ in their performance characteristics.</p>
<p>I <em>intellectually</em> knew these things but I was expecting to need some secret sauce, some healthy serving of reality to layer on top of the theory. There was none. It&#8217;s really just a computer.</p>
<p>This is not the same as impostor syndrome. That’s separate. The best term I have for it is &#8220;believing in magic”, which I would describe as a combination of grogginess and discomfort towards certain topics in computing.</p>
<p>The opposite of accepting magic is possessing “technical fearlessness”. Engineers who posses this type of fearlessness can move up and down the entire computing stack with ease, much like a violinist shifts positions as she plays a concerto.</p>
<p>They’ll disassemble, reverse-engineer, hack, and finally, invent. They possess the humility to accept that they don&#8217;t know everything (no one does), while simultaneously (and paradoxically) moving with a deep-seated confidence that there&#8217;s nothing in computing that&#8217;s outside their reach.</p>
<p>So how do you get there? You could chip away at the magic organically as you work on different things throughout your career. But that might be too slow. I do believe there&#8217;s a canon of work that every technologist should learn, which includes both theory and engineering. But here&#8217;s the kicker: you can&#8217;t just learn it intellectually.</p>
<p>To go from the abstract to the fearlessness, you have to build as you go along. <a href="http://matt.might.net/articles/what-cs-majors-should-know/">Matt Might&#8217;s list</a> is a good starting point. But since the goal of the list different than what I’m talking about here, I’d remove some things and add some others.</p>
<p>So here’s my message to all current and aspiring technologists: seek out the magic, kill the magic.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Debugging how you think about code signing]]></title>
<description><![CDATA[<p>I’ve spent the last 2 weeks researching and writing about code signing and provisioning for my upcoming book “iOS App Distribution &amp; Best Practices”. During my research there were a number of things I found surprising. This post documents my personal gotchas in the hopes it helps someone. I also offer five specific tips on [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2020/12/13/debugging-how-you-think-about-code-signing/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2020/12/13/debugging-how-you-think-about-code-signing</guid>
<pubDate>Sun, 13 Dec 2020 18:58:42 GMT</pubDate>
<content:encoded><![CDATA[<p>I’ve spent the last 2 weeks researching and writing about code signing and provisioning for my upcoming book <a href="https://www.pietrorea.com/2020/08/18/coming-soon-publishing-to-the-app-store-book">“iOS App Distribution &amp; Best Practices”</a>.</p>
<p>During my research there were a number of things I found surprising. This post documents my personal gotchas in the hopes it helps someone. I also offer five specific tips on how you can fix any faulty thinking you might have about these two topics.</p>
<p>You’ll find this post more helpful if you already have some understanding of code signing and provisioning. If you’re starting from scratch, check out the resources at the bottom of the post first.</p>
<h2>So why is it hard?</h2>
<p>Code signing and provisioning routinely trump even the most experienced developers on Apple’s platforms. There are a few reasons for this: the system behind them is complex and opaque. The frequency of issues is also low. You might run into issues at least once or twice a year when a certificate expires and at most (hopefully) once per release.</p>
<p>On top of high complexity and low frequency, you&#8217;re usually under time pressure when issues crop up. Code signing is one of the <em>last</em> things before you submit a build for review. If the release is late, the last thing you want to do is read a programming guide on Apple’s developer site or watch a WWDC video. One common way to fix a code signing issue is to <em>basically try anything and everything</em> until Xcode is happy. It sounds awful but that’s been my personal experience. Unfortunately, I don’t think I’m the only one.</p>
<h2>Tip #1: Start with the why</h2>
<p>A good place to start debugging how you think about code signing is making sure you have enough background context. Why did this system come about? After reading about the origins of code signing, I stopped seeing a mess of unrelated chores and started thinking in terms of producing something that plugs into Apple&#8217;s runtime systems.</p>
<p>You can actually trace back all your code signing woes to something that happened in New Jersey back in the 70’s. All operating systems made by Apple descend from Unix by means of NeXTSTEP and BSD. In Unix (developed at Bell Labs in Murray Hill, NJ) all programs run with the same access and privileges a the user running them. This made sense back then because you probably programmed and loaded all your programs yourself!</p>
<p>“You = your apps” is not a good assumption in modern times. The programs you run today are typically third-party apps. Your third-party apps shouldn&#8217;t have the same OS-level access as you in case they are malicious or become compromised.</p>
<p>So what did Apple do about this decades-old assumption? This is where the <strong>App Sandbox</strong> comes in. Apple made the sandbox part of iOS/watchOS/tvOS from day one and rolled it out to macOS at the same time Apple introduced the Mac App Store.</p>
<p>So if you&#8217;re thinking strictly in terms of code signing, you&#8217;ve gone two steps too far. Take a step back and think in terms of the App Sandbox and how to interact with it.</p>
<p>So what is the App Sandbox? It&#8217;s a system that enforces a strict separation between you and your apps and also separates each app from each other. Apple designed the App Sandbox to limit the damage a bad actor can inflict on your system if they get hold of one of your apps.</p>
<p>As an iOS developer, I’d obviously heard of the sandbox before but I thought the sandbox was just about restricting access to the system-wide file system. This is actually not the case at all. The App Sandbox applies to <a href="https://developer.apple.com/library/archive/documentation/Security/Conceptual/AppSandboxDesignGuide/AboutAppSandbox/AboutAppSandbox.html">a lot more</a>: hardware, user files, user data (e.g. calendars, contacts, e-mail) and to all system integrations that could pose a security risk (the ability to send push notifications, integrate with the Health app, etc).</p>
<p>So how does the App Sandbox relate to code signing and provisioning? A sandboxed app that wants to do something restricted must ask for permission from the OS and (sometimes) the user. <strong>This permission-based system only makes sense if Apple can unambiguously and securely identify apps</strong>, which is what code signing and provisioning are meant to do.</p>
<h2>Tip #2: Work backwards</h2>
<p>Another problem I had with code signing was losing track of how the different pieces relate to each other. Think of all the terms you have to keep in your head: certificates, entitlements, app IDs, public keys, private keys, provisioning profiles, code signing, and more.</p>
<p>A way to understand the relationships between them is by working backwards from an end goal. Now that you understand the historical need for the App Sandbox, think of your end goal as providing the sandbox with something that can answer its questions about your app at runtime. The end goal is to provide a <strong>code-signed provisioning profile</strong>, as shown below (full credits to raywenderlich.com for the image).</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-88" src="/wp-content/uploads/2023/01/image-1.jpeg" alt="" width="1613" height="1059" srcset="/wp-content/uploads/2023/01/image-1.jpeg 1613w, /wp-content/uploads/2023/01/image-1-300x197.jpeg 300w, /wp-content/uploads/2023/01/image-1-1024x672.jpeg 1024w, /wp-content/uploads/2023/01/image-1-768x504.jpeg 768w, /wp-content/uploads/2023/01/image-1-1536x1008.jpeg 1536w" sizes="auto, (max-width: 1613px) 100vw, 1613px" /></p>
<p>If you only remember one thing from this blog post, remember this image. You can replace whatever mental image you currently have of provisioning profiles with this old-timey scroll. The App sandbox asks questions and the different portions of the provisioing profile answer them (e.g. Who are you? What do you want to access?).</p>
<p><strong>Extra credit:</strong> Why does a provisioning profile need to be code signed? A provisioning profile is a plain old <code class="language-text">.mobileprovision</code> file on your computer. If the provisioning profile weren’t code signed, anyone could change the answers you&#8217;re providing to the App Sandbox. Not only would the App Sandbox not be able to trust you, the whole system would not make sense anymore.</p>
<h2>Tip #3: Learn to read provisioning profiles</h2>
<p>If the end goal is to furnish a code-signed provisioning profile, then you have to know where they live and learn how to read them. As for where they are, Xcode downloads and imports all provisioning profiles into <code class="language-text">~/Library/MobileDevice/Provisioning Profiles</code>.</p>
<p>Provisioning profiles are files encoded in the Cryptographic Message Syntax format (CMS) so you can&#8217;t just double-click on one to read it. Xcode doesn&#8217;t provide a good way to peek inside your provisioning profiles, so what can you do?</p>
<p>You can either use the <code class="language-text">security</code> command-line tool, like this:</p>
<div class="gatsby-highlight" data-language="text">
<pre class="language-text line-numbers"><code class="language-text">security cms -D -i /path/to/example.mobileprovision</code></pre>
</div>
<p>Or you can use Finder&#8217;s Quick Look preview. Simply navigate to any <code class="language-text">.mobileprovision</code> file and hit the space bar. You’ll see a graphical representation of your provisioning profile with all relevant sections:</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-90" src="/wp-content/uploads/2023/01/image-6.png" alt="" width="1058" height="1310" srcset="/wp-content/uploads/2023/01/image-6.png 1058w, /wp-content/uploads/2023/01/image-6-242x300.png 242w, /wp-content/uploads/2023/01/image-6-827x1024.png 827w, /wp-content/uploads/2023/01/image-6-768x951.png 768w" sizes="auto, (max-width: 1058px) 100vw, 1058px" /></p>
<p>The components to watch out for are the App ID, the list of entitlements and the certificate. Ad-hoc provisioning profiles also include a list of device IDs representing the devices where the app may be installed.</p>
<h2>Tip #4: Understand what invalidates provisioning profiles</h2>
<p>Troubleshooting invalid provisioning profiles is a common task for someone dealing with code signing issues. Now that you’re a pro at finding and reading provisioning profiles, make sure you understand the common scenarios that can invalidate them. The old-timey scroll from Tip #2 will help here.</p>
<p>A provisioning profile contains different components. Changes to a component will typically invalidate the whole thing. Some examples:</p>
<ul>
<li>Any change to the list of entitlements. For example, adding a new capability in the developer portal or in Xcode invalidates all previous provisioning profiles for that app.</li>
<li>Anything that invalidates the embedded certificate also invalidates the related provisioning profile. Either you or Apple can revoke a certificate or it can expire naturally after one year.</li>
<li>Not having the associated private key doesn’t technically invalidate a provisioning profile but you won’t be able to code sign it anymore.</li>
</ul>
<h2>Tip #5: Understand where artifacts originate and how they propagate</h2>
<p>One of the primary sources of confusion for me was the fact that provisioning profiles are <em>everywhere</em>. You see them on the developer portal, inside a hidden folder on your Mac, in Xcode and embedded in the app&#8217;s binary. This is disconcerting for a beginner. Is it all the same document? Where does it originate? Where does it go first and where does it go next? It’s a similar story for certificates and entitlements.</p>
<p>Along the way, Apple tried to be helpful by adding automatic code signing features to Xcode. Letting Xcode take care of code signing and provisioning is great if your use case is simple. But if you have to roll up your sleeves and manage code signing manually, I&#8217;ve found the automatic features to make everything more confusing because now there’s no single source of truth (which used to be the developer portal) and there are more places where you see the same artifacts.</p>
<p>You should aim to be clear about where certificates, entitlements and provisioning profiles originate and how they move through your development environment.</p>
<ul>
<li><strong>Certificates</strong> originate as certificate signing requests that you give Apple to sign. Xcode can do this on your behalf. The certificate, which contains your public key, goes on an amazing journey as part of the provisioning profile (see below) while the private key lives a secret life in Keychain Access.</li>
<li><strong>Entitlements</strong> get tacked onto an App ID in the developer portal. Xcode can also do this for you from the Capabilities menu. Entitlements also go on an amazing journey as part of the provisioning profile (see below).
<p>Entitlements are especially tricky because there are multiple layers of defaults and overrides. Check out <a href="https://developer.apple.com/library/archive/technotes/tn2415/_index.html#//apple_ref/doc/uid/DTS40016427-CH1-TP-ENTITLEMENTS_OVERVIEW_DIAGRAM">the diagram in this technical note</a> to see how entitlements resolve to values after considering all the different layers.</li>
<li><strong>Provisioning profiles</strong> also originate in the developer portal. Xcode can also generate them when automatic code signing is turned on. Once you get a provisioning profile on your machine, it lives in the aforementioned <code class="language-text">~/Library/MobileDevice/Provisioning Profiles</code> folder on your Mac. At build time, Xcode embeds the provisioning profile in the app&#8217;s binary.
<p>This means that anyone who downloads your app also gets a copy of your provisioning profile! Finally, the information in the provisioning profile gets copied into the digital signature during code signing.</li>
</ul>
<h2>Some parting thoughts</h2>
<p>This post has mostly been a journey into my own mind. The five tips are five things I clarified for myself as I wrote the chapter on code signing and provisioning. If you found this helpful, you should also refer to the resources listed below.</p>
<p>Please note that the programming guides refer to the App Sandbox as it refers to the Mac. Apple understandably writes very little about its “runtime policy system” but you can piece some things together by reading these Mac-specific documents.</p>
<ol>
<li><a href="https://asciiwwdc.com/2012/sessions/414">WWDC 2012 &#8211; Session 414: Building Archiving and Submitting Your App</a></li>
<li><a href="https://asciiwwdc.com/2013/sessions/710">WWDC 2013 &#8211; Session 710: A Practical Guide to the App Sandbox</a></li>
<li><a href="https://developer.apple.com/library/archive/documentation/Security/Conceptual/AppSandboxDesignGuide/AboutAppSandbox/AboutAppSandbox.html">App Sandbox Design Guide</a></li>
<li><a href="https://developer.apple.com/library/archive/documentation/Security/Conceptual/CodeSigningGuide/Introduction/Introduction.html">Code Signing Guide</a></li>
<li><a href="https://developer.apple.com/library/archive/technotes/tn2415/_index.html#//apple_ref/doc/uid/DTS40016427-CH1-TP-ENTITLEMENTS_OVERVIEW_DIAGRAM">Technical Note TN2415: Entitlements Troubleshooting</a></li>
</ol>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Core Data by Tutorials 8th Edition]]></title>
<description><![CDATA[<p>The eight edition of Core Data by Tutorials is out! This edition is compatible with Swift 5.3 and iOS 14. I can’t believe it’s been six years of book updates over six versions of iOS and five versions of Swift. Core Data continues to be a great choice for persisting and querying a complex object [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2020/11/24/core-data-by-tutorials-8th-edition/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2020/11/24/core-data-by-tutorials-8th-edition</guid>
<pubDate>Tue, 24 Nov 2020 18:58:12 GMT</pubDate>
<content:encoded><![CDATA[<p>The eight edition of Core Data by Tutorials is out! This edition is compatible with Swift 5.3 and iOS 14.</p>
<p>I can’t believe it’s been six years of book updates over six versions of iOS and five versions of Swift. Core Data continues to be a great choice for persisting and querying a complex object graph on Apple’s platforms.</p>
<p>I&#8217;m very grateful for our outstanding book team: Matthew Morey, Aaron Douglas, Darren Ferguson and Richard Turton.</p>
<p><a href="https://www.raywenderlich.com/books/core-data-by-tutorials/v8.0">https://www.raywenderlich.com/books/core-data-by-tutorials/v8.0</a></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Coming Soon: “iOS App Distribution & Best Practices” Book]]></title>
<description><![CDATA[<p>I’m happy to announce that I’m working on a new book with the raywenderlich.com team. I find it hard to believe that the last book I co-authored, Core Data by Tutorials, came out six years ago. I’ve felt the itch to work on a new book for a couple of years, specifically on the topic [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2020/08/18/coming-soon-publishing-to-the-app-store-book/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2020/08/18/coming-soon-publishing-to-the-app-store-book</guid>
<pubDate>Tue, 18 Aug 2020 18:57:11 GMT</pubDate>
<content:encoded><![CDATA[<p>I’m happy to announce that I’m working on a new book with the <a href="https://www.raywenderlich.com/">raywenderlich.com</a> team. I find it hard to believe that the last book I co-authored, <a href="https://www.amazon.com/Core-Data-Tutorials-Sixth-Persisting/dp/1950325040/">Core Data by Tutorials</a>, came out <em>six years ago</em>. I’ve felt the itch to work on a new book for a couple of years, specifically on the topic of app distribution, and I’m happy that it’s finally happening.</p>
<p>The working title for the new book is <strong>iOS App Distribution &amp; Best Practices</strong>and it is going to cover everything you have to do <em>after</em> you’re done coding. Like Core Data (less so now than in 2014), the road to getting your app in your users’ hands is paved with gotchas and frustration. Anyone who has wrestled with code signing or who has had to deal with an App Store rejection knows this.</p>
<p>The book will cover all the usual suspects like certificate management, code signing, provisioning profiles, entitlements, Testflight and app review. After you’ve learned how all of the basic blocks work (and why it’s hard to work with them), the book will move on to best practices like deploying internal builds, creating custom Xcode build configurations and connecting everything up to a CI/CD system. If this sounds like something you want to know more about, this book is for you.</p>
<p>I’ve wanted this book to exist ever since I started working as an iOS developer. Back when I first learned iOS development, I started out by building an app for a <a href="https://www.cs.princeton.edu/courses/archive/spring13/cos333/prevproj.html">college course</a>. I developed and demoed it primarily on the simulator and when it came time to put it on my iPhons 4S so I could bring it with me to interviews, I vividly remember spending an <strong>entire day</strong>figuring out app identifiers and provisioning profiles and code signing. The whole thing was foreign and confusing back then and it has not gotten much better.</p>
<p>I’m also incredibly excited and energized by the team that’s working on the book with me, which includes my co-author <a href="https://twitter.com/RushKeegan">Keegan Rush</a> and our excellent editors <a href="https://twitter.com/mandarazeware">Manda Frederick</a>, <a href="https://twitter.com/moayes">Soheil Azarpour</a>, <a href="https://twitter.com/TheJayvenNhan">Jayven Nhan</a> and <a href="https://twitter.com/OsterbergJordan">Jordan Osterberg</a>. Over the last six years, the process of writing a book for raywenderlich.com has improved and evolved a lot! Instead of writing in isolation, the process is highly collaborative. I can only describe it as the feeling you get when you’re part of a good scrum team. I can’t wait for the book to come out.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Deleting Derived Data with Automator]]></title>
<description><![CDATA[<p>Anyone who spends any significant time in Xcode has to delete the Derived Data directory from time to time. When you have an odd indexing problem that doesn’t go away, like faulty auto-complete, deleting Derived Data usually solves it. This used to be much easier in Xcode 7 circa 2015, but ever since Xcode 8 [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2020/07/31/deleting-derived-data-with-automator/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2020/07/31/deleting-derived-data-with-automator</guid>
<pubDate>Fri, 31 Jul 2020 18:53:40 GMT</pubDate>
<content:encoded><![CDATA[<p>Anyone who spends any significant time in Xcode has to delete the Derived Data directory from time to time. When you have an odd indexing problem that doesn’t go away, like faulty auto-complete, deleting Derived Data usually solves it.</p>
<p>This used to be much easier in Xcode 7 circa 2015, but ever since Xcode 8 there’s been no dedicated button to delete Derived Data. The workflow for doing this manually consists of going to Preferences &gt; Locations in Xcode, then clicking into the Derived Data location and deleting the directory in Finder.</p>
<p>That’s fine, but it takes 4-5 manual steps. There’s a much faster way of deleting Derived Data that I’ve been using for a couple of years now. And you get to use Automator!</p>
<h2>Start with a bash script</h2>
<p>The first thing you can do to make your life easier is to write a quick bash script to execute from the command line. The default location of the <code class="language-text">DerivedData</code> directory has not changed in years so it’s fairly safe to hardcode the path in your script.</p>
<div class="gatsby-highlight" data-language="bash">
<pre class="language-bash line-numbers"><code class="language-bash"><span class="token shebang important">#!/bin/bash</span>
<span class="token builtin class-name">echo</span> Removing Derived Data<span class="token punctuation">..</span>.
<span class="token function">rm</span> <span class="token parameter variable">-rf</span> ~/Library/Developer/Xcode/DerivedData
<span class="token builtin class-name">echo</span> RIP Derived Data</code></pre>
</div>
<p>Save it wherever you want. I call mine <strong>rm-derived-data.sh</strong>. Before you can run it, you have to make it executable with <code class="language-text">chmod</code> like this:</p>
<div class="gatsby-highlight" data-language="bash">
<pre class="language-bash line-numbers"><code class="language-bash"><span class="token function">chmod</span> +x ./rm-derived-data.sh</code></pre>
</div>
<p>Whenever you need to delete Derived Data you can just execute this bash script and you’re done. To make it easier on you, you can also export the path to this script into your shell’s $PATH so you can run it from any directory in Terminal.</p>
<h2>Automator App</h2>
<p>Running the script in Terminal is fine but I wanted something that could hook into Spotlight, which I use as a launcher all day every day. To that end, I learned that I could turn any script into an app using Automator. Once you do this, you can search for and execute the script from Spotlight. And if you save your Automator app in iCloud, this utility will be available on all of your machines without having to worry about syncing.</p>
<p>First, open Automator and select <strong>Application</strong>.<img loading="lazy" decoding="async" class="size-full wp-image-67 aligncenter" src="/wp-content/uploads/2023/01/image.png" alt="" width="848" height="808" srcset="/wp-content/uploads/2023/01/image.png 848w, /wp-content/uploads/2023/01/image-300x286.png 300w, /wp-content/uploads/2023/01/image-768x732.png 768w" sizes="auto, (max-width: 848px) 100vw, 848px" /></p>
<p>This Automator app consists of two steps, <strong>Run AppleScript</strong> and <strong>Display Notification</strong>. Find them in the list of steps and drag them into the right pane.</p>
<p>The AppleScript you need for the first step calls the bash script from earlier. Remember to replace <code class="language-text">thePath</code> with the path where you saved your script.</p>
<div class="gatsby-highlight" data-language="text">
<pre class="language-text line-numbers"><code class="language-text">on run {input, parameters}	
	set thePath to "~/Developer/scripts/xcode/rm-derived-data.sh"	
	do shell script thePath	
	return input
end run</code></pre>
</div>
<p>Note that Automator also has a &#8220;Run Shell Script&#8221; step and a &#8220;Run JavaScript&#8221; step that you could have used instead. But since this is Automator, I wanted to go full <a href="http://www.salsoghoian.com/">Sal Soghoian</a>.</p>
<p>The <strong>Display Notification</strong> step is optional. I added it because I noticed that deleting Derived Data can take up to a few minutes for a large app (!) and I like to know when it’s safe to build again.</p>
<p>The final Automator App should look like this:<img loading="lazy" decoding="async" class="size-full wp-image-69 aligncenter" src="/wp-content/uploads/2023/01/image-1.png" alt="" width="1822" height="1698" srcset="/wp-content/uploads/2023/01/image-1.png 1822w, /wp-content/uploads/2023/01/image-1-300x280.png 300w, /wp-content/uploads/2023/01/image-1-1024x954.png 1024w, /wp-content/uploads/2023/01/image-1-768x716.png 768w, /wp-content/uploads/2023/01/image-1-1536x1431.png 1536w" sizes="auto, (max-width: 1822px) 100vw, 1822px" /></p>
<p>Save your work. I named my app <strong>Derived Data Exterminator</strong> because I like the mental image of the Automator robot going up against my Derived Data directory.</p>
<p>As I mentioned before, you can save this app in iCloud if you want it to be available on all your machines. I saved my Automtor app in iCloud but I decided to save the bash script with all my other dev scripts, so I don’t get seamless syncing for free. If this is important to you, you should look into using &#8220;Run Shell Script&#8221; instead of &#8220;Run AppleScript&#8221;.</p>
<p>Time to test it! For best results, I like to close Xcode first. Hit <code class="language-text">Cmd + Space</code>to fire up Spotlight and start typing the name of your Automator app. As soon as you select it you’ll see a little gear in your menu bar. Once the script is done running you’ll see a notification.</p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-71 aligncenter" src="/wp-content/uploads/2023/01/image-2.png" alt="" width="385" height="100" srcset="/wp-content/uploads/2023/01/image-2.png 385w, /wp-content/uploads/2023/01/image-2-300x78.png 300w" sizes="auto, (max-width: 385px) 100vw, 385px" /></p>
<p>Running the Automator app is my preferred method of deleting Derived Data but I learned recently that you can also use Automator to inject a menu item into Xcode.</p>
<p>Open Automator again but this time select <strong>Quick Action</strong> instead of Application.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-73" src="/wp-content/uploads/2023/01/image-3.png" alt="" width="1822" height="1698" srcset="/wp-content/uploads/2023/01/image-3.png 1822w, /wp-content/uploads/2023/01/image-3-300x280.png 300w, /wp-content/uploads/2023/01/image-3-1024x954.png 1024w, /wp-content/uploads/2023/01/image-3-768x716.png 768w, /wp-content/uploads/2023/01/image-3-1536x1431.png 1536w" sizes="auto, (max-width: 1822px) 100vw, 1822px" /></p>
<p>In the top section, change <strong>Workflow receives</strong> to <strong>no input</strong> and select your installation of Xcode in the drop down next to it. Next, drag the same <strong>Run AppleScript</strong> and <strong>Display Notification</strong> steps like before and fill them the same way. This is what the end result looks like:</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-75" src="/wp-content/uploads/2023/01/image-4.png" alt="" width="1822" height="1698" srcset="/wp-content/uploads/2023/01/image-4.png 1822w, /wp-content/uploads/2023/01/image-4-300x280.png 300w, /wp-content/uploads/2023/01/image-4-1024x954.png 1024w, /wp-content/uploads/2023/01/image-4-768x716.png 768w, /wp-content/uploads/2023/01/image-4-1536x1431.png 1536w" sizes="auto, (max-width: 1822px) 100vw, 1822px" /></p>
<p>Save your work. I named my Quick Action <strong>Delete Derived Data (Automator)</strong>. In Xcode, it will start showing as a menu item up under <strong>Xcode &gt; Services</strong>.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-77" src="/wp-content/uploads/2023/01/image-5.png" alt="" width="1226" height="794" srcset="/wp-content/uploads/2023/01/image-5.png 1226w, /wp-content/uploads/2023/01/image-5-300x194.png 300w, /wp-content/uploads/2023/01/image-5-1024x663.png 1024w, /wp-content/uploads/2023/01/image-5-768x497.png 768w" sizes="auto, (max-width: 1226px) 100vw, 1226px" /></p>
<h2>A word of caution</h2>
<p>When you delete Derived Data you’re blowing away the data for <em>all</em> the apps you’ve built. This might be fine if you only work on one app at a time but if you work on several large projects at the same time you’re going to slow down your workflow.</p>
<p>Although there’s no official documentation about what gets dumped in there (that I could find), it helps to build an intuition about the kinds of problems that you can solve by deleting Derived Data. I only do it if I’m experiencing type ahead or code completion problems, or if the error in Xcode points to a file in Derived Data (this sometimes happens with Interface Builder files). I’m assuming Apple removed this button for good reasons so make sure you’re not willy-nilly blowing away your Derived Data every time you clean your build.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Saying Goodbye to Upside]]></title>
<description><![CDATA[<p>My last day at Upside was a week a ago. I haven’t written much about my job since I joined so before I moved on I wanted to write down a few memories. I joined Upside in the summer of 2017, almost 3 years ago. At the time I had decided to wind down my [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2020/07/12/saying-goodbye-to-upside/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2020/07/12/saying-goodbye-to-upside</guid>
<pubDate>Sun, 12 Jul 2020 18:51:51 GMT</pubDate>
<content:encoded><![CDATA[<p>My last day at <a href="https://www.upside.com/">Upside</a> was a week a ago. I haven’t written much about my job since I joined so before I moved on I wanted to write down a few memories.</p>
<p>I joined Upside in the summer of 2017, almost 3 years ago. At the time I had decided to wind down my <a href="https://www.pietrorea.com/2016/07/25/starting-a-new-journey">consulting shop</a> and start interviewing for a job. I wanted to find a growing company in DC that could leverage my mobile chops. After working from home for almost two years I was yearning to work in an office again.</p>
<p>At the time, Upside did not have an opening for an iOS developer. I remember using all the “outbound” techniques I learned for Sweetpea Mobile to get my foot in the door. Read: I spammed most of the leadership team on LinkedIn until I got an interview. Soon after, I joined Upside’s mobile team as an iOS developer.</p>
<p>When I joined Upside I was still feeling dejected from my failed attempt to bootstrap a dev shop. I was tired from wearing so many hats. I remember joining thinking that I’d be an individual contributor for the forseeable future. I wanted to become one of those indispensable software engineers. I don’t quite remember when or how I changed my mind, but after about six months I was already the unofficial lead engineer for the mobile team. I spent most of my time coordinating internally and externally but had no people management responsibilities.</p>
<p>In early 2018, Upside began to experiment with the feature team model. <a href="https://medium.com/pm101/spotify-squad-framework-part-i-8f74bcfcd761">Spotify popularized this model</a> but I was already aware of similar setups like the “2-pizza teams” I’d seen at Amazon. At its core, feature teams are all about engineer fungibility. That means anyone can work on any system, in any stack, at any point. The feature team is assigned a feature and they deliver it from beginning to end without any dependencies. Seemingly overnight I went from writing native Swift code to writing React and node. This was a great experience in retrospect but at the time it felt like a shock.</p>
<p>Right after the initial foray into feature teams, Upside spun up two new feature teams and I became the tech lead for one of them: Team Turboprop (see picture below for smiling Turboprop faces). The “tech lead” role at Upside is a hands-on people management position. It’s a combination of lead engineer and engineering manager.</p>
<p>The two years that I was on Team Turboprop have been the most fulfilling of my career. We worked on so many things! We started by building a self-service flight exchange system that no competitor had. When Upside pivoted to selling directly to companies, Turboprop was at the center of the new strategy. We created new user roles in the web app and shipped an entire suite of &#8220;corporate&#8221; features: admin functionality, onboarding of users, etc. Eventually we also came to own the profile and auth system.</p>
<p>The people management side of the job was also energizing, which surprised me. I was a first time manager and I was learning on the fly. The thing that worked for me was modeling myself after the best managers I’ve had in the past. Not only in how they encouraged me and matched me with good opportunities, but also in the quiet ways they created stability and prevented setbacks.</p>
<p>What I&#8217;m most proud of during my time at Upside is not a piece of code or a system running in production but rather the people that I was responsible for. I had the honor of helping a number of engineers achieve their goals of growing into their own leadership positions, either as team leads or as senior individual contributors.</p>
<p>What also surprised is how much we gelled as a team as time went on. Going to work didn’t feel like work. The team event we organized after shipping the “off-airport” car rental feature stands out as a nice memory. We used the feature we built to rent a minivan for the day and we drove an hour into Maryland to go to the best hotpot restaurant in the area.</p>
<p>If everything was so hunky-dory, you might be wondering&#8230;what happened? In good times, startups are risky and hard. Add a global pandemic that decimates the travel industry and a travel startup becomes unsustainable. It was a very difficult and emotional decision but in the end it felt like the time to say goodbye. Upside marches forward with some great people and I truly wish them the best.</p>
<p>So what&#8217;s next for me? I&#8217;ve joined Capital One&#8217;s mobile engineering team. I&#8217;ll be working on features for Capital One&#8217;s mobile app customers. This is exciting to me for several reasons.</p>
<p>The first is scale. Even though I’ve worked around <em>big companies</em> before (HuffPost was part of AOL and Quidsi was part of Amazon), I always worked at the subsidiary, never at the parent company. Most of the places I&#8217;ve worked at before had one mobile team, with a handful of engineers per platform. At Capital One there are over <strong>20 teams</strong> of engineers devoted to the Capital One mobile apps in my division alone. Team size and number of users are one to two orders of magnitude greater than anything I’ve ever seen or experienced.</p>
<p>I’m also excited because of the high caliber people that work there. These include former colleagues, people that write for <a href="https://www.raywenderlich.com/">raywenderlich.com</a> and folks I know from open source. At Upside, I did a lot of recruiting to fill open engineering positions. Every Capital One candidate I came across was next-level good.</p>
<p>Finally, I’m also happy that I’m an individual contributor again. Although at Upside I learned that my “track” will always be people management, the best engineering leaders I’ve observed have weaved in and out of coding several times. Being able to zoom in and out of code builds confidence, credibility and intuition. Beyond the practical benefits, as someone recently reminded me, coding is good for “an engineer’s soul”. I agree.</p>
<p>Overall, it feels similar to the way I felt back in 2017. Glad to be coding again and ready for a new adventure.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[VS Code Insiders & Settings Sync]]></title>
<description><![CDATA[<p>Like many developers, I often do my work on multiple machines. While I do not own a day phone and a night phone, I do have three Macs that I could get work on: an iMac that I share with the family, a personal laptop and a work laptop. This is usually not a problem [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2020/03/30/vs-code-insiders-settings-sync/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2020/03/30/vs-code-insiders-settings-sync</guid>
<pubDate>Mon, 30 Mar 2020 18:48:18 GMT</pubDate>
<content:encoded><![CDATA[<p>Like many developers, I often do my work on multiple machines. While I do not own a day phone and a night phone, I do have three Macs that I could get work on: an iMac that I share with the family, a personal laptop and a work laptop.</p>
<p>This is usually not a problem when it comes to the actual source code. I can push to Github from one machine, pull from Github from another and resume. The problem that I’ve always struggled with is keeping my IDE settings in sync.</p>
<p>I like tweak my key bindings, color themes and other settings to match my ideal workflow. So when I sit down at one of my computers and realize that I forgot to set up the Quick Open shortcut I use everywhere (<code class="language-text">Cmd + Shift + O</code>), it feels like I put my shoe on the wrong foot.</p>
<p>I’ve made several ill-conceived attempts to sync over some of my settings, but nothing has stuck. Each app does settings differently, and in the end it seems like there’s a lot of manual setup and syncing that needs to happen anyway. If you’ve found a good solution that works for you, I’d love to know.</p>
<p>Syncing IDE settings has been such a long-running frustration for me that I had <em>almost forgotten</em> that it’s possible to come up with a solution. That’s why when I read about <a href="https://code.visualstudio.com/docs/editor/settings-sync">Visual Studio Settings Sync</a> I was somewhere between a “yeah right” and a “hmmm…”.</p>
<p>I’m happy to report that it works. It’s only available in the <a href="https://code.visualstudio.com/insiders/">Visual Studio Code Insiders</a> build, so I installed that on all my computers first. My extensions, key bindings and IDE preferences are now being synced perfectly.</p>
<p>I would love to to talk to the product manager in charge of VS Code because this app continues to impress me. I hope Xcode follows suit at some point but I’m not going to hold breath. I also hope that Apple comes out with a generalized platform approach to give apps the ability to provide setting sync backed by iCloud. That would make owning several Macs much more palatable.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Try out NetNewsWire 5]]></title>
<description><![CDATA[<p>I’m currently on paternity leave for our second child. At the same time, the world is going through an unprecedented global pandemic, which requires everyone to practice social distancing. That means lots of time at home. Between bursts of child care I sometimes have some downtime to update this blog. After making some tweaks to [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2020/03/24/try-out-net-newswire-5/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2020/03/24/try-out-net-newswire-5</guid>
<pubDate>Tue, 24 Mar 2020 18:34:56 GMT</pubDate>
<content:encoded><![CDATA[<p>I’m currently on paternity leave for our second child. At the same time, the world is going through an unprecedented global pandemic, which requires everyone to practice social distancing. That means lots of time at home. Between bursts of child care I sometimes have some downtime to update this blog.</p>
<p>After making some tweaks to the plugin that generates this blog’s <a href="https://pietrorea.com/rss.xml">RSS feed</a>, I wanted to test out my changes using an RSS reader. I’ve been using <a href="https://reederapp.com/">Reeder</a>on iOS for years, but nothing on the Mac.</p>
<p>It didn’t take me long to find <a href="https://ranchero.com/netnewswire/">NetNewsWire</a>, an RSS reader worthy of an Apple Design Award. The app is open source so I went ahead and cloned the <a href="https://github.com/Ranchero-Software/NetNewsWire">GitHub repo</a> and built it with Xcode. I experienced some code signing issues (the year is 2020, right?) getting it to build with my free Apple Developer account, so I hopped onto their Slack and got some help from their community.</p>
<p>What struck me the most was the “philosophy” section featured on the app’s website.</p>
<blockquote><p>&#8220;We believe that apps should never crash. They should be free of bugs. They should be fast — they should feel lighter-than-air.&#8221;</p></blockquote>
<blockquote><p>&#8220;We believe that quality is more important than just piling on features; we believe that quality is the most important feature. And we believe that high quality is transformative — it makes for an app you never hesitate to reach for. You can rely on it, and you do, again and again.&#8221;</p></blockquote>
<blockquote><p>&#8220;This makes us slow to add features. We are adding features — but never at the expense of how it feels. Never at the expense of reliability and speed.&#8221;</p></blockquote>
<p>“Never at the expense of how it feels.”</p>
<p>Those words resonated very strongly with me. Their philosophy statement embodies my number one takeaway from all my years as an iOS developer. It takes an obsessive level of detail and care to make a truly great digital product. NetNewsWire gets it.</p>
<p>All of this is to say…make sure to try out NetNewsWire 5 on Mac and iOS. I’m fully switching from Reeder on all platforms after many years with it. The app is gorgeous, open source, and deeply aligned with my product values.</p>
<p>More importantly, it’s the app to use during these trying times. I recommend you subscribe to <a href="https://marginalrevolution.com/">Marginal Revolution</a> to get news and analysis on COVID-19. <a href="https://en.wikipedia.org/wiki/Tyler_Cowen">Tyler Cowen</a> has been my favorite economist since my university days and does a great job curating, synthesizing and reacting to the latest events.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[My favorite bug of 2018]]></title>
<description><![CDATA[<p>The last days of 2018 are upon us! It’s a time for introspection, new resolutions and DateFormatter bugs. Someone reported a curious bug in an iOS date picker that I help maintain. When selecting one of the last days of 2018, the date picker would incorrectly think the date was in 2019. For example, picking [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2018/12/10/my-favorite-bug-of-2018/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2018/12/10/my-favorite-bug-of-2018</guid>
<pubDate>Mon, 10 Dec 2018 18:31:22 GMT</pubDate>
<content:encoded><![CDATA[<p>The last days of 2018 are upon us! It’s a time for introspection, new resolutions and <code class="language-text">DateFormatter</code> bugs.</p>
<p>Someone reported a curious bug in an iOS date picker that I help maintain. When selecting one of the last days of 2018, the date picker would incorrectly think the date was in 2019. For example, picking 12/31/2018 would come back as 12/31/2019.</p>
<p>It turned out this was not a bug with the date picker, but rather how I wrote a particular date format. To illustrate my favorite bug of 2018, let’s start by creating a <code class="language-text">Date</code> for the last day of 2018:</p>
<div class="gatsby-highlight" data-language="swift">
<pre class="language-swift line-numbers"><code class="language-swift"><span class="token keyword">let</span> calendar <span class="token operator">=</span> <span class="token class-name">Calendar</span><span class="token punctuation">.</span>current
<span class="token keyword">let</span> lastDayOf2018Components <span class="token operator">=</span> <span class="token class-name">DateComponents</span><span class="token punctuation">(</span>calendar<span class="token punctuation">:</span> calendar<span class="token punctuation">,</span> year<span class="token punctuation">:</span> <span class="token number">2018</span><span class="token punctuation">,</span> month<span class="token punctuation">:</span> <span class="token number">12</span><span class="token punctuation">,</span> day<span class="token punctuation">:</span> <span class="token number">31</span><span class="token punctuation">)</span>
<span class="token keyword">let</span> lastDayOf2018 <span class="token operator">=</span> calendar<span class="token punctuation">.</span><span class="token function">date</span><span class="token punctuation">(</span>from<span class="token punctuation">:</span> lastDayOf2018Components<span class="token punctuation">)</span></code></pre>
</div>
<p>Let’s say you want to display the date as “Dec 31, 2018” so you code up a reasonable looking <code class="language-text">DateFormatter</code>:</p>
<div class="gatsby-highlight" data-language="swift">
<pre class="language-swift line-numbers"><code class="language-swift"><span class="token keyword">let</span> dateFormatter <span class="token operator">=</span> <span class="token class-name">DateFormatter</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
dateFormatter<span class="token punctuation">.</span>dateFormat <span class="token operator">=</span> <span class="token string-literal"><span class="token string">"MMM d, YYYY"</span></span></code></pre>
</div>
<p>Date formatter in hand, you go ahead and generate the string representation for the last day in 2018.</p>
<div class="gatsby-highlight" data-language="swift">
<pre class="language-swift line-numbers"><code class="language-swift"><span class="token keyword">let</span> dateToDisplay <span class="token operator">=</span> dateFormatter<span class="token punctuation">.</span><span class="token function">string</span><span class="token punctuation">(</span>from<span class="token punctuation">:</span> lastDayOf2018<span class="token punctuation">)</span>
<span class="token function">print</span><span class="token punctuation">(</span>dateToDisplay<span class="token punctuation">)</span></code></pre>
</div>
<p>However, the reasonable looking date formatter prints out “Dec 31, <strong>2019</strong>” instead of “Dec, <strong>2018</strong>”. This is because I used <strong>YYYY</strong> instead of <strong>yyyy</strong> in the date format.</p>
<p>This is such a common gotcha that it gets a prominent shoutout in <a href="https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/DataFormatting/Articles/dfDateFormatting10_4.html">Apple’s Data Formatting Guide</a></p>
<blockquote><p>A common mistake is to use YYYY. yyyy specifies the calendar year whereas YYYY specifies the year (of “Week of Year”) used in the ISO year-week calendar. In most cases, yyyy and YYYY yield the same number, however they may be different. Typically you should use the calendar year.</p></blockquote>
<p>What would it take to prevent this subtle bug? You either need to be the kind of developer that reads Apple’s programming guides cover to cover or you need to become the grizzled iOS developer that intimately knows all the warts in Foundation.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[New Blogging Platform: Gatsby.js]]></title>
<description><![CDATA[<p>You know you&#8217;re a developer when you&#8217;ve spent more time moving your blog from platform to platform instead of actually writing blog posts. Until recently, this blog was hosted on Squarespace, which I still recommend to anyone who wants to host a website with minimum hassle. In my case, I wanted to learn more about [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2018/05/31/new-blogging-platform-gatsby-js/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2018/05/31/new-blogging-platform-gatsby-js</guid>
<pubDate>Thu, 31 May 2018 18:28:38 GMT</pubDate>
<content:encoded><![CDATA[<p>You know you&#8217;re a developer when you&#8217;ve spent more time moving your blog from platform to platform instead of actually writing blog posts.</p>
<p>Until recently, this blog was hosted on <a href="http://squarespace.com/">Squarespace</a>, which I still recommend to anyone who wants to host a website with minimum hassle.</p>
<p>In my case, I wanted to learn more about statically generated sites so I decided to leave Squarespace&#8217;s high-touch walled garden for something that I could implement myself.</p>
<p>If you&#8217;re interested in static site generators, the first thing you realize is that there are lots and lots of frameworks to choose from. There&#8217;s a site called <a href="https://www.staticgen.com/">StaticGen</a> that lists all the popular static site generators and lets you filter them by programming language, template tool (e.g. <a href="https://handlebarsjs.com/">Handlebars</a>, <a href="https://github.com/dscape/jade">Jade </a>, etc) and popularity on GitHub.</p>
<p>In my particular case, I wanted to do something in JavaScript, so it came down to using either <a href="https://nextjs.org/learn/">Next.js</a> or <a href="https://www.gatsbyjs.org/">Gatsby.js</a>. Gatsby uses React.js and GraphQL, which I wanted to learn for work, so I settled on Gatsby.</p>
<h2>Gatbsy First Impressions</h2>
<p>I particularly like the &#8220;development workflow&#8221; of writing with Gatsby. Whenever I want to write a new blog post, all I have to do is create a new Markdown file and run <code class="language-text">gatsby develop</code> to see a live preview of my writing at <code class="language-text">http://localhost:8080/</code>. Gatsby uses <a href="https://webpack.js.org/">webpack</a> for hot reloads, so I can see my changes re-rendered on the browser as soon as I save the Markdown file on my machine.</p>
<p>The deployment process is similarly simple. Once I&#8217;m happy with a post, a simple <code class="language-text">yarn deploy</code> runs a script that syncs Gatsby&#8217;s local public folder with an S3 bucket that I set up to serve this site. AWS&#8217;s Route 53 directs traffic from my custom domain to this S3 bucket and voilà. Gatsby&#8217;s documentation on deploying to S3 was a bit sparse, so I may write a detailed blog post about how to do it.</p>
<p>Note that I deviated from the standard Gatsby setup in one important way. Most Gatsby installations have the site and the content in the same git repo. In my setup, the <a href="https://github.com/pietrorea/gatsby-blog">site</a> and the <a href="https://github.com/pietrorea/blog">content</a> are separate. I did this to future proof my blog. If I decide to change from Gatsby to something else in the future (Swift static site generator, anyone?), this separation of concerns will make it easier.</p>
<h2>Write More Using This One Weird Trick</h2>
<p>Something surprising happened as a result of using Gatsby to write this blog post. Using the same workflow and tools that I use for software development to write prose somehow reduced my writer&#8217;s block.</p>
<p>Maybe my brain strongly associates sending PRs and running terminal commands with work that I do everyday, so I might just have tricked my brain into thinking I was coding instead of writing.</p>
<h3>// TODOs in order of priority</h3>
<p>As of this writing, there are lots of features missing that you would typically find in a personal blog. I basically took Kyle Matthew&#8217;s excellent <a href="https://github.com/KyleAMathews/gatsby-starter-default">starter project</a> and made a few changes here and there.</p>
<p>Some startup person once said that if you&#8217;re not embarrassed by the first version of your product, then you launched too late. Well, right now the <code class="language-text">https</code> version of this site doesn&#8217;t take you anywhere, and that&#8217;s embarrassing.</p>
<p>Here&#8217;s a short list of improvements coming soon:</p>
<ul class="contains-task-list">
<li class="task-list-item"><input disabled="disabled" type="checkbox" /> HTTPS / SSL support</li>
<li class="task-list-item"><input disabled="disabled" type="checkbox" /> Add RSS feed</li>
<li class="task-list-item"><input disabled="disabled" type="checkbox" /> About page / resume / CV</li>
<li class="task-list-item"><input disabled="disabled" type="checkbox" /> Add Pagination</li>
<li class="task-list-item"><input disabled="disabled" type="checkbox" /> Add CloudFront CDN (related to HTTPs)</li>
<li class="task-list-item"><input disabled="disabled" type="checkbox" /> Write Swift static site generator</li>
</ul>
]]></content:encoded>
</item>
<item>
<title><![CDATA[99 [r]eddits v2.8.3 is now available]]></title>
<description><![CDATA[<p>For the past month, I&#8217;ve been working on an updated version of 99 redditsfor iOS with Aman. 99 reddits is a lightweight Reddit client that lets you quickly explore images and (some) animated GIFs from any subreddit. 99 reddits was first launched back in 2012. Up to this point Aman had been updating the app [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2017/11/28/99-reddits-for-ios-v283-is-out/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2017/11/28/99-reddits-for-ios-v283-is-out</guid>
<pubDate>Tue, 28 Nov 2017 18:26:48 GMT</pubDate>
<content:encoded><![CDATA[<p>For the past month, I&#8217;ve been working on an updated version of <a href="https://itunes.apple.com/us/app/99-edits/id474846610?mt=8">99 reddits</a>for iOS with <a href="http://www.loomba.org/">Aman</a>. 99 reddits is a lightweight Reddit client that lets you quickly explore images and (some) animated GIFs from any subreddit.</p>
<p>99 reddits was first launched back in 2012. Up to this point Aman had been updating the app 1-2 times per year with folks from Elance / oDesk and funding development with an In-App Purchase. Looking for a side project with real users and inspired by Artsy&#8217;s <a href="http://code.dblock.org/2015/02/09/becoming-open-source-by-default.html">Open by Default</a>, I shot him a PR one day.</p>
<p>Compared to other times I&#8217;ve worked on side projects, this release has been a real success. There are two things that made a big difference this time:</p>
<ul>
<li>Trusted team &gt; lonely developer. Aman and I have worked together for over 4 years at different companies and on different projects. I&#8217;ve learned a ton about product management from him. We know our working styles and know how to work well together. Putting together a release is no big deal because we&#8217;ve done it so many times before.</li>
<li>Having an audience! With zero marketing, 99 reddits had accumulated a couple thousand monthly active users. Writing software for an audience immediately raises the bar and creates a strong feedback loop.</li>
</ul>
<h2>Gotchas and Roadblocks</h2>
<ul>
<li>Because of trademark concerns brought up during app review, we had to change the name from the original &#8220;99 reddits&#8221; to &#8220;99 edits&#8221; and modify the app icon to hide Reddit alien. Unfortunately, this make the app harder to find, but this update is more for the devoted users that use 99 reddits regularly.</li>
<li><strong>ERROR ITMS-90101</strong>: &#8220;This bundle does not support one or more of the devices supported by the previous app version&#8221;. Did you know Apple doesn&#8217;t let you drop iPad support once you make your app universal? As part of the update, we wanted to focus all of our attention on iPhone since an overwhelming majority of usage happens on iPhone. Once we found out we weren&#8217;t allowed to drop iPad, I leaned heavily on UISplitViewController &amp; trait collections to reuse code between iPhone and iPad. I had to work around several UISplitViewController bugs around iOS 11 large titles and iPhone X layout.</li>
<li>Tech debt had piled up for 5 years. Working on this code base was like stepping through a time portal to a time when <a href="https://github.com/pokeb/asi-http-request">ASIHTTPRequest</a> and <a href="https://github.com/jverkoey/nimbus">NimbusKit</a> were the latest hotness. My first instinct was to rip out, rewrite and replace. Here&#8217;s where having a pro product manager was super helpful. Aman kept us focused on shipping, so we ended up with a good balance of product features and tech debt pay-down.</li>
</ul>
<h2>Release Notes</h2>
<ul>
<li>Removed payment/upgrade stuff. The app is now totally free. Thanks to all who paid over the years, your support meant a lot!</li>
<li>Improved cache management.</li>
<li>Many fixes, including crashing when saving a pic.</li>
<li>iPhone X and iOS 11 updates.</li>
<li>New iPad layout.</li>
</ul>
<h2>Questions?</h2>
<p>For product questions and support, you can head over to the official <a href="https://www.reddit.com/r/99reddits/">99 reddits subreddit</a>. Found a bug? Feel free to open an issue on <a href="https://github.com/TheLoombot/99-reddits">Github</a> or submit a pull request if you&#8217;re trained in the dark arts of Objective-C and preprocessor macros.</p>
<p><img loading="lazy" decoding="async" src="/wp-content/uploads/2017/11/99_edits-150x150.png" alt="" width="150" height="150" class="aligncenter size-thumbnail wp-image-378" srcset="/wp-content/uploads/2017/11/99_edits-150x150.png 150w, /wp-content/uploads/2017/11/99_edits.png 200w" sizes="auto, (max-width: 150px) 100vw, 150px" /></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Radar: UIToolBar pinned to bottom of the safe area broken on iPhone X]]></title>
<description><![CDATA[<p>Update 2017-12-04: &#8220;Engineering has determined that your bug report (35633289) is a duplicate of 34404165 and will be closed.&#8221; For the 99 reddits app, I updated the UI to respect the &#8220;safe area&#8221; in iOS 11. One of the view controllers made use of a UIToolBar, which doesn&#8217;t look right on iOS 11 when I [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2017/11/18/radar-uitoolbar-pinned-to-bottom-of-the-safe-area-broken-on-iphone-x/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2017/11/18/radar-uitoolbar-pinned-to-bottom-of-the-safe-area-broken-on-iphone-x</guid>
<pubDate>Sat, 18 Nov 2017 18:25:37 GMT</pubDate>
<content:encoded><![CDATA[<p><strong>Update 2017-12-04</strong>: &#8220;Engineering has determined that your bug report (35633289) is a duplicate of 34404165 and will be closed.&#8221;</p>
<p>For the <a href="https://itunes.apple.com/us/app/99-reddits/id474846610?mt=8">99 reddits</a> app, I updated the UI to respect the &#8220;safe area&#8221; in iOS 11. One of the view controllers made use of a UIToolBar, which doesn&#8217;t look right on iOS 11 when I attach the bottom of the toolbar to the bottom of the safe area (see attached screenshot).</p>
<p>Filed as rdar://35633289 and on <a href="http://www.openradar.me/35633289">Open Radar</a>.</p>
<h2>Summary:</h2>
<p>On an iPhone X, when you add a standalone UIToolBar to a view controller and add a constraint from the bottom of the UIToolBar to the bottom of the its view controller&#8217;s safe area, the bar button items appear outside the UIToolBar. It works perfectly on an iPhone 8.</p>
<h2>Steps to Reproduce:</h2>
<ol>
<li>In a storyboard file, add a UIToolbar to the initial view controller.</li>
<li>Add three constraints: trailing to the safe area&#8217;s trailing edge, leading to the safe area&#8217;s leading edge, and a constraint going from the bottom of the UIToolbar to the bottom of the view controller&#8217;s safe area.</li>
<li>Build and run on an iPhone X.</li>
</ol>
<h2>Expected Results:</h2>
<ul>
<li>The UIToolBar looks the same as if it had been the tool bar of a UIToolBarController.</li>
</ul>
<h2>Actual Results:</h2>
<ul>
<li>The bar button items in the UIToolbar appear above and outside the enclosing toolbar.</li>
</ul>
<h2>Version</h2>
<p>iOS 11.1 (15B87)</p>
<h2>Configuration</h2>
<ul>
<li>iPhone X</li>
</ul>
<p><img loading="lazy" decoding="async" src="/wp-content/uploads/2024/06/radar_bug_screenshot.png" alt="" width="500" height="867" class="aligncenter size-full wp-image-453" srcset="/wp-content/uploads/2024/06/radar_bug_screenshot.png 500w, /wp-content/uploads/2024/06/radar_bug_screenshot-173x300.png 173w" sizes="auto, (max-width: 500px) 100vw, 500px" /></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Core Data by Tutorials (Fourth Edition) Now Available]]></title>
<description><![CDATA[<p>I&#8217;m happy to announce that there&#8217;s a new edition of Core Data by Tutorialsavailable today, fully updated for iOS 11, Swift 4 and Xcode 9. How time flies! I still remember working on the original version of the book back in 2013 and it doesn&#8217;t seem that long ago. That&#8217;s the same year Apple announced [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2017/10/12/core-data-by-tutorials-fourth-edition-updated-for-swift-4-ios-11-and-xcode-9/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2017/10/12/core-data-by-tutorials-fourth-edition-updated-for-swift-4-ios-11-and-xcode-9</guid>
<pubDate>Thu, 12 Oct 2017 18:24:21 GMT</pubDate>
<content:encoded><![CDATA[<p>I&#8217;m happy to announce that there&#8217;s a new edition of <a href="https://www.raywenderlich.com/173790/core-data-by-tutorials-updated-for-swift-4-and-ios-11">Core Data by Tutorials</a>available today, fully updated for iOS 11, Swift 4 and Xcode 9. How time flies! I still remember working on the original version of the book back in 2013 and it doesn&#8217;t seem that long ago. That&#8217;s the same year Apple announced Swift 1.0 at WWDC. It was a busy time getting up to speed on this new language and rewriting our Objective-C drafts.</p>
<p>Even among experienced iOS developers, Core Data is infamous for its learning curve and sharp edges. With newer options for persistence such as <a href="https://realm.io/">Realm</a> and <a href="https://firebase.google.com/">Firebase</a>, I see a lot of iOS developers skip right past Core Data, ignoring the framework that ships with the SDK.</p>
<p>The truth is that Core Data offers a robust, free, solution that integrates nicely with all the native frameworks and tools you already use every day. No other solution integrates directly with UITableView, features a model editor built right into Xcode or plugs directly into Instruments. Plus you definitely know no one is going to acquire Core Data and <a href="http://blog.parse.com/announcements/moving-on/">shut it down</a>. Book or no book, if you&#8217;ve never tried to use Core Data, I encourage you at least kick the tires a bit.</p>
<p>Many thanks to my co-authors Aaron Douglas, Saul Mora, and Matthew Morey. And special thanks to Ray Wenderlich for bringing us together and to the many editors and technical editors we&#8217;ve had throughout the years: Rich Turton, Greg Heo, Darren Ferguson, Sam Davies, Bradley Phillips, Brian Moakley and Chris Belanger.</p>
<p><img loading="lazy" decoding="async" src="/wp-content/uploads/2017/10/core_data_by_tutorials_4th_ed-232x300.png" alt="" width="232" height="300" class="aligncenter size-medium wp-image-383" srcset="/wp-content/uploads/2017/10/core_data_by_tutorials_4th_ed-232x300.png 232w, /wp-content/uploads/2017/10/core_data_by_tutorials_4th_ed.png 238w" sizes="auto, (max-width: 232px) 100vw, 232px" /></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[“No Man Is an Island” or “Building Complex Systems at Sweetpea”]]></title>
<description><![CDATA[<p>One of the first things I noticed after striking out on my own is how much my old employer did on my behalf. I’m not talking about the obvious things like pay and benefits. Instead, I’m talking about the (sometimes invisible) support structure in mid-size to large companies. Doing Everything A job title usually comes [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2016/08/19/no-man-is-an-island/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2016/08/19/no-man-is-an-island</guid>
<pubDate>Fri, 19 Aug 2016 18:20:12 GMT</pubDate>
<content:encoded><![CDATA[<p>One of the first things I noticed after <a href="http://pietrorea.com/blog/2016/07/25/starting-a-new-journey">striking out on my own</a> is how much my old employer did on my behalf.</p>
<p>I’m not talking about the obvious things like pay and benefits. Instead, I’m talking about the (sometimes invisible) support structure in mid-size to large companies.</p>
<h2>Doing Everything</h2>
<p>A job title usually comes with a well-defined area of responsibility. Software engineers focus on software engineering. Lawyers focus on legal matters. Accountants focus on accounting. As tired and overworked as you may have felt at your old job, you never had to do everything.</p>
<p>When you strike out on your own, the default state of the world is that you have to do everything.</p>
<p>If you don’t follow up on an invoice, you won’t get paid. The internet is down? Can’t yell at IT to fix it anymore. You have to get on your hands and knees and rewire your Ethernet connection.</p>
<blockquote><p>&#8220;Corporate accounts payable, Nina speaking. JUST a moment.” &#8211; Nina, Office Space</p></blockquote>
<p>As it turns out, Nina from Office Space had an important job. Nina and the rest of her colleagues (well, maybe not Milton) were providing crucial internal services to the organization so you could keep going to work every day.</p>
<h2>The 3 Areas of An Effective Company: Core Competency, Front Office, Back Office</h2>
<p>As I made the move to working for myself, I struggled to wrap my head around these different roles and how they worked together.</p>
<p>The more I thought about it, the more I came to think of them as three distinct areas: the core competency, the front office, and the back office.</p>
<h3>1. Core Competency</h3>
<p>The core competency differs between companies. It’s your secret sauce—the “it” factor that differentiates your company.</p>
<p>As you can probably tell, this division oversimplifies the world a bit. Sometimes the secret sauce is not a particular set of functions but rather the interplay between one or two functions, or even structural differences that have taken you years to build.</p>
<p>The core competencies for Sweetpea are <strong>engineering</strong>, <strong>design</strong>, <strong>product management,</strong> <strong>project management</strong> and <strong>QA</strong>.</p>
<h3>2. Front Office</h3>
<p>I see the front office as what moves the core competency forward. It includes <strong>sales</strong>, <strong>marketing</strong>, <strong>PR</strong> and <strong>business development</strong>.</p>
<p>In a software agency, you may have a stellar core team of software engineers and designers, but if no contracts are coming in, your team of all-stars will just be sitting around doing nothing.</p>
<h3>Back Office</h3>
<p>Ah, the back office. It’s sometimes so easy to write off these activities as “overhead” but they’re crucial to keeping you afloat. This includes <strong>HR</strong>, <strong>finance &amp; accounting</strong>, <strong>legal</strong>, <strong>employee services</strong> and <strong>IT</strong>.</p>
<p>Not only are these important tasks, they are easy to do wrong. For example, I am perfectly comfortable doing many of the functions in the “Front Office” but I am not as comfortable with some of the back office tasks.</p>
<p>Why? Some of these functions—like legal and accounting (even IT, for non-technical business owners)—should be performed by trained professionals.</p>
<h2>Building a Complex System</h2>
<p>As I build the different areas for Sweetpea, at first I was intimidated by all the things I needed to assemble.</p>
<p>It may seem like my background as a software engineer is almost useless for many of these activities. However, I found there were plenty of lessons from software engineering that helped tremendously with the other areas of the business.</p>
<p>Isn’t a company just a complex system, embedded in even bigger complex systems (societies, legal systems, etc)?</p>
<p>I think so, which is good news for me, since I’ve been working on complex systems for years as a software engineer.</p>
<p>I understand things like throughput, reliability, failsafes and single points of failure. I know about modular design and interfaces that can talk to one another. Thinking about these concepts is second nature for an experienced software engineer.</p>
<p>As I’ve learned, business systems are very similar.</p>
<p>With this in mind, I now think of Sweetpea Mobile as an API fronting a complex system, and it’s not so scary anymore.</p>
<p>I’ve thought a lot about Sweetpea as an API. In particular, I’ve tried to create a <strong>well-defined</strong> API by being deliberate about my target audience and the services that I provide. I’m planning on writing more about that later.</p>
<h2>Asking For Help</h2>
<p>One of the main points of this post is that there is too much to do for one person.</p>
<p>So, what did I do about that? I had already been working with VA based in the Philippines for about eight years now. She helps me with bookkeeping and other administrative work.</p>
<p>Since there’s so much to do, I’m growing the team by bringing on a second part-time VA. She is based in Texas, so we’ll be able to work concurrently.</p>
<p>This is a move so that I can better balance ongoing client work and business development to move Sweetpea forward.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Starting a New Journey]]></title>
<description><![CDATA[<p>Two months ago I left my full time software engineering job at Quidsi/Amazon to move to Washington D.C. This move was primarily a personal decision to be closer to family. At the same time, I also wanted the opportunity to focus full-time on software development consulting. I even incorporated a company to do it! It’s [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2016/07/25/starting-a-new-journey/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2016/07/25/starting-a-new-journey</guid>
<pubDate>Mon, 25 Jul 2016 18:18:11 GMT</pubDate>
<content:encoded><![CDATA[<p>Two months ago I left my full time software engineering job at Quidsi/Amazon to move to Washington D.C. This move was primarily a personal decision to be closer to family.</p>
<p>At the same time, I also wanted the opportunity to focus full-time on software development consulting. I even incorporated a company to do it! It’s called <a href="https://www.sweetpeamobile.com/">Sweetpea Mobile</a>.</p>
<p>What does this mean? Instead of having one employer and one project to work on, I have several clients and different things to work on. It’s called Sweetpea Mobile because of its focus on mobile platforms such as iOS and Android.</p>
<h2>Sweetpea’s Opportunity</h2>
<p>Over the past five years, I’ve worked on a few mobile-focused software development teams, and I’ve been lucky (some may say unlucky) to work through different pain points and challenges along the way.</p>
<p>Some were unique to whatever employer I was working for at the time, but others were not. In fact, there was one specific challenge I saw over and over every place I worked.</p>
<p>Every company seems to be having trouble finding, hiring, and retaining mobile developers.</p>
<h2>“I can’t hire mobile developers. HELP!”</h2>
<p>Here’s a question people ask me all the time:</p>
<blockquote><p>&#8220;I am hiring a senior iOS engineer with 4-6 years of experience in New York City who can also implement a graph traversal algorithm on a whiteboard. Know anyone?&#8221;</p></blockquote>
<p>Maybe not in those exact words, but that is really what they mean.</p>
<p>It’s not that these people don’t exist. They do. It’s just that the number of requirements has reduced the applicant pool to a ludicrously small size.</p>
<p>Add some more explicit or implicit requirements (e.g. they need to be a U.S. citizen or green card holder, jive well with my company culture, hold a C.S. degree from a top school, etc.) and it’s no wonder hiring even one mobile developer can take anywhere from 6-12 months.</p>
<h2>Potential Traps</h2>
<p>Hiring in the tech industry is difficult. If you are hiring mobile developers right now, you’ll have a tough road ahead. If you are in this situation, there are two potential traps to look out for:</p>
<ul>
<li>You’ll hire <strong>too quickly</strong> and hire the wrong people.</li>
<li>You’ll hire <strong>too slowly</strong> and risk losing out on a good market opportunity.</li>
</ul>
<p>But wait! You have more options. You always have more options.</p>
<p>If you’re having a tough time hiring mobile developers, here are are the three things you can do:</p>
<h3>1. Grow ‘em</h3>
<p>Instead of hiring new folks, you can train your current software engineers in mobile app development. This is the route Facebook chose when they doubled down on native app development back in 2012-2013.</p>
<p>They didn’t have enough expertise in-house, and they couldn’t hire them fast enough, so they partnered with Big Nerd Ranch to train their current employees.</p>
<p>“Growing” from within comes with its own risks, of course.</p>
<p>Training takes time. The developers you train will have to re-focus their attention to mobile projects instead of whatever they were doing before (which is probably what you want anyway). And of course, short term training doesn’t give you years of experience overnight.</p>
<h3>2. Rent ‘em</h3>
<p>Instead of hiring mobile developers or training your existing developers, you can temporarily bring in subject matter experts as contractors to augment your existing team.</p>
<p>This assumes you already have a go-to-market strategy and a team that is mostly complete but missing a few key components (like the mobile developers!).</p>
<p>These subject matter experts will be doing the actual work. They’ll also help you “seed” your team with the core expertise you need to train your own people, if you decide to go that route.</p>
<h3>3. Outsource ‘em</h3>
<p>If you don’t have a team of engineers, designers, and product managers in place, you can choose to outsource the whole project to another company.</p>
<p>“Outsourcing” has gotten a bad rap, but this option can be right for you, depending on your business and your core competency (e.g. your secret sauce).</p>
<p>For example, why would David’s Bridal hire an in-house mobile development team to build their app? Mobile development is not their core competency…renting out dresses is. Thus, it makes sense that they went with <a href="https://www.prolificinteractive.com/">Prolific Interactive</a> to build their app.</p>
<p>Likewise, why would Chipotle hire a team of full-time developers to create and maintain their watchOS app? They make burritos, not smartwatch apps! Therefore it makes sense that they decided to hire <a href="http://sequence.com/">Sequence</a>.</p>
<h3>4. If All Else Fails, Hire Different(ly)</h3>
<p>If you decide you really need to hire someone for an in-house position, it’s important to take a good look at your list of “requirements.” Relaxing one or two constraints can make all the difference.</p>
<p>For example, can you stomach hiring someone remote or part-time? A self-learner from a code school instead of MIT?</p>
<h2>Enter Sweetpea Mobile</h2>
<p>Sweetpea Mobile’s market opportunity comes from this question I hear so often:</p>
<p>“I want to hire a mobile developer right now, but I’m having a really hard time. Can you help?”</p>
<p>My vision for Sweetpea is to listen to these companies, understand their situation, and give them choices they may not have considered before.</p>
<p>Together, we’ll figure out what option is best for their specific situation:</p>
<ul>
<li>Grow &#8217;em</li>
<li>Rent &#8217;em</li>
<li>Outsource &#8217;em</li>
</ul>
<p>And while I’m not a recruiter, if the company needs more help than I can provide on my own, I’ll do what I can to connect them with the right resources.</p>
<h2>Sweetpea’s Challenges</h2>
<p>Nothing worth doing is ever easy. As I begin this new adventure, I see three primary obstacles:</p>
<h3>1. I Am One Person</h3>
<p>There is only so much one person can do. If I stay as a one man operation, I’ll only be able to work on one or two projects at a time.</p>
<p>It may be that the best I can do for some companies is help them “rent ‘em” (i.e. staff augmentation). And by “rent them” I really mean “rent me.”</p>
<h3>2. Only One Discipline</h3>
<p>To create something of value, you need different disciplines: user experience, graphic design, product management, project management, native app development, backend development, marketing, sales, etc.</p>
<p>As a one-man band, I can only offer services in what I’m good at, and that is iOS development. If I were selling cakes, I would only be able to sell you the flour. I can’t make you the whole cake!</p>
<h3>3. Owning Your Own Ideas</h3>
<p>A consultant is a third party that joins your team temporarily. By definition, they don’t have the final say in the direction of the product or the business. Furthermore, consultants (like management consultants) sometimes don’t even have their hand in the implementation of their ideas.</p>
<p>For someone like me who’s worked primarily on mobile products rather than client projects, this will take getting used to.</p>
<p>This is not an “either-or” scenario, as many software development shops do client work as well as develop their own applications.</p>
<p>For example, I’ve enjoyed using <a href="https://www.kaleidoscopeapp.com/">Kaleidoscope</a> from <a href="https://blackpixel.com/">Black Pixel</a>, <a href="http://martiancraft.com/products">Slender</a> from <a href="https://blackpixel.com/">Martian Craft</a> and <a href="http://sparkinspector.com/">Spark Inspector</a> from <a href="https://www.foundry376.com/">Foundry376</a></p>
<h2>Next Steps</h2>
<p>There you have it…a big opportunity, a vision of the future, and some obstacles ahead.</p>
<p>As Lin-Manuel Miranda now famously wrote: “How lucky we are to be alive right now.”</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Tools of the Trade for iOS Development]]></title>
<description><![CDATA[<p>During the past few years of doing mobile development I’ve found a number of tools that have saved me time and frustration. This is by no means a comprehensive list of all the tools out there, but rather the small set that I’ve found helpful. They are also not all limited to iOS development. Some [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2015/11/08/tools-of-the-trade-for-ios-development/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2015/11/08/tools-of-the-trade-for-ios-development</guid>
<pubDate>Sun, 08 Nov 2015 18:12:36 GMT</pubDate>
<content:encoded><![CDATA[<p>During the past few years of doing mobile development I’ve found a number of tools that have saved me time and frustration. This is by no means a comprehensive list of all the tools out there, but rather the small set that I’ve found helpful. They are also not all limited to iOS development. Some will be helpful on other mobile platforms or for general software development.</p>
<p>These posts usually group apps into different categories but I’m going to list them in (roughly) the order that I started using them.</p>
<h3><a href="https://developer.apple.com/xcode/">Xcode</a></h3>
<p>Duh, right? Like many before, my journey into iOS began when I downloaded Xcode for the first time. These days I like to code using Xcode’s built-in Midnight theme. I also have <a href="http://alcatraz.io/">Alcatraz</a> set up on my machine to manage my Xcode plugins. My favorite plugins are <a href="https://github.com/neonichu/BBUDebuggerTuckAway">BBUDebuggerTuckAway</a>, <a href="https://github.com/kattrali/deriveddata-exterminator">DerivedData Exterminator</a> and <a href="https://github.com/stefanceriu/SCXcodeSwitchExpander">SCXcodeSwitchExpander</a>.</p>
<h3><a href="http://www.sourcetreeapp.com/">SourceTree</a></h3>
<p>SourceTree is my favorite git client (although I’ve also experimented with <a href="http://www.git-tower.com/">Tower</a>). It works really nicely with Github and Bitbucket.</p>
<h3><a href="https://www.atlassian.com/software/jira">JIRA</a></h3>
<p>JIRA is Atlassian’s bug tracking software. I don’t find JIRA very useful when I&#8217;m building something from scratch. To me, any kind of bug tracking software becomes a lot more useful once you have something out there to fix, maintain or improve.</p>
<h3><a href="http://www.sublimetext.com/">Sublime Text</a></h3>
<p>Sublime Text is my favorite general purpose text editor. Even though iOS developers work with native code most of the time, there are times when we have to roll up our sleeves and dive into some HTML or CSS. I’ve also found Sublime to be a good tool for JavaScript.</p>
<h3><a href="http://xscopeapp.com/">xScope</a></h3>
<p>Designers hate it when your implementation looks nothing like their designs. Measuring pixel distances and aligning things in straight lines don’t come naturally to me so I use this little tool to help me implement UI designs to a high degree of fidelity. xScope includes tools such as rulers, overlays and guides.</p>
<h3><a href="http://www.charlesproxy.com/">Charles</a></h3>
<p>Charles is my favorite HTTP/HTTPS debugging tool. It’s a proxy that intercepts all network requests coming in and out of your app. I’ve come to love its &#8220;Map Local&#8221; feature to simulate “what-if” scenarios with your API.</p>
<h3><a href="http://menial.co.uk/base/">Base</a></h3>
<p>Base is a lightweight SQLite browser. I started using this tool when I was first learning about Core Data since Core Data is often backed by SQLite. You can use Base to find out exactly what&#8217;s saved on disk.</p>
<h3><a href="http://www.peerassembly.com/linguan.html">Linguan</a></h3>
<p>Localizing an app to other languages by hand is no fun. To make matters worse, Xcode doesn’t provide a GUI to get the job done quickly. Linguan is the localization GUI Xcode should have had. This little tool has saved me hours of tedious manual labor.</p>
<h3><a href="http://sparkinspector.com/">Spark Inspector</a></h3>
<p>Attach Spark Inspector to your running app and it will show you a 3D model of your view hierarchy. Spark is useful when you’re debugging your layout or your views. I also hear good things about Reveal, although I’ve never tried it.</p>
<h3><a href="http://www.deploymateapp.com/">Deploymate</a></h3>
<p>When your app supports multiple versions of iOS, you have to be careful about <a href="http://www.raywenderlich.com/42591/supporting-multiple-ios-versions-and-devices">backward compatibility issues</a>. For example, if you use a new API that didn’t exist in an older version of iOS, your app will crash on older devices. Deploymate is a static analyzer tool that alerts you of this type of problem. I suggest using it before submitting a new version of your app to Apple.</p>
<h3><a href="http://martiancraft.com/products/slender.html">Slender</a></h3>
<p>You’re adding assets when you add new feature, but are you remembering to remove old assets when you remove old features? Probably not. Slender scans your project for assets that you no longer use so you can remove them.</p>
<h3><a href="http://cocoapods.org/">Cocoapods</a></h3>
<p>Cocoapods is the de facto dependency manager for iOS and Mac OS projects. If you want to add a third party library to your project, it’s as easy as adding a line of text to your Podfile and executing a terminal command. I can’t recommend it enough.</p>
<h3><a href="https://try.crashlytics.com/">Crashlytics</a></h3>
<p>Getting timely crash reports from users is essential to improving the quality of your applications. Crashlytics is one of many crash reporting tools available for iOS. I’ve also worked with Testflight, HockeyApp and Crittercism.</p>
<h3><a href="http://www.kaleidoscopeapp.com/">Kaleidoscope</a></h3>
<p>Kaleidoscope is Black Pixel’s diffing tool. You can use it to compare text, images and directories but I mainly use it for comparing two different images. For example, I&#8217;ll use Kaleidoscope to compare a mockup with a screenshot of my live UI. I then use this information to improve and iterate my UI implementations.</p>
<h3><a href="http://simpholders.com/">Simpholders</a></h3>
<p>One of the advantages of running your app on the iOS simulator is that you can inspect your app&#8217;s file system using Finder. This is practically impossible on a physical device. The problem is that the iOS simulator is buried somewhere in ~/Library and its location changes with every version of iOS (or so it seems). Simpholders is a shortcut to the simulator directories that you can access from the menu bar.</p>
<p>If you think I’ve left out an important tool, please go ahead and let me know in the comments. Each tool listed on this post has either increased my productivity or increased the overall quality of the apps I&#8217;ve worked on. I’m sure I’ll be adding more tools to the list as time goes on. Enjoy!</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Core Data by Tutorials updated for Xcode 6.1]]></title>
<description><![CDATA[<p>We’ve updated Core Data by Tutorials for Xcode 6.1. The update includes a number of small Swift changes and some fixes for errata that readers pointed out. Here’s the official announcement. If you played with Swift while it was still in beta, you probably realized that your projects would stop compiling going from one Xcode [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2014/10/31/core-data-by-tutorials-updated-for-xcode-61/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2014/10/31/core-data-by-tutorials-updated-for-xcode-61</guid>
<pubDate>Fri, 31 Oct 2014 18:11:51 GMT</pubDate>
<content:encoded><![CDATA[<p>We’ve updated Core Data by Tutorials for Xcode 6.1. The update includes a number of small Swift changes and some fixes for errata that readers pointed out. Here’s the <a href="http://www.raywenderlich.com/87276/core-data-tutorials-updated-xcode-6-1">official announcement</a>.</p>
<p>If you played with Swift while it was still in beta, you probably realized that your projects would stop compiling going from one Xcode beta to the next.</p>
<p>Even though Swift is technically not in beta anymore, moving from Xcode 6.0 to Xcode 6.1 was no different. We’re still in the (very) early days of Swift.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Core Data by Tutorials Now Available]]></title>
<description><![CDATA[<p>Good news — Core Data by Tutorials launched yesterday in PDF format. The book is written in Swift and it covers everything from the fundamentals up to the new iOS 8 APIs. The whole process was a great team effort and I’m very happy that it’s finally out in the world. Personally I prefer following [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2014/10/16/core-data-by-tutorials-now-available/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2014/10/16/core-data-by-tutorials-now-available</guid>
<pubDate>Thu, 16 Oct 2014 17:26:00 GMT</pubDate>
<content:encoded><![CDATA[
<p>Good news — Core Data by Tutorials launched yesterday in PDF format. The book is written in Swift and it covers everything from the fundamentals up to the new iOS 8 APIs. The whole process was a great team effort and I’m very happy that it’s finally out in the world.</p>



<p>Personally I prefer following a tutorial step by step rather than listening to a lecture or reading a book. I’ve always been a fan of learning by doing, especially if I’m starting from scratch.</p>



<p>Here’s a link to the announcement on Ray’s site. Also <a href="http://www.raywenderlich.com/85578/first-core-data-app-using-swift">here’s</a> a sneak preview of chapter 1 in blog post form. I hope you guys enjoy the book.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[WWDC 2014: A Strategy of Great Work]]></title>
<description><![CDATA[<p>I just finished watching a WWDC talk titled A Strategy of Great Work. It&#8217;s a beautiful talk by Ken Kocienda, a software engineer who&#8217;s worked at Apple for more than a decade.. He goes through 8 stories and 11 lessons that he learned during his tenure at Apple. The last lesson is &#8220;you are never done&#8221;. [&hellip;]</p>
 ]]></description>
<link>https://pietrorea.com/2014/07/25/a-strategy-of-great-work/?utm_source=rss&amp;utm_medium=rss</link>
<guid isPermaLink="false">https://pietrorea.com/2014/07/25/a-strategy-of-great-work</guid>
<pubDate>Fri, 25 Jul 2014 00:11:19 GMT</pubDate>
<content:encoded><![CDATA[<p>I just finished watching a WWDC talk titled <a href="http://asciiwwdc.com/2014/sessions/237">A Strategy of Great Work</a>. It&#8217;s a beautiful talk by Ken Kocienda, a software engineer who&#8217;s worked at Apple for more than a decade.. He goes through 8 stories and 11 lessons that he learned during his tenure at Apple.</p>
<p>The last lesson is &#8220;you are never done&#8221;. He ends with this quote from Steve Jobs:</p>
<blockquote><p>&#8220;If you do something and it turns out pretty good, then you should go do something else wonderful, not dwell on it too long. Just figure out what&#8217;s next.&#8221;</p></blockquote>
<p>You accomplished something. Great. What&#8217;s next? How are you going to top yourself next time? It reminds me of Elizabeth Gilbert&#8217;s <a href="http://www.ted.com/talks/elizabeth_gilbert_success_failure_and_the_drive_to_keep_creating#t-37182">TED talk</a> about her drive to keep creating. Two different fields, same idea.</p>
]]></content:encoded>
</item>
</channel>
</rss>