<?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[Paul Stamatiou]]></title>
        <description><![CDATA[PaulStamatiou.com - Technology, Design and Photography]]></description>
        <link>https://paulstamatiou.com</link>
        <image>
            <url>https://paulstamatiou.com/favicon.svg</url>
            <title>Paul Stamatiou</title>
            <link>https://paulstamatiou.com</link>
        </image>
        <generator>RSS for Node</generator>
        <lastBuildDate>Thu, 19 Mar 2026 04:32:06 GMT</lastBuildDate>
        <atom:link href="https://paulstamatiou.com/posts.xml" rel="self" type="application/rss+xml"/>
        <copyright><![CDATA[All rights reserved 2005-2026]]></copyright>
        <item>
            <title><![CDATA[2025]]></title>
            <description><![CDATA[<p>This isn&#x27;t my usual deep-dive article where I unpack a specific subject such as <a href="https://paulstamatiou.com/stocketa">an app I built</a>, my <a href="https://paulstamatiou.com/craft">obsession with craft</a>, or <a href="https://paulstamatiou.com/revisiting-the-apple-ipod">revisiting an old iPod</a>. I set out to share a few reflections and musings on a year marked by personal and professional change. This was a year of stripping back to the essentials: where I live, how I work, and what I build.</p>
<p><strong>I&#x27;ve been running <a href="https://paulstamatiou.com/timeline">this site</a> for just over 20 years now.</strong> I began writing it in my dorm room at Georgia Tech, hosted on a G4 Mac Mini<sup><a rel="footnote" href="#footnote-1" id="r1">1</a></sup>, as a way for me to share technical how-to guides and news. I used WordPress for the first handful of years, then the Ruby static site generator Jekyll for a decade. It wasn&#x27;t until 2024 that I redesigned and rebuilt this site from scratch using Next.js.<sup><a rel="footnote" href="#footnote-2" id="r2">2</a></sup></p>
<p>I&#x27;ll be turning 40 years old in 2026, which is still surreal to me. For my entire career, I was always the younger one on the team, and what feels like a sudden shift means that&#x27;s no longer true. In many ways, that change is actually a clarifying feeling.</p>
<p>I&#x27;m more focused and fired up to do great work than I&#x27;ve ever been. I&#x27;m driven by the desire to craft great products: things I can be proud of working on. My framing shifted from "Can I help this team build this product?" to "Is this the problem I want to spend my best years on?" I&#x27;ve developed a visceral aversion to working in any environment where I don&#x27;t feel like I can do the best work of my career.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2025/12/sesame-office-view.jpg" alt="The view from the Sesame office in San Francisco" />
<small>The <!-- --><a href="https://x.com/Stammy/status/1980688519397077398/">view from the Sesame office</a><!-- --> in San Francisco where I now work</small>
<p>My taste and judgment have compounded over these years. I&#x27;ve been through similar experiences that I can draw from across whatever I&#x27;m working on. Even on minor UI challenges alone, I&#x27;m still surprised at how often I pull inspiration from my time at Twitter where density was king and compact timelines ruled everything. I always try to keep that as just one input though, especially working in AI when so much is continually changing and you can&#x27;t bring assumptions with you.<sup><a rel="footnote" href="#footnote-3" id="r3">3</a></sup></p>

<h3>My 2025 at a glance</h3>
<ul>
<li>Sold my house.</li>
<li>Left my role as Co-Founder and Head of Design at Limitless (née Rewind AI).</li>
<li>Took 4 months off. Traveled, talked to 30+ founders, companies, and investors as I explored new opportunities.</li>
<li>Started a new role as Head of Design at <a href="https://sesame.com">Sesame</a>.</li>
<li>Started working in an office full-time. After years working remotely, I&#x27;m loving it.</li>
<li>Bought a car after 7 years without one, and learned my lesson about buying a new redesign generation car.</li>
<li>Limitless was acquired by Meta.</li>
<li>Personal resets:
<ul>
<li>Stopped consuming caffeine entirely. Decaf coffee only, not even green tea.</li>
<li>Had my second year of no alcohol.</li>
<li>Stopped wearing my Apple Watch (got annoyed with notifications, wanted to simplify.)</li>
<li>Mostly stopped wearing contact lenses in favor of <a href="https://paulstamatiou.com/gear/edc">my glasses</a><sup><a rel="footnote" href="#footnote-4" id="r4">4</a></sup>.</li>
</ul>
</li>
</ul>
<h3>Selling my house</h3>
<p>The year started with me finally selling the one-bedroom condo I had purchased a decade earlier. <strong>I completely regret purchasing that place.</strong> Not because it had major maintenance issues or anything like that, but because it was a horrible investment. I had it for 10 years and still <em>lost</em> money on it once you factor in the lower sale price, prep work to sell (staging, floor upgrades, painting), and associated fees.</p>
<p>It was a relatively new building in a bustling shopping and restaurant area in Nob Hill near Russian Hill. The entire building was only nine years old when I bought my unit, so I only had minor maintenance tasks over the years. I loved living there. The unit was modern, had a good HOA, no issues with neighbors, and had 500/500 Webpass as the ISP (this was before fiber was commonplace and before Google Fiber purchased Webpass).</p>
<img src="https://turbo.paulstamatiou.com/uploads/2025/12/stammy-condo-1.jpg" alt="San Francisco - Nob/Russian Hill - condo living room and kitchen" width="1500" height="999" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/stammy-condo-2.jpg" alt="San Francisco - Nob/Russian Hill - condo living room and interior" width="1344" height="999" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/stammy-condo-3.jpg" alt="San Francisco - Nob/Russian Hill - condo interior" width="1344" height="999" />
<small>The condo staged for sale.</small>
<p>Why did I buy this place to begin with? I got it in 2015 when I was 29. I had been at Twitter for a few years and made some money from the Twitter IPO. I hated having roommates, and the alternative of paying $4,000–$5,000 a month to rent my own apartment didn&#x27;t feel like a good idea. And at the time, it felt like you couldn&#x27;t go wrong buying in San Francisco. More and more companies were becoming SF-based instead of Silicon Valley, and many friends and coworkers around me were buying homes too.</p>
<p>I purchased it with 25% down and a 2.75% 7-year ARM mortgage from First Republic Bank (RIP, they were great). I figured seven years was plenty of time to either sell or refinance before the rates increased. That didn&#x27;t help either.</p>
<p>I <a href="https://paulstamatiou.com/new-york">moved to New York</a> in 2019 and rented out my condo through a property management company that handled everything while I was out of state. I was in NYC for four years and lost money every month renting it out. Not to mention the property management company was horrible and a pain to deal with. My 7-year ARM&#x27;s fixed period ended in mid-2022 while I was in New York while the rate was increasing monthly. By the time I sold the unit, my expired 2.75% ARM mortgage had exceeded 7.5%. It wasn&#x27;t worth refinancing by then, I knew I wanted to sell it soon.</p>
<p>My wife and I came back to San Francisco in 2023. That same horrible property management company forgot to have the tenant sign a lease (you had one job..), and the tenant ended up moving out unexpectedly a few months in. It lined up perfectly with the end of our apartment lease in New York, so we decided to head to San Francisco for a few months to fix up the condo, sell it, then head back to NYC.</p>
<p>When we got back in January 2023, it wasn&#x27;t a great time to sell, so we stayed. We didn&#x27;t mind escaping the New York winter for a while, and the AI boom was starting to make SF feel alive again. We still love New York, but at the moment it really feels like if you work in tech and AI, you <em>need</em> to be here. The energy is palpable.</p>
<p>We eventually got around to selling it at the start of 2025. I always thought selling it would be a hassle and that I would need to do upgrades to make it enticing. Well, it ended up being so much easier to sell than I expected.</p>
<p>A former coworker introduced me to a small real estate agency; they were perfect. I dropped off the keys and they took it from there. They refinished the floors, upgraded some things in the bathroom, updated the heating system, painted, and staged. In less than two months, it sold. I received 11 offers: four competitive and three all cash. Even though I lost money on the sale all things considered, I had expected it to sell for considerably less given it was listed in January instead of the ideal time in spring.</p>
<p>I learned my lesson with this place. I don&#x27;t see myself purchasing a house in San Francisco anytime soon. The opportunity cost of the down payment alone stings. It would have tripled in a basic total U.S. stock market ETF over those 10 years.</p>
<p>We&#x27;ve since been renting in Noe Valley for the last year. I finally have enough space and my own garage, so I moved over all of my stuff that had been stored with family: my <a href="https://paulstamatiou.com/gear/eames-lounge-chair-ottoman">Eames chair</a>, <a href="https://paulstamatiou.com/gear/apple-pro-display-xdr">Pro Display XDR</a>, and <a href="https://x.com/Stammy/status/1972400342097903642">old gear</a> like this original <a href="https://paulstamatiou.com/gear/apple-isight">iSight</a>.</p>
<p>Finding this rental was a huge challenge. Every evening for what felt like a year was spent scouring rental sites before we eventually found it off-market through a friend. At one point there was an apartment in Pacific Heights we loved so much we wrote a love letter (more common with purchases, not rentals), offered many months of cash up front, and even extra rent. There was just too much competition.</p>
<p>I frequently hear from people saying they&#x27;re moving to San Francisco in a month or two. My advice is always the same: start looking for your apartment as early as possible!</p>
<h3>Leaving Limitless</h3>
<p>2025 started with an itch. After two and a half years of working on <a href="https://web.archive.org/web/20231221114250/https://www.rewind.ai/">Rewind</a>, then through its evolution to Limitless and the <a href="https://www.wired.com/story/taking-baby-steps-toward-the-ai-meeting-singularity/">Limitless Pendant</a>, I needed a change. I needed a new design and product challenge.</p>
<p>In my time there, we really embodied what a startup is all about. We had a <a href="https://x.com/Stammy/status/1638995043263578112">true customer focus</a>, endless product iteration, countless product strategy refinements, and long hours sweating the details. We were a remote team of ~15-20 people in recent years. I was the only designer for a period and wrote about what this was like in <a href="https://paulstamatiou.com/the-startup-designer">The Startup Designer</a>.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2025/12/rewind-limitless-team-1.jpg" alt="Rewind/Limitless team" width="2500" height="1842" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/rewind-limitless-team-2.jpg" alt="Rewind/Limitless team" width="2500" height="2499" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/rewind-limitless-team-3.jpg" alt="Rewind/Limitless team" width="2500" height="1875" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/rewind-limitless-team-4.jpg" alt="Rewind/Limitless team" width="2500" height="2034" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/rewind-limitless-team-5.jpg" alt="Rewind/Limitless team" width="2500" height="2431" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/rewind-limitless-team-6.jpg" alt="Rewind/Limitless team" width="2500" height="1875" />
<small>The Limitless team at various offsites.</small>
<p><strong>We built a lot of stuff as we searched for product-market fit</strong>. Rewind was a native Mac app that captured everything you&#x27;d seen (via screen capture), said and heard (via opt-in meeting and audio recording), compressed it, and made it actionable. You could visually rewind time as well as search or ask AI to find anything you&#x27;ve seen.</p>
<p>I loved that it had a local-first approach, private by design, and was a bit uncanny until you got used to it. An app that records your screen all the time? Crazy. But it worked.</p>
<p>I would tell people that making Rewind was probably a similar user and marketing challenge to what the team at 1Password likely went through when they were starting out in the mid-2000s. "You want me to put all my passwords into this one app I&#x27;m supposed to trust with my digital life?" Crazy. But it worked.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2025/12/rewind-mac-1.jpg" alt="Rewind Mac app - Ask Rewind feature" width="1922" height="1372" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/rewind-meetings.jpg" alt="Rewind Mac app - Rewind meeting recording and summarization" width="3612" height="2008" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/rewind-search.jpg" alt="Rewind Mac app - Rewind search results UI" width="2000" height="1252" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/rewind-site-1.jpg" alt="Rewind website" width="1916" height="3246" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/rewind-site-2.jpg" alt="Rewind website - Private by design" width="1914" height="3236" />
<small>The Rewind Mac app. <strong>Bottom right</strong>: Rewind website I designed and built.</small>
<p>We also made <a href="https://x.com/Stammy/status/1684279648019189761">Rewind for iOS</a>, then I spent some time diving into Windows development with C# and WinUI as we worked on a <a href="https://www.youtube.com/watch?v=-80W4f103lE">Windows app focused on using a local LLM</a>.</p>
<p>While the product had some challenges with search quality due to limitations from the local approach, I still think the Rewind concept is solid. Microsoft famously thought so too and created the Rewind-inspired <a href="https://arstechnica.com/gadgets/2024/05/microsofts-new-recall-feature-will-record-everything-you-do-on-your-pc/">Recall feature</a>. There are some things I&#x27;d approach differently if Rewind were rebuilt from the ground up today: prioritize task-based workflows over pure recall, and explore using lightweight visual models for data classification.</p>
<video controls="true" poster="">
      
      <source src="https://turbo.paulstamatiou.com/uploads/2025/12/lenny-rewind.mp4" type="video/mp4">
      Your browser does not support the video tag.
    </video>
<small>Rewind described on <!-- --><a href="https://youtu.be/2ezz4KJe7kA?t=3686">Lenny&#x27;s podcast</a></small>
<p>We then pivoted to a cloud-based product called Limitless, largely as a result of feeling limited by what we could achieve with Rewind&#x27;s local-based approach. There was the cross-platform Limitless web and desktop app, and then the React Native mobile app.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2025/12/limitless-site-1.webp" alt="Limitless website" width="2919" height="2894" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/limitless-site-2.webp" alt="Limitless website" width="2924" height="2768" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/limitless-site-4.webp" alt="Limitless website" width="2716" height="3025" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/limitless-site-3.webp" alt="Limitless website" width="2924" height="2899" />
<video controls="true" poster="https://turbo.paulstamatiou.com/uploads/2025/12/limitless-website-poster.jpg">
      <source src="https://turbo.paulstamatiou.com/uploads/2025/12/limitless-website.webm" type="video/webm">
      <source src="https://turbo.paulstamatiou.com/uploads/2025/12/limitless-website.mp4" type="video/mp4">
      Your browser does not support the video tag.
    </video>
<small>The Limitless.ai website I designed and built <!-- --><a href="https://x.com/Stammy/status/1779860940541808935">with lots of design details</a><!-- -->. My favorite detail was custom animating cursors when you selected a new Pendant color.</small>
<p>Limitless started with meeting recording and summary functionality. That was a recurring use case people had with Rewind. While I personally felt that functionality wasn&#x27;t the most exciting thing to work on, nor did it have staying power with countless meetings-focused competitors working on the exact same thing, we had an ambitious roadmap. The goal was to continually add more data sources over time for context.</p>
<p>One of those data sources was to be our own hardware, <a href="https://ammunitiongroup.com/projects_pt/pendant/">the Limitless Pendant</a>, to capture in-person meetings and conversations to help differentiate us from competitors.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2025/12/limitless-iphone-app.webp" alt="Limitless app for Pendant on iPhone" width="3990" height="2266" />
<small>Early versions of Limitless for iPhone I designed.</small>
<p>The Pendant was a bold bet, but after a year of building its companion app and dogfooding it, <strong>I realized it wasn&#x27;t a product for me.</strong> I take privacy extraordinarily seriously and lean introverted, so I wasn&#x27;t exactly comfortable wearing a recording device out of the house and asking for consent every time I encountered someone new. On top of that, my wife wasn&#x27;t comfortable with me wearing it at home either. The product had real use cases, and we heard about that consistently from customers, but it wasn&#x27;t for me.</p>
<p>Meanwhile, the tech industry was exploding as LLM capabilities improved at a rapid clip and I felt like I was watching from the sidelines. Agents, deep research, multimodal models, new interaction paradigms... I wanted to be at the forefront of that. The opportunity cost felt too high. My heart wasn&#x27;t in it, and I decided to leave.</p>
<h3>Acquired by Meta</h3>
<p>The Rewind and Limitless story came to a close some months later at the end of 2025 with <a href="https://www.reuters.com/business/meta-acquires-ai-wearables-startup-limitless-2025-12-05/">a Meta acquisition</a>. It felt like a great time for the team to join a larger company with the means to really compete with AI hardware and services coming out across the industry. It was a well-deserved exit for the team.</p>
<p>Financially, I received a modest sum for shares I had early exercised, and for my vested in-the-money stock options. I had also previously sold some equity<sup><a rel="footnote" href="#footnote-5" id="r5">5</a></sup> right after the company&#x27;s last public round.</p>
<p>I&#x27;ll likely put some of it toward a few angel investments. I&#x27;ve done several angel investments in the past, mostly in crypto companies like <a href="https://rainbow.me/">Rainbow</a> and <a href="https://xmtp.org/">XMTP</a> (the messaging protocol now used by Coinbase Base and World). However, I&#x27;ve declined to do them more regularly because I feel that to do a good job, you need to have the time and bandwidth to stay on top of deal flow—seek it, meet the founders, and maybe you end up investing in 1 out of every 10+ teams you come across.</p>
<h3>Time off</h3>
<p>After leaving Limitless, I gave myself permission to slow down before jumping into something new. I ended up taking four months off, though it didn&#x27;t really feel like time off at all. I was meeting with founders, companies, and VCs for weeks, and also spent time I was working on my design portfolio.In hindsight I went overkill on the portfolio—I had two versions, the most comprehensive of which was 177 slides—but the act of doing it was a great way to reflect on how I worked, what gave me energy, and what drained it.</p>
<p>My wife made the most of me no longer working nights and weekends, and we ended up taking a few trips. First to <a href="https://x.com/Stammy/status/1908877984490205577">Germany</a> and <a href="https://x.com/Stammy/status/1907755587359899709">Austria</a>, then later to Milan and <a href="https://x.com/Stammy/status/1929600296700805413">Lake Como</a> for a friend&#x27;s birthday.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2025/12/austria-1.jpg" alt="Austria" width="3024" height="4032" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/austria-2.jpg" alt="Austria" width="3024" height="4032" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/austria-3.jpg" alt="Austria" width="3024" height="4032" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/austria-4.jpg" alt="Austria" width="3024" height="4032" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/austria-5.jpg" alt="Austria" width="3024" height="4032" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/austria-6.jpg" alt="Austria" width="3024" height="4032" />
<small>Altaussee and Hallstatt, Austria. I haven&#x27;t traveled with my <!-- --><a href="https://photos.paulstamatiou.com/">big Sony a7R IV</a><!-- --> in some years. I get by with my iPhone, shooting in RAW and minor edits in Darkroom app.</small>
<p><strong>I stopped consuming caffeine entirely</strong> in 2025. It was during the trip to a medical health resort called MayrLife on Lake Altaussee, Austria that made that happen. This place was strict: a set schedule with strict meal times along with no caffeine or alcohol. The alcohol part was fine, but getting off of caffeine was a challenge.</p>
<p>I had zero alcohol in all of 2024 and maybe just 5 drinks for all of 2025. I just don&#x27;t really care for it anymore, and never loved the feeling of feeling <em>something</em> the next morning even if I only had two cocktails the night before. After the first full year of zero alcohol, it&#x27;s like I was rewired and completely don&#x27;t even care for alcohol anymore. I&#x27;ll have some non-alcoholic beers and mocktails at times, of course.</p>
<p>I had been used to having a 2-3 strong cups of coffee every day. I ended up having about 4 or 5 days of caffeine withdrawal migraines as I went cold turkey. After that, I decided I didn&#x27;t want to go back to my normal coffee routine. I still love coffee and have a cup of decaf every morning though. I&#x27;ve learned all about the different kinds of decaf processes like Swiss Water Process (chemical free; the lowest caffeine but the worst taste) and Ethyl Acetate (best taste). My current decaf favorite is by Perc Coffee, but I&#x27;m still trying out others I&#x27;m discovering on the r/decaf subreddit.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2025/12/lake-como-1.jpg" alt="Lake Como" width="3024" height="4032" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/lake-como-2.jpg" alt="Lake Como" width="3072" height="4096" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/lake-como-3.jpg" alt="Lake Como" width="3024" height="4032" />
<small>Lake Como, Italy. Went for my friend <!-- --><a href="https://www.vermilion.fund/about">Ashley</a><!-- -->&#x27;s birthday.</small>
<p>After the initial withdrawal issues, staying off of caffeine wasn&#x27;t that bad. Decaf coffee doesn&#x27;t dehydrate you during the day, which is something I could feel. I used to rely on melatonin and sometimes magnesium to more easily fall asleep at night after a day of coffees, but now I don&#x27;t need that either. The biggest downside is that while I love the flavor of coffee it&#x27;s harder to find good decaf options at coffee shops. If they do have decaf, it&#x27;s likely just one kind and only served as an americano, not pour over or brewed.</p>
<p>I also took the time to hit reset and simplify a few other things in my life. On the nerdy side, I <strong>got rid of the two servers I had been running</strong> for a while. I had one server that managed this website&#x27;s email newsletter, that I publish to very infrequently. I had been using a self-hosted web app called Sendy that uses AWS SES to send emails cheaply. I ditched that in favor of <a href="https://x.com/Stammy/status/1881046251984077177">Kit</a>. But between that and my other server I used to host my personal Mastodon instance, I hated having to login every few weeks to install an update or fix something. It&#x27;s a small thing, but it freed up mental space.<sup><a rel="footnote" href="#footnote-6" id="r6">6</a></sup></p>
<p>I <strong>stopped wearing my Apple Watch too</strong>. I was constantly annoyed by all the useless notifications and buzzing on my wrist. While I appreciated the health tracking functionality, I wanted to simplify. It didn&#x27;t start as an overnight consciousness decision. I got a <a href="https://paulstamatiou.com/gear/casio-f91w-watch">simple Casio F-91W watch</a>, changed the strap and started wearing it some days. Eventually that became everyday. Half of what I appreciate is that it&#x27;s not a smartwatch. The other half I appreciate is that it&#x27;s just so small and lightweight.</p>
<h3>Exploring what&#x27;s next</h3>
<p>I wrote down what was critical to me as I started thinking about what I wanted in a new role. At the end of the day, I wanted to work with an <strong>exceptionally talented team</strong>, at the <strong>forefront of AI</strong>, with leadership and a CEO who <strong>genuinely care about quality</strong>, and <strong>as little organizational friction as possible</strong> between us and an <strong>outstandingly well-crafted product</strong>.</p>
<p>I wasn&#x27;t in a rush to find the next thing. I had time and wanted to optimize for seeing what was out there first. I&#x27;m often reminded of <em><a href="https://blog.samaltman.com/how-to-be-successful">How To Be Successful</a></em> by Sam Altman, where he writes:</p>
<blockquote>
<p>“I am willing to take as much time as needed between projects to find my next thing. But I always want it to be a project that, if successful, will make the rest of my career look like a footnote.”</p>
</blockquote>
<p>Being in San Francisco and being public about the fact that I was looking for my next thing was like a cheat code for that process. My days were filled as I met with several dozen founders, companies, VCs and friends.</p>
<p>Every founder and team I met with had a unique perspective on where the world is heading, and they were fighting through the ambiguity to get there. It&#x27;s still wild to me that this level of energy and ambition is just par for the course in San Francisco.</p>
<p>I&#x27;m grateful to folks who took time to chat with me:</p>
<ul>
<li><strong>Investors:</strong> A16Z, NEA, First Round Capital, Felicis Ventures, Bain Capital Ventures, Sutter Hill Ventures, Lightspeed Venture Partners, <a href="https://x.com/marcbhargava">Marc Bhargava</a> from GC and others.</li>
<li><strong>Companies:</strong> Cursor, Perplexity, Notion, Hooglee, Arcade AI, Microsoft AI, Sesame, LM Studio, OpenAI, Anthropic, Figma, World Labs and more.</li>
<li><strong>Friends:</strong> I reconnected with friends and acquaintances from Physical Intelligence, Vercel, Shortwave, Luma Labs, Streak CRM, Visual Electric, Humane/HP IQ, Variant.ai, Shopify, Macroscope, Agora.xyz, Adam Lisagor, Ulf Schwekendiek, Jake Jolis and others.</li>
</ul>
<h3>What I Learned</h3>
<p>A few things crystallized from all these conversations:</p>
<ul>
<li>Some founders are really, really good at talking about their company. They have a clear view of the future and make the steps to get there feel obvious, almost expected. Almost like Steve Jobs&#x27;s "reality distortion field." Their energy is infectious.<sup><a rel="footnote" href="#footnote-7" id="r7">7</a></sup></li>
<li>Builders are back. Thanks in no small part to AI, teams are doing more with far less. Orgs are extremely flat. ICs are preferred over managers. Designers who code aren&#x27;t a nice-to-have anymore: they&#x27;re the norm. The era of bloated teams shipping slowly feels firmly behind us.<sup><a rel="footnote" href="#footnote-8" id="r8">8</a></sup> The <a href="https://www.implications.com/p/insights-on-collapsing-the-talent">talent stack</a> has collapsed.</li>
<li>The best designers, engineers, and product managers who weren&#x27;t already working closely with AI were thinking about leaving their companies.</li>
</ul>
<h3>What I Wanted</h3>
<p>All of this helped me articulate exactly what I wanted next after talking with small teams and large teams.</p>
<p>I&#x27;m happiest, most productive, and most ambitious working on 0→1 products and bold bets that scratch at something new in AI, where there&#x27;s a shared understanding of quality. I would much rather be the first designer tasked with creating an app or site from scratch than a designer or manager on a team of dozens responsible for just a sliver of an app. Not on a team of dozens optimizing something that already exists. I wanted to stay close to the craft while also growing a team.</p>
<p>When I began this process, I actually thought I wanted to optimize for compensation and go to a late-stage, pre-IPO, or public company. I had always felt like you wanted to alternate between riskier early-stage startups and late-stage companies in your career so you wouldn&#x27;t get "behind" with savings and investments. It became clear to me that was not where my heart was at all. I needed to work on something I was beyond passionate about with a team that shared that desire.</p>
<h3>Joining Sesame</h3>
<p><a href="https://sesame.com">Sesame</a> ended up being everything I was looking for and more. It&#x27;s been phenomenal across the board: the shared appreciation and ambition for excelling at craft, the remarkable team comprised of industry veterans, and the bold bets we&#x27;re making on the product we&#x27;re building. Yes… I know everyone says this about their company when they join, but that&#x27;s really how I feel.</p>
<p>I&#x27;ve never worked somewhere that truly cared about craft and understood it <em>this</em> much. A lot of that is due to the CEO, <a href="https://x.com/brendaniribe">Brendan Iribe</a>, who was one of the founders of <a href="https://en.wikipedia.org/wiki/Reality_Labs">Oculus VR</a>. Brendan reached out after I published <em><a href="https://paulstamatiou.com/browse-no-more">Browse No More</a></em>. He&#x27;s one of those founders I was alluding to in the previous section: someone who&#x27;s really, really good at speaking about the importance of what the team is building, about taste, and about how great products are made.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2025/12/sesame-2.jpeg" alt="Sesame team" width="2884" height="2623" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/sesame-4.jpeg" alt="Sesame team" width="2451" height="2794" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/sesame-1.jpeg" alt="Sesame office" width="4096" height="3112" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/sesame-3.jpg" alt="Sesame team" width="2500" height="1875" />
<small>Sesame team offsite in Skamania, Washington</small>
<p>I&#x27;ve been on enough teams to know that it really doesn&#x27;t matter if various executives on the leadership team say quality matters. In my experience, it <em>has</em> to come directly from the CEO too. Brendan gets it; for software and for hardware. I later met the rest of the team, including the CPO <a href="https://twitter.com/natemitchell">Nate Mitchell</a> (also one of the founders of Oculus VR), and it was clear this was a team I needed to work with.</p>
<h3>What We&#x27;re Building</h3>
<p><strong>We&#x27;re building both software and hardware.</strong> On the software side, we&#x27;re building what we call personal agents. They&#x27;re not productivity assistants, they&#x27;re more like a collaborator and thought partner you just talk with. But even that description doesn&#x27;t do our ambitions here justice. They&#x27;re much more than that.</p>
<p>We&#x27;ve been focusing on making them remarkably lifelike. That comes across in their unique personalities and how they carry the conversation. It&#x27;s the sort of thing you need to experience to see what I mean: you can try our <a href="https://app.sesame.com/">research preview</a> released earlier in 2025 that over a million people have used. We&#x27;re also working on an iOS app—you can <a href="https://www.sesame.com/beta">get on the waitlist here</a>.</p>
<blockquote>
<p>"This is not another productivity assistant. It&#x27;s something different: a lifelike, expressive collaborator—designed to engage and evolve with its user over time."</p>
</blockquote>
<p>The second piece is hardware. We&#x27;re making <strong>the world&#x27;s best intelligent eyewear</strong>. They&#x27;re fashion-forward and made for all-day comfort. Sequoia has more details on both our software and hardware in their article <em><a href="https://sequoiacap.com/article/partnering-with-sesame-a-new-era-for-voice/">A New Era for Voice</a></em>.</p>
<p>The mission we talk about that I really love is that we&#x27;re working towards <strong>bringing the computer to life</strong> with our hardware and focus on voice-first AI. We&#x27;ve been saying "software is eating the world" for 15 years now. Now as AI is eating software, hardware is becoming the new distribution and interaction frontier for AI. I&#x27;m not saying we won&#x27;t have phones in 5 years (I still absolutely love mine), but I&#x27;m eager to spend time collaborating with the team here to see what these new interfaces will enable.</p>
<blockquote>
<p>"Hardware becomes a more popular moat (amid a surge of hardware startups). In a world where everyone can make their own software, unique products will emerge that tightly couple hardware and software."
—<a href="https://x.com/scottbelsky/status/2005639350554407187">Scott Belsky</a></p>
</blockquote>
<img src="https://turbo.paulstamatiou.com/uploads/2025/12/sesame-7.jpg" alt="Sesame team" width="2500" height="1875" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/sesame-6.jpg" alt="Sesame team" width="2500" height="1831" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/sesame-9.jpg" alt="Sesame team" width="2500" height="1875" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/sesame-5.jpg" alt="Sesame office" width="2037" height="2500" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/sesame-10.jpg" alt="Sesame team" width="2500" height="1562" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2025/12/sesame-11.jpg" alt="Sesame team" width="2500" height="1655" />
<small>Sesame San Francisco one week when the NYC and Bellevue teams were visiting. <strong>Top</strong>: I&#x27;m on the left</small>
<p>And after five years of almost entirely working from home, I&#x27;m thrilled to be back in an office. When covid started, I thought I&#x27;d never go back to the office. I loved having my own desk setup and being able to focus.</p>
<p>Now <strong>I just miss working with people, whiteboarding design ideas, and perfecting prototypes right next to teammates.</strong> Also, teams building hardware kind of need to be in person with the number of physical prototypes we&#x27;re continually crafting and testing out.</p>
<h3>Design @ Sesame</h3>
<p>It&#x27;s been six months since I joined as Sesame&#x27;s Head of Design, based out of our San Francisco office. My current day-to-day is heavy on design and code (Figma & Xcode for our iOS app)<sup><a rel="footnote" href="#footnote-9" id="r9">9</a></sup> and helping out with things across product, hardware, brand, and marketing.</p>
<p>We&#x27;ve got a lot in store for design this year across mobile, web, brand, and hardware. It&#x27;s always a fun design challenge to work beyond just software product design. <a href="https://basheer.co/">Basheer Tome</a> joined my team to focus on hardware design, interaction design, prototyping, and everything in between. He had previously worked on Google Glass, Google Pixel Buds, autonomous driving, and all sorts of projects spanning PM, ID and CMF at Fellow.</p>
<p>I&#x27;m looking forward to growing our design team this year. I&#x27;m the only software product designer at the moment<sup><a rel="footnote" href="#footnote-10" id="r10">10</a></sup>, and am looking to hire a seasoned <a href="https://jobs.ashbyhq.com/sesame/430ccfb7-2358-4ce9-9e00-fd84d4e28332">product designer</a> to work closely with me in our San Francisco office with a focus on visual design with a passion for craft and design engineering.</p>
<p><a href="https://www.sesame.com/team">We&#x27;re hiring</a> for quite a few different roles outside design too.</p>
<h3>How I worked in 2025</h3>
<p>I finally perfected my home office setup. For the two years prior I had a small desk in the bedroom at my previous place. Once we moved, I finally had space to build things out the way I wanted. I had room for my iMac G3 and vintage gadgets, a <a href="https://paulstamatiou.com/gear/uplift-standing-desk">much larger 72x30" standing desk</a>, and a lounge chair behind it. I also finally shipped my Pro Display XDR to San Francisco from where it had been in storage at my in-laws&#x27; house on the East Coast.</p>
<img src="https://paulstamatiou.com/gear/desk/stammy-desk-setup-DSC07675.jpg" alt="Uplift V2 Standing Desk" width="3000" height="2000" />
<small><a href="https://paulstamatiou.com/gear/apple-imac-g3">iMac G3</a><!-- -->, <!-- --><a href="https://paulstamatiou.com/gear/apple-studio-display">Studio Display</a><!-- -->, <!-- --><a href="https://paulstamatiou.com/gear/apple-pro-display-xdr">Pro Display XDR</a><!-- -->, <!-- --><a href="https://paulstamatiou.com/gear/moergo-glove80-keyboard">Glove80 keyboard</a><!-- -->, <!-- --><a href="https://paulstamatiou.com/gear/uplift-standing-desk">Uplift Standing Desk</a><!-- --> with <!-- --><a href="https://paulstamatiou.com/gear/diy-desk-led-lighting">custom LED lighting</a><!-- -->.</small>
<p>For the last decade, I&#x27;ve had occasional wrist pain during extended computing sessions, but I have it under control these days with a combination of an adjustable desk (kept low enough so my elbows are properly angled), the <a href="https://paulstamatiou.com/gear/moergo-glove80-keyboard">Glove80 split ergonomic ortholinear keyboard</a>, a Logi Lift vertical mouse, and a wrist brace for long sessions.</p>
<p>Using a keyboard like the Glove80 (or similar models like the Kinesis Advantage2 I used before it) takes some getting used to, but it&#x27;s worth it if you&#x27;re in a similar boat with wrist pain from RSI. Separately, I try to use AI voice dictation apps like <a href="https://aquavoice.com/share?code=PS-AKOL">Aqua</a> to speak instead of type when I can. I haven&#x27;t quite built that habit yet. I&#x27;ve been thinking about getting a gooseneck desk mic for the office, like some other coworkers have, to do this more often.</p>
<p>I&#x27;ve made a few other additions to my gear recently, but the standouts are my <a href="https://paulstamatiou.com/gear/apple-imac-g3">333MHz Revision D iMac G3 from 1999</a>, my <a href="https://x.com/Stammy/status/1985174125963550959">original iSight camera</a>, and my new <a href="https://paulstamatiou.com/gear/owc-express-4m2-nvme-ssd-enclosure">OWC 4-bay M.2 SSD RAID enclosure</a>. With the latter I&#x27;ve also started using <a href="https://immich.app/">Immich</a> to manage my photos (hosted on my Mac, behind Tailscale) and will probably migrate my Google Photos to it.</p>
<img src="https://paulstamatiou.com/gear/apple-imac-g3-copyright-paulstamatiou-3.jpg" alt="Apple iMac G3" width="2500" height="1780" /><br /><br /><img src="https://paulstamatiou.com/gear/apple-imac-g3-copyright-paulstamatiou-2.jpg" alt="Apple iMac G3" width="2500" height="2500" /><br /><br /><img src="https://paulstamatiou.com/gear/apple-imac-g3-copyright-paulstamatiou.jpg" alt="Apple iMac G3" width="2500" height="2038" />
<small>I&#x27;ve been meaning to post a much more in-depth article about the iMac. I updated the RAM, converted the HD to an SLC NAND flash CompactFlash card, and applied new thermal paste to the CPU heatsink. So much nostalgia.</small>
<p>Ironically, I now work in the office on weekdays, so the setup doesn&#x27;t get as much use anymore. I purchased a car for my commute, the newly redesigned 2025.5 Audi SQ5 SUV. I haven&#x27;t had a car since I sold my E92 M3 about 7 years ago. Mechanically, it&#x27;s great: quick, makes a nice sound, and overall fun to drive. The rest is just okay. The interior design leaves a lot to be desired. There&#x27;s ugly piano black plastic everywhere and too many controls are touch-based.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2025/12/audi-sq5-cel-commute.jpg" alt="Audi SQ5 Check Engine Light" width="2500" height="1875" />
<small>Driving to work… notice the check engine light that comes on and off randomly. Take it from me: don&#x27;t buy the first year of a new car generation.</small>
<p>But the icing on the cake is the garbage computer system. Not the infotainment system (though I really dislike that it lacks a traditional tachometer gauge cluster setting), but the whole car&#x27;s computer system has been remarkably buggy. Various warnings and check engine lights constantly come on and then vanish on their own. I took it in for service just a month after I purchased it. They kept it for more than a week and the issues persisted. Others on Reddit are having similar problems and hope an upcoming software update will fix everything. I&#x27;ve definitely learned my lesson about buying a new generation car.</p>
<h3>Apps I love</h3>
<img src="https://paulstamatiou.com/gear/mnemosyne-kleid-notebook.jpg" alt="Maruman Mnemosyne x Kleid A5 Notebook" />
<small>Okay it&#x27;s not an app, but I love taking notes, sketching UI designs and scratching off to-do list items in <!-- --><a href="https://paulstamatiou.com/gear/maruman-mnemosyne-kleid-notebook">Mnemosyne x Kleid notebooks</a><!-- --> with my <!-- --><a href="https://paulstamatiou.com/gear/baronfig-squire-pen">Baronfig Squire</a><!-- -->. I also love <!-- --><a href="https://amzn.to/4joRdoF">Uchida Le Pens</a><!-- --> for sketching too. I&#x27;ve gone through a few in 2025.</small>
<ul>
<li>
<p><strong><a href="https://www.diabrowser.com/">Dia</a></strong> has been my primary browser for the majority of 2025. After living with Arc for the few years prior, I&#x27;m really accustomed to a browser with side tabs. I&#x27;ve tried to get into the ChatGPT Atlas browser and Perplexity&#x27;s Comet browser but they never stuck for me, even with the promise of all their agentic functionality.
I just don&#x27;t really have a huge need to automate things just yet.</p>
<p>Actually, I take that back, I would but the few times I&#x27;ve tried current solutions they were too slow and inaccurate. Maybe later in 2026. About 99% of what I have AI do in a browser for me is summarize long articles, and I use both Dia&#x27;s integrated chat for that, and recently, Anthropic&#x27;s <a href="http://claude.ai/chrome/">Claude browser extension</a> for that.</p>
<p>I just hope that Dia keeps its craft and charm even after its parent company&#x27;s acquisition by Atlassian.</p>
</li>
<li>
<p><strong><a href="https://flighty.com/">Flighty</a></strong> for insanely good flight tracking. I don&#x27;t fly <em>that</em> much and this app is still worth every penny. I get notified of flight delays before the airlines send notifications. I can more easily look up alternate routes, see where the inbound plane is, and more. It&#x27;s just a delightfully well-crafted app.</p>
</li>
<li>
<p><strong><a href="https://apps.apple.com/us/app/yuka-food-cosmetic-scanner/id1092799236">Yuka</a></strong> lets you look up the health impact of various food and cosmetic items. My wife and I use it often to make better choices when shopping, such as avoiding harmful chemicals.</p>
<p>There are a few apps like it but it&#x27;s simple and works well. It does not have data about microplastics (you should definitely take a look at Nat Friedman&#x27;s <a href="https://www.plasticlist.org/">PlasticList</a>) yet unfortunately, but other apps like Olive and Oasis Health do.</p>
<p>These days we&#x27;re much more mindful about what we bring into the house and have replaced pans with non-toxic ceramic ones, plastic cutting boards with oiled wood ones, avoiding certain dish detergents, et cetera.</p>
</li>
<li>
<p><strong><a href="https://mercury.com/share/stammy">Mercury</a></strong> is hands down the best personal banking app and bank out there. There&#x27;s an annual fee but you get a lovely, well-designed modern app with things like automatic transfer rules to move money around (e.g., don&#x27;t keep cash in checking, always move to HYSA) and support for sending wires really easily.</p>
</li>
<li>
<p><strong><a href="https://netnewswire.com/">NetNewsWire</a></strong> combined with <a href="https://paulstamatiou.com/hello-rss">Feedbin</a> is my RSS reader setup of choice. NNW has been around since I had a G4 Mac Mini in my college dorm in 2004. Great, simple piece of software. Though I do wish it had slightly more robust search functionality.</p>
</li>
<li>
<p><strong><a href="https://culturedcode.com/things/">Things</a></strong> has been my to-do list app for many years. Simple, well-built apps for desktop and phone. I have a few minor design gripes with it (what designer <em>wouldn&#x27;t</em> have strong thoughts about their to-do list app) but it gets the job done. There&#x27;s an <a href="https://github.com/hald/things-mcp">unofficial Things MCP server</a> I&#x27;ve been meaning to integrate into my workflow too.</p>
</li>
<li>
<p><strong><a href="https://raindrop.io/">Raindrop</a></strong> is where I send articles I want to read later, curate design inspiration, save interesting links, and everything in between. It also saves a permanent copy of each link you bookmark so it&#x27;s still accessible even if that page ceases to exist on the web. I try to go through it weekly to organize and review what I&#x27;ve saved.</p>
</li>
<li>
<p><strong><a href="https://obsidian.md/">Obsidian</a></strong> (with the Cupertino theme) is my catch-all for daily notes and more. I pay for Obsidian Sync service too. While I have various folders for different types of documents from outlines and drafts of blog posts to documents for ideas, I primarily use it for work. I create a new file each week where I write notes for the week. At the bottom of each week&#x27;s document I keep a running to-do list. At the end of each day I&#x27;ll reprioritize that list or write down an action plan if I&#x27;m in the middle of a large task so I&#x27;m prepared the next morning.</p>
<p>While I really love Obsidian, it&#x27;s not perfect. Searching for files is really, really rough in my experience. I <em>need</em> to keep things in organized folders as I know I&#x27;ll need to find them later and can&#x27;t rely on search. Also, despite a robust developer community, there&#x27;s not yet an amazing LLM solution. Fortunately everything in Obsidian is flat files, so I often use Claude Code with my Obsidian vault for things like synthesizing summaries and themes across a lot of files.</p>
<p>And finally, the other thing I don&#x27;t love about Obsidian is the mobile app navigation. It&#x27;s likely a downside of it being a highly-extensible and cross-platform app, instead of a more opinionated native iOS app.</p>
</li>
</ul>
<p>Despite using all these apps for notetaking, saving, and curating, I don&#x27;t really like the term second brain for this PKM stack. This quote below from <a href="https://www.joanwestenberg.com/i-deleted-my-second-brain-692aa40d59d5f06dd5131e43/">I Deleted My Second Brain</a> resonates with me to a degree, and I sometimes find myself saving things I never revisit.</p>
<blockquote>
<p>"The “second brain” metaphor misfits how human memory works: associative, embodied, and purposefully forgetful.</p>
<p>When I first started using PKM tools, I believed I was solving a problem of forgetting. Later, I believed I was solving a problem of integration. Eventually, I realized I had created a new problem: deferral. The more my system grew, the more I deferred the work of thought to some future self who would sort, tag, distill, and extract the gold.</p>
<p>That self never arrived.""</p>
</blockquote>
<h3>The Year of Claude Code</h3>
<p>2025 was the year of coding agents for me (and everyone else too). It&#x27;s a remarkable, remarkable tool. At the start of the year I mostly used Cursor for smaller tactical changes, but I quickly became heavily dependent on Claude Code. It just kept getting better throughout the year.</p>
<blockquote>
<p>"Claude Code (CC) emerged as the first convincing demonstration of what an LLM Agent looks like - something that in a loopy way strings together tool use and reasoning for extended problem solving. In addition, CC is notable to me in that it runs on your computer and with your private environment, data and context."<br/>
—<a href="https://karpathy.bearblog.dev/year-in-review-2025/">Karpathy</a></p>
</blockquote>
<p>There&#x27;s many articles online on the proper way to configure and use Claude Code, how to put skills, agents, and <code>CLAUDE.md</code> to work for you, but <a href="https://x.com/bcherny/status/2007179832300581177">this thread from the Claude Code creator</a> in particular is worth a scroll:</p>
<blockquote>A Tweet embed was not displayed. Read this article in a browser to see it as intended.</blockquote>
<p>Tools like Claude Code still need constant babysitting and can sometimes get stuck in a loop, trying the same solutions that didn&#x27;t work. I find it critical to try out other models regularly, even for the same task. For example, I get the feeling that Sonnet/Opus aren&#x27;t <em>amazing</em> at more advanced or recent SwiftUI tasks. In a recent example it gave me the old GeometryReader hack for getting scroll offset from a ScrollView instead of the single <code>.scrollPosition()</code> modifier I wanted.</p>
<p>These days I&#x27;m usually bouncing between Claude Code (usually via their official extension inside Cursor, which has nice expandable inline diffs) and Gemini 3 Pro via Cursor Agents. I don&#x27;t have a set workflow. Sometimes I&#x27;ll have Opus make a plan, then have GPT poke holes through it before Claude Code implements. I&#x27;ve also dabbled with tools like <a href="https://x.com/Stammy/status/1955785843521757695">Conductor</a>.</p>
<p>Aside from the obvious desire for faster and smarter models that just nail each task, there&#x27;s one thing I wish these tools were better at: <strong>undo</strong>.</p>
<p>I know version control is technically my job. Git exists. But when I&#x27;m iterating quickly on a specific piece of functionality, I want to easily roll back to the last known good version without thinking about it. That&#x27;s often from a previous agent response. I can leave a trail of commits behind me, but that doesn&#x27;t look great on a PR. I can spend more time amending commits or dealing with git rebase, but that&#x27;s friction I&#x27;d rather avoid.</p>
<p>This feels like something these tools themselves should help with. Cursor, for example, doesn&#x27;t have diffs for each agent response. If you want to undo the last change, you have to ask the LLM to do it, wait, and hope nothing else unexpected is changed in the process. Compare that to just discarding changes if you&#x27;d made a git commit.</p>
<h3>Design + AI</h3>
<p>Much of what I do is design something from scratch in Figma, get it to around 90% or to a point where I have a few options I can&#x27;t decide between without trying them out, and then begin building it. Figma is very much still a starting point. Lots of iteration—in aesthetics, interactions, and logic—happens while I&#x27;m building and feeling it out with real builds.<sup><a rel="footnote" href="#footnote-11" id="r11">11</a></sup> For me that even meant going deep on working with metal shaders this past year: an area that seemed too complex to approach previously.<sup><a rel="footnote" href="#footnote-12" id="r12">12</a></sup> However, I will sometimes use Figma MCP to help speed up parts of the development workflow.</p>
<p>The act of building and testing out as you build is what design is all about to me. It rapidly surfaces new ideas for iterations and directions. There should have never been a design to engineering "handoff" phase. It&#x27;s the same thing. Every designer should be a design engineer too. Being able to more rapidly build designs and interactions also means you no longer have to scratch your head trying to decide if you should come up with a long dissertation about why a certain piece of feedback from a peer or executive isn&#x27;t worth pursuing. Most of the time, you can just try it out and see how it feels that day. Don&#x27;t close off paths too soon.</p>
<p>The biggest shift in design has not been on the visual design front for me. I don&#x27;t necessarily need production assets with models like Nano Banano Pro, nor are there any UI design tools good enough yet to truly enhance my visual and UI design workflow… yet. I&#x27;ve tried to use them for coming up with design inspiration for things like iconography and brand design tasks at times, but haven&#x27;t found anything that truly enhances my workflow yet.</p>
<p>Designers need to push on what AI isn&#x27;t good at yet. To me, that means constantly seeking inspiration, curating, and communicating well. <strong>Always be curious.</strong></p>
<p>You need to constantly be seeking information and inspiration. It can come from anywhere. Archive what feels good, interesting, or provocative to you. Hone your taste. The best designers I know are always curating. Some on Are.na and X. Some just in their own Figma moodboards. Some with link saving tools like Raindrop. Build that habit.</p>
<h3>Restraint in AI</h3>
<p>With Claude Code, Cursor Agents, and dozens of other AI dev tools anyone can build for themselves now. We&#x27;re entering the era of rapidly created, personalized and bespoke software. It&#x27;s going to seem even more insane this year.</p>
<p><strong>Just because you can, doesn&#x27;t mean you should.</strong></p>
<p>The hard part now isn&#x27;t building. It&#x27;s restraint in this world where we have more capabilities than ever.</p>
<p>I&#x27;ve noticed this industry is a bit too trigger-happy to jump into Claude Code and start generating, then immediately commit what was one-shotted. Maybe we should all be doing our own product plan mode outside of Claude Code&#x27;s plan mode.</p>
<p>Taking a step back to ask what we&#x27;re actually building and why before we start. It&#x27;s too easy to skip the product thinking and strategy. That&#x27;s the necessary but slow and hard work of deciding what should exist, why, and who it&#x27;s for in the first place.</p>
<p>What I&#x27;m referring to is just the normal product development process we&#x27;ve been doing for decades. Nothing new here. Just a reminder to not skip it when AI makes the building process closer and closer to a single button press.</p>
<p>As I design things I&#x27;m continually in a loop asking myself things like:</p>
<ul>
<li>Do I even need that (button/view/interaction)?</li>
<li>Is that implied constraint absolutely required? Is it validated?</li>
<li>And some of the Rick Rubin questions like "What&#x27;s the simplest way to express this idea?" or "What&#x27;s the core feeling or essence we&#x27;re trying to convey?"</li>
<li>I also constantly reference the <a href="https://longform.asmartbear.com/extreme-questions/">brainstorming questions in this article</a>.</li>
</ul>
<p>Similarly, even if AI does make something for you and does it well, quality can drop fast if you&#x27;re not careful to polish and clean up everything afterwards. For code quality and product design quality. Always polish it yourself. That&#x27;s where craft lives.</p>
<h3>Thoughts on personality in AI</h3>
<p>Everyone&#x27;s building some sort of agentic assistant right now. Connect your calendar. Integrate your email. Take actions. It all feels the same. A lot of assembled parts. Too many teams skip the hard parts: personality that builds trust, memory that truly enables continuity, and extensibility that meets you where you are. They also don&#x27;t think enough about the <em>why</em>. Okay, so you can access my calendar… now when and why am I supposed to use this?</p>
<p>That&#x27;s why too many of these tools today feel like packaged slop.</p>
<p>Personality and memory are what make these tools feel familiar and natural, not merely transactional. When GPT-4o was retired after GPT-5 launched, people were genuinely upset. They had gotten attached to how 4o wrote, how it felt. That&#x27;s not nothing. As AI becomes more ubiquitous, more ambient—even worn—this will only matter more. Even in quick interactions, the wrong tone and style is <a href="https://x.com/xlr8harder/status/2005195519732355194">immediately clocked</a>.</p>
<p>Personality, memory, and extensibility form the defining triad of future agentic systems that you&#x27;ll <em>want</em> to use:</p>
<ul>
<li>Personality: Comfortable, safe, and genuinely helpful across long-running exchanges and fleeting moments alike. It builds trust, maintains patience when things break, keeps people engaged over time, and even makes things fun when warranted.</li>
<li>Memory: For intimately understanding your preferences, retrieving past decisions, and helping proactively (or at least trying to) without overstepping or making assumptions. Memory is tricky to get right. When unexpected and done poorly it can fail hard and quickly erode trust. It&#x27;s not just RAG or long context. It&#x27;s selective context, memory, and reasoning working together.</li>
<li>Extensibility: What use would this all be if these systems couldn&#x27;t do things for you and integrate into your workflows and tools?</li>
</ul>
<p>It&#x27;s time to stop thinking about building these systems as a series of LEGO bricks to slap together.</p>
<h3>2026</h3>
<p>2025 was a lot of change compressed into twelve months—new job, new house, new daily habits. Most of it came down to getting rid of stuff, physically and mentally, that were getting in the way. Now I&#x27;m at Sesame working on problems I actually want to solve with people who care about the same things I do. This has been a lengthy article… a lot longer than I had originally planned. If you made it this far, <em>thank you</em> for reading.</p>
<hr/>
<p>While I&#x27;ve been religiously saving interesting links and articles for inspiration in Raindrop, one thing I&#x27;ve started doing in the last year is maintaining a single markdown file where I paste interesting design-related quotes and related things. I wanted to close this article with a few of those.</p>
<p>I always like to refer to old computer and operating system reference material and designs for inspiration. The creators of these systems started from what felt like a blank canvas, drawing on things like the desktop metaphor, to build what we have today. I try to get myself into the mindset they might have been in when thinking about the next generation of computing we&#x27;ll have with AI. Palm webOS is a great one too… I got a <a href="https://paulstamatiou.com/gear/palm-pixi-plus">Palm Pixi Plus</a> recently:</p>
<blockquote>A Tweet embed was not displayed. Read this article in a browser to see it as intended.</blockquote>
<blockquote>
<p>"People aren&#x27;t trying to <em>use computers</em>—they&#x27;re trying to get their jobs done."<br/>
—Apple, <a href="https://andymatuschak.org/files/papers/Apple%20Human%20Interface%20Guidelines%201987.pdf">Human Interface Guidelines: The Apple Desktop Interface (1987)</a></p>
</blockquote>
<p>On seeing things fresh and getting unstuck:</p>
<blockquote>
<p>"[…] looking closely at the micro level can unblock you for understanding the macro level. […] Pirsig&#x27;s Brick is a tool for seeing things freshly “without primary regard for what has been said before” which creates that perfect tension of challenge and ability enabling flow."<br/>
—Jordan Moore, <a href="https://jordanm.co.uk/2023/02/14/how-to-dismantle-a-creative-wall.html">How to Dismantle a Creative Wall</a></p>
</blockquote>
<blockquote>
<p>"But there&#x27;s a paradox at the heart of design that&#x27;s rarely discussed: the discipline that most profoundly determines how lasting and inspiring a work of design can be is a designer&#x27;s ability to look away — not just from their own work, but from other solutions, other possibilities, other designers&#x27; takes on similar problems. […]</p>
<p>The most innovative solutions often come from designers who are aware of conventions but not beholden to them. […]</p>
<p>This discipline of looking away preserves the singularity that makes great design resonant. When we constantly reference existing solutions, our work inevitably gravitates toward the mean. […]</p>
<p>This is perhaps the most difficult discipline in design — harder than mastering software, harder than learning color theory, harder than understanding grids and proportions. It requires confidence to trust your own vision when countless examples of "how it&#x27;s done" are just a search away. It demands the courage to pursue a direction that hasn&#x27;t been validated by others.<br/>
—Christopher Butler, <a href="https://www.chrbutler.com/good-design-comes-from-looking-great-design-comes-from-looking-away">Good Design Comes from Looking, Great Design Comes from Looking Away</a></p>
</blockquote>
<p>On design conviction:</p>
<blockquote>
<p>"There&#x27;s an important rule of prototyping: <strong>find the fun first and build from there</strong>. In all of your brainstorming, you need to determine what is actually fun to play. Sometimes a really complex or interesting system is compelling to plan out, codify, and parse as an algorithm… but then turns out to be lackluster to engage with. Keep moving. Find this fun as fast as possible, and don&#x27;t accept anything less. Your players won&#x27;t either."<br/>
—Andrew Zigler, <a href="https://www.andrewzigler.com/blog/mud-cookbook-design-meets-implementation/">MUD Cookbook: design meets implementation</a></p>
</blockquote>
<blockquote>
<p>"Conviction often stands in opposition to market trends. To have conviction before validation may make you seem weird or delusional, but it defines great artists—the ability to appreciate what others overlook or even fight against."<br/>
—Willem Van Lancker, <a href="https://vanlancker.substack.com/p/design-literacy">Design Literacy</a></p>
</blockquote>
<blockquote>
<p>"Hayden, you can&#x27;t change the world. It&#x27;s not possible. All you can do is try to make your own world and then invite other people to be a part of it."<br/>
—<a href="https://www.starwars.com/news/hayden-christensen-revenge-of-the-sith-20">George Lucas</a> to Hayden Christensen</p>
</blockquote>
<p>On soul:</p>
<blockquote>
<p>In its purest form, design is <em>poiesis</em>. It is drawing ideas from the ether. It&#x27;s a Muse.</p>
</blockquote>
<blockquote>
<p>"Beautifully designed products without soul, are just that: representational garden art. In all of our history, we&#x27;ve never had more money to design beautiful, functional and usable products. The bar is higher than ever, yet, they&#x27;ve never been more boring and devoid of soul."<br/>
—Steyn Viljoen, <a href="https://viljoen.space/writing/beautiful-boring-and-without-soul">Beautiful, boring, and without soul</a></p>
</blockquote>
<p>On software today, especially with this era of personalized software:</p>
<blockquote>
<p>"software isn&#x27;t just functional anymore. it&#x27;s quietly turned into a lifestyle brand, a digital prosthetic we use to signal who we are, or who we wish we were.[…] people don&#x27;t just use these apps. they use them to imagine themselves differently. more organized. more intentional. more in control. apps like superhuman or linear aren&#x27;t just tools, they&#x27;re lifestyle upgrades. software that feels like a reward. a signal that you care about your time, your taste."<br/>
—<a href="https://omeru.bearblog.dev/lifestyle/">you are what you launch: how software became a lifestyle brand</a></p>
</blockquote>
<blockquote>
<p>"We stopped doing the real thing that would be the most empathetic, useful, and that would actually serve business outcomes best: building stuff that worked well and that people would love."<br/>
—Jenny Wen, <a href="https://jennywen.ca/notes/dont-trust-the-design-process">Don&#x27;t trust the (design) process</a></p>
</blockquote>
<p>As for books, I did not read much at all in 2025 and really need to change that in 2026, similar to my <a href="https://paulstamatiou.com/reading-more-kindle-oasis">2017 goal of reading 24 books</a>. I&#x27;m currently reading <a href="https://amzn.to/4ppuSbL">The Soul of A New Machine</a> and <a href="https://amzn.to/3YoSgLF">The History of the Future: Oculus, Facebook, and the Revolution That Swept Virtual Reality</a>. I&#x27;ll probably find more from <a href="https://news.ycombinator.com/item?id=46345897">this list of books mentioned on Hacker News</a>.</p>
<br><br><br><hr><br><h3>Footnotes</h3><p><a href="#r1">1</a><!-- --> After 20 years, I finally got my G4 Mac Mini back. The person I sold it to reached out after noticing my gear pages where I&#x27;ve been collecting vintage gadgets and asked if I wanted my old Mac Mini back. I need to add it to my gear section. I have an old <!-- --><a href="https://paulstamatiou.com/gear/intel-mac-mini">Intel Mac Mini</a><!-- --> too.</p><p><a href="#r2">2</a><!-- --> I&#x27;ve been running this site for half my life. These days I mainly just try to keep my gear pages updated frequently, and then only focus on an article when I have some topic I want to go deep on, a perspective I think is unique and worth unpacking, or generally just something I want to nerd out on. That tends to mean about one longer article per year, which is fine with me. Work consumes a lot of my time and I&#x27;m passionate about designing and building great products.</p><p><a href="#r3">3</a><!-- --> Also, I&#x27;ve worked with too many people who use their past experiences as the primary input for a decision. That&#x27;s not only the wrong approach all too often, but it also makes everyone around them resent their unwillingness to consider new ideas and perspectives (or even just entirely different culture, values, quality, people).</p><p>Not to mention.. do you know how annoying it is to keep hearing, "When I was at [company], we did X."? I always, always try to catch myself when I&#x27;m about to say that about my time at Twitter or another past company.</p><p><a href="#r4">4</a><!-- --> Even with fresh daily contacts, they&#x27;re still nowhere near as comfortable as glasses on my eyes. Glasses are just easier and I&#x27;ve started collecting eyewear I really like, such as <!-- --><a href="https://paulstamatiou.com/gear/mr-leight-marmont-glasses">Mr. Leight</a><!-- --> and <!-- --><a href="https://paulstamatiou.com/gear/lindberg-now-titanium-glasses">Lindberg</a><!-- -->.</p><p><a href="#r5">5</a><!-- --> Not being emotional with investments like that and being quick to diversify is something I learned after being at Twitter for 9 years where the stock was performing pretty poorly most of the time. Whenever I&#x27;d vest new RSUs and have an open trading window I&#x27;d immediately sell them. The logic there was "if you had $X in cash right now, would you go out and buy Twitter stock?" The answer for me was usually no.</p><p><a href="#r6">6</a><!-- --> Mastodon didn&#x27;t quite pan out. I got really excited about the prospect of owning and hosting my own social media back when the Twitter exodus began in 2023… but it was never quite as active over there (same with Threads and Bluesky), and I still prefer Twitter/X.</p><p><a href="#r7">7</a><!-- --> I stopped the process with one company after meeting the CEO I would have worked with who lacked that energy. Instead, it felt like they sucked all the energy from the conversation.</p><p><a href="#r8">8</a><!-- --> 5-10 years ago it felt like there was a wave of designers that figured success was going on the management track early (after sometimes just 2 years as an IC) when on a large team and we had bloated teams with too many managers that slowly lost touch of craft over time. Now they&#x27;re having a hard time getting back into IC.</p><p>Similarly, designers that don&#x27;t do well with 0-1 design from scratch, for example without relying on existing design systems, will have a harder time operating on these smaller, craft-focused teams. AI tools today can&#x27;t help that much on the visual design side, and people lacking those foundational skills will need to find ways to adapt.</p><p><a href="#r9">9</a><!-- --> My 2.5 years endlessly designing, building, then redesigning and rebuilding every part of my app <!-- --><a href="https://paulstamatiou.com/stocketa">Stocketa</a><!-- --> prepared me well for sweating the front-end details. Lately I&#x27;ve also been touching some metal shaders as well.</p><p><a href="#r10">10</a><!-- --> We do, however, have quite a few hardware product designers and industrial designers.</p><p><a href="#r11">11</a><!-- --> The new problem is now when people ask for a specific Figma mock of something in the app; the latest version <em>is</em> in the app and it&#x27;s much more work to go back and update Figma mocks to be production accurate. Probably a product opportunity for Figma there.</p><p><a href="#r12">12</a><!-- --> Dan Hollick&#x27;s <em><a href="https://www.makingsoftware.com/chapters/shaders">Making Software</a></em> chapter about shaders is a great read.</p>]]></description>
            <link>https://paulstamatiou.com/2025-year-in-review</link>
            <guid isPermaLink="true">https://paulstamatiou.com/2025-year-in-review</guid>
            <dc:creator><![CDATA[Paul Stamatiou]]></dc:creator>
            <pubDate>Mon, 12 Jan 2026 16:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Browse No More]]></title>
            <description><![CDATA[<p><strong>I&#x27;m no longer browsing the web</strong>; I&#x27;m consuming AI answers instead.</p>
<p>I love and adore today&#x27;s so-called <em>AI answer engines</em>: tools like ChatGPT, Perplexity, Grok, Copilot, and Gemini. I use them at least a dozen times throughout the day, and I&#x27;m sure you use them frequently as well. Their convenience is undeniable.</p>
<p>I turn to these tools to save me some clicks, but I give up control for that convenience. What I gain in efficiency—no longer needing to browse through slow-loading ad-heavy websites just to find out how to tie a Windsor knot or grab a recipe—I lose in the personality, idiosyncrasy, and creativity that makes the web feel authentic. We&#x27;ve come to expect, seek, and rely on this.</p>
<p>Browsing with traditional search engines wasn&#x27;t exactly seamless but you were in the driver&#x27;s seat. You would occasionally end up on some obscure personal site or forum that was unexpectedly right up your alley.</p>
<p>Those magical detours defined our web experience, enriching us with insight and creativity while establishing human connections. Today&#x27;s instant answers with these AI tools sacrifice this beautiful chaos that once made the internet so captivating. But there&#x27;s hope—a new kind of browsing experience might just be around the corner.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2025/03/stammy-ai-answer-engines-3.webp" alt="AI answer engines - Copilot, Gemini, Perplexity, ChatGPT, Grok, Meta, Phind, You" width="8380" height="4752" />
<small>We&#x27;re increasingly experiencing the web like this.</small>
<p>Before we had AI answer engines, and before we had search engines we just had lists of links with web directories like aliweb, Yahoo! Directory and dmoz. You&#x27;d tediously wade through these directories to find and absorb content you were interested in, or just to explore and tinker. Everything online was created by people and you were getting a glimpse into their world with each site.</p>
<p>The web grew. We gained search engines, blogs, feed readers, social media and more. While there were new ways of creating content and new ways of consuming, when you really needed something you&#x27;d still turn to a search engine and click around until you found what you needed.</p>
<p>This led to inevitable moments of delightful and serendipitous discovery. There was real joy in discovering another unique voice online, someone whose articles and interests were right up your alley. Their style of writing lended itself to being devoured in one sitting, while you scan their site to see how you can bookmark or subscribe to keep tabs on their latest works.</p>
<p>It wasn&#x27;t just about stumbling upon a random personal blog that was a fun occasion. It was finding communities you didn&#x27;t know existed. Even just recently as I&#x27;ve been <a href="https://x.com/Stammy/status/1878265690643407233">upgrading my iMac G3</a> and running into some issues, I came across a forum for Mac OS 9 enthusiasts that was chockfull of the exact type of content I was looking for. It was not easy finding it. It didn&#x27;t happen in one sitting, or with one tool and ended up being something I caught in passing that someone said in a video on a blog. But the payoff was worth it for that moment.</p>
<p>Serendipity while browsing the web wasn&#x27;t just a byproduct of how the web began to form. It stretched our empathy by exposing us to diverse voices, nudged us out of echo chambers, and kept our web from becoming monotonous.</p>
<p><strong>That style of surfing the web is fading away.</strong> What social media hasn&#x27;t already taken over, or search engines haven&#x27;t already diluted by sending us to ad-laden mainstream sites, is now steadily being eroded by AI-powered answer engines.</p>
<p>AI answer engines are phenomenal in what they do. I can fire off a prompt and relatively quickly get a blurb with the exact information I need. It really can&#x27;t be overstated how great they are.</p>
<p>But I&#x27;ve lost something profound in the process—the <strong>joy of the unexpected detour</strong>. <strong>I&#x27;m not really browsing the web anymore</strong>. At best, <strong>I&#x27;m just browsing AI interpretations of a limited slice of the web.</strong> A slice that I didn&#x27;t even pick or have control over. My surface area for discovery is now whatever these tools decide to show me.</p>
<p>It&#x27;s not just me. Traditional search engines are evolving into answer engines. Zero-click searches are rising and will continue to rise. <a href="https://searchenginewatch.com/p/seo-in-a-zero-click-world">Nearly 60% of Google searches</a> now end without the user clicking to any site. And now Google is experimenting with "<a href="https://blog.google/products/search/ai-mode-search/">AI mode</a>"<sup><a rel="footnote" href="#footnote-1" id="r1">1</a></sup> to take this to the next level.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2025/03/stammy-google-ai-sge.webp" alt="Traditional search engines are becoming answer engines. Google&#x27;s prominent Search Generative Experience (SGE) and its focal CTA to show more" width="2438" height="1682" />
<small>Traditional search engines are becoming answer engines. Google&#x27;s prominent Search Generative Experience (SGE) and it&#x27;s focal CTA to show more. I love <!-- --><a href="https://paulstamatiou.com/gear/oura-ring/">my Oura ring</a><!-- --> for what it&#x27;s worth.</small>
<h3>Core issues</h3>
<h3>Is this really a problem?</h3>
<p>This is just another classic example of technology evolving. Who cares if it&#x27;s a bit harder to find some smaller websites? I see a few issues at play here, and it extends beyond just web browsing. At a high level, these AI answer engines lack transparency in how they work, remove control, and homogenize what&#x27;s left, sucking all vibrancy out of what makes the web special.</p>
<ul>
<li>
<p><strong>1) Deprioritized attribution</strong></p>
<p>These tools largely show sources as a tiny footnote link. As an industry we started using that design pattern to link to receipts to prove the LLM was not hallucinating. We need to highlight great content when it&#x27;s most relevant, not bury it with a link and a little generic hovercard or popover.</p>
</li>
<li>
<p><strong>2) The black box of search</strong></p>
<p>How do these tools index and rank the web? How do they decide what content is most relevant to a given question or user? They largely prioritize mainstream sources. How do they interpret your question and turn it into keywords to search their bespoke web index? How do they know when they&#x27;ve retrieved enough info? We lost the agency over these things we had  with search engines.</p>
</li>
<li>
<p><strong>3) Summary homogenization and mode collapse</strong></p>
<p>Even with access to diverse web sources, responses from these tools can feel a bit... off. Fine for when you&#x27;re only looking to fetch basic facts, but limiting and less vibrant for anything else. <strong>It&#x27;s like having access to every book in the world, but only being able to read them summarized by the same person with the same writing style.</strong></p>
</li>
</ul>
<h3>1) Deprioritized attribution</h3>
<p>The way these AI answer engines approach attribution leaves a lot to be desired. The early days of LLMs were especially riddled with hallucinations. The industry began using tiny numeric footnote citations to show that they had the receipts and there was actual data behind each sentence. I even did the same (albeit showing screenshot thumbnails too) when designing and building <a href="https://x.com/Stammy/status/1643659759122518018">this feature</a>.</p>
<p>In addition, these tools try to impress upon us that they are mighty and have referenced some huge number of webpages while coming up with each response. They display this information as a pile of favicons or list of sources, with no easy way to understand why they were included or how they were used. You&#x27;re not meant to wade through it, nor should you have to.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2025/03/stammy-answer-engine-attribution-4.webp" alt="AI answer engines showing web source attribution with inline citations, hover cards and more" width="3052" height="1844" />
<small>Web source attribution shown on these tools with inline citations, source bars, and hover cards.</small>
<p>Each source receives roughly the same visual representation with these tools. There&#x27;s no transparency if it&#x27;s from a reputable mainstream news site, a single author that&#x27;s a domain expert given their past works, or a site you&#x27;ve frequented before. At most you&#x27;ll get an expanded card or sidebar showing more the favicon, domain name, article title along with truncated content.</p>
<p>Some tools do it better than others, including the domain name as the citation instead of a number, or listing a few sources in the footnotes. But that still doesn&#x27;t tell me much about the site, author, why this particular source was selected, and how its content was used. There&#x27;s lots of signals that can be used to help guide understanding here.</p>
<p>It would also be interesting to also consider LLMs employing a system similar to X&#x27;s Community Notes (née <a href="https://en.wikipedia.org/wiki/Community_Notes">Birdwatch</a> when I worked at Twitter) to clarify the context of and add perspective of web sources. For example, a source might seem upstanding but then you discover a whole Hacker News thread explaining in detail why it&#x27;s not accurate.<sup><a rel="footnote" href="#footnote-2" id="r2">2</a></sup></p>
<p>And finally, if you take a particularly dystopian view it&#x27;s not hard to see potential second order effects of these tools with their deprioritized attribution. Perhaps authors will begin focusing on their own empires, where they have control over how their content is seen and monetized—such as moving it to private newsletters, away from the prying eyes of LLMs. AI companies may license data from bigger sites that do this, but definitely not your personal blog or sites on <a href="https://blog.kagi.com/small-web">the small web</a>.</p>
<p>Better or more prominent attribution isn&#x27;t the solution to everything. It&#x27;s a way of framing content to reflecting a broader range of perspectives, and elevating enough signals to allow the reader to understand what they&#x27;re presented and why. Simply sampling the top X keyword results on a topic isn&#x27;t enough to do this or reduce the echo chamber feeling; you also need greater control, understanding, and transparency in the search process.</p>
<h3>2) The AI search black box</h3>
<p>We also face lack of transparency regarding how these tools search the web to gather and process information needed to answer your questions. There is the potential for search and ranking bias, or lack of clarity at the least. Questions like "How are they creating their search indexes?", "What do they value when ranking sites?", and "How do they select a set of web results for user queries?" get elevated.</p>
<p>AI answer engines make countless hidden decisions about what sources matter and what information is relevant—all without your input or awareness. <strong>You get the illusion of comprehensiveness</strong>, when in reality you&#x27;re getting a narrow slice of available information filtered for you.</p>
<p>These tools each have their own way of searching the web. Some may lean on third-party search indexes like Bing (ChatGPT) or X/Brave Search (Grok) but conduct their own crawling and ranking, while others handle everything independently. You&#x27;ve probably become fairly accustomed to how results feel in Google or DuckDuckGo, and you have a good grasp of how to wrangle them to find what you&#x27;re looking for.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2025/03/stammy-ai-sources-details.webp" alt="" width="2950" height="1670" />
<small>Expanded web sources shown in Grok, Perplexity, and ChatGPT. All lack context about what kinds of sites these are, why they were selected, and how they were used.</small>
<p>Now we&#x27;re dealing with a new system entirely, but this time you&#x27;re disarmed—<strong>you&#x27;ve lost your agency</strong> to fiddle with keywords, endlessly navigate pages, decide when to try a new query because one wasn&#x27;t fruitful, and so on. Of course, you can always ask the AI answer engines a different question or provide a follow-up, but you still lack control over how they&#x27;re translating your prompt into an index search.</p>
<p>Perplexity, for example, tries to provide greater transparency when doing a Pro search by showing the exact keywords they used to search their web index. However, I find this approach gives me even <em>less confidence</em> in what it was doing. Customers approach these tools thinking they are all-knowing AI supercomputers... and then see their thoughtfully-posed question get dumbed down to a 4 word search? I have no control over that process nor when it decides to keep searching.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2025/03/stammy-perplexity-pro-search-expanded.webp" alt="Perplexity Pro search with expanded status showing search details" width="2684" height="2000" />
<small>Perplexity Pro search showing different keywords used for a web search based on the question.<br/><br/>This screenshot also perfectly illustrates the core problem. The entire Internet has been talking about <!-- --><a href="https://daringfireball.net/2025/03/something_is_rotten_in_the_state_of_cupertino">Gruber&#x27;s post about Apple Intelligence</a><!-- -->, that should have been included as a source but I have no clarity into how it ranked, searched, and selected these mostly mainstream sources.</small>
<p>What that type of UI does accomplish well is the job of communicating progress successfully during a long-running task. Even more intricate UIs exist, such as those from ChatGPT, Perplexity, Gemini, and Grok for <em>deep research</em><sup><a rel="footnote" href="#footnote-3" id="r3">3</a></sup> tasks that providing a peek into CoT reasoning.
ChatGPT&#x27;s deep research does do one novel thing when presenting sources though, it shows a tiny snippet of <em>how</em> that result was used.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2025/03/stammy-chatgpt-deep-research-sources-description.webp" alt="ChatGPT&#x27;s deep research starts to add a bit of context about what a source was used for: a welcome step in the right direction." width="2266" height="1768" />
<small>ChatGPT&#x27;s deep research starts to add a bit of context about what a source was used for: a welcome step in the right direction.</small>
<p>There&#x27;s also risk on the other side of it: letting users assume that the response they get is the truth. Maybe the cursory web search the answer engine did behind the scenes wasn&#x27;t thorough enough? This is especially the case when dealing with niche topics. (Grok does the absolute worst here: for niche topics it won&#x27;t reference <em>any</em> websites at all!) You&#x27;ve really got to scour the web to find what you need. If these tools are just a few keyword searches in their search index, that won&#x27;t cut it. They don&#x27;t know when to keep searching or ask for further clarification.</p>
<p>I realize that having to fiddle with search engines, while it can be seen as a control, can also be a nuisance at times. I&#x27;m not trying to be too dismissive here.</p>
<p>The huge benefit I&#x27;m flying past is that LLMs do a pretty solid job of understanding your intent and nuance—a crucial trait, given that most people still struggle to write great questions. Though I also think we should do more to guide people here; Elicit does a <a href="https://x.com/Stammy/status/1892615079302209727">nice job with this UI</a> to suggest different ways to ask precise questions.</p>
<video controls="true" poster="">
      
      <source src="https://turbo.paulstamatiou.com/uploads/2025/03/elicit-ask-question-ui.mp4" type="video/mp4">
      Your browser does not support the video tag.
    </video>
<small>Research tool Elicit helps its users determine if their question is strong enough and suggests ways to improve.</small>
<p>We deserve so much more here. If AI tools understand our intent so well, they should deliver much more natural, interesting, and diverse results that feel indistinguishable from having a panel of experts at your side.</p>
<h3>3) Summary homogenization and mode collapse</h3>
<p>You know the feeling. AI-generated content often doesn&#x27;t <em>feel</em> great. It feels slightly off; vaguely mechanical, even predictable. LLMs are largely consensus machines. In the pursuit of zero bias, you end up systematically smoothing out any novel perspectives or viewpoints introduced through these already not-too-diverse web sources used as context.</p>
<p>This feeling where models lose their creativity after post-training is often called <a href="https://gwern.net/doc/reinforcement-learning/preference-learning/mode-collapse/index">mode collapse</a>. Its makes LLMs particularly unsuitable for tasks like creative writing. Sudowrite, an AI writing tool, specifically addressed this problem of "AI-isms" when <a href="https://x.com/superamit/status/1897757915051966875">announcing their new writing model</a>. And just recently, OpenAI mentioned they&#x27;re working on a <a href="https://x.com/sama/status/1899535387435086115">model made for creative writing</a>.<sup><a rel="footnote" href="#footnote-4" id="r4">4</a></sup></p>
<p><strong>When you try to please everyone, you wow no one.</strong></p>
<p>The <a href="https://x.com/benhylak/status/1891421918479184100?s=46&t=AgMC5vUAQsda9BGeY3pppw">way we build and train LLMs</a> has led us to this. I could keep going down the rabbit hole and discuss the need for LLMs to get better at <em>creativity</em>. This is another thing you feel, even if you can&#x27;t quite put your finger on it.</p>
<p>People could tell <a href="https://x.com/sjwhitmore/status/1894294114511790270">when Sonnet 3.7 felt a bit worse than 3.5</a>. They were impressed when <a href="https://x.com/localghost/status/1895394522726813847">GPT 4.5 could do more</a> despite <a href="https://x.com/sjwhitmore/status/1895546829607203159">not being a benchmark-killing model</a>. I&#x27;ve definitely noticed this with 4.5 and have been <a href="https://x.com/Stammy/status/1887951663098642662">putting my Pro subscription to use</a>.  I just wish we as an industry cared as much about <a href="https://gwern.net/creative-benchmark">this side of LLMs</a> as we did with coding and reasoning capabilities.</p>
<p>Even with the right web sources, there&#x27;s little insight into how AI answer engines use the content of each web source when generating their answers. Similar to the potential for search bias, we lack insight into how each web source is weighed and what other signals are used for determining what to incorporate in responses. <strong>Without intentional guidance, LLMs naturally lean toward averaging rather than amplifying unique, minority, or particularly insightful viewpoints.</strong></p>
<p>Okay, maybe we&#x27;re onto something here. But where does that intentional guidance come from?</p>
<h3>Intentional personalization</h3>
<h3>Tools that grow with you. Tools that understand you.</h3>
<p>Today&#x27;s AI answer engines face fundamental challenges that go beyond the feeling of nostalgia for the old web, surfacing some bespoke notion about serendipitous discovery, or wanting more indie content bubbled up. The real issues—weak attribution, black-box decision-making, and homogenized responses—threaten to flatten rather than enrich how we use the web. Browsing the web isn&#x27;t and shouldn&#x27;t be a one size fits all experience.</p>
<p>The current generation of AI tools faces a prodigious challenge: <strong>how can they surprise and delight you when they know almost nothing about you?</strong></p>
<p>The solution isn&#x27;t overwhelming people with more controls, endless configuration opportunities, or exceedingly prominent website cards and attribution. People are confused enough as is selecting the model to use, or having to choose between needing a web search, a pro search, or a deep search, et cetera.</p>
<h3>What personalization really means</h3>
<p>These tools need to be more personalized to you and tailored to your needs. I know, I know... the term <em>personalization</em> gets tossed around a lot for countless uses—often carrying negative connotations, conjuring images of invasive ad targeting. But there&#x27;s a better way.</p>
<p><strong>AI personalization doesn&#x27;t have to be about consuming every detail of your life or cloning yourself.</strong> We&#x27;ve fended off giving too much personal data to individual companies, why start now? You don&#x27;t need to be digitally cloned to help you throughout your day. Even a little bit of info about your past interactions, goals, and interests can go a long way to delivering experiences that resonate more deeply with you.</p>
<h3>A better way</h3>
<p>This might come as a shock but I don&#x27;t believe we want to embody some magical "it just works" scenario with personalized AI where these tools know <em>everything</em> about you, build some comprehensive understanding or model of you, and act as you. I believe a more intentional, transparent approach would serve us better, for several critical reasons:</p>
<ul>
<li><strong>Behavior ≠ intent:</strong> What I do on my computer, phone, or browser is not always what I want to do or who I want to be. That can be a moving target. Just because one user ends up seeing and reading a lot about pop culture news doesn&#x27;t mean they&#x27;re not more interested in reading about another topic they&#x27;re having trouble discovering. This is why it&#x27;s not as easy as just sucking in as much raw data from the user as possible.</li>
<li><strong>Context matters:</strong> Your needs and motivations can change quickly. They can be based on time, location, task, who you&#x27;re with, and more. You might be focused on a particular project and don&#x27;t want personalization to be influenced by what you do at other times. I like to think about this akin to having different profiles in your browser. When researching a specific industry or topic for work, I don&#x27;t want my personal interests bleeding into my results, and vice versa. This goes much deeper than just a work and home separation.</li>
<li><strong>Transparency is non-negotiable:</strong> Users deserve clarity about how their data shapes their experience. This means showing when personalization is active and providing intuitive controls. Even something as small as highlighting a blurb you enjoyed, requesting more depth on topics of interest, or correcting AI assumptions about your knowledge level.</li>
</ul>
<p>Providing users transparency and control in tweaking how AI interprets them is critical to seeing, reinforcing, and correcting assumptions as they go. We need to invest in exploring some of these things as an industry. These tools are remarkably complex and we can&#x27;t hope to nail it on the first try without some light user guidance along the way.</p>
<p>I&#x27;m okay doing a bit of work as an end user to shape my experience; and this doesn&#x27;t just have to be a text response. As a random example, imagine a simplified interest graph representing how the AI understands you, where you prune irrelevant nodes, amplify important ones, and add entirely new focus areas that the system may have missed.</p>
<p>This isn&#x27;t an entirely new concept, I think we&#x27;re just so focused on increasingly more capable foundational models and discrete skills like reasoning that we&#x27;re not quite at the point of going broad enough for things like this. OpenAI has inched in this direction in the past with its <a href="https://openai.com/index/memory-and-new-controls-for-chatgpt/">Memory</a> and <a href="https://help.openai.com/en/articles/8096356-custom-instructions-for-chatgpt">Custom Instructions & Traits</a> features.<sup><a rel="footnote" href="#footnote-5" id="r5">5</a></sup></p>
<img src="https://turbo.paulstamatiou.com/uploads/2025/03/chatgpt-memories-traits.png" alt="ChatGPT&#x27;s take on personalization with Memory, Custom Instructions, and Traits" width="2500" height="2344" />
<small>ChatGPT&#x27;s first steps towards personalization with Memory and Custom Instructions</small>
<p>These current implementations don&#x27;t yet fulfill the capabilities I&#x27;ve outlined here. For example, it&#x27;s unclear how ChatGPT decides to save memories, as they often seem to sporadic while also too specific. Additionally, custom instructions are great for high-level information about you, but things like traits feel more task and prompt-specific; not necessarily something I&#x27;d always want at the account level.</p>
<h3>Personalizing without overreaching</h3>
<p>Okay so providing users some control to tweak as they go is all fine... but what kind of source data are we talking about here?</p>
<p>Controlling the OS or the browser are the most powerful positions to be in. While it&#x27;s hard for most large companies to even think about competing at the OS level, several have begun to compete with browsers: The Browser Company and Perplexity have already announced working on new AI browsers. Maybe OpenAI will enter the arena too.</p>
<p>Even basic browsing data offers powerful personalization potential. What content did you engage with deeply versus merely glance at? What did you create versus consume? Which topics consistently draw your attention over time? These patterns reveal far more than explicit preferences ever could.</p>
<p>There&#x27;s a lot more to talk about when it comes to data capture here—from OS file access to accessing more detailed info from messaging apps, connecting to various cloud providers (email, docs, bookmarks), or even just knowing what apps someone is using or has installed while accomplishing a task. Some of those can be considerably harder integrations to justify with the additional privacy questions they raise.</p>
<p>I&#x27;m already on a bit of a tangent here, but I think the best route, barring inventing your own OS or browser that magically gets massive market adoption, is diving deeper into task-based routes of asking for, clarifying, and showing how context is used (touched on in <a href="#a-better-way">[object Object]</a>). It won&#x27;t be easy though. You&#x27;ll need to build systems for storing and querying these preferences with each LLM interaction. You won&#x27;t want to just inject a ton of this as context with every call.</p>
<p>The key is balancing intentional personalization with user agency.</p>
<h3>Why does personalization matter again?</h3>
<p>Even with light personalization, AI answer engines could meaningfully tailor their responses to you. They would know you&#x27;re very technical and experienced with the topic at hand to skip the basics and dive deeper into technical concepts. They would know you&#x27;ve been writing about technology for 20 years and really enjoy the underlying ways things work and always want that deeper understanding. And so many other things that might seem like minute details at first, but combined really add up.</p>
<p>They could know enough about you, your past interactions, interests and goals to guide you without overstepping, respecting your time and intelligence. A thoughtfully personalized system would:</p>
<ul>
<li><strong>Connect the dots:</strong> Help connect new concepts and topics to previous ones you&#x27;ve read about as a frame of reference.</li>
<li><strong>Identify and manage echo chambers:</strong> Help you peek outside the echo chamber by surfacing novel perspectives.</li>
<li><strong>Leverage trusted sources:</strong> Help you learn from web sources you&#x27;re already familiar with, while balancing new perspectives you may desire.</li>
<li><strong>Anticipate needs:</strong> Proactively suggest content you may be looking for before you&#x27;ve had to ask, in addition to doing tasks for you (The agentic aspect of this type of personalization could warrant an article of its own.)</li>
</ul>
<p>Technology that knows you, even loosely, and helps you out in these ways isn&#x27;t a particularly novel concept, but we can&#x27;t lose sight of it as we design, iterate, and build these AI tools we all use.</p>
<h3>Preserving the web&#x27;s magic</h3>
<p>Don&#x27;t get me wrong, I love these tools. ChatGPT, Perplexity, Gemini, Grok, and others have earned their place in my daily workflow, largely displacing my use of traditional search engines.Yet without thoughtful evolution, they risk homogenizing and muting the web&#x27;s rich diversity into bland, generic responses—eliminating what made the internet magical to begin with.</p>
<p>The large companies behind these tools have every incentive to develop deeper, more nuanced understandings of their users. In recent months, we&#x27;ve seen firsthand that these companies don&#x27;t have much of a moat. Switching costs for users are as low as can be: just head to the App Store and pick up the next AI tool topping the charts. We saw it with DeepSeek one week and Grok another.</p>
<p>By adding more intentional personalization to their products, these companies will not only grow their moat and deliver more impactful, tailored answers but also embrace and highlight the web&#x27;s unique voices and perspectives.</p>
<p>Will it help them directly achieve AGI? Maybe not. But it might start to <em>feel</em> like AGI sooner when these tools are more personalized.</p>
<p>This requires inching towards intentional personalization with refined AI product functionality, greater transparency about how these systems make decisions or apply personalization, and intuitive controls to let users guide their experience without becoming overwhelmed. We can augment human curiosity and creativity rather than replace it.</p>
<p>The magic of browsing the web isn&#x27;t quite gone, but it&#x27;s waiting to be reinvented.</p>
<br><br><br><hr><br><h3>Footnotes</h3><p><a href="#r1">1</a><!-- --> It&#x27;s always interesting to see how companies market their AI capabilities. Some really try to downplay AI and make it more about the opportunity, not the technology. Perplexity has more humanizing taglines like "Where knowledge begins", Grok has "Understand the universe", and OpenAI is rather utilitarian with ChatGPT just focusing on uses it can do without a specific tagline (of course OpenAI itself is all about safe and beneficial AGI), and then Google does the opposite and just calls it... "AI mode".</p><p><a href="#r2">2</a><!-- --> I know that is a bit crazy to consider; imagine just visiting a site today and your browser tells you this site is not accurate or has some other editorial issue with the content. That&#x27;s not the job of a browser or other foundational technology, right? The difference here is that people did not seek this content out themselves, and they don&#x27;t know what they&#x27;re looking at or have all the tools available to decide on their own at a glance. The AI answer engine dug that all up on its own, so it&#x27;s critical to provide as much info as possible to help people be informed about what they&#x27;re consuming. You can&#x27;t just put a disclaimer at the bottom saying AI can make mistakes and move on.</p><p><a href="#r3">3</a><!-- --> With every AI company coming out with roughly the same features it&#x27;s starting to get a bit noisy with all the different modes, let alone models, to use to accomplish your task. That&#x27;s another problem entirely, but I&#x27;m not here to talk about that. <strong>I just want to say how amazed I was the first time I used ChatGPT Deep Research.</strong> I forked over the $200/mon for the Pro subscription (and I&#x27;m still paying for it the next month) and give it a whirl.</p><p>It&#x27;s remarkable how comprehensive it is with just about any prompt. It asks you for feedback before it dives in so you can steer it a bit more which is nice, though the UI for that could be easier than having to reply in a single textarea to a bunch of bullets/questions. ChatGPT Deep Research is the type of thing that gets me really excited about the evolution of these AI tools. They materially save me time and help me go deeper on things that interest me, like learning about topics thoroughly.</p><p><a href="#r4">4</a><!-- --> There was <!-- --><a href="https://x.com/Srirachachau/status/1899591681802227889">a whole bunch of discourse</a><!-- --> about this on X, particularly around whether people even want to read stories made by AI. I think we&#x27;re jumping too far to one end of the spectrum where AI is writing everything. As a writer, I want an LLM that can act as a thought partner. I will provide the ideas, outlines, drafts and I want something to act as an editor, devil&#x27;s advocate, and mentor all in one. For that role it&#x27;s key that these tools can actually write well too, not just code, execute python scripts for complex math, and help with reasoning. The way they communicate is critical too. I&#x27;m not just thinking about it for writing articles. I want this for helping me frame documents like persuasive product briefs I write, et cetera.</p><p><a href="#r5">5</a><!-- --> Another sign that OpenAI is thinking about personalization was spotted in <!-- --><a href="https://x.com/OpenAIDevs/status/1899531367056064814">their recent announcement</a><!-- --> for the new Responses API. They showed a brief example use case for the <code>file_search</code>  tool to gather user preferences for an agentic task. The exact implementation was left up to the API consumer in that example of course. While this article is generally about AI answer engines and the web, personalization like this will be especially important for agents.</p><br/><p><strong>The title of this article</strong> is a reference to an immersive theater work called <!-- --><a href="https://en.wikipedia.org/wiki/Sleep_No_More_(2011_play)">Sleep No More</a><!-- --> I saw in NYC a few years ago. It tells the story of Macbeth and there&#x27;s some interesting parallels I&#x27;m drawing on from this article. For one, loss of agency. When you visit you&#x27;re immersed in an environment where you feel like you lose control (similar to what AI answer engines feel like they&#x27;re doing today). You&#x27;re a spectator wandering around while confusing things happen around you.</p>]]></description>
            <link>https://paulstamatiou.com/browse-no-more</link>
            <guid isPermaLink="true">https://paulstamatiou.com/browse-no-more</guid>
            <dc:creator><![CDATA[Paul Stamatiou]]></dc:creator>
            <pubDate>Thu, 13 Mar 2025 16:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[The Startup Designer]]></title>
            <description><![CDATA[<p>There&#x27;s nothing glamorous about being a designer at a startup. It&#x27;s a role that frequently values speed and pragmatism over going <a href="https://paulstamatiou.com/craft">deep in the craft</a>. It&#x27;s not all big launches, viral tweets, building for happy paths, and clear-cut product requirements.</p>
<p>However, it can be incredibly rewarding. The fun comes from being able to excel at learning new skills and wearing many different hats while being solely responsible for large efforts.</p>
<img src="https://paulstamatiou.com/media/2024/starcraft.jpg" alt="Starcraft" />
<small>The "Fog of War" in StarCraft hides areas that have yet to be explored.</small>
<ul>
<li>
<p>The startup designer&#x27;s greatest strength is their speed and versatility. It&#x27;s the light aiding in the search for product-market fit as resourcefully as possible.</p>
</li>
<li>
<p>The startup designer is <a href="https://twitter.com/Stammy/status/1563886808546611202">part artist, part scientist</a>. The scientist views product design as something to be tamed with rules, systems, and principles; a thorough optimizer. The artist is aware of some of those rules but often chooses their own path. The artist runs by feel, and is known to always detach components. One crafts a system that helps with consistency, accessibility and scaling; the other continually challenges it and provides the friction needed to improve it.</p>
</li>
<li>
<p>The startup designer can survive—and thrive—without relying on a design system. They can go from a blank canvas for a new homepage or landing page design and bring it to life in a way that embraces the brand and marketing strategy.</p>
</li>
<li>
<p>The startup designer is <a href="https://paulgraham.com/relres.html">relentlessly resourceful</a>, and embraces any task, even the mundane, unfamiliar, or gargantuan. Helping with company swag, brand design, icon design, packaging print design, use case landing pages, et cetera. There are a few exceptions where outsourcing makes sense, but most of the time there&#x27;s not enough time to find a contractor, onboard them, ramp them up on project context, and guide them through iterations.</p>
</li>
<li>
<p>The startup designer knows where to compromise on quality, when to push for it hard, and how to advocate for it beyond intuition, armed with customer feedback, insights, and company goals.</p>
</li>
<li>
<p>The startup designer perpetually exhibits strong ownership and knows what to work on. Their priorities come up naturally from working closely with the team and seeing what users are running into. They know the right fidelity, speed, and urgency for each task.</p>
</li>
<li>
<p>The startup designer embraces ambiguity and is naturally optimistic. The cards are already stacked against every early stage startup. The team needs to be crazy enough to see through it all and envision the future they&#x27;re building and convincing others of. When there are inevitable moments of uncertainty—with a feature, with the entire product, with a company pivot—the startup designer takes action to find clarity, gather data, and explore alternate solutions. <a href="https://twitter.com/JamesClear/status/1795843808963248316">The pessimist criticizes, the optimist creates.</a></p>
</li>
<li>
<p>The startup designer balances their desire for craft and extremely high-quality shipped products with the pre-PMF startup&#x27;s need to prioritize shots on goal. The faster you&#x27;re able to ship (and nurture what is shipped), the more shots you can take, and the more likely you&#x27;ll reach product-market fit. There are times when spending an extra week or two ironing things out and polishing matters, but most of the time it&#x27;s hard to make that ROI math work. This compromise is one of the harder parts of the job.</p>
</li>
<li>
<p>The startup designer doesn&#x27;t try to predict designs needed for future versions of a feature that hasn&#x27;t been built yet. They do enough design due diligence to make sure it works reasonably well for the near-term, then move on. Chances are that feature won&#x27;t live long or work out anyways. And if it does well, it&#x27;ll probably be redesigned and rebuilt based on new information.</p>
</li>
<li>
<p>The startup designer fully separates themselves from the work. There is no time for ego. There will be hard feedback at every turn: from the team, from the customers. Everything worked on is the result of countless iterations. There&#x27;s no point getting worked over a design that probably won&#x27;t matter in the long run, or even next week when they&#x27;re focused on something else.</p>
</li>
<li>
<p>The startup designer is pragmatic. They know they can&#x27;t refine everything to perfection before it gets shipped, and that not everything will ship. But they know when it&#x27;s worth advocating for a bit more quality and rigor.</p>
</li>
<li>
<p>The startup designer has a natural urge to thoroughly explore designs for any task. Even with a minor visual design task, the startup designer knows the power of continuining to explore iterations and alternate designs. Sometimes the best design is Frame 1, sometimes it&#x27;s Frame 37.</p>
</li>
<li>
<p>The startup designer knows that even unshipped designs provide value. These designs can show the team what&#x27;s possible for the future vision. They can prove a certain direction isn&#x27;t worth investing in. They can show why another design is a better choice. Some of the startup designer&#x27;s best design work will go unshipped and they know that&#x27;s okay.</p>
</li>
<li>
<p>The startup designer is vocal. About product direction and requirements. About technical issues affecting users. About marketing and storytelling. About branding. About prioritizing issues. Not only about their own thoughts, but also about the customers&#x27; thoughts.</p>
</li>
<li>
<p>The startup designer asks a lot of the same questions to drive toward simplicity. Is X even needed? How can we remove this step? Is this actually a problem? Why can&#x27;t X and Y be the same thing? There&#x27;s a myriad of basic foundational questions like this for any set of designs that can help frame the challenges in a new light.</p>
</li>
<li>
<p>The startup designer never simply hands off designs. They care too much to treat them like finished objects to be lobbed over a fence. They document the basics but know there is no substitute for working closely with the team to build it together. New information, such as technical constraints, edge cases, and forgotten error states, always bubbles up while building, and the startup designer is there to help, often jumping into the code.</p>
</li>
<li>
<p>The startup designer is technical. Not just to prototype ideas, help build features or add polish, but also to intimately understand technical constraints of the product which helps them with design exploration.</p>
</li>
<li>
<p>The startup designer knows that new ideas need to be protected and nurtured to be able to have a chance at growing. They will set context with stakeholders, share exploratory visuals or <a href="https://twitter.com/Stammy/status/1364261677898870785">docs</a>, and continually find ways to evangelize.</p>
</li>
<li>
<p>The startup designer talks to customers directly, shares concepts and synthesizes feedback. They tell everyone about <a href="https://www.amazon.com/Mom-Test-customers-business-everyone-ebook/dp/B01H4G2J1U?&linkCode=ll1&tag=paulstamatiou-20&linkId=7bc55d1068cf621d14b3a6bbbe8f98f4&language=en_US&ref_=as_li_ss_tl">The Mom Test</a>.</p>
</li>
<li>
<p>The startup designer knows what altitude to operate at. One feature might require a few optimizations via incremental design, while another may deserve taking a step back and rethinking the entire foundation or direction.</p>
</li>
</ul>
<p>The startup designer may not know to do all these things on Day 1, but learns over time.</p>]]></description>
            <link>https://paulstamatiou.com/the-startup-designer</link>
            <guid isPermaLink="true">https://paulstamatiou.com/the-startup-designer</guid>
            <dc:creator><![CDATA[Paul Stamatiou]]></dc:creator>
            <pubDate>Tue, 27 Aug 2024 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Stocketa]]></title>
            <description><![CDATA[<div>Please read <a href="https://paulstamatiou.com/stocketa/" title="Stocketa">this Stocketa article</a> in a browser to see embedded Stocketa videos.</div>
<p>It was March 2020, I was in New England when covid quarantine had just begun and I found myself much more homebound. In these situations I&#x27;m not one to just do nothing. I always have some sort of project or hobby to keep me busy, be it taking and editing photos, writing detailed blog posts, or coding something.</p>
<p>I had always wanted to learn iOS development, so this felt like the perfect opportunity. I was particularly keen to learn SwiftUI to build my designs natively. Years back I had dabbled with writing an Objective-C app, but it never quite filled me with joy, to say the least. As a designer, I&#x27;ve spent the last decade getting good with prototyping tools and frameworks to mimic realistic, interactive mobile prototypes. Building it myself was the natural next step to give me even more control over the experience, and <a href="https://paulstamatiou.com/craft/">get even deeper into the craft.</a></p>
<p>I started learning Swift and SwiftUI basics with courses like Design+Code, and Hacking with Swift. But I knew myself—I learn best with a project of my own. I knew exactly what I wanted to build: a better stock portfolio tracker. The stock market had taken a plunge with covid and I was doing dozens of trades per week with everything on sale. It would be fun to have a simple app of my own to track the performance of my trades instead of dealing with the subpar sites and apps from my stockbrokers.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-stocketa-phone.webp" alt="Stocketa app" width="3442" height="2754" />
<p>Little did I know this project would consume my nights and weekends for over two years, often spending 10-20 hours a week on it. I built a ton of functionality, sweat all the details, wrote a comprehensive node backend for it, created an LLC for it, and managed an active Testflight. I was learning Swift and SwiftUI along the way, so I was often redesigning and rebuilding as I went.</p>
<p>Eventually, I decided to stop pursuing it. I&#x27;ll get into the why a bit later. <strong>This post is for me to document <a href="https://stocketa.com">Stocketa</a>.</strong> I designed and built a lot that I&#x27;m proud of and want to have somewhere to archive it before I pull the plug.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-stocketa-app-store.webp" alt="10 images that would have been used for the Stocketa App Store screenshots if Stocketa had been published" width="3233" height="2720" />
<small>The mostly-finished App Store screenshots that would have been published.</small>
<h3>What is <s>was</s> Stocketa</h3>
<p>Stocketa was a simple portfolio tracker designed with care. It came out of my frustration of having to check the clunky apps and sites that my brokers had just to get a glimpse at how my investments were doing. I&#x27;m a casual investor and don&#x27;t need much from a tool like this but I had assets in various places, and I just wanted one easy and well-designed place to check them. I wanted to see real per-transaction gain/loss info, based on my own cost basis.</p>
<p>While there are tons of apps, brokers, and neobanks that address this, nothing quite felt like what I wanted. There were several types of solutions in this space:</p>
<ul>
<li>First off, there are simple stock apps like Apple Stocks that let you see stock charts, news, and more. They have good data and don&#x27;t require any accounts to use. However, they offer no functionality to log your holdings and track your gains/losses.</li>
<li>There are lots of broker apps (e.g., Robinhood) that let you trade and track your holdings, but they only let you see your holdings from them, not from any other financial services you might use.</li>
<li>Then there&#x27;s a whole category of what I&#x27;d call advanced stock services like TradingView (and several that have since died or pivoted over the years), but they&#x27;re not mobile-first or as elegant as I wanted.</li>
<li>There are broader investment advisor services like Personal Capital. While they do often have some aggregator functionality to link up your other accounts, they&#x27;re not that powerful for diving into individual assets, aren&#x27;t particularly well-designed, and are primarily focused on upselling you on their own investment advising services (seriously, I used to get endless 8am calls from Personal Capital).</li>
<li>And there are lots of smaller apps on the App Store where you can track your holdings but the design and UX leaves a lot to be desired. I&#x27;ve tried most of them.</li>
</ul>
<p>From a design perspective, I generally found that financial apps bias towards density when displaying your assets. They assume you have tons of stocks and prioritize a list view where you have to tap in to a detail view to see more info. I found myself constantly tapping in, manipulating a chart or looking at some basic stats, then swiping back and repeating all that for several stocks. It was not easy or the kind of at a glance info I wanted.</p>
<p>That left me with my challenge. I wanted a <em>simple</em> portfolio tracker aimed at the casual investor. It didn&#x27;t have to do it all, but it should aim to do a few things well. An app just for me.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-stocketa-iphone-DSC06278.webp" alt="Stocketa running on an iPhone" width="3000" height="2007" />
<h3>Going custom</h3>
<p>I was more than thrilled to be working on a new app from scratch. After years of working at large companies with rigid design systems and gobs of stakeholders for every little design decision, I was yearning for some creative freedom. Freedom from process, freedom from typical design constraints. I would be in full control, designing and building it myself. <strong>It was <em>my</em> <a href="https://paulstamatiou.com/side-projects/">side project</a> after all</strong>.</p>
<p>I had gotten tired of designing for traditional mobile apps. You know the type.. you add a tab bar, a typical navigation stack, page header and the app already feels significantly basic, muted, and limited out of the gate.</p>
<p><strong>This was my place to have fun.</strong> I wanted to go custom and toss out whatever components the system gives you for free. And I knew that by having to figure out how to build various UI components from scratch, I&#x27;d learn a lot along the way. Almost all of Stocketa&#x27;s UI is custom.</p>
<p>I will say that <strong>going custom is almost always the absolutely <em>wrong</em> thing to do</strong> 99% of the time. The operating system you&#x27;re working in—be it iOS, Android, macOS—has invested a ton in a highly-considered suite of components. They&#x27;re remarkably accessible, well-tested, and work on a variety of devices.</p>
<p>It&#x27;s absolutely no small feat to consider creating a custom component for your app. However, when going custom does make sense and you&#x27;re okay with the added scope and responsibility, the app becomes your canvas to do whatever you want and <em>make it yours</em>.</p>
<p>The first area where custom made sense for me was general app navigation. When I got started, I knew I wanted this app to have minimal app chrome. I didn&#x27;t want a standard tab bar and header taking up space. I wasn&#x27;t going to require much navigation: most things would just live inside the stock cards from the home timeline.</p>
<p>The app would be focused around showing more with less. Personally, I only cared about tracking a few stocks, but I hated the work of constantly having to tap in to see a detail view, or interact with the chart. As such, the main scroll view needed to be more immersive and not get occluded by unnecessary app chrome.</p>
<p>It started with app navigation, custom stock cards, sheets, and more. Needless to say, I spent a lot of time on the details with everything being custom. Below are a few examples:</p>
<div>Please read <a href="https://paulstamatiou.com/stocketa/" title="Stocketa">this Stocketa article</a> in a browser to see embedded Stocketa videos.</div>
<h3>Designing and building</h3>
<p>I started with the basics: getting a scroll view of stock cards working, adding charts, and hooking it up to a database for persistence (initially Core Data before moving to Firebase). Then I added the requisite network calls and polling to update the stock card from a financial data provider. I started with IEX as the data provider as they had a decent API, reasonable pricing, and allowed commercial use, which would be required for a consumer app like this to go on the App Store.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-early-stocketa-build.webp" alt="Early Stocketa build screenshot" />
<small>Working on an early build in 2020.</small>
<p>One of the initial key decisions with Stocketa was that I wanted to track stock transactions in a comprehensive way. Simply logging the number of shares you had for each stock was not going to cut it. This ended up being a significant amount of work to do properly, but it was necessary:</p>
<ul>
<li>For each stock sale or purchase I wanted to be able to display not only the total gain/loss, but per-transaction gain/loss so you could tell if an individual transaction was a good trade.</li>
<li>When it comes to stock sales, I needed to know the cost basis method (FIFO, LIFO, et cetera) so I could correctly calculate and display the realized and unrealized gains on a particular transaction. When selling shares, I also needed to know from which previous transaction or transactions the shares would be sold so I could get the correct cost basis and accurately calculate the gain/loss based on the cost basis method.</li>
<li>And then there was dealing with stock splits, which seems simple at first glance but ended up being quite a bit of work to build in a robust way: not simply altering previous transactions. They should be automatically applied for new splits, but also able to be manually applied if you didn&#x27;t log split-adjusted transactions.</li>
</ul>
<img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-slides-Stocketa18@2x.jpg" alt="A glimpse at part of how comprehensive transaction types in Stocketa were shown" width="3840" height="2160" />
<small>A glimpse at part of how comprehensive transaction types in Stocketa were shown.</small>
<p>At some point I gave it a name: Stocketa. In Greek you might say "marketa" (Μαρκέτα, though αγορά might be a more proper word) when referring to a market, so this was like coalescing Stock and Market with that in mind.</p>
<hr/>
<p>When I was interviewing for a new job in 2021, I created these slides as part of my presentation after talking about my work at Twitter for the previous 9 years. These weren&#x27;t all of Stocketa slides, and there was a lot of additional talking points I had for each slide, but you get the idea.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-slides-Stocketa01@2x.jpg" alt="" width="2000" height="1125" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-slides-Stocketa02@2x.jpg" alt="" width="2000" height="1125" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-slides-Stocketa03@2x.jpg" alt="" width="2000" height="1125" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-slides-Stocketa04@2x.jpg" alt="" width="2000" height="1125" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-slides-Stocketa05@2x.jpg" alt="" width="2000" height="1125" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-slides-Stocketa06@2x.jpg" alt="" width="2000" height="1125" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-slides-Stocketa07@2x.jpg" alt="" width="2000" height="1125" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-slides-Stocketa08@2x.jpg" alt="" width="2000" height="1125" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-slides-Stocketa09@2x.jpg" alt="" width="2000" height="1125" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-slides-Stocketa10@2x.jpg" alt="" width="2000" height="1125" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-slides-Stocketa11@2x.jpg" alt="" width="2000" height="1125" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-slides-Stocketa12@2x.jpg" alt="" width="2000" height="1125" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-slides-Stocketa13@2x.jpg" alt="" width="2000" height="1125" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-slides-Stocketa14@2x.jpg" alt="" width="2000" height="1125" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-slides-Stocketa15@2x.jpg" alt="" width="2000" height="1125" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-slides-Stocketa16@2x.jpg" alt="" width="2000" height="1125" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-slides-Stocketa17@2x.jpg" alt="" width="2000" height="1125" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-slides-Stocketa18@2x.jpg" alt="" width="2000" height="1125" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-slides-Stocketa19@2x.jpg" alt="" width="2000" height="1125" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-slides-Stocketa20@2x.jpg" alt="" width="2000" height="1125" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-slides-Stocketa21@2x.jpg" alt="" width="2000" height="1125" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-slides-Stocketa22@2x.jpg" alt="" width="2000" height="1125" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-slides-Stocketa23@2x.jpg" alt="" width="2000" height="1125" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-slides-Stocketa24@2x.jpg" alt="" width="2000" height="1125" />
<small>Slides touching on various parts of Stocketa as of late 2021. The design of many of these screens is now outdated, but it&#x27;s a good look at a point in time.</small>
<h3>A note about SwiftUI</h3>
<p>I kept designing, building.. and then redesigning and rebuilding. One of the side effects of learning Swift and SwiftUI as I was building this was that I was constantly redoing specific pages and parts of the app as I went. I continually found better ways to build things, and similarly I would continually refine designs. About a year or so into building Stocketa I <a href="https://paulstamatiou.com/getting-started-with-swiftui/">wrote about my experience with SwiftUI</a>. Much of that still rings true.</p>
<p>SwiftUI has come a long way since iOS 13. It&#x27;s more performant, there&#x27;s more parity in available components and functionality compared with UIKit, and you get more control over things. And with iOS 17, you get some goodies like shaders, keyframes, scroll transitions, and more.</p>
<video controls="false" poster="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-xcode-swiftui-preview-stocketa-poster.webp">
      <source src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-xcode-swiftui-preview-stocketa.webm" type="video/webm">
      <source src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-xcode-swiftui-preview-stocketa.mp4" type="video/mp4">
      Your browser does not support the video tag.
    </video>
<small>Xcode showing a SwiftUI preview.</small>
<p>There&#x27;s still a gap between the types of things you can do with AppKit and UIKit, but SwiftUI is undeniably a powerful tool that&#x27;s dramatically more approachable. And not just a coding tool; it&#x27;s a great design tool. Designers can quickly lay things out, hook up interactions, and get a real feel for a design using a native tool.</p>
<p>Almost all of Stocketa&#x27;s UI is built with SwiftUI. There were only a few occasions when I found it necessary to use UIKit to achieve some goal.<sup><a rel="footnote" href="#footnote-1" id="r1">1</a></sup> None of this would have been possible, or drawn me to take a closer look into building iOS apps, if it hadn&#x27;t been for SwiftUI.</p>
<h3>What I built</h3>
<p>I used the app daily and continued pouring time into every feature and detail to meet my high quality bar. While I initially planned for this to be a simple to build app that would not require a backend, or even any user accounts, that did not last for long. I quickly realized I needed my own backend to unlock a few things.</p>
<p>At first, this was so I didn&#x27;t have to include the API key for my financial data provider inside the app for security reasons—I wouldn&#x27;t want someone to find it and start running up my bill by abusing it. I created a backend proxy for the API with rate-limiting and throttling. Then, I wanted to have it be authenticated with user accounts, so I added Sign In With Apple along with a stock data caching system so that I only had to fetch stats for a stock once with a certain time period (depending on the particular stat that was either seconds, 24 hours, or weekly) regardless of however many user accounts needed that stock info. The main goal with that was to also reduce my costs associated with financial data API usage.</p>
<p>By this point I really started enjoying the speed at which I could update endpoints and business logic entirely on the backend. I started moving logic I had in the app to the backend. <strong>Stocketa was starting to come together.</strong></p>
<p>Even though this was just a solo project, I used Linear to keep track of tasks, ideas, features, customer feedback, and milestones.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-stocketa-linear.webp" alt="My Linear app usage for Stocketa" />
<p>I had prioritized lists of things to build and bugs to fix. I was using—and loving—Linear for this. Here&#x27;s a list of <em>most</em> of the things I built for Stocketa:</p>
<div>Please read <a href="https://paulstamatiou.com/stocketa/" title="Stocketa">this Stocketa article</a> in a browser to see embedded Stocketa videos.</div>
<p>I ran a small TestFlight alpha with close friends, then increasingly I added more people. At one point I was up to around 1,000 people. That was the most I wanted to allow. I received lots of feedback from overall great first impressions (below), to general feature requests, and of course lots of bug reports.</p>
<blockquote>
<p>Already the app is filling a need for me in its personal approach to tracking investments: no pushing for sales, no integrations with brokers and no unnecessary permissions. Brilliant.</p>
</blockquote>
<blockquote>
<p>Simply amazed at the SwiftUI work you’ve poured into this app. So beautiful. The onboarding alone is a masterclass in attention to detail. Bravo.</p>
</blockquote>
<blockquote>
<p>love it, this feels so polished and slick already... really great use of SwiftUI</p>
</blockquote>
<blockquote>
<p>Just got the invite, added my stocks... the animations are beautiful, design is clean and precise... it’s all around beautiful. Congrats!</p>
</blockquote>
<blockquote>
<p>F**k, man. This app is incredible. You’re building all of this on your own?</p>
</blockquote>
<blockquote>
<p>Dude. This app is f**king beautiful. Really great job. Just imported shares - super easy.</p>
</blockquote>
<blockquote>
<p>This NUX is insane. The particles when you add a stock. Gives me the happy brain chemicals..</p>
</blockquote>
<p>I had thousands on a waiting list but there were API and hosting costs associated with the increased usage that I didn&#x27;t want to bear yet, as well as a huge increase in support and customer feedback that took a lot of time to manage. You start to hear the same types of feedback, and it just becomes a chore to manage that many emails. That good news was that something was resonating and people cared enough to go through the work to send in bug reports and feature requests.</p>
<h3>The website</h3>
<p>At some point early in feature development I took a break to focus on the website. At first I wanted a simple landing page to build interest, and collect emails for a waitlist so I could keep people in the loop. And I didn&#x27;t want to spend that much time on it.</p>
<video controls="true" poster="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-stocketa-v0-landing-page-poster.webp">
      <source src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-stocketa-v0-landing-page.webm" type="video/webm">
      <source src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-stocketa-v0-landing-page.mp4" type="video/mp4">
      Your browser does not support the video tag.
    </video>
<small>Video: Initial Stocketa teaser homepage.</small>
<p>There was nothing fancy or particularly special about this initial page. It was just something quick I wanted to get out the door. And now, a while later, there&#x27;s a lot I hate about this early design. The background texture was too strong, the headline alignment feels odd with the phone.. but I digress.</p>
<p>In that initial design I did start playing with some wave-related elements—a loose reference to stock market charts going up and down. And then to add to that, I built a few mini stock cards gently hovering in place (thanks to <code>offset-path</code> CSS along with 2 keyframe animations) in the background. Each stock card had an SVG line chart—loosely based on that stock&#x27;s actual performance around the time—that would animate on page load. I ended up keeping a version of these mini stock cards on the latest version of the website, and then on an onboarding screen inside the app.</p>
<p>The original inspiration for these random floating stock cards was from my now <a href="https://photos.paulstamatiou.com/work">out-of-date work page</a> where I highlighted projects with some large cards, each with their own intro animation based on the project. One of them was for my work on Twitter Video, where video clip thumbnails would fan out from the phone on hover (shown below).</p>
<video controls="true" poster="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-portfolio-twitter-video-hover-poster.webp">
      <source src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-portfolio-twitter-video-hover.webm" type="video/webm">
      <source src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-portfolio-twitter-video-hover.mp4" type="video/mp4">
      Your browser does not support the video tag.
    </video>
<small>The floating mini stock cards on the Stocketa homepage were inspired by the hover state animation on this project card from my old portfolio page.</small>
<h3>Homepage design <code>v1.0</code></h3>
<video controls="true" poster="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-old-stocketa-website-poster.webp">
      <source src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-old-stocketa-website.webm" type="video/webm">
      <source src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-old-stocketa-website.mp4" type="video/mp4">
      Your browser does not support the video tag.
    </video>
<small>Video: The first full version of Stocketa.com in early 2021, currently <strong><a href="https://stocketa.com/v1/">archived here</a></strong>. The App Store QR code was meant to be displayed on scroll but in this version I didn&#x27;t have that hooked up as the app wasn&#x27;t live.</small>
<p>In early 2021 I ended up getting around to designing and building out the first complete homepage for Stocketa. I had enough functionality and features built that it felt worthy of investing some time into showcasing them on the site.</p>
<p>Lots of app websites at the time (and still now) had the typical hero section on their homepage: some app screenshot in a phone frame off to one side, with accompanying header and subtitle text adjacent. Nothing wrong with that, but I wanted something a bit more engaging. I wasn&#x27;t entirely interested in optimizing for conversion, and cramming a lot in above the page fold.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-old-stocketa-explorations.webp" alt="Old Stocketa explorations" />
<small>Initial design explorations in figma.</small>
<p>I thought it would be nice to try to do something where the 3D phone frame was angled and then began to change position on scroll while a brief teaser video of the app functionality played. Apple had done something similar in recent years with product pages, such as the first-generation AirPods Pro. They used over 100 frames of the AirPods that would progress as you scrolled:</p>
<video controls="true" poster="https://turbo.paulstamatiou.com/uploads/2023/08/airpods-pro-first-gen-site-animation-poster.webp">
      
      <source src="https://turbo.paulstamatiou.com/uploads/2023/08/airpods-pro-first-gen-site-animation2.mp4" type="video/mp4">
      Your browser does not support the video tag.
    </video>
<small>Example of a technique used by Apple.</small>
<p>There&#x27;s a lot of ways to achieve an effect like this. One route route is using Lottie and essentially converting each frame of your video or animation to a base64-encoded string in a json file for the Lottie web player to manage. It&#x27;s not a flawless solution, however, and can incur some large file sizes depending on what you&#x27;re doing. It&#x27;s best for vector micro-animations, not large devices with complex visual content. I also didn&#x27;t want to incur the cost of that large initial json download blocking the very first thing you see on the site.</p>
<p>Instead I opted to have javascript display a sequence of frames composited to <code>canvas</code> along with an offscreenCanvas for performance. I used <a href="https://rotato.app/">Rotato</a> to import my short Stocketa screencast, create a 3D phone video, and then create a PNG sequence of frames. I wasn&#x27;t super pleased with the quality—the phone frame didn&#x27;t look super realistic and had some rough pixelated edges—but it was good enough compared to doing it all by hand with other design tools.</p>
<video controls="true" poster="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-old-stocketa-website-hero-animation-poster.webp">
      <source src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-old-stocketa-website-hero-animation.webm" type="video/webm">
      <source src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-old-stocketa-website-hero-animation.mp4" type="video/mp4">
      Your browser does not support the video tag.
    </video>
<small>Scroll-based Stocketa 3D phone, paired with subtle parallax for header elements and the floating stock cards. There were some other minor scroll effects like the gradient glow behind the phone spreading.</small>
<p>I then exported optimized transparent webp, and jpg files (with accompanying alpha masks created in Sketch to save bandwidth) and had the javascript detect which file type to use for the animation. While I was pleased with how this effect turned out, it ended up becoming a rather huge annoyance when I wanted to update the content later—it&#x27;s a pain to generate, optimize, and update the image sequence each time.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-old-stocketa-site-grid-layout-2.webp" alt="Old Stocketa Layout" width="3278" height="2452" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-old-stocketa-site-grid-layout-1.webp" alt="Old Stocketa Layout" width="3244" height="2400" />
<small>Other bits of the website: cards for various features.</small>
<p>And finally, as for the rest of the content on this site I went with a basic feature card approach, sometimes called a "bento box" layout; particularly when varying card sizes are used. This is a layout that I&#x27;ve grown to like a bit less over the years as it has become very common.</p>
<h3>Homepage design <code>v2.0</code></h3>
<video controls="true" poster="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-new-stocketa-website-poster-2.webp">
      <source src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-new-stocketa-website.webm" type="video/webm">
      <source src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-new-stocketa-website.mp4" type="video/mp4">
      Your browser does not support the video tag.
    </video>
<small>Video: New Stocketa site</small>
<p>A year later, it was time for another redesign. Stocketa had more functionality, and a lot more refinements. I had more to share, and I had grown tired of the 3D phone frame interaction. It was neat but it was just there for show; it wasn&#x27;t the best way to show off parts of the app as it scrolled off screen. It was also a pain to update the frame sequences. I essentially just wanted to take screenshots of the real app from the iOS simulator and upload them.</p>
<p>Separately, I didn&#x27;t want a super long page with a lot of repetitive modules and screenshots. I wanted a skimmable feature list. I began to wonder if I could get away with just a single phone frame on the site that showed everything.</p>
<p>I eventually landed on a two pane approach: the device frame was always in view, fixed on the right side, while the scrollable left side contained the feature list. The trade-off with this design was that it would require hovering over each feature item to be able to update the screenshot shown in the device frame. I figured an interesting compromise to that would be having the phones stack up and away on scroll. Almost like the old Apple Time Machine backup UI.</p>
<p>I built several versions of this and found that it didn&#x27;t feel great. There wasn&#x27;t much scroll distance so if you scrolled at a normal or fast pace, you&#x27;d see a bunch of phones flicker by you as the animations tried to keep up. It was too busy and hectic, not to mention a lot of state management to deal with jumping between your current scroll-based position screenshot to a hover-based screenshot if you hovered over a feature list item. I ended up simplifying a bit and only having the scroll-based UI manage just a few states: the intro phone frame, the first feature screenshot, and then a final animation at the bottom of the page.</p>
<video controls="true" poster="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-stocketa-homepage-v2-responsive-poster.webp">
      <source src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-stocketa-homepage-v2-responsive.webm" type="video/webm">
      <source src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-stocketa-homepage-v2-responsive.mp4" type="video/mp4">
      Your browser does not support the video tag.
    </video>
<small>The website&#x27;s mobile layout uses a carousel of screenshots in the header.</small>
<p>After sorting out the core interactions, I had to figure out how to deal with mobile and tablet interactions. The fix two-pane layout made this a bit of a challenge. I ended up turning the header into a carousel of device frames you could scroll through.</p>
<p>And then finally, I added a few small bits of polish ✨:</p>
<ul>
<li>Hero title text gradient changes based on scroll</li>
<li>The icon accent color and background circle color change based on scroll</li>
<li>When hovering over any feature list item, there is a subtle background color change created by an overlaid gradient. SVG-created noise/grain is also overlaid on top of the background.</li>
<li>When hovering over any feature list item, or when you&#x27;re reached the end of the page, there&#x27;s a subtle icon particle emitter that floats up icons from the bottom. Each feature used a different icon for this.</li>
</ul>
<video controls="true" poster="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-stocketa-homepage-v2-particle-emitter-poster.webp">
      <source src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-stocketa-homepage-v2-particle-emitter.webm" type="video/webm">
      <source src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-stocketa-homepage-v2-particle-emitter.mp4" type="video/mp4">
      Your browser does not support the video tag.
    </video>
<small>Particle emitter effects: icons float up from the bottom, based on the feature list item being hovered on. There&#x27;s also another very subtle emitter generating some tiny floating particles.</small>
<p>Overall I liked this design, but looking back at almost a year later, the gradient text and background colors feel a bit too much for my taste now.</p>
<h3>API troubles</h3>
<p>Eventually it became clear that the quality of financial data Stocketa relied on was not cutting it. The first provider I used, IEX, would sometimes have charts outdated, inaccurate prices (especially for less frequently traded assets on the IEX exchange), and lacked data for OTC markets (they required you sign a pricey license directly with OTC), as well as significantly limited data for Nasdaq-listed stocks (even basic things like pre-market and after-hours data). The last straw was when IEX dropped mutual fund data entirely, all without any advance notice.</p>
<p>I later used another provider that allowed commercial use that didn&#x27;t charge too much ($100/month) but I had even more problems with their data and reliability. Endpoints were even returning old and incorrect data, and even once alerted to issues, their team would not only ignore the bugs but claim they didn&#x27;t exist. I couldn&#x27;t ship Stocketa with unreliable financial data to people that would be paying me for a quality app.</p>
<p>I also could not get certain types of data with paid APIs. I had to build a scraping engine on my backend that would visit a few sites to get the data I needed for less updated data like dividend yield, earnings dates, and even for OEF data (other providers would be more than a day delayed for this at times).</p>
<p>Needless to say, this was all frustrating. It was a hassle, hard to maintain, and unreliable. At the same time, my backend continued getting more involved to deal with more and more of the intricacies of dealing with stocks. Things like dealing with companies merging or stock tickers renaming.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/08/copyright-paulstamatiou_com-stocketa-backend.webp" alt="Stocketa Backend" />
<small>~13k LOC node/express backend (shown in Zed but I now prefer <!-- --><a href="https://twitter.com/Stammy/status/1713303350987698459">Cursor</a><!-- -->) for Cloud Run. It manages auth, caching, news, core business logic, cleaning up data, notifications, widgets, working with multiple API, and a bit of scraping. This was my first time doing anything of this size with node and typescript.</small>
<p>Starting out I thought getting access to a stock market data API would be the easy part. I quickly learned about the world of market data feeds, SIPs (Securities Information Processor), and vendor agreements.</p>
<p>Quality market data exists, it&#x27;s just not made for indie app developers. It&#x27;s very expensive. Several leading U.S. market data providers have commercial use data pricing starting at $2,000 per month. And that&#x27;s not for everything, if you need things like index data or options data, there&#x27;s more charges ahead.</p>
<p>I spoke with one of these providers last year, trying to get them to understand how small app developers need affordable commercial use data. They presented a startup-focused plan that they were pitching for $499/month in addition to a per-MAU fee. Even that I would still consider very expensive for my needs, and it seems like that may have fallen by the wayside and is no longer promoted on their website.</p>
<p>I could spend months developing Stocketa, incurring that monthly API cost until I went live (or risk getting shutdown if I tried to use a cheaper non-commercial plan during the TestFlight phase) then not make enough money to cover costs on the App Store and have to shut it down shortly after anyways.</p>
<p>Overall, it feels like no one in this cares to cater to the developer and startup crowd, or they believe there&#x27;s not much money for them to pursue there. This was the same case with Plaid when I briefly looked into getting access to their investments API to automatically sync holdings data. They required some sort of minimum length contract.</p>
<h3>Why I stopped working on Stocketa</h3>
<p>When I started this project, I really began to wonder why where weren&#x27;t any great indie apps focused on stocks like this. Just simple, well-designed apps to help the casual investor keep track of their investments. Well I think I was starting to get my answer: getting quality financial data, even just for the United States, is a nightmare. You can only get it if you have a lot of money to invest in your project. And good luck if you really want a great API with comprehensive international data.</p>
<p>I can&#x27;t help but draw parallels to what happened recently with the Twitter and Reddit APIs. The risk of running your project or business solely on top of another company&#x27;s API, no matter how reliable you think they may be, is extremely high.</p>
<p>Stocketa was always meant to be a side project—never a real business. For it to be a real business, I would need to keep adding functionality and introducing more ways to make money. I couldn&#x27;t just have a simple and elegant little app tracking your stocks. It would have to do more, like dipping into financial advice services, or offering stock trading. That&#x27;s a hyper-competitive space lined with massive companies. That would mean a busier, cluttered app. The exact reason why I started Stocketa was because of all those cluttered apps.</p>
<p><strong>I decided to stop working on Stocketa for a few reasons:</strong></p>
<ul>
<li>
<p><strong>Data:</strong> As mentioned above, all the expenses and challenges associated with acquiring reliable, affordable, and high-quality financial data that would make it feasible to release this as a reasonably priced subscription-based app.</p>
</li>
<li>
<p><strong>Support:</strong> The associated investment in customer support. Based on how people were using my TestFlight, it was going to be a significant investment to keep up with support, emails, maintenance, and ongoing feature development. However, part of this was likely due to complexity incurred from having to fix or skirt around unreliable data. There were lots of things I wanted to keep improving and refining with the app and that wouldn&#x27;t end any time soon.</p>
<p>If I were to release and charge for Stocketa, I would feel especially on the hook to resolve issues in a timely manner and that&#x27;s not something I can accomodate now because of the next point.</p>
</li>
<li>
<p><strong>Time:</strong> And most importantly, I&#x27;ve found something more worthy of my complete focus and attention: Rewind AI. I sunk a lot of nights and weekends into Stocketa over the years. It consumed every spare moment, even taking over my occasional time writing blog posts here when I had something to share. That was something I really missed. Now, I would much rather be focusing my creative thinking time on how I can improve and grow Rewind.</p>
</li>
</ul>
<p>I originally started working on Stocketa with one goal: to learn Swift and SwiftUI my way with a project that was interesting to me. At the time that was scratching my own itch of keeping track of my investments. While it turned into a much larger and unshipped project, I learned a ton about native iOS development and was able to push myself creatively.</p>
<p>These days I&#x27;m happiest investing my design, product and development time into Rewind AI, where my SwiftUI knowledge learned with Stocketa has been tremendously helpful.</p>
<br><br><br><hr><br><h3>Footnotes</h3><p><a href="#r1">1</a><!-- --> I only had to go down to UIKit a few times. One time for things like custom text fields for more control over interactions, styling, text input, and formatting. Another to use a CollectionView for drag-to-reorder stocks. A third time for creating particle emitters in a few places, like confetti effects, as well as one area where I have some twinkling stars in a night illustration when the stock market is closed. And one last time to get more control over gestures. I needed to get a location when a long press <em>begins</em> and SwiftUI LongPressGesture() didn&#x27;t provide that, so I used UILongPressGestureRecognizer instead.</p>]]></description>
            <link>https://paulstamatiou.com/stocketa</link>
            <guid isPermaLink="true">https://paulstamatiou.com/stocketa</guid>
            <dc:creator><![CDATA[Paul Stamatiou]]></dc:creator>
            <pubDate>Mon, 16 Oct 2023 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Digital clutter]]></title>
            <description><![CDATA[<p>I started taking photography more seriously about a decade ago. I shot photos in RAW with increasingly higher megapixel cameras, spent a lot of time post-processing photos—see my 30K word post about <a href="https://paulstamatiou.com/building-a-windows-10-lightroom-photo-editing-pc/">building a custom Adobe Lightroom PC</a>—and designed and built custom photo stories to share them.</p>
<p>While I would go through the process of culling photos that I published online, I didn’t do that for what I backed up. I kept <em>everything</em>. I always thought, "what if I want to go back to this and edit it differently one day?"</p>
<p>I kept every RAW photo I shot, every video, every GoPro clip... I even kept every phone photo going back to my first iPhone. And why not, storage is cheap and easy, right?</p>
<p>The terabytes kept adding up. I added close to a terabyte with <a href="https://photos.paulstamatiou.com/new-zealand/">New Zealand</a>. Hundreds of gigs with <a href="https://photos.paulstamatiou.com/africa/">Africa</a>. When you hit a few terabytes the obvious solution is to move to a NAS, or Network Attached Storage. I wrote about this extensively in 2015 with <a href="https://paulstamatiou.com/storage-for-photographers-part-2/">Storage for Photographers (Part 2)</a>.</p>
<p>Years back these were pretty dumb devices that would just appear as a networked drive for your computer to manage. Today, they’re full-blown personal servers, capable of running self-hosted apps and services. That makes it easy to have them encrypt your data, and automatically back your files up to cloud services, which is probably what you want if you’re paranoid about backups and try to follow the 3-2-1 rule.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2017/08/copyright-paulstamatiou_com-DSC05186-2000.jpg" alt="NAS setup" />
<small>My NAS setup some years back.. it became far messier over the years after I moved to NYC and had less space for networking gear.</small>
<p>Over the years I paid thousands of dollars just to keep those RAW photos safe. At one point I think I had copies on 3 or 4 separate cloud services.. you know, just in case. I later upgraded to another NAS that was physically a bit smaller.</p>
<p>In hindsight, I couldn&#x27;t care less about 90% of all that data, if not more. The fact that I had terabytes of available storage made it all too easy to not be picky with what I was backing up and just archive everything.</p>
<p>When it was time to move to a different apartment, I took that as the perfect excuse to simplify. I no longer wanted a NAS in my life. A little whirring box, always making random hard drive noises, always taking up space, always making heat. Though I’m sure my perspective would be a bit different if I had enough space to hide the NAS in a perfect server closet completely out of sight and mind.</p>
<p>I needed to get rid of tons of RAW photos for which I no longer cared. I knew I wouldn’t be able to get rid of everything and I still wanted maybe 2 TB of local storage, separate from my computer. My first inclination was to just look for a tiny NAS that I could load up with 2.5” SATA SSDs, or something even better like M.2 NVMe SSDs. I didn’t find anything I liked—most small NAS devices would still require some massive barrel-jack power adapter.</p>
<h3>Picking an M.2 SSD enclosure</h3>
<p>I ended up deciding to get a small, simple external Thunderbolt SSD enclosure. In particular, I wanted an M.2 NVMe SSD enclosure. M.2 SSDs are much smaller and faster than other modern SSDs using SATA. I wanted an small, bus-powered enclosure that was Thunderbolt 3 or 4, and had some basic heatsink or thermal pad for the SSD.</p>
<p>There were a few options I looked at. The <a href="https://www.amazon.com/dp/B07ZWPH7G3?_encoding=UTF8&psc=1&linkCode=ll1&tag=paulstamatiou-20&linkId=ec9bd7e1c319cc02b39d8045c1d94095&language=en_US&ref_=as_li_ss_tl">Sabrent Rocket Nano</a> looked perfect at first glance due to its tiny size but they don&#x27;t sell it as an enclosure, and it&#x27;s only USB-C, not Thunderbolt, so I ruled that out. Then I looked at a <a href="https://www.amazon.com/Thunderbolt-Certified-Tool-Free-Enclosure-EC-T3NS/dp/B08FT59SB6?ie=UTF8&linkCode=ll1&tag=paulstamatiou-20&linkId=e9fc4a2515dc46de1493ee73d89912ad&language=en_US&ref_=as_li_ss_tl">Thunderbolt 3 enclosure from Sabrent</a>. Unfortunately, some reviews pointed out issues with performance and reliability that had me concerned. There was also a new <a href="https://satechi.net/products/usb4-nvme-ssd-pro-enclosure?variant=40188470067288">Thunderbolt 4 enclosure from Satechi</a>, but it wasn&#x27;t shipping (and still seems to be out of stock). That aside, it looked like a great option, but it was far too large for some reason.</p>
<p>After a lot of looking I eventually landed on the <a href="https://www.amazon.com/OWC-Envoy-Express-Thunderbolt-Enclosure/dp/B08LYQPRPJ?&linkCode=ll1&tag=paulstamatiou-20&linkId=6eab0ee6644082eab4ef5f7e6ba7ea89&language=en_US&ref_=as_li_ss_tl">OWC Envoy Express</a>. I was hoping for a more aesthetically pleasing option but OWC has been a reputable brand I&#x27;ve been familiar with so it felt like the safe option. I don&#x27;t like how the Thunderbolt cable is part of the case design (you can detach it but you have to open the case), but it wasn&#x27;t a dealbreaker for me. At the time I purchased this, it was a bit cheaper at $79.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/04/copyright-paulstamatiou_com-owc-envoy-express-ssd.jpg" alt="OWC Envoy Express Thunderbolt 3 SSD enclosure" />
<small>The Envoy Express enclosure alongside a cheaper USB-C enclosure I got for another spare SSD I had.</small>
<p>The Envoy Express enclosure is all metal and seems very well-made so I&#x27;m quite pleased with it.</p>
<p>As for what SSD to use with the enclosure, I decided to use one I already had: an older 2 TB Samsung 970 Evo. At the time I was also parting out and selling <a href="https://paulstamatiou.com/gear/desktop-pc/">my gaming PC</a> (didn&#x27;t use it enough after I got an Xbox Series X and it was taking up space) and I decided to repurpose the 2 NVMe SSDs I took from it. If you want to do the same, you can find affordable 1 and 2 TB options from Western Digital, Samsung, and SK Hynix among others. It&#x27;s when you start looking for 4TB SSDs that the prices go up considerably.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2019/05/copyright-paulstamatiou_com-DSC2824-2000.jpg" alt="My old desktop PC" />
<small>My old desktop PC where I salvaged my M.2 SSDs from</small>
<p>Installing the SSD in the OWC enclosure took less than a minute. There&#x27;s two screws to open the case, then one more screw to fasten the SSD. The case has a built-in thermal pad that touches the top of the SSD, though I wish it had some sort of cooling for the bottom as well.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/04/copyright-paulstamatiou_com-owc-envoy-express-ssd-2.jpg" alt="Samsung 970 EVO SSD inside OWC Envoy Express Thunderbolt 3 enclosure" />
<small>Breathing new life into my old 970 EVO M.2 SSD by putting it in the OWC Envoy Express enclosure.</small>
<h3>Setup and disk encryption</h3>
<p>The next thing I did was open up Disk Utility on macOS, format the SSD, then set up encryption. While there&#x27;s lots of ways to encrypt your data—like VeraCrypt which touts plausible deniability with hidden volumes—I opted for the <a href="https://support.apple.com/guide/disk-utility/encrypt-protect-a-storage-device-password-dskutl35612/mac">encryption functionality built into macOS</a> for simplicity.</p>
<p>With the SSD ready to go, the hard part was determining what photos and data I wanted to from my NAS I wanted to keep and transfer to this SSD. This was made particularly hard as my NAS was very slow. I had gigabit ethernet but that doesn’t matter, these spinning disks are barely faster than 100MB/s for sequential read even with a RAID setup. So my long process over a week or so was transferring a folder or two to my laptop overnight, as much as I could with the available space I had on my MacBook Pro&#x27;s internal SSD.</p>
<p>Once on my laptop I had to go through and decide what to delete and what to keep. There were a lot of easy ways I was able to save space by cutting things like GoPro videos of which I had hundreds of gigs from trips. I didn&#x27;t care for that footage much and the important clips I had already used in other videos elsewhere.</p>
<p>But there&#x27;s no getting around it, this was an arduous process. For some older trips I only kept the post-processed original size JPGs and deleted the RAWs. Then there were tons of just random photos I deleted. It took me a few days but eventually I was able to shave a few terabytes; enough to fit the important stuff on this 2 TB SSD. (I had a bit of overflow which I tossed on the other USB-C external enclosure I had which I won&#x27;t use often so the speed isn&#x27;t important).</p>
<h3>Cloud encryption and backup</h3>
<p>With the photos and data trimmed down and ready to transfer to the SSD, I needed to figure out how I wanted to have this SSD backed up and encrypted on cloud services. For that I turned to <a href="https://www.arqbackup.com/">Arq</a>.</p>
<p>Arq is a backup power tool for advanced users. It&#x27;s a standalone Mac app that connects to just about any cloud service including AWS, Backblaze, OneDrive, Wasabi, Google Cloud, as well as all S3-compatible storage providers. The best part is that you bring your own credentials for those cloud services, and you have fine-grained control over how things are backed up, stored, encrypted, and much more.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/04/copyright-paulstamatiou_com-arq-macos-ssd-backup.jpg" alt="Arq backup app for macOS" />
<p>I decided to separate my photos and other more important data into different folders with different backup strategies. Photos took up most of the 2 TB and I wanted them backed up but I didn&#x27;t expect to access them frequently so I didn&#x27;t want to use the Amazon "S3 Standard" storage class. I decided to use S3 Glacier Instant Retrieval for my photos.</p>
<p>I&#x27;m no stranger to Glacier, Amazon&#x27;s slower and cheaper data archival storage tier, and have been using some form of it for a decade, but I never had a great experience. It always felt unpredictable and slow; yes, I realize that&#x27;s the basically the trade-off you sign up for. As of 2021, Amazon added a new type of Glacier storage called Instant Retrieval. So you get the benefit of more affordable data archival storage along with quicker retrieval times.</p>
<p>There&#x27;s quite a few S3 storage classes to select from: Standard, Standard Infrequent Access, One Zone Infrequent Access, Glacier Instant Retrieval, Glacier Flexible Retrieval, Glacier Deep Archive. It&#x27;s important to familiarize yourself with the <a href="https://aws.amazon.com/s3/storage-classes/">functionality of the S3 storage class</a> you plan on using. And that&#x27;s just with AWS, you can to use any other cloud provider you like with Arq.</p>
<p>To give you a rough idea of the prices associated with some of these S3 storage classes, <strong>here&#x27;s what it would cost to store 2 TB per month</strong>, with no other actions or transfers:</p>
<table><thead><tr><th>S3 Storage Class</th><th>Monthly price to store 2 TB</th></tr></thead><tbody><tr><td>S3 Standard</td><td>$47.10 USD</td></tr><tr><td>S3 Standard Infrequent Access</td><td>$25.60 USD</td></tr><tr><td>S3 One Zone Infrequent Access</td><td>$20.48 USD</td></tr><tr><td>S3 Glacier Instant Retrieval</td><td>$8.19 USD</td></tr><tr><td>S3 Glacier Flexible Retrieval</td><td>$7.41 USD</td></tr><tr><td>S3 Glacier Deep Archive</td><td>$2.05 USD</td></tr></tbody></table>
<p>And then, for my other data, which was more important and not nearly as sizable, I opted for S3 Standard Infrequent Access. Here&#x27;s how that looks in Arq:</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/04/copyright-paulstamatiou_com-arq-macos-ssd-backup-settings-3.jpg" alt="Arq showing different S3 storage classes for different folders" />
<small>Arq showing different S3 storage classes for different folders</small>
<p>Arq also lets you specify encryption for your data—separate from the macOS encryption I set up that&#x27;s required to mount the drive—so I did that as well. It&#x27;s important to note that you will need the Arq client to be able to access the encrypted files again; they&#x27;re unreadable if you go directly to the storage bucket on S3.</p>
<p>That&#x27;s it! I&#x27;m very happy with the new setup. I&#x27;m relieved to no longer have a NAS taking up space and making noise in my house. The external SSD is tiny and I still have control over where my data is backed up online. I can easily add more cloud storage destinations later on as I see fit.</p>
<h3>Cloud control</h3>
<p>However, after all this work slimming down my archives, the job is not done. My NAS was just the first target. I still have a stockpile of data and memories across other services like Google. Take Google Photos for example. Absolutely amazing service. I love the heck out of the product. And while Apple&#x27;s Photos functionality is great, I&#x27;ve always loved all that Google Photos had to offer from amazing search to strong sharing functionality.</p>
<p>I just wish Google Photos wasn&#x27;t owned by Google. I&#x27;m trying to reduce my reliance on consumer-oriented Big Tech products like this in favor of services where I have more control. Google has been heralded for their data portability tool Google Takeout, which includes Google Photos data, but in my experience using it was all but pleasant.</p>
<p>First, I had to wait days to let the archives prepare, which I understand what needs to happen with this much data so that&#x27;s fine. But then, I had to download more than a dozen separate zipped files amounting to over 800 GB. I don&#x27;t even think I had that much space on my laptop, let alone extra space to be able to unzip them all. And once unzipped, I don&#x27;t recall the files having any sort of helpful organization to make it feasible to trim down moments you don&#x27;t need. I gave up on that.</p>
<p>Cloud storage services make it all too easy to eagerly backup anything and everything without being intentional. Now we&#x27;ve all inadvertently become data hoarders.</p>
<p>Just because we have easy access to near-infinite and increasingly more affordable storage doesn&#x27;t mean we <em>should</em> be using all that space. The next generation of cloud-based services need to design for curation and control. It doesn&#x27;t feel like an immediate concern, but it will only continue to increase.</p>
<p>These days getting your Google account hacked isn&#x27;t just about your email. It may be about your entire digital life. This is more than just decluttering, it&#x27;s about control, <a href="https://paulstamatiou.com/getting-started-with-security-keys/">security</a> and privacy too.</p>]]></description>
            <link>https://paulstamatiou.com/digital-clutter</link>
            <guid isPermaLink="true">https://paulstamatiou.com/digital-clutter</guid>
            <dc:creator><![CDATA[Paul Stamatiou]]></dc:creator>
            <pubDate>Sat, 15 Apr 2023 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Hosting your own Mastodon server]]></title>
            <description><![CDATA[<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-mbp.jpg" alt="Mastodon admin settings for discovery" />
<p>A lot has happened since I published my article on the <a href="https://paulstamatiou.com/mastodon/">open source decentralized social networking service Mastodon</a> a few weeks ago. I saw a lot of interest in and discourse around that post that was great to see. Since then, a few notable things have happened that have caused Mastodon usage to spike yet again.</p>
<p>Twitter unsurprisingly ended up entirely banning third-party Twitter clients, including hugely popular ones like Tweetbot and Twitterific. I briefly summarized the ebb and flow of being a developer working with the Twitter API in the last post:</p>
<blockquote>
<p>"Long story short, Twitter made it hard. Hard to even get an API key and get your app approved. Hard to get bugs fixed or new features accessible via the API. Hard to access the data developers wanted. Hard to not hit arbitrary constraints or limits. Things were always changing, rugs were pulled, announcements about new priorities and new rugs were made, only for them to be pulled again (read <a href="https://www.theverge.com/2021/11/15/22779149/twitter-api-version-2-official-decentralized">this</a>, <a href="https://techcrunch.com/2022/11/02/twitter-cancels-its-chirp-conference-for-developers-amid-management-transition/">this</a> and <a href="https://techcrunch.com/2022/12/15/developer-platforms-are-all-about-trust-and-twitter-lost-it/">this</a>)".</p>
</blockquote>
<p>Well, the final rug was pulled. Fortunately, there was a bit of a silver lining. The folks at Tapbots were able to launch their lovely Mastodon app <a href="https://tapbots.com/ivory/">Ivory</a>. The launch went so well that a flood of people took that as an opportunity to take a closer look at Mastodon and join. Mastodon has grown from 500,000 active users last year to now being <a href="https://mastodon.social/@mastodonusercount">almost at 10 million</a>.</p>
<p>Mastodon just keeps getting better. There&#x27;s more authentic conversations and far less linkbait and thread spam from influencers. It feels like a place I&#x27;d prefer spending more of my time to catch up on things.</p>
<p>With my interest in Mastodon, I recently decided I wanted to take the next step and host my own Mastodon server for my account: <a href="https://stammy.design/@stammy">@stammy@stammy.design</a>. In my <a href="https://paulstamatiou.com/mastodon/">previous post about Mastodon</a> I provided some details about different routes you could take to self-host Mastodon. Today, I&#x27;ll show you how you can host your own Mastodon instance, step-by-step.</p>
<div><h3>Table of contents</h3><p>This is a long post and took me more than a month to write, but you don&#x27;t have to go through it all. At a high-level I show two routes to hosting your own Mastodon server: a simple route employing a fully-managed webhost, and a much more comprehensive and advanced route involving a traditional webhost.</p><p>I also make sure you&#x27;re good to go with maintenance tips, debugging tips, scripts to backup your database, purge storage and more.</p><ul>
<li><a href="https://paulstamatiou.com/hosting-your-own-mastodon-server/#so-you-want-to-host-your-own-mastodon-server">So you want to host your own Mastodon server?</a></li>
<li><a href="https://paulstamatiou.com/hosting-your-own-mastodon-server/#choose-how-youd-like-to-host">Choose how you&#x27;d like to host</a></li>
<li><a href="https://paulstamatiou.com/hosting-your-own-mastodon-server/#setting-up-mastodon-with-mastohost">Setting up Mastodon with Masto.host</a></li>
<li><a href="https://paulstamatiou.com/hosting-your-own-mastodon-server/#setting-up-mastodon-with-a-regular-webhost">Setting up Mastodon with a regular webhost</a></li>
<li><a href="https://paulstamatiou.com/hosting-your-own-mastodon-server/#logging-into-mastodon">Logging into Mastodon</a></li>
<li><a href="https://paulstamatiou.com/hosting-your-own-mastodon-server/#migrating-your-account">Migrating your account</a></li>
<li><a href="https://paulstamatiou.com/hosting-your-own-mastodon-server/#what-to-expect">What to expect</a></li>
<li><a href="https://paulstamatiou.com/hosting-your-own-mastodon-server/#maintaining-debugging-and-optimizing-your-server">Maintaining, debugging, and optimizing your server</a></li>
<li><a href="https://paulstamatiou.com/hosting-your-own-mastodon-server/#the-end">The end</a></li>
</ul></div>
<h3>So you want to host your own Mastodon server?</h3>
<p>And why you would want to do host your own Mastodon server? If you&#x27;ve read this far, you probably already have a hunch or two as to why, but here are a few excuses to choose from:</p>
<ul>
<li>
<p>You value being in complete control over your Mastodon identity, data, and privacy. You don&#x27;t want to risk it on an instance where you don&#x27;t know the moderators, don&#x27;t want to be under their control, or simply don&#x27;t trust them to maintain the server long-term.</p>
</li>
<li>
<p>You want a speedy Mastodon experience. By controlling your own instance you can set it up with the appropriate resources and hosting location near you to keep Mastodon feeling speedy at all times. That&#x27;s not the case with various instances, especially the larger ones experiencing rapid growth.</p>
</li>
<li>
<p>You want a weekend project, because Mastodon is open source and able to be self-hosted</p>
</li>
<li>
<p>You see lots of people running their own instance and it seems cool.</p>
</li>
<li>
<p>You want a better Mastodon user name, one that speaks more to your identity or interests. Run Mastodon on your long-time domain name or an entirely new one, paired with whatever user name you like.</p>
</li>
</ul>
<p>Whatever your reason for wanting to host your own Mastodon server, I&#x27;m here to help you get started. I&#x27;ll walk you through the process of setting up your own Mastodon server. I&#x27;ll also provide some tips along the way to help you get the most out of your Mastodon experience.</p>
<h3>What you&#x27;ll need</h3>
<p>At a bare minimum, you&#x27;ll need a domain, some money, and some time:</p>
<p><strong>A domain.</strong> Picking the user name and domain name you wish to use for your new Mastodon instance is probably the hardest part.</p>
<p>You&#x27;ll need a domain name you can connect with your new Mastodon server. You should also know the basics of how to modify DNS records on it. This varies by domain name registrar but is generally pretty easy to figure out. If you don&#x27;t have a preferred registrar yet, Google Domains is pretty easy and you don&#x27;t have to make a new account with two-factor auth if you&#x27;re already a Google user.</p>
<p>Otherwise, I also like Amazon AWS Route 53, but it&#x27;s a bit harder to use and they don&#x27;t support nearly as many top-level domains (such as .design, .dev, et cetera) as other registrars.</p>
<p><strong>Some money.</strong> For a single user instance you can get away with $6/mo with the lowest plan on masto.host. but if you have a lot of followers (or just want a beefier server), you&#x27;ll want to upgrade to a bigger plan and that could run you closer to $50/mo.</p>
<p><strong>And a few hours.</strong></p>
<p>If you opt for a more involved hosting setup you&#x27;ll need access to a few more things, such as an SMTP server to send emails, and optionally, access to a cloud service such as Amazon S3 to host media. I&#x27;ll get into that in a bit.</p>
<hr/>
<h3>Choose how you&#x27;d like to host</h3>
<p>The easy way or the hard(er) way?</p>
<p>I&#x27;ll show you two different ways to setup your own Mastodon server. For the most part I&#x27;m assuming you are only setting up Mastodon for yourself, or just a few people. This guide is not really meant for someone wanting to setup a Mastodon server that will accomodate hundreds of users as that will take you down a different path.</p>
<h3>Option 1: Using a dedicated Mastodon host</h3>
<p>The easiest way to get your own Mastodon server up and running quickly is with a host that specializes in Mastodon hosting. There are <a href="https://docs.joinmastodon.org/user/run-your-own/">several</a>, but I&#x27;ll share how to use one of the most popular ones, Masto.host.</p>
<p>So what exactly do I mean by dedicated host? You won&#x27;t have to worry about the typical setup and maintenance required with a regular host, like configurations, software updates, backups, et cetera. This might be route for you if you want the easiest possible way to get started, and having full server control is not as important to you. You won&#x27;t have complete control over the hardware, the software (beyond Mastodon itself), how your media is stored and served, or anything lower level like that.</p>
<p>While you won&#x27;t have the ability to tweak things and keep an eye on performance, but it&#x27;s an easy way to get started for cheap. The most affordable Masto.host plan is only $6 per month for up to 20GB of media storage and 2GB database. For a casual single user without a lot of followers this should be okay. Masto.host lets you upgrade to higher plans if you need later on.</p>
<p>Personally, I did not want to use an option like this. I wanted to be able to serve my media files with a CDN, control the entire server config, as well as just know more about the hardware used in my server (SSD? NVMe SSD? etc). I always want to have significant headroom on my server in case any of my Mastodon posts goes viral. I don&#x27;t want to have a bogged down server limiting the reach of my posts.</p>
<h3>Option 2: DIY with a regular webhost and server</h3>
<p>The other option is getting a VPS or dedicated server, setting up Mastodon and its dependencies. While this route takes considerably more time to setup, it&#x27;s the most flexible by far. You control everything and you can eke out more performance and functionality. And some hosting providers will give you a head start with a Linux image with Mastodon pre-installed—there&#x27;s quite a few things to configure but this makes it a bit easier.</p>
<p>Maybe you decide you want to modify the code to <a href="https://stammy.design/@stammy/109764353001942728">remove a rate limit</a>, or change the character limit of posts? Maybe you want to move to a fork of Mastodon, like Hometown. Want to serve your media from a fast CDN on a subdomain that you have backed up? You can do all of that on your own server.</p>
<p>As expected, it will take longer to setup (a few hours) and it will probably cost more. But if you&#x27;re reading this far, you probably already know your having own server is right for you.</p>
<h2>Setting up Mastodon with Masto.host</h2>
<h3>Option 1, the easy way</h3>
<p>This is by far the easiest way to get started. By the end of this section, you&#x27;ll have your own Mastodon instance running on your own domain. You only need access to your domain name registrar (or DNS provider if use a separate service) so you can change a DNS record.</p>
<p>You don&#x27;t have to worry about getting access to an SMTP server to send notification emails, nor will you have to figure out how to save media files to a cloud provider.</p>
<h3>Sign up and change DNS</h3>
<p>Visit <a href="https://Masto.host">Masto.host</a>, choose a plan, and provide your domain name (though you can run it as a subdomain on masto.host if you wish). You&#x27;ll be greeted with a page telling you to add a DNS <code>A</code> record so your domain name can point to your Masto.host server.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-setup-masto-dns.jpg" alt="Masto.host DNS setup page" />
<p>Every domain name registrar / DNS provider has a slightly different way of modifying DNS records, so I can&#x27;t show too much more detail there. You&#x27;ll likely need to log into where you have your domain name registered and look for some DNS or zone settings.</p>
<h3>Installation</h3>
<p>When you&#x27;ve successfully added that DNS record, Masto.host should automatically detect it and begin installation.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-setup-masto-install.jpg" alt="Masto.host install in progress" />
<p>The installation screen said this process usually took a few minutes. Unfortunately, in my case it actually took a whopping 8 hours. I hope that&#x27;s just temporary due to a temporary spike in new users.</p>
<h3>Create your Mastodon user & upgrade permissions</h3>
<p>Once that&#x27;s done you can go right to your new Mastodon instance and create an account. This will be your Mastodon account, so choose the username you want.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-setup-masto-just-installed.jpg" alt="Masto.host - New mastodon server setup" width="1999" height="1310" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-setup-masto-change-user-role.jpg" alt="Masto.host - changing user role to Owner" width="2000" height="1167" />
<p>After creating your Mastodon account, you&#x27;ll just need to do one more thing. Go back to Masto.host and look for a button called "Change User Role." Here you can upgrade your new account to have "Owner" privileges. Now your account will have access to a new Administration tab in Preferences.</p>
<h3>That’s it!</h3>
<p>That&#x27;s pretty much it! There are some things to fill out, and settings to change in Preferences which I go over later in this article, but your server is now online and ready to explore!</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-setup-masto-dashboard.jpg" alt="Masto.host server detail page" width="2000" height="1317" />
<small>The Masto.host site leaves a lot to be desired. You can only see how much storage your media and database use.</small>
<p>Aside from that, there&#x27;s not much you can control or change with Masto.host. The site lets you do a few things like download daily backups for your own safe-keeping, change your plan, and opt to install ElasticSearch for an additional monthly fee.</p>
<p>ElasticSearch lets your Mastodon instance have full-text search for logged in users to search their own posts, bookmarks, favorites, and mentions on your server. I probably would not recommend it if you have the smallest server plan as it can use a good bit of RAM; it&#x27;s unclear how much RAM your Masto.host server has and how much RAM ElasticSearch is configured to use.</p>
<h3>What you can&#x27;t do</h3>
<p>There are a few things you won&#x27;t be able to do with a setup like Masto.host where you don&#x27;t have control over the exact configuration. One of these is so-called single user mode. This mode makes the homepage your profile instead of a timeline of users. Typically, you would just update your <code>.env.production</code> file enable it. Though this is a pretty easy thing for Masto.host to build into their web dashboard as a future setting.</p>
<p>Similarly, you can&#x27;t do a more advanced username where you could have a username like you@example.com even though Mastodon may actually be hosted on a subdomain like you@social.example.com. This is described in the <a href="https://docs.joinmastodon.org/admin/config/#web_domain">Mastodon documentation as WEB_DOMAIN</a>.</p>
<h2>Setting up Mastodon with a regular webhost</h2>
<h3>Option 2, the not-so-easy way (DigitalOcean VPS)</h3>
<p>This section is for people like me that want more control over their server and the software that runs on it, and don&#x27;t mind a few twists and turns to get there. In this section we&#x27;ll pick out server hardware and options, create an account to send emails with SMTP, setup media storage with a cloud provider, follow a setup wizard in the command line and then configure a few things.</p>
<p>You should be comfortable with Linux and command line basics for this setup process as well as ongoing server maintence.</p>
<h3>Getting an SMTP server</h3>
<p>First, we&#x27;ll need to get access to an SMTP server to let Mastodon send email notifications. While this seems like a step that should be optional, it&#x27;s required by Mastodon to send emails used to verify new accounts. There are many ways to get access to an SMTP server:</p>
<ul>
<li>
<p><strong>Setup and configure an MTA like <code>postfix</code>, <code>exim</code>, or <code>sendmail</code></strong> on your server. This <a href="https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-postfix-as-a-send-only-smtp-server-on-ubuntu-22-04">is not a particularly easy route</a>. You may still have deliverability issues, or your <a href="https://www.digitalocean.com/blog/smtp-restricted-by-default">webhost may restrict SMTP</a>. It&#x27;s also not advisable to run an SMTP server on the same IP as your web server.</p>
</li>
<li>
<p><strong>Use your email provider&#x27;s SMTP server.</strong> If you use <a href="https://support.google.com/a/answer/176600">GMail (details linked)</a>, <a href="https://support.microsoft.com/en-us/office/pop-imap-and-smtp-settings-for-outlook-com-d088b986-291d-42b8-9564-9c414e2aa040">Outlook</a>, <a href="https://www.fastmail.help/hc/en-us/articles/1500000279921-IMAP-POP-and-SMTP">Fastmail</a> or similar email service providers, you can try to just use their SMTP server. This will require you to provide some credentials (either by generating a unique app-specific password, or your email password), and send from the same email address and domain you currently use with your email.</p>
</li>
<li>
<p><strong>Use a dedicated SMTP provider</strong> like Amazon AWS SES (Simple Email Service), Mailjet, Resend, SendGrid, Mailgun, SMTP2Go, SparkPost, ZeptoMail, Postmark, and many more. I personally use AWS SES and would recommend it if you&#x27;re already using AWS services in some capacity. Setting up SES is a <a href="https://docs.aws.amazon.com/ses/latest/dg/send-email-getting-started-migrate.html">bit involved though</a>, and you&#x27;ll be in a sandbox period at first.</p>
</li>
</ul>
<p>While I personally use AWS SES, I was looking for something even easier to setup for this article and after trying a few, had a great experience getting started with Mailjet. By comparison, trying to setup SendGrid was a disaster; way too many steps involved, including having to talk with support.</p>
<p>There&#x27;s a few steps to follow before you can get your SMTP server login credentials but Mailjet makes it pretty straightforward:</p>
<ul>
<li>
<p>Sign up for a free account at <a href="https://www.mailjet.com/">Mailjet</a>.</p>
</li>
<li>
<p><strong>Add your domain</strong> as a new sender domain. Click "Setup my SMTP" (or navigate to Sender domains from Account) to add your domain.</p>
</li>
<li>
<p><strong>Validate your domain</strong> by adding a TXT DNS record. You&#x27;ll need to log into your DNS provider or domain name registrar to edit that.</p>
</li>
<li>
<p><strong>Authenticate the domain</strong> by adding 2 TXT DNS records for SPF and DKIM.</p>
</li>
<li>
<p><strong>Specify the email address you&#x27;ll send from</strong> and marking it as transactional.</p>
</li>
<li>
<p><strong>Get your API key and SMTP server URL</strong>. This can be found under "SMTP and SEND API Settings" on the Account page. When setting up Mastodon, the API key will act as your SMTP username and the API secret will act as your password.</p>
</li>
</ul>
<div><h3>Tip: Use your webhost for DNS too</h3><p>You may want to just use whichever hosting provider you end up choosing as your DNS provider as well, instead of your domain name registrar (if they differ). Most hosts make it a bit easier to set your <code>A</code> record that points to your server if they also manage the DNS.</p><p>In this article I show how to use DigitalOcean as your hosting provider, so you can skip ahead to that part below or create an account and <!-- --><a href="https://docs.digitalocean.com/products/networking/dns/how-to/add-domains/">follow these instructions</a><!-- -->.</p></div>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-mailjet-domains.jpg" alt="" width="2000" height="1516" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-mailjet-domains-dns.jpg" alt="" width="2000" height="1205" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-mailjet-sender-address.jpg" alt="" width="2000" height="1162" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-mailjet-apikey.jpg" alt="" width="2000" height="2200" />
<small>Mailjet is one of the easier ways to get access to </small>
<p>Keep your new SMTP credentials handy, you&#x27;ll need it soon.</p>
<h3>Picking your webhost</h3>
<p>You can get a Linux server up and running from any number of hosting providers (like AWS EC2 or Lightsail, Linode, Hetzner, DigitalOcean, Vultr, etc) if you&#x27;re comfortable with the <a href="https://docs.joinmastodon.org/admin/install/">standard Mastodon installation process</a>. If you go this route you&#x27;ll need to install various system packages, Ruby, Node, Postgres and nginx among others.</p>
<p>However, I&#x27;m going to focus on using a DigitalOcean "Droplet" for this article. Mainly because they have a <a href="https://marketplace.digitalocean.com/apps/mastodon">1-Click Mastodon installer</a>. It saves you a good bit of time but there&#x27;s still more to do after that I&#x27;ll walk you through.</p>
<p>Droplets are DigitalOcean&#x27;s name for their Linux-based virtual machines running on virtualized hardware. They have a good variety of hardware to choose from, including options for faster NVMe SSDs which I really appreciate.</p>
<p>Lets get started! Click "Create Mastodon Droplet" on <a href="https://marketplace.digitalocean.com/apps/mastodon">the 1-click installer page</a> and create an account if you don&#x27;t have one yet.</p>
<h3>Picking your hardware</h3>
<p>After logging in you&#x27;ll be sent to a page to create your new Mastodon droplet and select what hardware to use. How much CPU, RAM and storage space do you need? Storage doesn&#x27;t really matter as we&#x27;ll be hosting uploaded media on a separate cloud service. As for storage speed, DigitalOcean droplets only offers SSDs and faster NVMe SSDs; no slower mechanical hard drives. You can opt for the NVMe SSD if you wish (I did) but it&#x27;s probably overkill for most people just setting up a single-user personal Mastodon instance.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-digitalocean-setup-droplet.jpg" alt="Creating your DigitalOcean droplet server for Mastodon" width="1000" height="1124" />
<small>Creating a DigitalOcean "droplet" server</small>
<p>With CPU and RAM, it&#x27;s definitely a lot of "the more, the better" and whatever you can afford, but here&#x27;s some additional context to think about it with:</p>
<p><strong>RAM:</strong> When it comes to RAM, while you could get by with 1GB, I would say you&#x27;d want at least 2GB, especially if you plan to run ElasticSearch on your instance. I ended up going with 4GB and my machine on average consumes about ~2GB of RAM so I have a good amount of headroom.</p>
<p><strong>CPU:</strong> CPU is critical to several parts of what run Mastodon like Sidekiq, a background job processor, and Puma, the app server on top of nginx. The more CPU resources you have available, the more processes and threads you can spin up without bogging down your system. With the web server for example, if you increase the number of threads you&#x27;ll use more CPU, but if you create more processes, you&#x27;ll use more RAM.</p>
<p>I picked a server with 2 Intel cores and it has been doing fine with my Mastodon activity with about 4,000 Mastodon followers.</p>
<div><h3>Tip: Start small</h3><p>With DigitalOcean droplets you can easily upgrade to a more powerful machine, but you may not be able to downgrade to a less powerful machine. This is usually due to having a disk image that&#x27;s too large for another server.</p><p>I suggest starting with a server that has 2GB of RAM. If you find you need more RAM, CPU, disk space, et cetera, you easily upgrade later. It takes maybe 5-10 minutes to upgrade and DigitalOcean handles everything for you automatically.</p></div>
<p>After selecting your server hardware, you&#x27;ll want to select the option to enable monitoring and backups. Then, click "Advanced" and enable IPv6. And finally, you&#x27;ll need to create or provide an SSH key. I highly recommend following <a href="https://docs.digitalocean.com/products/droplets/how-to/add-ssh-keys/">their SSH instructions</a> so you can use a key that your computer has so you can easily access your server with <a href="https://iterm2.com/">your preferred terminal app</a>. You can still use the web console provided by DigitalOcean but it&#x27;s a bit clunky.</p>
<div><h3>Option: Managed Database</h3><p>I ended up selecting the option to have a managed database for an extra $15 per month. If you don&#x27;t mind the extra cost it&#x27;s nice for it&#x27;s automatic backups that let you revert to any point in time. That being said, for a single user Mastodon instance, you probably won&#x27;t get any performance benefit out of it, just peace of mind. And since it&#x27;s basically another remote server, you can access it with a tool like SQLPro for Postgres (if you&#x27;ve configured its security settings to allow your IP) if you&#x27;re so inclined to poke around in the database.</p><p><strong>Important:</strong> If you select the managed database option while creating your Mastodon 1-Click droplet, it should automatically put the correct database credentials for you, but there is one more place where you need to specify the database access credentials: <code>/etc/environment</code>. If you don&#x27;t do this you may see Mastodon admin CLI commands fail, such as when trying to modify your first Mastodon account to give it owner privileges.</p><p>You will also want to verify that <code>/etc/environment</code> has the correct database name specified. By default it should be <code>mastodon_production</code>.</p><p>And finally, you will need to add the following to <code>/home/mastodon/live/.env.production</code>:</p><pre><code class="language-plaintext">DB_SSLMODE=require
# You may also need to do the following as a hack
# More context: https://github.com/mastodon/mastodon/discussions/19917
NODE_TLS_REJECT_UNAUTHORIZED=0
</code></pre><p>And then restart the services <code>sudo systemctl restart mastodon-*</code>. Without those lines, you may see some errors in the streaming service logs.</p><p>And finally, you&#x27;ll want to go to DigitalOcean, click on your managed database, then visit settings to ensure you restrict connections to just your IP and your Mastodon server under the "Trusted sources" section.</p></div>
<p>Click <strong>Create Droplet</strong> and your server should be ready in about 30 seconds or so.</p>
<h3>Adding your domain & setting up DNS</h3>
<p>Next up, we&#x27;ll need to add your domain name to DigitalOcean and setup necessary DNS records.</p>
<div><h3>Tip: Using a Mastodon on a domain where you already host a website, without exposing the subdomain</h3><p>If you wanted to use a domain where you&#x27;re already hosting a website, you may think that it&#x27;s not possible to host Mastodon on that domain without resorting to a subdomain which would leave you with a lengthy Mastodon username like <code>username@social.example.com</code>.</p><p>Fortunately there&#x27;s a a lesser known Mastodon tip that lets you host Mastodon on a subdomain but allows your username to be shown as being directly on the root domain itself, such as <code>username@example.com</code>. This is done by setting the <code>WEB_DOMAIN</code> environment variable to the root domain. This is not something that the Mastodon setup wizard will ask you about, but it&#x27;s something you can do after the setup wizard is complete by manually editing the <code>.env.production</code> file, typically located in the <code>/home/mastodon/live</code> directory.</p><p>This is described in the <!-- --><a href="https://docs.joinmastodon.org/admin/config/#web_domain">Mastodon documentation as ,[object Object]</a><!-- --> and <code>LOCAL_DOMAIN</code>. To sum up: with this configuration you can have Mastodon hosted on a subdomain but completely hide that from people that follow you. They&#x27;ll only see your username at your root domain.</p></div>
<ul>
<li>Click the menu on your droplet and select <strong>Add a domain</strong>.</li>
<li>Type in the domain you want to use for Mastodon, and select your droplet server from the dropdown.</li>
<li>If you haven&#x27;t done so already, you&#x27;ll want to go to your domain name registrar and designate DigitalOcean as the DNS host by adding the 3 nameservers shown. More info <a href="https://docs.digitalocean.com/tutorials/dns-registrars/">can be found here</a>.</li>
<li>Finally, you just need to add an <code>A</code> record for your droplet. Just type <code>@</code> for the Hostname and click the dropdown to select your droplet to automatically select the IP address needed.</li>
</ul>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-digitalocean-server-setup-add-domain.jpg" alt="Add domain to DigitalOcean" width="2000" height="1312" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-digitalocean-server-setup-add-domain-2.jpg" alt="Adding your domain to digitalocean" width="2000" height="725" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-digitalocean-server-setup-add-domain-record.jpg" alt="Adding DNS A record in DigitalOcean" width="2000" height="610" />
<p>After DNS propagates in a few moments you&#x27;ll be able to directly SSH into your server with just <code>ssh root@yourdomain.com</code>, assuming you setup your SSH key earlier.</p>
<h3>Setting up cloud file storage</h3>
<p>Before we can start setting up Mastodon, there&#x27;s one more thing we need to do: setup and get login credentials for cloud object storage for all user-uploaded files on your Mastodon instance. This part is optional: Mastodon can easily host files directly from your server.</p>
<p>However, hosting user-uploaded files on a cloud service instead of your Mastodon server has some benefits. First, it takes the load off your web server to respond to requests for media, freeing up your server to respond to other requests. This is especially important if you have a less powerful server. It&#x27;s an easy way to make things more performant. Second, cloud object storage providers are made for serving static files quickly and that&#x27;s especially true if you use one with a CDN.</p>
<p>There are a lot of services to choose from such as DigitalOcean Spaces, Wasabi, Minio, Google Cloud Storage, Amazon S3, and any service that offers S3-compatibility like <a href="https://developers.cloudflare.com/r2/examples/mastodon/">Cloudflare R2</a>.</p>
<p>I personally use Amazon S3 with a CloudFront distribution (CDN), used on a CNAME subdomain. It was a bit more involved to setup, including creating separate IAM and bucket permissions, so I wanted to show a simpler solution for this article, using DigitalOcean Spaces. If you&#x27;re familiar with AWS, that&#x27;s a great route to consider though.</p>
<p>The easiest way is to use DigitalOcean&#x27;s own object storage solution, Spaces. It costs $5/month for 250GB of storage with 1TB of outbound transfer. That should be more than enough space for most.</p>
<p>To get started, click the <strong>Create</strong> button at the top of DigialOcean&#x27;s dashboard and select Spaces to create a bucket for storing your Mastodon server&#x27;s files. Here you&#x27;ll need to pick a bucket name and location, which should default to the same region as your droplet server. The bucket name doesn&#x27;t matter much as it&#x27;s not readily visible to your users unless they dig into their browser web inspector. You&#x27;ll also want to check the box to enable CDN.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-digitalocean-create-spaces-bucket.jpg" alt="Creating DigialOcean Spaces bucket" width="2000" height="1611" />
<p>After you create the bucket you&#x27;ll need to specify a subdomain to access your files from and setup an SSL certificate so HTTPS will work. DigitalOcean makes this pretty easy. Go to the <strong>Settings</strong> tab of your new Spaces bucket and click <strong>Change → Edit CDN Settings</strong>.</p>
<p>Select a subdomain name that you&#x27;ll use for hosting user-uploaded media on your Mastodon server, like <code>files.yourdomain.com</code>. While this is optional, it&#x27;s a nice touch. After the certificate is created, the next step is to just select it from the dropdown on the Settings page under CDN as shown below. If you&#x27;re lost at any point during this process, more <a href="https://docs.digitalocean.com/products/spaces/how-to/enable-cdn/">details can be found here</a>.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-digitalocean-create-spaces-bucket-cdn.jpg" alt="Edit CDN Settings" width="2000" height="1000" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-digitalocean-create-spaces-bucket-cdn-subdomain.jpg" alt="Create subdomain for Spaces CDN and setup SSL certificate" width="2000" height="1762" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-digitalocean-create-spaces-bucket-cdn-subdomain-config.jpg" alt="Configure CDN" width="2000" height="1569" />
<p>The final step is getting the API key and secret for your new bucket. On the main Spaces page (click Spaces from the sidebar) there is a link at the top right titled <strong>Manage keys</strong>. Click that and then you can generate a new key and give it a name. Once you&#x27;re done with that copy your key and secret for use later.</p>
<h3>Setting up Mastodon</h3>
<p>By this point your DigitalOcean project should look like this: you have a droplet server, a Spaces bucket, and an attached domain.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-digitalocean-server-setup.jpg" alt="DigitalOcean Droplet and project dashboard" width="2000" height="1348" />
<p>You&#x27;re ready to begin the actual Mastodon setup! Mastodon is already installed thanks to the 1-Click Droplet installer. You just need to access the setup wizard via the command line. You can use the built-in console on the website or SSH into it with your preferred terminal app. The website console can be accessed by selecting <strong>Access console</strong> from the <strong>...</strong> menu on your droplet. I prefer directly SSHing into the server with <code>ssh root@yourdomain.com</code>.</p>
<p>When you&#x27;re connected to your server, you&#x27;ll instantly see the Mastodon setup wizard start to run:</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-digitalocean-mastodon-setup-wizard.jpg" alt="Setting up Mastodon in the command line" width="2000" height="1217" />
<small>The Mastodon setup wizard</small>
<div><h3>Tip: If you make a mistake...</h3><p>If at any point you make a mistake while working in the command line setup wizard and need to undo something, just close the SSH session or web console, and re-open it. The setup process will start over again until it&#x27;s completed.</p></div>
<p>You&#x27;ll be asked to answer a few questions and fill in some details and credentials:</p>
<ul>
<li>
<p><strong>Domain name:</strong> Your domain name for Mastodon.</p>
</li>
<li>
<p><strong>Do you want to store user-uploaded files on the cloud? (y/N):</strong> Type <code>y</code> for yes.</p>
</li>
<li>
<p><strong>Provider:</strong> Select DigitalOcean Spaces.</p>
</li>
<li>
<p><strong>Space name:</strong> The bucket name you chose.</p>
</li>
<li>
<p><strong>Space region:</strong> Type in the region for your spaces bucket. When you go to copy your Spaces endpoint, it&#x27;ll be the subdomain after your bucket name that&#x27;s short (like <code>nyc3</code>) depending on the hosting location.</p>
</li>
<li>
<p><strong>Space endpoint:</strong> Your Spaces "Origin Endpoint" as seen on the DigitalOcean website <em>but with the bucket name subdomain at the front removed</em>. Even though you setup the CDN, for this you need the non-CDN URL or it won&#x27;t work. For me it was the following but this varies based on the location you chose:</p>
<pre><code>https://nyc3.digitaloceanspaces.com
</code></pre>
</li>
<li>
<p><strong>Do you want to access the uploaded files from your own domain?</strong>: This is asking if you want to use a CNAME alias for your hosted files, for example to appear as if they are hosted from your domain. I&#x27;ll assume you followed the directions above for setting up Spaces CDN with a subdomain and certificate, so you can say <code>yes</code>.</p>
</li>
<li>
<p><strong>SMTP server:</strong> Check with your SMTP provider, but in the case of Mailjet it was <code>in-v3.mailjet.com</code> for me. This could be different for you.</p>
</li>
<li>
<p><strong>SMTP port:</strong> Depends on your SMTP provider, but likely <code>587</code>.</p>
</li>
<li>
<p><strong>SMTP username / password:</strong> Provide the username and password for your SMTP provider. If you&#x27;re using Mailjet as described above the API key will act as your SMTP username and the API secret will act as your password.</p>
</li>
<li>
<p><strong>SMTP authentication:</strong> The default <code>plain</code> should be fine. You may also be asked for an OpenSSL verify mode, for that you can usually input <code>peer</code> or <code>none</code>.</p>
</li>
<li>
<p><strong>Email address to send emails "from":</strong> Hit enter to accept the default <code>notifications@yourdomain.com</code> address.</p>
</li>
<li>
<p><strong>It is time to create an admin account that you&#x27;ll be able to use from the browser! Username:</strong> Pick the username that you&#x27;ll want to use for your Mastodon profile.</p>
</li>
</ul>
<p>Your full Mastodon handle will end up being <code>@yourusername@yourdomain.com</code>.</p>
<p>At this point you&#x27;ll be given a password to log into your new Mastodon account. You&#x27;ll want to change it to something stronger after you log in for the first time (more on that later). But before that can be done you&#x27;ll need to follow the instructions to setup your SSL certificate with Let&#x27;s Encrypt so https will work for your domain.</p>
<p>If you find yourself struggling to get the Let&#x27;s Encrypt process to work, check the DNS records on your domain to ensure everything is setup correctly, particularly the <code>A</code> record for the domain and that you&#x27;ve correctly added the DigitalOcean nameservers with your registrar. Also, you can just give it some time for DNS to propagate and try again later.</p>
<p>There&#x27;s just a few more things to do before logging into your new Mastodon server.</p>
<h3>Fixing the cloud storage config</h3>
<p>Unfortunately I was unable to get DigitalOcean Spaces cloud object storage with CDN working flawlessly out of the gate and had to manually edit a few lines in a config file. We&#x27;ll be editing the <code>.env.production</code> file—where a lot of Mastodon settings live— to adjust some of the media storage settings.</p>
<ul>
<li>
<p><strong>If you&#x27;re using the subdomain as shown during Spaces setup:</strong>
You&#x27;ll need to add a line for <code>S3_ALIAS_HOST</code> as shown below. This value is the same as the subdomain you setup earlier along with the SSL certificate. Then you&#x27;ll need to modify the S3_ENDPOINT and S3_HOSTNAME values to be in this format.</p>
<pre><code>S3_PROTOCOL=https
# Replace the following with your bucket name 
S3_BUCKET=stammy-mastodon
# Replace with your bucket region
S3_REGION=nyc3
# Replace with the subdomain you setup earlier for your Spaces bucket / CDN
S3_ALIAS_HOST=files.stammy.social
# Change the region in the URL below to match your bucket region
S3_ENDPOINT=https://nyc3.digitaloceanspaces.com
# This is your "Origin Endpoint" as found on your Spaces bucket page
S3_HOSTNAME=stammy-mastodon.nyc3.digitaloceanspaces.com
</code></pre>
</li>
<li>
<p><strong>If you&#x27;re not using a subdomain alias for hosting your files:</strong> You will need to remove the bucket name from your DigitalOcean Spaces bucket&#x27;s "Origin Endpoint" that is used as your hostname. Ensure your S3_ENDPOINT and S3_HOSTNAME look like this. Remove any line with S3_ALIAS_HOST if it already exists.</p>
<pre><code>S3_ENABLED=true
S3_PROTOCOL=https
S3_BUCKET=stammy-mastodon
# Replace nyc3 region in the next 3 lines with your bucket region
S3_REGION=nyc3
S3_HOSTNAME=nyc3.digitaloceanspaces.com
S3_ENDPOINT=https://nyc3.digitaloceanspaces.com
</code></pre>
</li>
<li>
<p><strong>If you used Amazon S3 with CloudFront instead:</strong> If you went for the more advanced route of using S3 with a CloudFront distribution connected to a CNAME on your domain, you will configure it like this:</p>
<pre><code># Your S3 bucket name. 
S3_BUCKET=my-mastodon-files
# Replace us-east-1 with your bucket region, lowercase.
S3_REGION=us-east-1
# Hostname is likely your bucket name + .s3.amazonaws.com
S3_HOSTNAME=my-mastodon-files.s3.amazonaws.com
# Only use if you&#x27;ve configured a CloudFront CNAME on your domain with SSL cert 
# If you&#x27;re not using a CNAME, remove this line and then change the S3_HOSTNAME to the default (such as s3.us-east-1.amazonaws.com based on your region)
S3_ALIAS_HOST=turbo.stammy.design
# You do not need an S3_ENDPOINT line
</code></pre>
</li>
</ul>
<p>Once you&#x27;ve made the changes to your <code>.env.production</code> file, you&#x27;ll need to restart the Mastodon services to apply the changes:</p>
<pre><code>sudo systemctl restart mastodon-*.service
</code></pre>
<h3>Upgrading your Mastodon account privileges</h3>
<p>By default your new Mastodon account does not have all privileges available. Mastodon allows an account to have roles like Moderator, Admin, and Owner. You&#x27;ll want to modify your account to have the Owner role. This can be done using the admin CLI tool called <a href="https://docs.joinmastodon.org/admin/tootctl/">tootctl</a>.</p>
<p>Connect to your server via SSH again (or DigitalOcean&#x27;s web console) and run the following commands:</p>
<pre><code># Change from the root user to the mastodon user 
sudo su - mastodon 
# Change to the Mastodon bin directory 
cd /home/mastodon/live/bin
# Modify your account to have the Owner role
RAILS_ENV=production ./tootctl accounts modify admin --role Owner
</code></pre>
<p>This may take a few seconds then you should see "OK". If you have any issues, or are using a different webhost, just confirm that you&#x27;re in the right directory. If you have an error running this and happen to be using the DigitalOcean managed database, you may need to configure the database in another file. Read the <a href="#managed-db">managed database</a> section for details.</p>
<h3>Enabling single user mode</h3>
<p>If this Mastodon account is for you and you only, you can enable single user mode to have the Mastodon homepage be a profile view of your account. By default, this is not enabled and the Mastodon homepage is a timeline view.</p>
<p>To enable this, you&#x27;ll need to edit <code>.env.production</code> and then restart the web server.</p>
<pre><code># Change from the root user to the mastodon user 
sudo su - mastodon 
# Change to the Mastodon web directory 
cd /home/mastodon/live
# Edit the .env.production file in Vim
vim .env.production
</code></pre>
<p>Now you&#x27;ll need to create a new line anywhere in the file by moving the cursor with the arrow keys, tapping i to enter Insert mode, creating a new line, then typing in the following line:</p>
<pre><code>SINGLE_USER_MODE=true
</code></pre>
<p>Tap ESC to exit insert mode, and then type :wq and hit enter to save and exit vim. And finally, exit mastodon user mode to go back to root by typing <code>exit</code>, and then restart the web server:</p>
<pre><code># Restart the web server, this can take a few seconds
systemctl restart mastodon-web.service
</code></pre>
<h3>Ensuring your SSL cert will auto-renew without issue</h3>
<p>Mastodon uses the popular certbot tool from the EFF to obtain certs from Let&#x27;s Encrypt and enable HTTPS on your server. That part all worked great during the initial setup. Certificates from Let&#x27;s Encrypt last for 90 days before they need to be renewed. Certbot makes them easy to auto-renew: it should have installed a cron with it either in a systemd <code>certbot.timer</code> (see it with <code>systemctl show certbot.timer</code> if you&#x27;re curious) or in <code>/etc/cron.d/certbot</code>.</p>
<p>You&#x27;ll need to ensure that your cert will auto-renew without issue. Shouldn&#x27;t this work out of the box? It should, yes. However, I began poking around in my setup and noticed a configuration issue by default (not sure if this is a DigitalOcean Mastodon installer issue or a Mastodon issue) that would lead to renewal failing.</p>
<p>The default method used is called standalone mode and it only works when the web server is not running, which won&#x27;t happen during auto-renewal unless you setup your own cron that also stops and starts the server for renewal. This is fine for the initial setup, but if you want to auto-renew your cert, you&#x27;ll need to use a different method. For more context on this issue, see this commit has <a href="https://github.com/mastodon/documentation/pull/1036/commits/9bc371f3547a884aa094a1151e813f678bd0623e">updated installation instructions</a> that were never merged to Mastodon main, and <a href="https://github.com/mastodon/documentation/issues/940">this issue</a>.</p>
<p>First, see if you&#x27;ll even have an issue by doing a dry run invocation of the certbot renew command:</p>
<pre><code>sudo certbot renew --dry-run
</code></pre>
<p>If the dry run says the renewal would be successful, you don&#x27;t need to do anything else and your setup is all good. If it says renewal will fail, you likely need to do the following:</p>
<pre><code># Edit this config file, swapping out example.com for your domain 
vim /etc/letsencrypt/renewal/example.com.conf
</code></pre>
<p>Then find the line that says <code>authenticator = standalone</code> and replace it with these two lines below and save the file.</p>
<pre><code>authenticator = nginx
installer = nginx
</code></pre>
<p>Now you can do a dry run again and it should say the renewal would be successful as shown below:</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-certbot-renew-dryrun.png" alt="Terminal showing a dry run of certbot renew for SSL cert" width="2000" height="1039" />
<h3>Final setup: updating packages, enabling the firewall, etc..</h3>
<p>At this point you could skip ahead and check that Mastodon works and log into your account for the first time, but you&#x27;ll need to come back to complete a few more things. For the most part you just need to <a href="https://docs.joinmastodon.org/admin/prerequisites/#do-not-allow-password-based-ssh-login-keys-only">follow this Mastodon guide</a> where you&#x27;ll update system packages, configure fail2ban to block repeated login attempts and setup a firewall.</p>
<p>The DigitalOcean website has its own interface for configuring a firewall but after repeated attempts I was unable to get it working, so I stuck with the route recommended by Mastodon: iptables.</p>
<h3>Optional: Configure IPv6</h3>
<p>During DigitalOcean droplet setup you checked a box to enable IPv6 connectivity for your server. Even though that is enabled, you will need to edit some files and add a DNS record. Follow <a href="https://docs.digitalocean.com/products/networking/ipv6/how-to/enable/#on-existing-droplets">this DigitalOcean guide.</a></p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-digitalocean-ipv6-aaaa.png" alt="DigitalOcean adding AAAA record for IPv6" width="2000" height="504" />
<p>Then you&#x27;ll need to add an <code>AAAA</code> DNS record to your domain. An <code>AAAA</code> record is like an <code>A</code> record that points to your server, but for IPv6. DigitalOcean should automatically show you your server&#x27;s IPv6 address in a dropdown when creating that record.</p>
<h3>Optional: Setting up automatic database backups</h3>
<p>If you opted not to go for the DigitalOcean managed database upgrade, you&#x27;ll want to a way to export and save backups of your database on a recurring basis. The easiest way to do this is to setup a cronjob that runs a script to dump your database, zip it up, and save it to a cloud storage bucket with the Amazon AWS command line interface. Since we already setup Spaces for cloud object storage, we can re-use that to save your database backups, though if you want to spend the extra time to use a separate cloud provider or bucket for saving only backups, that is preferrable.</p>
<p>First, you&#x27;ll need to install the AWS CLI. You could follow <a href="https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2-linux.html#cliv2-linux-install">this guide</a> to install the AWS CLI, but likely you can just install it with: <code>apt</code>:</p>
<pre><code># Run as root 
apt install awscli
# Provide your credentials for your Spaces bucket, api key and secret when prompted 
aws configure 
# Switch to the Mastodon user
sudo su - mastodon 
# Test to see that it works by listing what&#x27;s in your Spaces bucket 
# Note: you need to replace the region with your region if different 
# Any time you interact with the AWS CLI, you need to use the --endpoint-url option to 
# specify that we are using DigitalOcean Spaces, not Amazon S3
aws --endpoint-url https://nyc3.digitaloceanspaces.com s3 ls

cd /home/mastodon

# Now we&#x27;ll create the script to backup the database
vim backup_database.sh
</code></pre>
<p>Tap i to enter Insert mode in vim, and paste the following, replacing the Spaces region in the endpoint URL with your Spaces region code:</p>
<pre><code class="language-bash">#!/bin/bash

# Create a filename with the date and time
FILENAME=mastodon_production_$(date +%Y%m%d%H%M).gz

# Dump the database, gzip it, and save locally 
pg_dump mastodon_production | gzip > ${FILENAME}

# Upload the file to your Spaces bucket
# Important: Replace the region with your region if different
# Important: Replace the bucket name &#x27;stammy-mastodon&#x27; with your bucket name
aws --endpoint-url https://nyc3.digitaloceanspaces.com s3 cp ${FILENAME} s3://stammy-mastodon/backups/

# Delete the local file
rm ${FILENAME}
</code></pre>
<p>Save the script (Tap ESC to exit insert mode, type :wq, hit Enter), then made it executable:</p>
<pre><code>chmod +x backup_database.sh
</code></pre>
<p>Now we&#x27;ll create a cronjob to run the script every day:</p>
<pre><code># Enter cron job editor. If you&#x27;re asked what editor to use, select vim again.
crontab -e
</code></pre>
<p>Create a new line after the comment block at the time, and enter the following to create a database backup every week. If you want more frequent backups, you can customize it to your liking, such as with <code>0 0 */3 * *</code> for every 3 days. Take a look at <a href="https://crontab.guru/">crontab.guru</a> to help you figure out what values to input.</p>
<pre><code># Backup every week
@weekly ./backup_database.sh
</code></pre>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-autobackup-database.png" alt="Configuring a cronjob to backup the database" width="2000" height="1309" />
<p>Save the file and you should be good. You may want to try manually running the script now (<code>./backup_database.sh</code>) to ensure it works, and check your Spaces bucket to see a new file was added to the backups directory.</p>
<h3>Optional: Install ElasticSearch</h3>
<p>If you want the ability for you and your Mastodon instance users to be able to search their own posts, bookmarks, favorites, and mentions, you&#x27;ll need to install ElasticSearch. This is optional because it&#x27;s really not that useful. You cannot search across instances, and it does not even support showing posts from other people on other servers that your server has seen but that do not mention you, even if you follow them.</p>
<p>It also takes a bit of RAM, so I especially would not recommend install ElasticSearch if you only have 2GB of RAM or less server. It can be done, but I don&#x27;t think it&#x27;s worth it.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-elastic-search-off.jpg" alt="What mastodon search looks like without elastic search installed" width="2000" height="1263" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-elastic-search-on.jpg" alt="Mastodon with elastic search installed, showing search results" width="2000" height="1901" />
<small><strong>Left:</strong> Mastodon search without ES installed. <strong>Right:</strong> With ES installed, showing local results for people, hashtags and posts, including your own.</small>
<p>To install ElasticSearch, you can <a href="https://docs.joinmastodon.org/admin/optional/elasticsearch/">follow these instructions from the Mastodon site</a>. However, when you get to the part of the guide that tries to enable the service, you may see this error:</p>
<pre><code>Job for elasticsearch.service failed because a fatal signal was delivered to the control processed
</code></pre>
<p>This is likely to happen if your machine doesn&#x27;t have enough RAM. By default ElasticSearch tries to take a lot of RAM, so you&#x27;ll want to configure it to use less. For example, if you only wanted it to use 512MB of RAM, you can create a new file <code>memory.options</code>:</p>
<pre><code># Create an elastic search config file to limit memory usage
vim /etc/elasticsearch/jvm.options.d/memory.options
</code></pre>
<p>Then enter these two lines to specify a min and max amount of RAM that ElasticSearch can use. For example, a min of 256MB and max of 512MB:</p>
<pre><code>-Xms256m
-Xmx512m
</code></pre>
<p>Save the file and try to start the service again:</p>
<pre><code>systemctl daemon-reload
systemctl enable --now elasticsearch
</code></pre>
<p>Run the rest of the steps mentioned in the guide and you should have functional search on your instance. You may run into one more issue resulting in a security warning. This <a href="https://github.com/mastodon/mastodon/issues/18625">github thread</a> is helpful for resolving that (though I think it was also fixed recently in Mastodon 4.1.0).If you want to go down the rabbithole you can modify <a href="https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html">more security settings</a> but it&#x27;s likely not a huge deal as we&#x27;ll be setting up a firewall that won&#x27;t allow port access to ElasticSearch.</p>
<h2>Logging into Mastodon</h2>
<h3>Changing settings, configuring scripts & testing</h3>
<p>If you used a fully-managed host like Masto.host (mentioned earlier), you&#x27;ve already created an account and logged in. If you&#x27;ve followed the guide for creating your own server for Mastodon, then you were given a temporary password to login with. Now it&#x27;s time to visit your website and sign into Mastodon. You&#x27;ll also want to immediately enable two-factor auth.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-web-signin.jpg" alt="Mastodon server logged out view after installing Mastodon" width="2000" height="1328" />
<small>Your new homepage (single user mode enabled) will look empty like this</small>
<p>After signing in, click <strong>Preferences</strong> in the sidebar. The first thing we want to do is confirm that upgrading your account to the owner role actually worked. You should see a tab for <strong>Administration</strong> along with others like Sidekiq and PgHero. It should look like this:</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-web-admin-tab.jpg" alt="Mastodon Admin Settings" width="2000" height="1813" />
<p>Feel free to browse the Profile tab to fill out your bio and related settings. Importantly, I think "Require follow requests" may be on by default which you probably want to disable.</p>
<p>Next, here&#x27;s a few things to setup:</p>
<h3>Fill out server details</h3>
<p><strong>Administration → Server Settings → Branding:</strong> Fill out the name and description for your server. This is displayed alongside your profile, homepage, and posts so it&#x27;s quite visible. You can also specify an image to display there.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-web-server-branding.jpg" alt="Mastodon admin settings for server branding" width="2000" height="1873" />
<h3>Disable new account creation</h3>
<p><strong>Administration → Server Settings → Registrations:</strong> If this server is just for you, you&#x27;ll want to disable account creation by changing the <strong>Who can sign-up</strong> setting to nobody.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-web-disable-signups.jpg" alt="Mastodon admin settings to disable new user registrations" width="2000" height="1027" />
<h3>Disable unauthenticated access to public timelines</h3>
<p><strong>Administration → Server Settings → Discovery:</strong> This is just a preference but since this is my own server, I only want my posts easily accessible. I wanted to disable the <code>/public</code> (the "Federated" tab) timeline which displayed posts from other people. I&#x27;m also a little concerned about liability related to my server hosting content from other people (as mentioned in <a href="https://paulstamatiou.com/mastodon/#self-hosting-your-own-mastodon-instance">my last Mastodon post</a>) so making those posts harder to find seems best.</p>
<p>As such, I unchecked <strong>Allow unauthenticated access to public timelines</strong>.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-web-discovery.jpg" alt="Mastodon admin settings for discovery" width="2000" height="2210" />
<h3>Adjust media and content retention</h3>
<p><strong>Administration → Server Settings → Content retention:</strong> This page has some important settings that control how much media and content is kept on your server. If you follow or interact with lots of people on Mastodon (or have any relays setup), you will see the size and costs associated with your cloud object storage provider rise.</p>
<p>You change safely set the <strong>media cache retention period</strong> to something like 7-30 days. I went with 7 and haven&#x27;t noticed any odd behavior. This will delete downloaded media files (from other servers, stored on your server or cloud storage) after the specified period. If your server requests the media again, it will be re-downloaded so there&#x27;s no real harm in setting it too low, you can always change it.</p>
<p>The other setting <strong>content cache retention period</strong> is a bit less safe to tinker with and will delete posts from other users on your server. I decided not to touch this and will see if I need to change it if my database grows too large over time.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-web-content-retention.jpg" alt="Mastodon admin settings for content and media retention" width="2000" height="1135" />
<h3>Setting up a cron job for periodic cleanup tasks</h3>
<p>The media retention setting in the admin interface is just one setting. You have far more control at your disposal with the <code>tootctl</code> admin command in the command line. In fact, running these commands regularly is a recommend part of setup, mentioned under <a href="https://docs.joinmastodon.org/admin/setup/#cleanup">periodic cleanup tasks</a>.</p>
<p>For this, I have several of the commands running as a cronjob. I put them in a bash script for a cronjob to run. I could have put them directly in the crontab editor as a weekly task but it&#x27;s easier to keep it in one file where I know it will run serially, without having to specify different run times for each job so they don&#x27;t run at the same time, potentially bogging down your server.</p>
<p>Here&#x27;s a list of the commands I run regularly. I put them in a bash script named <code>cleanup.sh</code> that I store in my home directory <code>/home/mastodon</code>:</p>
<pre><code># This does the heavy lifting and removes locally cached copies of media attachments from other servers
# By default its set to delete media older than 7 days. 
# Adjust days with --days, eg --days 3 for a more aggressive setting
RAILS_ENV=production /home/mastodon/live/bin/tootctl media remove

# Remove local thumbnails for preview cards (the thumbnail when links are shared, etc)
# The default is 180 days and under 14 days is not recommended as they will not be refetched
RAILS_ENV=production /home/mastodon/live/bin/tootctl preview_cards remove --days 60

# Deletes remote accounts that never interacted with local accounts 
# Removes many avatar and header images as part of this
RAILS_ENV=production /home/mastodon/live/bin/tootctl accounts prune

# Removes files that do not belong to existing media attachments 
# For example if you attached a file to a post composer but never posted it
# This command and the one after it are slow to run, so I like to keep them for last
RAILS_ENV=production /home/mastodon/live/bin/tootctl media remove-orphans

# Remove unreferenced statuses from the database, such as statuses that 
# came from relays or from users who are no longer followed by any local accounts, 
# and have not been replied to or otherwise interacted with
RAILS_ENV=production /home/mastodon/live/bin/tootctl statuses remove
</code></pre>
<pre><code># Switch to the mastodon user and home directory 
sudo su - mastodon
# Create bash script 
vim cleanup.sh
# Make the script executable
chmod +x cleanup.sh
# Add the bash script to crontab
crontab -e
</code></pre>
<p>In crontab, add this line and then save:</p>
<pre><code>@weekly ./cleanup.sh
</code></pre>
<p>I set it to run weekly but you may prefer to run it more often. I&#x27;ve been running my own Mastodon server for a month now and with this setup my cloud media storage is only at <code>8.5GB</code> with my usage.</p>
<h3>Use custom CSS to hide or modify things</h3>
<p><strong>Administration → Server Settings → Appearance:</strong> This part is completely optional but I found myself wanting to hide certain parts of the site navigation that aren&#x27;t useful to others as my Mastodon server is only for me. I hid the sign in buttons for logged out users. I hid the "Local" tab for me when logged in: useless for me as I&#x27;m the only account on the server. I also hid the "Learn more" button that shows up next to the server details (felt pretty obvious that the server was just for me and I wanted to simplify things a bit).</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-web-appearance.jpg" alt="Mastodon admin server settings for appearance." width="2000" height="1593" />
<pre><code>// hide sign in buttons (you&#x27;ll have to manually visit /auth/sign_in)
.navigation-panel .navigation-panel__sign-in-banner, 
.ui__header__links a[href="/auth/sign_in"],
.ui__header__links button { display: none !important; }

// Hide the "Local" tab for logged in users (only do this if you&#x27;re the only user on the server)
.navigation-panel a[href="/public/local"] { display: none !important; }

// hide server details "Learn more" button
.server-banner .button { display: none !important; }
</code></pre>
<h3>Bonus: Clean up the admin UI with an Arc Boost</h3>
<p>If you&#x27;re running this Mastodon account for you, and you only, you may find the default admin dashboard has a lot of space taken up by useless information, such as showing you the number of new accounts created. I prefer to keep some of that hidden to clean up this page.</p>
<p>Unfortunately, just adding CSS to hide it as in the previous step does not seem to work for admin pages. So I turned to a feature from my browser, Arc, called Boosts. It&#x27;s an easy way to locally inject CSS (or JS as needed) into any website. Other browsers have similar ways of doing things with extensions. I created an Arc Boost to simply hide a few dashboard modules:</p>
<pre><code># Not pretty, but it does the job
.dashboard .dashboard__item { display: none; }

.dashboard .dashboard__item:nth-child(3), 
.dashboard .dashboard__item:nth-child(9) { display: block; grid-column: span 3; }

.dashboard .dashboard__item:nth-child(12),
.dashboard .dashboard__item:nth-child(13) { display: block; }
</code></pre>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-admin-ui-cleanup2.jpg" alt="Mastodon admin UI with a few modules hidden with CSS." width="2000" height="1667" />
<small>Admin UI, with a bit less clutter for single-user instances.</small>
<h3>Try posting an image</h3>
<p>And one last thing you&#x27;ll want to do is try posting with an image attached. This will confirm your cloud object storage configuration works correctly and that your system can resize images. What you&#x27;ll want to look out for is that dragging an image into the post composer shows a thumbnail preview, and osting it shows the image without requiring you to refresh the page.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-web-test-media-upload.jpg" alt="Mastodon admin settings" width="2000" height="1462" />
<h2>Migrating your account</h2>
<h3>If you have an existing Mastodon account on another server</h3>
<p>Now you&#x27;re ready for the fun part: moving your existing Mastodon account over to your new server, along with your followers. Mastodon does a great job with this and while it&#x27;s not perfect for reasons I&#x27;ll mention below, your followers will automatically move with you. You can read a bit about the process from the <a href="https://docs.joinmastodon.org/user/moving/#move">Mastodon documentation</a>, but it unfortunately does not go into much detail.</p>
<p>Here are the key things to know about migrating your account:</p>
<ul>
<li>
<p><strong>Your posts don&#x27;t move with you.</strong> Posts on your existing Mastodon account do not move with you to the new server. This is unfortunate, but likely a product of how the federation is done (every server that interacted with your posts would have to update). If you only care about the content of your posts and not the engagement around them, you could repost them one by one to your new server (before you do the migration), and edit the date in the database to the original date. But that&#x27;s weekend project territory to write a script to do that for you... I digress.</p>
</li>
<li>
<p><strong>Your followers move with you.</strong> Your followers will get transferred pretty immediately. When I migrated my account, all of my ~3,000 followers were moved within a day with maybe 75% in the first few hours. It&#x27;s not entirely flawless though, I did lose about 20 followers in the process.</p>
</li>
<li>
<p><strong>You have to manually re-follow accounts you follow.</strong> You have to export a CSV file of accounts you follow from the old server and upload that on the new server. It&#x27;s really easy, but it does mean that people you follow will receive a notification that you followed them. It&#x27;s not ideal but people will start poking around and realize you just moved servers. I&#x27;ve noticed it dozens of times with people I follow and quickly pieced it together.</p>
</li>
<li>
<p><strong>Your old profile shows a banner that you&#x27;ve moved to another server.</strong> And your old account will be in a locked down state. You can login but you can&#x27;t post or edit anything aside from exporting data from the preferences page.</p>
</li>
<li>
<p><strong>You can&#x27;t migrate your account again for 30 days.</strong> So make sure you&#x27;re using a username and domain you like.</p>
</li>
</ul>
<p>Lets get started! The actual first step is creating an account on your new server, which you&#x27;ve already done.</p>
<h3>Step 1: Create an account alias on the new server</h3>
<p>Setting up a Mastodon account migration is a two-way process. The new server needs to be aware of the old account, and the old server needs to send everything to the new server that&#x27;s expecting it.</p>
<p>So the first step is to log into your new server, open <strong>Preferences → Profile</strong> and click on the link under "Moving from a different account." On this page you need to provide your old Mastodon account in the format <code>myusername@example.com</code>.</p>
<p>This step is harmless and reversible—the actual migration does not start until the later steps.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-migration-step1-make-old-acct-alias.jpg" alt="Mastodon account migration: adding an account alias of the old account on the new server" width="2000" height="1207" />
<small>On the new server, add an alias for your old account.</small>
<h3>Step 2: Export your account data from the old server</h3>
<p>Next, you&#x27;ll want to export data from the old server. Most importantly, you&#x27;ll want to export a CSV of accounts you follow so you can later import this on the new server. You can also export files for your muted accounts, blocked accounts, bookmarks, lists, and blocked domains. Go to your old server to download these files: <strong>Preferences → Import and Export → Data export</strong>.</p>
<p>On this page you can also request an export of your posts and uploaded media from the old server. This is just for you to have as you can&#x27;t import posts on the new server. Also, it may not work you depending on your old server. I&#x27;ve tried to request my archive on my old server numerous times and it never generated a download for me.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-migration-step2-download-exports.jpg" alt="Mastodon account migration: export data from the old server" width="2000" height="1235" />
<small>Export data from the old server, especially the list of accounts you follow.</small>
<h3>Step 3: Begin the migration on the old server</h3>
<p>Now it&#x27;s time for the actual migration. This will move followers from your old account to your new account. This cannot be undone, so be sure you&#x27;re ready and have setup your server to your liking before proceeding. This is also a good time to edit anything on your old account (edit bio, delete any posts, etc) as you won&#x27;t be able to change it later.</p>
<p>On the old server, go to <strong>Preferences → Profile → Move to a different account</strong> and click the link mentioned. This will take you to the account migration page. Carefully read the bulleted list to understand the implications of this move. Then, enter your new account&#x27;s handle and the password used for your old server.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-migration-step3.jpg" alt="Mastodon account migration: Starting the migration on the old server by providing the new account handle" width="2000" height="1462" />
<small>Starting the migration on the old server by providing the new account handle.</small>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-migration-step3-profile-redirect.jpg" alt="Mastodon account migration:" width="2000" height="1210" />
<small>Your old account will now display header saying your account has moved.</small>
<p>Now the migration will start. As mentioned earlier, your posts will not move to the new server, only your followers.</p>
<p>If you have a lot of followers or a particularly low-end server, it may be a good idea to keep an eye on your server as this migration process will keep it busy for a while. You can take a look at system resources with the <code>top</code> or <code>htop</code> commands.</p>
<p>And you can see what Mastodon is doing by looking at the Sidekiq dashboard, accessible in <strong>Preferences → Sidekiq.</strong> You can click around to see what jobs are running or failing. For the most part you don&#x27;t need to worry too much. Common job failures are often related to other instances having timeouts. The only cause for concern would be an error indicating connectivity issues with your database, which could mean you may want to adjust the Sidekiq concurrency (mentioned a bit later) in <code>/etc/systemd/system/mastodon-sidekiq.service</code>.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-migration-step3-server-active.jpg" alt="Mastodon account migration:" width="2000" height="1394" />
<small>Moving your followers will keep your machine busy. You may wish to keep an eye with <code>htop</code>.</small>
<h3>Step 4: Import your following list</h3>
<p>The last step of the migration process is to import the CSV files you exported in step 2, the most important of which is the list of accounts you follow. On your new server go to <strong>Preferences → Import and export → Import</strong>. Select what type of CSV file you&#x27;re importing in the dropdown, select the CSV file and upload.</p>
<p>You can safely import all lists except the following list before you&#x27;ve actually started your migration (step 3) if you wish.</p>
<p>I recommend waiting a while after step 3 has had time to move most of your followers over before importing your following list. Your server may be quite busy with step 3 so it doesn&#x27;t hurt to do this an hour later.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-migration-step4-new-server-import.jpg" alt="Mastodon account migration: Importing following list and other CSV files" width="2000" height="1243" />
<small>Importing your list of accounts you follow</small>
<p>That&#x27;s it! All of your followers should get moved over shortly and you&#x27;re ready to start using your own Mastodon server. It&#x27;s probably a good idea to have a post or two so your followers don&#x27;t see an empty profile if they happen to venture to your profile.</p>
<p>If you want to have a bit of fun, you can start looking into adding custom emojis (sometimes called <a href="https://emojos.in">emojos</a> in the context of Mastodon) to your server. Take a look at <strong>Preferences → Administration → Custom emojis.</strong> where you can upload an image and assign it a shortcode. You can even use them in your username.</p>
<hr/>
<h3>What to expect</h3>
<h3>Missing some posts and replies? Yeah, that&#x27;s normal...</h3>
<p>After you&#x27;ve had some time to use your new server, you may see some odd behavior that may lead you to something is broken with your server. Profile pages for accounts may be almost entirely empty, or only have a few posts. Post detail views may not have all the engagement or replies you might expect compared to visiting the original post URL on the remote server.</p>
<p>I&#x27;m just here to tell you this is normal. It&#x27;s not a good thing, but it&#x27;s the current state of how Mastodon works.</p>
<p><strong>Missing posts on a profile:</strong> When you follow someone on your server, or visit the profile of someone you don&#x27;t follow, Mastodon does not go and fetch all of their posts. That would be taxing on their server and yours. So what happens instead is you get some basic profile info, a post or two (pinned ones) and that&#x27;s it. Then, the next time your server sees a post from this user (because you follow them or other some action lead to your server seeing this post), it will then appear on their profile. This is not ideal and it wouldn&#x27;t be unreasonable for Mastodon to fetch a few more posts with a way to request them on demand.</p>
<p><strong>This will get a bit better over time.</strong> Your server is brand new, you only just followed accounts and your server has yet to see a lot of new posts and fill up profiles with new posts going forward. You&#x27;ll still stumble across a user account that your server has never seen before an experience the same blank profile behavior but at least now you know why that is.</p>
<p><strong>Missing replies on posts</strong> from other accounts (not your own posts) is a similar situation; your server may have low federation and not be aware of some of those replies. Understanding why this is the case ends up going down a rabbithole of understanding federation more and how your server even comes to know about posts, and under what conditions another server sends a post to your server.</p>
<p>This <a href="https://github.com/mastodon/mastodon/issues/14017">Mastodon GitHub issue</a> outlines the situations where your server comes to know about posts:</p>
<ul>
<li>Someone on your instance follows the person who posted, at the time it was posted</li>
<li>Someone you (or anyone else on your instance) follow boosts or replies to that toot</li>
<li>Under some conditions, if that post was a reply to someone you (or anyone else on your instance) follow</li>
<li>The post mentions anyone on your instance</li>
<li>The post was a pinned post when the account was discovered by your instance</li>
<li>Someone on your instance manually fetches a post by pasting the URL in the search bar</li>
</ul>
<p>This is a hot topic these days and I&#x27;ve seen discussions happening around people wanting to add buttons in Mastodon clients to explicitly load all replies on a post, or <a href="https://github.com/mastodon/mastodon/issues/17213">older posts on a profile</a>, from the remote servers. There&#x27;s various technical issues with some of these routes, but I&#x27;m curious to see if this situation evolves as I for one would love a refined experience here.</p>
<h2>Maintaining, debugging, and optimizing your server</h2>
<h3>A few things to be aware of</h3>
<p>This section is for people running their own server, <em>not</em> through a fully-managed host like Masto.host.</p>
<h3>Updating Mastodon</h3>
<p>You&#x27;ll need to keep up to date with Mastodon updates to get new features, performance and security updates. You can check for new updates on the GitHub project page but it&#x27;s probably easiest to subscribe to the atom feed in your news reader of choice, such as NetNewsWire.app. Here&#x27;s the <a href="https://github.com/mastodon/mastodon/releases.atom">releases feed</a>, or <a href="https://github.com/mastodon/mastodon/releases">the website</a> if you prefer.</p>
<p>The steps you need to follow for each update may vary, but additional steps will be mentioned in the release notes for each release. Generally you&#x27;ll need to SSH into your server, fetch the latest release with git, and restart some services. Find the complete steps here: <a href="https://docs.joinmastodon.org/admin/upgrading/">Upgrading to a new release</a>.</p>
<p>You should check now that your server is on the latest Mastodon version. At the time of this writing, the DigitalOcean 1-click installer is running an outdated version.</p>
<h3>Updating your Ubuntu server</h3>
<p>Along with maintaining and keeping Mastodon up to date, you&#x27;ll want to do the same with your server. If you followed along with the DigitalOcean route explained above, your machine uses Ubuntu OS, apt package manager and has a specific package called <code>unattended-upgrades</code> installed by default. That package will automatically install essential security updates, but <a href="https://www.digitalocean.com/community/tutorials/how-to-keep-ubuntu-20-04-servers-updated">you can modify it to update even more</a>.</p>
<p>I don&#x27;t want to get too in the weeds about linux server maintenance as everyone seems to have their own specific practice about when to update things, how to update them, and when to leave it alone.. you know, if it ain&#x27;t broke don&#x27;t fix it. Some people may prefer to update all packages every week. Not including security essentials, that&#x27;s a bit too much for me and feels like I&#x27;d constantly be signing up for a potential debugging session if anything unexpected happens.</p>
<p>Personally, I just update available packages whenever I get around to it, perhaps every month or two. Usually with these:</p>
<pre><code># Refresh list of available updates 
sudo apt update
# View list of available upgradable updates
apt list --upgradable
# Upgrade packages 
sudo apt upgrade
# Remove unneeded packages not installed by you 
sudo apt autoremove

# Alternatively, instead of the lines above:
sudo apt update && sudo apt upgrade –y && sudo apt autoremove -y
</code></pre>
<h3>When things go wrong</h3>
<p>I wanted to provide a few pointers for things to look into when things go wrong with your Mastodon server. There&#x27;s no way I can provide a general solution to what could be a specific problem you may encounter, but here&#x27;s a few things may be a good place to start:</p>
<ul>
<li>
<p><strong>Check service status:</strong> Run this to get a quick look at the core Mastodon services: <code>mastodon-web.service</code>, <code>mastodon-sidekiq.service</code>, and <code>mastodon-streaming.service</code>.</p>
<pre><code>sudo systemctl status mastodon-*
</code></pre>
<p>In addition to status of the 3 core Mastodon services (you&#x27;ll want to see "active (running)" in green), this command will show the last 10 lines from the logs for each service.</p>
</li>
<li>
<p><strong>Check the logs</strong>: This may sound obvious but knowing how to check and work with logs is critical. It&#x27;s the best way to know what&#x27;s going on with your machine. To access any of the logs for the aforementioned 3 services, we use a tool called <code>journalctl</code> to read and filter system logs that are saved in the binary "journal" by systemd. You can always run <code>man journalctl</code> to see more details on how you can use it; it&#x27;s very powerful.</p>
<p>It&#x27;s a good idea to go through the logs for each Mastodon service after you&#x27;ve set everything up to make sure that things are working smoothly. Here&#x27;s a few examples of how you can use it:</p>
<pre><code># Show the last 50 lines of the mastodon-web log
# and keep showing new lines as they come in (that&#x27;s the -f follow flag)
sudo journalctl -u mastodon-web -n 50 -f

# Or read the mastodon-streaming log 
sudo journalctl -u mastodon-streaming -n 50 -f

# Or the mastodon-sidekiq log 
sudo journalctl -u mastodon-sidekiq -n 50 -f

# Or only show me sidekiq logs that have priority level 4 (warn) or higher
sudo journalctl -u mastodon-sidekiq -f -n 100 -p 4

# And you can always pipe it to grep
# For example to show any lines from the web logs that have a status code of 500
sudo journalctl -f -u mastodon-web -n 500 | grep "status=500"
</code></pre>
<p>You can do a lot with these commands. This helped me initially discover database connection issues when I over-eagerly tried to optimize configs, and helped me notice that I forgot to require SSL for my remote database.</p>
</li>
<li>
<p><strong>Restart things:</strong> You can restart or reload (like a restart but no downtime as it reloads the config, if supported by the service) these services with a command like:</p>
<pre><code>sudo systemctl restart mastodon-web
</code></pre>
</li>
<li>
<p><strong>Check sidekiq:</strong> Sidekiq is the background job processor for Mastodon. It&#x27;s how Mastodon manages receiving new posts, sends our your posts, and more.</p>
<p>Generally you don&#x27;t need to worry too much about what it&#x27;s doing, but there&#x27;s one key scenerio to be aware of: if you have a massive queue of jobs that are piling up. What this looks like is the "Enqueued" tab in the Sidekiq dashboard will show a large number that&#x27;s not going down in a reasonable amount of time.</p>
<p>This would mean your machine cannot keep up. You may notice significant delays in receiving new posts on your server. A Mastodon instance running well would have likely have few to no tasks busy or queued, and when when queued tasks are added, they get processed quickly. If this happens to you, it could mean your server is underpowered and trying to do too much (don&#x27;t use any relays if you are), or could benefit from optimizing your sidekiq setup (more later).</p>
<p>There&#x27;s also a tab for dead jobs in Sidekiq. These are tasks that have failed repeatedly and will not be retried. You&#x27;ll just want to glance at those to ensure the issues are not related to you. Even if some jobs fail, you&#x27;ll likely see that they are HTTP connection or timeout errors with other servers and likely not your issue.</p>
</li>
</ul>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-sidekiq.jpg" alt="Mastodon sidekiq job processor" width="2000" height="1102" />
<small>Access the sidekiq dashboard directly in <strong class="semibold">Preferences → Sidekiq</strong></small>
<h3>Optional: Extend your post character limit beyond 500</h3>
<p>It&#x27;s your server, you control the code so why not extend your server&#x27;s character limit well past the default limit of 500 characters? Doing this will take just a few minutes, all you have to do is change a number in 2 files, precompile assets, and then restart some services.</p>
<p>This article goes into detail about the process: <a href="https://write.as/sweetmeat/customize-mastodon-to-change-your-post-character-limit">Customize Mastodon to Change Your Post Character Limit</a>. However, keep in mind that you&#x27;ll have to reapply these changes with every Mastodon update.</p>
<p>I changed my character limit to 15,000. In reality I won&#x27;t be posting things that long, though I did take advantage of a 1,000 character reply which was very handy and I didn&#x27;t have to try to split it up into multiple replies or aggressively truncate my thoughts. The change works seamlessly: people on other Mastodon (or other ActivityPub software) servers will see the longer posts, and all Mastodon clients should see the updated limit in their post composer interfaces.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-extended-char-limit.jpg" alt="Mastodon composers with extended character limit: Ivory and Mastodon web" width="2000" height="1282" />
<small>Extended character limit recognized by <a href="https://tapbots.com/ivory/" title="Ivory for iOS by Tapbots">Ivory</a> and Mastodon Web.</small>
<h3>Optional: Change your join date</h3>
<p>One annoying thing of creating a new Mastodon server, or migrating to a new one, is that your join date—shown prominently on your profile—reflects the date you created the new account. It doesn&#x27;t inherit the date of your previous account(s) that you migrated.</p>
<p>Since you&#x27;re running your own server and have access to the database, the join date is easy to change. You can change it to your original account creation date, or any date you like. Why not? It&#x27;s your server, do with it what you want. SSH into your server, or use the web console from your hosting provider and run the following commands:</p>
<pre><code>sudo su - mastodon 

# Enter PostgreSQL interactive terminal for the Mastodon database
psql -d mastodon_production

# Update the join date for your account...
# Replace YOUR_USERNAME with your username (does not include domain name)
# Replace date with your desired date, using the exact same format 
UPDATE accounts SET created_at=&#x27;2018-01-01 00:00:00&#x27; where username=&#x27;YOUR_USERNAME&#x27;;

# Exit the PostgreSQL interactive terminal
exit
</code></pre>
<h3>Optimizing Mastodon for your server</h3>
<h3>Proceed at your own risk</h3>
<p>If you&#x27;re just running your own single-user Mastodon instance that you expect to be low traffic, you don&#x27;t need to touch anything in this section; the defaults are fine for your system. But if you have a beefy server with extra RAM and cores to put to use, you have a lot of followers, and/or you just generally want to nerd out on squeezing more performance from your server then read ahead.</p>
<p>As a word of caution, changing things in various Mastodon config files can easily take your server offline. I recommend doing this before you&#x27;ve done a migration, or late at night to minimize the effects of downtime. Also, I highly recommend setting up Rewind AI on your Mac so you can easily retrace your steps when you&#x27;re changing things and running commands.</p>
<p>By following this guide, you&#x27;ve already done an important performance tweak: using a cloud object storage solution for hosting all media for your Mastodon posts. The most common things advanced users will do includes modifying sidekiq to use separate processes for each queue, as well as setting up pgbouncer for PostgresSQL.</p>
<h3>Resources</h3>
<p>Scaling Mastodon can be a deep topic depending on your needs. I&#x27;m only concerned with running Mastodon as a single-user instance, but it&#x27;s helpful to better understand the pieces of Mastodon and what can and should be changed and when.</p>
<p>The Mastodon website has a page about <a href="https://docs.joinmastodon.org/admin/scaling/">scaling your server</a>. It&#x27;s particularly good to learn the relationship between threads and processes with the web server (threads max out your CPU first, processes max out your RAM first), as well as learning about pgbouncer to help reduce any database connection bottlenecks.</p>
<p>Then there&#x27;s the lengthy and advanced article <a href="https://hazelweakly.me/blog/scaling-mastodon/">Scaling Mastodon: The Compendium</a>. Most of the topics in there might be a bit overkill for a small single-user instance though.</p>
<h3>Sidekiq</h3>
<p>I mentioned a bit about what to be on the lookout for <a href="#sidekiq">with sidekiq earlier in this article</a>, such as having a backed up queue. The first thing I did with sidekiq is slightly increase the number of threads. By default using the DigitalOcean droplet, you may have a default of <code>25</code> for <code>DB_POOL</code> and the concurrency flag <code>-c</code>.</p>
<p>However, the number of <code>max_connections</code> for the Postgres database by default is 100. Counterintuitely, if you opted for a separate managed database from DigitalOcean you may have only 25 database connections available, in which case you may opt to setup their pgbouncer feature called "connection pools"; that&#x27;s what I did. If you do the same, you&#x27;ll need to change your database connection info so Mastodon connects to pgbouncer on a different port.</p>
<p>What I did was edit <code>/etc/systemd/system/mastodon-sidekiq.service</code> and change the <code>DB_POOL</code> value to 50, as well as the number after <code>-c</code> on the ExecStart line. You don&#x27;t want to tell sidekiq to consume all of our available database connections as each Puma web server thread will need a database connection too.</p>
<pre><code>Environment="RAILS_ENV=production"
# Edit this 
Environment="DB_POOL=50"
Environment="MALLOC_ARENA_MAX=2"
Environment="LD_PRELOAD=libjemalloc.so"
# and the number after -c 
ExecStart=/home/mastodon/.rbenv/shims/bundle exec sidekiq -c 50
</code></pre>
<p>Then I also configured sidekiq to automatically restart every 6 hours. There seems to be an <a href="https://github.com/mastodon/mastodon/issues/16495">open issue</a> where sidekiq memory usage continually creeps up over time. Honestly, this was one of the firs things I configured and never ran without this setting so I&#x27;m not entirely sure how necessary it is. But I haven&#x27;t had any issues.</p>
<pre><code>Restart=always
RuntimeMaxSec=21600
</code></pre>
<p>After modifying <code>mastodon-sidekiq.service</code>, you&#x27;ll need to run these:</p>
<pre><code>systemctl daemon-reload
systemctl restart mastodon-sidekiq.service
</code></pre>
<h3>Puma</h3>
<p>The other thing I did was adjust the number of threads and proccesses used by puma, the Mastodon web/app server. If you expect a lot of web traffic, or just like to be prepared, you may be interested in tweaking puma as well.</p>
<p>I initially looked into this because had some unused RAM on my server and wanted to let puma use a bit more. In the process I learned that the <a href="https://ruby.social/@evanphx/109365852402052564">it&#x27;s recommended to allocate</a> 1.5 processes per CPU core. So my server has 2 cores, so I can get away with 3 processes for puma. I set it to also use 10 threads per process.</p>
<p>Edit <code>/etc/systemd/system/mastodon-web.service</code> and add these two lines (or modify if they already exist):</p>
<pre><code># Set this to 1.5 * number of cpu cores
# Find your # of cores by running: cat /proc/cpuinfo | grep processor | wc -l
Environment="WEB_CONCURRENCY=3"
# The number of threads per process. If you&#x27;re RAM constrained, you may want to lower this.
Environment="MAX_THREADS=10"
</code></pre>
<p>Save the file and restart the service:</p>
<pre><code>systemctl daemon-reload
systemctl restart mastodon-web.service
</code></pre>
<p>That being said, you don&#x27;t really need to mess with puma much. For a single user instance the vast majority of your traffic will be from people interacting with your posts via a Mastodon app/client through their server—not directly via your website—which is not served by the web service.</p>
<hr/>
<p>This is barely scratching the surface with what&#x27;s possible for optimizing and scaling Mastodon. I&#x27;m just running my own single-user instance and it&#x27;s been running great so far. If you&#x27;re not sure what to do, I would recommend not touching anything and seeing how your server works for a while. You can keep an eye on system logs as <a href="#go-wrong">mentioned earlier</a>, as well as sidekiq.</p>
<h3>The end</h3>
<p>This article has been in the works for a while now but hopefully it has helped you get a better understanding what&#x27;s involved with hosting your own Mastodon server, how to keep it running smoothly, and how to tweak it to your liking.</p>
<p>It&#x27;s a bit of work to get running but the benefits of owning your online identity and data with Mastodon are well worth it. If you&#x27;ve enjoyed this article, please share it with anyone that might find it useful, and of course follow me on Mastodon on my new instance: <a href="https://stammy.design/@stammy">@stammy@stammy.design</a>.</p>]]></description>
            <link>https://paulstamatiou.com/hosting-your-own-mastodon-server</link>
            <guid isPermaLink="true">https://paulstamatiou.com/hosting-your-own-mastodon-server</guid>
            <dc:creator><![CDATA[Paul Stamatiou]]></dc:creator>
            <pubDate>Tue, 07 Mar 2023 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Mastodon]]></title>
            <description><![CDATA[<img src="https://turbo.paulstamatiou.com/uploads/2022/12/copyright-paul-stamatiou_com-stammy-mastodon-ivory.jpg" alt="A Mastodon app called Ivory" />
<small>A Mastodon app called Ivory</small>
<p><a href="https://paulstamatiou.com/odeo-launches-twttr-hellodeo/">I first wrote about Twitter</a> (née twttr) just over 16 years ago. Over the years, Twitter’s place and impact in the world has become clear. It’s not just a place to hear about breaking news, keep up with celebrities or see what your politicians are saying. It’s a place where communities are formed and thrive. It is the global town square.</p>
<p>But that’s all been changing daily ever since Elon Musk took over. This has become the tipping point for many to reconsider their reliance on big tech companies with closed platforms and to be in control of their data. This whole Twitter/Elon saga sucks, but maybe it’s just the kick we needed.</p>
<p>And with that, I’m starting to spend more time on Mastodon, and I’ll tell you why. Follow me on Mastodon: <a href="https://stammy.design/@stammy">@stammy@stammy.design</a> (you’ll have to search for it on your Mastodon server).</p>
<hr/>
<div><h3>Part 2: Hosting your own Mastodon server</h3><p>Want to have complete control and host your own Mastodon server?</p><p>Shortly after I wrote this post, I loved Mastodon so much I decided to host my own server and document the process for those that would want to do the same. In <strong><a href="https://paulstamatiou.com/hosting-your-own-mastodon-server/">Hosting your own Mastodon server</a></strong> I show two ways to host your own server (using a fully-managed Mastodon host, and using a VPS provider). I go into everything from scripts to backup your database and run media clean up tasks, to advanced settings to optimize your server, and much more.</p><a href="https://paulstamatiou.com/hosting-your-own-mastodon-server/" title="Hosting your own Mastodon server"><img src="https://turbo.paulstamatiou.com/uploads/2023/01/copyright-paulstamatiou_com-mastodon-mbp.jpg" alt="Hosting your own Mastodon server" /></a></div>
<hr/>
<p>Twitter quickly became a core part of how I used the internet, made friends, learned things, kept up with the world, killed time, and so much more. I eventually went to <a href="https://paulstamatiou.com/joining-twitter/">work at Twitter for nine years</a>. Twitter, the company, had lots of ups and downs, but the people behind it cared so much about the platform and its place in the world. It’s the critical conversational layer of the internet. Creators have active social media accounts elsewhere online, but they always relied on Twitter to truly connect and have conversations with their community. It was the vital hub.</p>
<p>Well, it’s a different bird site now. I don’t intend to summarize the series of events and drama that have unfolded ever since Elon Musk took over Twitter, nor do I have the energy for that, but if you’ve seen even a portion of all the headlines, you get where I’m coming from.</p>
<p>Seeing the company&#x27;s culture get slaughtered so quickly was hard. It was a culture woven around caring for coworkers, caring for people that used Twitter, and caring about the good of the service.</p>
<p>A few weeks ago was the last straw for me. Reputable accounts were randomly banned, and Twitter announced that people could no longer Tweet links to other social networks that were deemed competitive. Then more people were banned for saying they were leaving. And then, suddenly, this big policy suddenly vanished.</p>
<p>I lost a lot of hope and confidence in Twitter and how it is being run. I still think Twitter will be around for some time, but I’m not sure how much I want to continue investing in it as much as I used to.</p>
<p>I had seen some folks migrating away to alternate services in recent months but didn’t think much of it. Twitter was here to stay, right?</p>
<h3>Fool me once...</h3>
<p>The Twitter/Elon saga has a silver lining that I can appreciate. It shows us that we’ve all become too comfortable with just a few large tech companies amassing our info, controlling our data, and what we do with it.</p>
<p>If you’re the typical user of internet services from large companies, you probably haven’t had too many issues. Sure, maybe you got locked out of your Google account once, and it took a long time for support to help you out, but for the most part, you didn’t have to think about it. The big companies were mostly staying in their lane and not doing anything too egregious (aside from miscellaneous privacy dramas). But they could have been.</p>
<p>This Twitter drama is a perfect example of what can go wrong and how quickly it can go wrong. It’s too much. I’ve invested a lot of time into Twitter (thanks to <a href="https://twitter.com/stammy">the 53,000+ of you</a> that have been following me there).</p>
<p>I no doubt expect Elon to reverse some of his decisions from the regular backlash from users and press, but there’s no trust anymore. Even if a new CEO or a new owner is announced, I don’t know if Twitter can ever be truly trusted again. Fool me once, shame on you, fool me twice, shame on me..</p>
<p>All this to say, I think it’s time we take more control of our data. I’ve been trying to reduce my reliance on Google accounts and services already. I’m sure I end up moving on to Proton or elsewhere in 2023.</p>
<p>This does all make me a tad nostalgic for the early 2000s. We were all just running our own little blogs in a corner of the internet and keeping up with each other with RSS readers. Social media was just our own little websites. Why can’t we just go back to that?</p>
<h3>Mastodon</h3>
<h3>A decentralized social network built on an open protocol</h3>
<img src="https://turbo.paulstamatiou.com/uploads/2022/12/mastodon-site.webp" alt="The Mastodon server I use, stammy.design" />
<small>The Mastodon server I use, <a href="https://stammy.design/@stammy">stammy.design</a>, though most Mastodon sites looks like this.</small>
<p>I’ve started spending more time on <a href="https://joinmastodon.org">Mastodon</a>, open-source software for running a decentralized social networking service that’s not somewhat similar to Twitter. It’s decentralized in that there’s no single website or company running the show. It’s not a single platform.</p>
<p>Instead, Mastodon is comprised of a network of independent servers, which you may see referred to as Mastodon instances. Each server is run by a different person that manages and moderates it. You can sign up for an account on any server you want, and you can follow people on any other server just like you would on Twitter. (There are exceptions, like if one server blocks another server—defederation).</p>
<p>Mastodon was first released in late 2016 by <a href="https://mastodon.social/@Gargron">Eugen Rochko</a>, who wanted to create a platform not controlled by a single company or person. Mastodon was developed as a non-profit, and the platform is ad-free. It has made specific design choices to reduce harassment and give users more control over their experience and create a safer environment.</p>
<p>As a long-time Twitter employee, I had heard of Mastodon many times (as well as a predecessor, <a href="https://en.wikipedia.org/wiki/Diaspora_(social_network)">diaspora</a>) but never took much time to dive deeper. It always felt like a rudimentary platform 10 years behind Twitter. In hindsight, it was foolish to think of it in terms of features rather than protocols. That was the real innovation with Mastodon, not whether it had certain product features.</p>
<p>Mastodon servers communicate with each other with open-source software using a standardized, open protocol called ActivityPub for sharing updates. There are quite a few other open-source projects using ActivityPub, such as <a href="https://pixelfed.org/">Pixelfed</a> and <a href="https://pleroma.social/">Pleroma</a>, but Mastodon is the most popular. You can even run your own Mastodon instance all by yourself if you want.</p>
<p>You may also see it referred to as a <a href="https://en.wikipedia.org/wiki/Distributed_social_network">federated social network</a> and <a href="https://en.wikipedia.org/wiki/Fediverse">fediverse</a>. There’s also a bit of nuance here when it comes to federation. It’s a form of decentralization, but not every instance needs to connect with another instance. A Mastodon instance itself can be entirely self-contained, with users on it following each other only (though not common). While a huge benefit, federation also leads to some product constraints.</p>
<h3>Federated, like email</h3>
<p>Federation also means that you not only have to know someone’s username but also their server. This leads to email-like usernames, such as mine: <a href="https://stammy.design/@stammy">@stammy@stammy.design</a>. You need both bits of information to follow someone, which makes it a tad harder to use than a centralized service. Someone can always just search for you with your username only, but it’s not reliable for various reasons related to how the federation is done.</p>
<p>This also means your username can’t really be taken. It could be taken on a particular Mastodon server, but you can always use another server or self-host Mastodon on your own domain. It also leads to there being no such thing as verified accounts on Mastodon. There’s no central authority deeming which account is verified or not.</p>
<h3>And it’s growing.</h3>
<p>Mastodon is having a bit of a moment right now. The non-profit that runs Mastodon even <a href="https://arstechnica.com/tech-policy/2022/12/twitter-rival-mastodon-rejects-funding-to-preserve-nonprofit-status/">turned away multiple VC investment offers</a>. With all that’s happening at Twitter, people have been longing for a more stable product, one where their data could be more trusted, one that’s ad-free, supported by communities, and moderated by communities. One where terms and policies don’t change daily.</p>
<p><a href="https://blog.mozilla.org/en/mozilla/mozilla-launch-fediverse-instance-social-media-alternative/">Mozilla announced</a> they will be launching their own instance—<code>Mozilla.social</code>—next year in pursuit of building a healthy alternative to today’s social media platforms. Even the <a href="https://www.washingtonpost.com/technology/2022/12/17/how-to-join-mastodon/">Washington Post</a> wrote about how to get started with Mastodon.</p>
<blockquote>
<p>"While there is no shortage of social media platforms new and old, this is a radically different approach to social media that offers something traditional social media cannot. This may be one of the reasons why <strong>Mastodon has recently exploded in popularity, jumping from approx. 300K monthly active users to 2.5M</strong> between the months of October and November, with more and more journalists, political figures, writers, actors and organizations moving over."</p>
<p>—<a href="https://blog.joinmastodon.org/2022/12/twitter-suspends-mastodon-account-prevents-sharing-links/">Mastodon</a></p>
</blockquote>
<h3>Getting started with Mastodon</h3>
<h3>It’s not easy, but it’s worth it.</h3>
<p>Now that we’ve got a basic grasp of Mastodon, how it’s federated like email but similar in functionality to Twitter, it’s time to give it a try.</p>
<p>But maybe a bit of a heads-up first. While Mastodon may feel comparable in look and functionality to Twitter, it’s probably best to approach Mastodon with the mindset that it is a new platform rather than trying to view it as a Twitter clone. There are key differences that will take some getting used to, and it will be a bit harder to get started.</p>
<p>The first challenge is signing up. You can’t just go to the Mastodon website and create an account. You first need to pick <em>where</em> you want your account by picking a Mastodon server you wish to call your home.</p>
<h3>Pick a server, follow anyone on any server</h3>
<p>The concept of Mastodon servers ends up being a confusing part of the Mastodon onboarding and usage experience. Even after you have an account on one server, you can’t just log into any other Mastodon server. You always have to log into yours. But you will be able to follow anyone on your own server, even if they’re on a different Mastodon server.</p>
<p><strong>So how do you find and pick a server, and does it matter which one you pick?</strong> There are several schools of thought on this, but I’ll try to explain it as best I can.</p>
<ul>
<li>
<p><strong>The argument for picking any server:</strong> You can easily change servers later on if you want. Just pick a server that looks interesting and go for it. If you already know other Mastodon users that you want to follow and don’t need too much assistance with discovering content and accounts, you’ll be okay.</p>
</li>
<li>
<p><strong>The argument for carefully picking your server:</strong>
Picking a server is like deciding where to live in a city or what subreddit you want to frequent. You’ll more easily run into the same people and content if you pick a server that’s relevant to your interests. You’ll also be more likely to find people who are interested in the same things as you.</p>
<p>This is especially important if you are new to Mastodon and don’t know of many other people you’d want to follow that are on Mastodon.</p>
<p>With Mastodon, in addition to your typical Home timeline comprised of people you explicitly follow, you also get two bonus timelines: a local timeline comprised of people on your specific Mastodon server and a federated timeline of posts from people your Mastodon instance knows about (not a full firehose of all Mastodon posts, just the one your instance subscribes to via relays and from people the instance follows).</p>
<p>Having a high-quality local timeline gives you an opportunity to more easily discover great content related to your interests, helps other people discover you, and vice versa. This is important for a lot of reasons, the leading of which is that it’s harder to discover people to follow on Mastodon. There is no algorithmic timeline injecting relevant content you may like into your timeline, and searching on Mastodon is not great.</p>
<p>So that’s one part of it. The other part is maybe more important: picking a server is also like picking your landlord. Do you trust the admin of the server to host your identity? Do you think they have the technical know-how to maintain and secure the infra as needed? Are they making backups? What if they get lazy, and you’re stuck on a 2-year-old version of Mastodon lacking all the new features? Do they have a plan for financially supporting the infra? Or are they running an overloaded server that is extremely slow?</p>
<p>And finally, each Mastodon server has its own set of rules in place. The rules give you an idea of the type of community you would be joining. People that don’t abide by the rules can be actioned on by the server’s moderators and admins.</p>
</li>
</ul>
<h3>Finding your server</h3>
<p>If there are already a lot of people you want to follow on a particular server, that’s probably a good place to start. Examples of Mastodon servers I come across often include ones like <code>mastodon.design</code>, <code>front-end.social</code>, <code>hachyderm.io</code>, <code>infosec.exchange</code>, <code>indieweb.social</code> and more.</p>
<p>An easy way to find where your friends are on Mastodon is by using <a href="https://debirdify.pruvisto.org/">Debirdify</a> or <a href="https://fedifinder.glitch.me/">fedifinder</a>. You authenticate your Twitter account, and it will tell you where people you follow on Twitter are on Mastodon if they’ve made Mastodon accounts. It’s an easy way to get an idea of Mastodon instances you may want to use.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2022/12/debirdify-stammy.webp" alt="Debirdify screenshot" width="2144" height="3496" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2022/12/fedifinder-stammy.webp" alt="Fedifinder screenshot" width="2144" height="1616" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2022/12/movetodon-stammy.webp" alt="Move to don screenshot" width="1924" height="1616" />
<small>Debirdify, Fedifinder and Move to don</small>
<p>You’ll quickly notice that <strong>not all servers have open, public registration</strong>. Some may just be entirely closed or require an invite and are meant for a smaller community. Others require approval by the admin before you can join. And others may only be temporarily closed, so the admins have time to upgrade their servers to deal with the influx of new users, and you may just need to try again later.</p>
<p>You can, of course, just browse yourself and see what’s out there. Tools like <a href="https://instances.social/">instances.social</a>, <a href="https://mastodonservers.net/">MastodonServers.net</a>, <a href="https://fedidb.org/network">FediDB</a>, and the <a href="https://joinmastodon.org/servers">official Mastodon servers page</a> can help with that.</p>
<p>I’m on <s>macaw.social, a small private Mastodon instance created by former Twitter employees meant for former Twitter employees and friends</s> <a href="https://stammy.design">stammy.design</a>, my self-hosted Mastodon instance.</p>
<p>If this is all a bit confusing, you can always just pick from one of the huge Mastodon instances like mastodon.social, mas.to, and mastodon.cloud. However, since most of these are getting a ton of new users now, they are more likely to feel slower until they scale up their infrastructure.</p>
<hr/>
<h3>Self-hosting your own Mastodon instance</h3>
<h3>A bit more than meets the eye</h3>
<p>Of course, the beauty of the Fediverse is that you can just host your own instance, own your data, and have complete control of your Mastodon identity! If you know that this is what you want to do, there are a few routes to take.</p>
<ul>
<li>
<p><strong>Managed hosting:</strong>
There are a few hosting companies that specialize in hosting Mastodon servers, such as <a href="https://masto.host/">Masto.host</a> among <a href="https://docs.joinmastodon.org/user/run-your-own/#so-you-want-to-run-your-own-mastodon-server">others</a>, though at this time some have paused new signups due to high demand.</p>
</li>
<li>
<p><strong>DIY hosting:</strong> And then you can just do it all yourself following the <a href="https://docs.joinmastodon.org/admin/install/">official guide</a> on any server where you can set up Postgres, Redis, Ruby, and Sidekiq. You’ll need to have an email host so your Mastodon instance can send emails to you, and you’ll likely want some cloud storage, such as S3, for your media and files. You’ll also want to have a system in place for regular database backups. Here’s an article I found outlining someone’s experience <a href="https://www.micahwalter.com/notes-on-running-a-mastodon-server-on-aws/">setting up their instance on AWS</a>.</p>
<p>Running a server yourself is a bit more involved than setting up a simple static website or WordPress install. And depending on how many relays you set up (more on that later), you may find yourself tuning the Sidekiq background job processor config so it can run faster. If you still want to DIY but prefer a bit of assistance, the hosting provider DigitalOcean has a <a href="https://www.digitalocean.com/community/tutorials/how-to-install-mastodon-with-digitalocean-marketplace-1-click">"1-click" setup for Mastodon</a>. It’s still not a walk in the park, but it saves you quite a bit of work in the command line.</p>
</li>
</ul>
<p><strong>But with great power comes great responsibility.</strong> By hosting a Mastodon instance, you’ll be liable for the content on your server created by your users <em>and</em> anyone you follow as well as what they boost (boosts are like ReTweets).</p>
<p>Yes, you read that right. The way Mastodon works, <strong>everything you view on your Mastodon account, including media, is actually hosted on your server</strong>, even if the Mastodon user you follow is on another instance. Their instance just sent that post to yours, essentially. So any text or media in their posts is now hosted by you. And if your instance has any relays setup, you’ll have a lot more content being cached and served from your instance.</p>
<p>This goes down the path of needing to register a designated DMCA agent if you want to be careful. The EFF has a detailed article on the topic: <a href="https://www.eff.org/deeplinks/2022/12/user-generated-content-and-fediverse-legal-primer">User Generated Content and the Fediverse: A Legal Primer</a>. This <a href="https://twitter.com/rahaeli/status/1593819064161665024">a long thread</a> and <a href="https://denise.dreamwidth.org/91757.html">accompanying blog post</a> also outlining some of the legal ramifications of hosting your own Mastodon instance.</p>
<p>So until you’re 100% sure you want to take on that commitment and liability, maybe start off by joining an instance hosted by a seasoned admin and donate to help them manage infra costs and things.</p>
<div><h3>A note about relays</h3><p>I mentioned relays a few times above, so what are they? Relays are servers running specific software that can help supply smaller instances with content from other Mastodon instances. Why would you want this? To help you discover content and accounts.</p><p>Remember how I said that Mastodon comes with three timelines you can follow: home (people you follow), local (accounts on your instance), and federated? The federated timeline is composed of posts from any accounts anyone on your instance follows, in addition to anything provided by relays that the instance is subscribed to.</p><p>Unfortunately, I’ve found it challenging to find good relays with communities and content I would want to feed into my own instance. Many instances I would want to add as a relay don’t run a relay. There’s little incentive for them to add it anyways: more work for their server and more costs associated with that.</p><p>At the same time, adding random relays from unknown communities isn’t a good idea either. The content could be questionable, and you’ll be hosting all that media yourself, which opens you up to more liability and more hosting costs.</p><p>That’s one benefit of not running a single-user instance just for yourself. It’ll be a bit more work for you to discover new content and accounts you enjoy as you won’t have much of a local or federated timeline at your disposal.</p></div>
<hr/>
<h3>How to find people to follow?</h3>
<p>You’ve found a Mastodon server you like, created an account, and now you want to find out who to follow or how to find people you already follow on Twitter. There are a few great tools to help with this.</p>
<ul>
<li>
<p><strong><a href="https://movetodon.org/">Move to don</a></strong>: This is probably the easiest way to get started. Connect with your Twitter account, and it just shows you people you follow that are now on Mastodon, providing you an easy way to follow them all or individually. You’ll want to keep checking it over days/weeks/months as more people sign up for Mastodon. <strong>Update:</strong> It seems Twitter has disabled Move to don&#x27;s API access but <a href="https://mastodon-flock.vercel.app/">Mastodon Flock</a> seems like a good replacement.</p>
</li>
<li>
<p><strong><a href="https://twitodon.com/">Twitodon</a>, <a href="https://debirdify.pruvisto.org/">Debirdify</a> and <a href="https://fedifinder.glitch.me/">Fedifinder</a></strong>: I mentioned some of these tools earlier for helping you find instances, but they also help you find people to follow from your existing network on Twitter. However, at the moment, they are a bit manual and rely on providing you with an exported CSV file of user accounts for you to upload and import into your Mastodon instance.</p>
</li>
<li>
<p><strong><a href="https://followgraph.vercel.app">Followgraph for Mastodon</a></strong>: This is another great tool, but unlike the others doesn’t need you to connect your Twitter account. Instead, you just provide it with your Mastodon handle (or anyone else’s), and it recommends other accounts to follow based on who your followers follow.</p>
</li>
<li>
<p><strong><a href="https://fediverse.info/explore/people">Fediverse.info</a></strong>: Another tool for helping you find people to follow. This one works by letting you browse by hashtags people have put in their bio.</p>
</li>
</ul>
<p><strong>Following Twitter accounts directly on Mastodon</strong>
And finally, if you’re devoted to Mastodon and don’t feel like checking Twitter all that often anymore, you can use some <a href="https://github.com/NicolasConstant/BirdsiteLive">software called BirdsiteLive</a>—an "ethical ActivityPub bridge to Twitter"—to follow people that are only on Twitter. It needs to be hosted to use, but you can <a href="https://fedidb.org/software/birdsitelive">find live instances of it on FediDB</a>. Basically, you just type in a Twitter username, and it gives you a Mastodon username to follow. At this time, one example instance that’s online is <a href="https://bird.makeup">Bird.makeup</a>.</p>
<p><strong>Cross-posting between Twitter and Mastodon</strong>
If you’re interested in posting to both Mastodon and Twitter at the same time, you can use a tool called <a href="https://moaparty.com/">Moaparty</a> or <a href="https://mikeindustries.com/blog/archive/2022/12/how-to-automatically-post-your-tweets-to-mastodon">do it yourself with IFTTT</a>. However, as a word of caution, some Mastodon folks don’t appreciate this behavior and may even consider it spammy. I agree with that sentiment: treat Mastodon as its own thing.</p>
<h3>Mastodon apps</h3>
<h3>And how developers have truly embraced Mastodon</h3>
<img src="https://turbo.paulstamatiou.com/uploads/2022/12/stammy-on-mastodon-ivory-app.webp" alt="Ivory Mastodon client" />
<small><a href="https://tapbots.com/ivory/">Ivory</a>, the Mastodon client for iOS and macOS, by <a href="https://tapbots.com/">Tapbots</a></small>
<p>Now for the fun part: exploring the world of Mastodon apps and clients.</p>
<p>There are several ways to interact with Mastodon. You can, of course, use the standard Mastodon web interface for your server, as well as the official Mastodon iPhone and Android apps to log into your server.</p>
<p>If you want a more advanced web experience, you can go to Preferences ’ Appearance and enable the "advanced web interface" to give you a multi-column layout reminiscent of TweetDeck (there&#x27;s also <a href="https://mastodeck.com/">Mastodeck</a>). And if you would prefer a simpler web client, take a look at Pinafore.social. <strong>Update:</strong> it looks like Pinafore is shutting down but the <a href="https://elk.zone/">Elk web client looks amazing</a>.</p>
<p>But I’m not here to tell you about the official apps. I want to talk about the growing and thriving developer community that is fully embracing Mastodon and the potential of the decentralized protocol. To paint a picture of why this is such a big deal, you also have to understand how much of a hassle it has been over the last decade to build anything on top of the Twitter API. It was especially hard to see as a long-time employee.</p>
<p>Long story short, Twitter made it hard. Hard to even get an API key and get your app approved. Hard to get bugs fixed or new features accessible via the API. Hard to access the data developers wanted. Hard to not hit arbitrary constraints or limits. Things were always changing, rugs were pulled, announcements about new priorities and new rugs were made, only for them to be pulled again (read <a href="https://www.theverge.com/2021/11/15/22779149/twitter-api-version-2-official-decentralized">this</a>, <a href="https://techcrunch.com/2022/11/02/twitter-cancels-its-chirp-conference-for-developers-amid-management-transition/">this</a> and <a href="https://techcrunch.com/2022/12/15/developer-platforms-are-all-about-trust-and-twitter-lost-it/">this</a>).</p>
<p>No one knows this pain better than the team at Tapbots, makers of a popular third-party Twitter client called Tweetbot. I’ll be the first to say I did not like Tweetbot—not due to anything about the app itself; it was beautifully executed and well-built—I was just designing for the official Twitter apps. Tweetbot had nice details, but I never really used it much, though oddly enough, quite a few of the Twitter iOS engineers used it over the years, if that tells you anything.</p>
<p>Needless to say, the Tapbots team had to deal with all the ups and downs that came with building on top of the Twitter API. Twitter wasn’t necessarily fond of third-party clients that they couldn’t effectively monetize or control.</p>
<p>Mastodon brought the winds of change, an open web not controlled by any single entity. <a href="https://tapbots.social/@mark/109524033562967560">Mark Jardine</a> from Tapbots wrote a thread outlining his experience building on top of Twitter, contrasted with their new focus on Mastodon:</p>
<blockquote>
<p>“As much as Twitter has brought us success, it has also been extremely frustrating for the past 6-7 years trying to build something great with a nerfed API.”[…]</p>
<p>“Building an app for an open and decentralized social platform felt so refreshing. Inspirational! I haven’t been so excited designing something in a long time. With Tweetbot, we were always fighting with the API limitations while knowing in the back of our minds that someday the API could be taken away.”</p>
<p>“I didn’t realize it then, but that killed a lot of our excitement and enthusiasm. With @ivory, we are just ecstatic every single day. It’s just been a pure joy to make software again.”</p>
<p>—<a href="https://tapbots.social/@mark/109524033562967560">@mark@tapbots.social</a></p>
</blockquote>
<p>Tapbots is building a lovely Mastodon client for iOS and macOS called <a href="https://tapbots.com/ivory/">Ivory</a>. But they’re not the only ones ramping up development on a Mastodon client. There’s also Mammoth, an app in development by iOS developer <a href="https://mastodon.social/@JPEGuin">Shihab Mehboob</a> along with his team. I’ve also been testing Mammoth, and if you’re used to the official Twitter mobile apps, you’ll find Mammoth familiar.</p>
<p>Then there’s Metatext, Toot!, tooot, Mastoot, Mast, Tusker, and Woolly, <a href="https://github.com/Dimillian/IceCubesApp">IceCubesApp</a>, among others. Some of these are in Testflight and are best found by following the developers on Mastodon. The official Mastodon site has a <a href="https://joinmastodon.org/apps">list of public third-party apps</a> as well.</p>
<h3>Using Mastodon</h3>
<h3>Toots, boosts, and bad search, oh my!</h3>
<p>So you’ve made it. You have an account, you’ve followed some people, and you have installed a lovely Mastodon app. Time to get to know Mastodon a bit better. If you’re coming from Twitter, you’ll pick it up quickly, but there are a few quick differences:</p>
<ul>
<li><strong>Tweets → Toots</strong>: This was the Mastodon word for a post for a long-time, but a recent software update renamed the "Toot" button to simply "Publish." Some folks still refer to posts as toots.</li>
<li><strong>ReTweets → Boosts</strong>: Sharing a post on Mastodon is done by boosting, much like ReTweeting. If anything, boosting is encouraged and seemingly more common on</li>
<li><strong><s>Quote Tweets</s></strong>: Mastodon has no equivalent of Quote Tweets. You can only boost a post. This was an <a href="https://blog.joinmastodon.org/2018/07/cage-the-mastodon/#:~:text=Another%20feature%20that%20has%20been%20requested%20almost%20since%20the%20start%2C%20and%20which%20I%20keep%20rejecting%20is%20quoting%20messages">intentional design decision meant to curb abuse and harassment</a>. However, with the <a href="https://en.wikipedia.org/wiki/Eternal_September">Eternal September</a> of Twitter users flooding Mastodon, it is a bit of a hot topic and has come up often recently. Here’s <a href="https://macaw.social/@dml/109569707633229305">some more thoughts on the topic</a> from an engineer I worked with at Twitter who knows the problem space well. But they eventually find their way on Mastodon; the Mastodon founder <a href="https://mastodon.social/@Gargron/109623910323239777">recently expressed some interest</a> in a version you can opt out of.</li>
<li><strong>280 character limit → 500 character limit</strong>: Toots are 500 characters! Enjoy the extra space to share your thoughts without easily getting misinterpreted. You can also reply to your own toots to create a thread, though the composer doesn’t have the built-in functionality to create a thread that Twitter has (and that I designed while at Twitter). However, since it is open-source software on top of ActivityPub, anyone running their own instance <a href="https://write.as/sweetmeat/customize-mastodon-to-change-your-post-character-limit">can modify this limit</a> to be much larger.</li>
<li><strong><s>Verification</s></strong>: As mentioned earlier, Mastodon has no concept of account verification, though some users add <code>:verified:</code> to their username and it gets rendered as a checkmark on their avatar in some Mastodon apps. Separately, links on your profile can get verified if you add a <code>rel="me"</code> link on your site.</li>
<li><strong><s>Direct Messages</s></strong>: Mastodon doesn’t really have a concept of direct messages at this time. While you may see a DM tab in some Mastodon clients, they are really just toots with the privacy setting set to "only those mentioned." But the account you mention can mention someone else in their reply, and they will get added to the DM. It’s important to note that they are also not encrypted, so your Mastodon instance admin (along with the admin of any instance you&#x27;re sending to) would be able to see it in the database if they really cared to look it up.</li>
<li><strong>Lists</strong>: While both Twitter and Mastodon have the ability to create and follow custom lists of accounts, they work a bit differently on Mastodon. You can only add people to a list that you’re already following. On Twitter, you could add anyone to a list even if you didn’t follow them, which made it great for creating separate timelines you could hop between as you wished. However, I did see some chatter about Mastodon considering this, under the moniker <a href="https://github.com/mastodon/mastodon/issues/16556">exclusive lists</a>.</li>
</ul>
<p>There are also a few other features like following hashtags (though it has some limitations) and the ability to put a post behind a Content Warning (the "CW" icon in the Mastodon post composer). Aside from that, you get the expected functionality of being able to attach video, images, and polls in addition to being able to adjust post privacy settings.</p>
<p>There’s one more thing, and this one may take some getting used to. Full-text search of the contents of Mastodon posts isn’t really a thing. You can search for accounts, and you can search for hashtags. Searching for accounts works pretty well, especially when including the full <code>@username@example.com</code> format. Searching for hashtags is a bit more limited and will only surface results that your instance knows about from local posts and federated posts. But your server doesn’t instantly know about all posts on the fediverse, so you may not see all the results you expect. You can get some very limited searching for your own posts, mentions, favorites, and bookmarks if your server admin setup <a href="https://docs.joinmastodon.org/admin/optional/elasticsearch/">ElasticSearch</a>.</p>
<p>Search could get better if someone made their own service dedicated to indexing, relaying, and searching the fediverse, but that is no small technical (and expensive) feat.</p>
<p>Isn’t it pretty bad that there’s no good search? Well, along with the lack of Quote Boosts, this is framed as a purposeful design decision (though it also feels like a technical challenge):</p>
<blockquote>
<p>"Mastodon deliberately does not support arbitrary search. If someone wants their message to be discovered, they can use a hashtag, which can be browsed. What does arbitrary search accomplish? People and brands search for their own name to self-insert into conversations they were not invited to."</p>
<p>—<a href="https://blog.joinmastodon.org/2018/07/cage-the-mastodon/">Mastodon</a></p>
</blockquote>
<h3>My thoughts on Mastodon</h3>
<h3>Vast potential mixed with non-trivial constraints</h3>
<p>Mastodon brings a lot to the table with its federated model of sharing utilizing an open protocol. It’s easy for anyone to host their own instance and own their data while participating in a large network with many communities. It’s not owned by anyone, nor can it be. It’s an open-source project run by a non-profit. Anyone can fork the code and do what they wish.</p>
<p>But, it’s not easy for anyone to get started. There’s no question about it, you cannot come from a centralized and well-capitalized product like Twitter and expect the same of a decentralized, open-source project. Mastodon is very rough around the edges when you approach it from a mindset of the former:</p>
<ul>
<li>
<p><strong>Hard to sign up. Hard to find communities</strong>: Okay, so I just installed the app... I can’t just create an account? I have to pick a server? Even with the official Mastodon app providing a list of instances to choose from, it’s still confusing. How can I see an example of the content and people on each server to know I’m choosing the right one? What are the implications of choosing a server? Is it publicly facing? Can I change it later? Is it easy to change? Et cetera.</p>
</li>
<li>
<p><strong>Hard to find people</strong>: Once you have an account, you’re still in for more uphill battles. How can you even find good, relevant, and interesting accounts to follow? You have to rely on word of mouth or third-party tools.</p>
</li>
<li>
<p><strong>Hard to find content</strong>: It’s hard to continually discover the type of content you enjoy. There’s no algorithmic timeline to inject new content into your home timeline. You have to rely on... hashtags, people you follow boosting content from others, and remember to continually check the federated and local timelines of your Mastodon instance. Using hashtags started to feel so thirsty even years ago, but now it seems like a necessity?</p>
</li>
</ul>
<p>Federation brings power. It brings constraints.</p>
<h3>Challenge 1: Following accounts and engaging with posts not on your server</h3>
<p>One early challenge you’ll run into with federation is simply around following people as well as engaging with posts you find on other instances. Let’s say I find a link to a Mastodon post externally (as in not something I come across while logged into my own Mastodon server). It could be a link on someone’s blog, from a chat app, and so on. By clicking that link, I am going to the post hosted on Mastodon instance that is not my instance. Even though I may be logged into my own Mastodon instance, this other instance doesn’t know or care about that. I’m just a visitor and have no account with that instance. I can’t favorite the post, reply, or even follow the author.</p>
<p>Instead, the onus is on me to find a way to that same profile or post, but within my Mastodon instance where I’m logged in and can carry out any actions I want to take. <strong>This is super annoying</strong> and happens all the time. For example, I can’t link you to my Mastodon profile <a href="https://stammy.design/@stammy">@stammy@stammy.design</a> and have you tap follow. That would only work if you already had an account on stammy.design. So you have to copy the username, then go to your Mastodon website or app and search for my account.</p>
<p>What’s the solution? Nothing great. A partial solution for desktop is to use a <a href="https://github.com/bramus/mastodon-profile-redirect">Chrome extension that redirects profiles</a> to your own instance, but it doesn’t work for posts (you can&#x27;t just reformat the URL as the ID of the post isn’t the same across instances). And I’ve seen some chatter about an <a href="https://github.com/mastodon/mastodon/issues/19954">intents/handler-style way to deal with this</a>.</p>
<h3>Challenge 2: Sometimes you just don’t see things</h3>
<p>A recurring theme with federation and Mastodon is around how your instance only knows about things it knows about. It doesn’t automatically know about every post across every Mastodon server online. This can lead to some unexpected behavior:</p>
<ul>
<li>
<p><strong>Profiles you visit may be empty at first.</strong> They won’t have any posts if your server has never encountered this account before (and no one else on your server has followed or interacted with the account). Following the account will start to get new posts from that account, but don’t expect it to instantly fill it up with every historical post from that account.</p>
</li>
<li>
<p><strong>Not all public replies to a post may be visible.</strong> This one is the most concerning. Your server may not know about all the replies to a post, and therefore you may only be seeing a slice of the conversation on a post. Simon Willison has a great dive into the issue <a href="https://fedi.simonwillison.net/@simon/109559268498004036">in this thread</a> on his personal instance.</p>
</li>
<li>
<p><strong>You may not be able to see a complete list of someone&#x27;s followers</strong>. Similar to the above, your server likely has a limited view into who follows that account.</p>
</li>
<li>
<p><strong>Boost and favorite counts may not be accurate.</strong> Same story here; your server only knows what it knows about. If you want to get a real understanding of a post&#x27;s true engagement, your Mastodon client may have an action in a menu for something like "open original post."</p>
</li>
</ul>
<p>So, how can you get your Mastodon server to know more? If you’re on a larger instance or tend to mainly communicate with people on the same server, you’re less likely to run into these issues. There’s not much of a fix aside from the admin adding a ton of relays to ingest as many posts from the fediverse as it can, but that’s not ideal for various reasons.</p>
<h3>Challenge 3: Moderation and incentives</h3>
<p>And one last challenge I see is typically listed as a good thing about Mastodon: moderation. I’m annoyed with Twitter because it seems like they are continually changing the rules, banning people arbitrarily, and I didn’t want my identity held hostage. Well, the exact same thing can happen on Mastodon and more.</p>
<p>How do you moderate a federated network? You leave it up to the instances to moderate themselves. You just have to trust the admins of each instance to do the right thing, and the idea is that by picking your instance, you’re picking a community you embrace and feel part of, and everyone will follow the established rules. And if you’re doing all that, you shouldn’t have an issue, right?</p>
<p>This quote from Noah Smith in his article <a href="https://noahpinion.substack.com/p/the-internet-wants-to-be-fragmented">The internet wants to be fragmented</a> sums up nicely why moderation is great:</p>
<blockquote>
<p>"<em>Community moderation works.</em> This was the overwhelming lesson of the early internet. It works because it mirrors the social interaction of real life, where social groups exclude people who don’t fit in. And it works because it distributes the task of policing the internet to a vast number of volunteers, who provide the free labor of keeping forums fun, because to them maintaining a community is a labor of love. And it works because if you don’t like the forum you’re in — if the mods are being too harsh, or if they’re being too lenient and the community has been taken over by trolls — you just walk away and find another forum."</p>
</blockquote>
<p>That seems fine, and if you don’t like it, you can find another instance or host your own. But what if you couldn’t move your account? If you don’t get along with your instance admin, it seems <a href="https://twitter.com/alexqgb/status/1594079081649184769">they can even block your move to another instance</a>.</p>
<p>Okay but that’s like the worst-case scenario, right? Yea, that’s true. But there’s one more unpleasant situation. Running a Mastodon instance is a non-trivial amount of work. There’s technical setup and regular maintenance to keep on top of, there are real costs associated with hosting, and there’s legal risk as well.</p>
<p>Since there are no real incentives to host and moderate a Mastodon instance, you could end up on a poorly run instance. If you’re not on a well-run instance, best case scenario, sometimes your server is a little slow or isn’t always running the latest software, but it is generally okay. The worst case scenario is that, uh, your server goes down permanently, along with your Mastodon identity and all your data.</p>
<p>All this to say, choosing your Mastodon server is an especially important task. One thing that would make this better is if Mastodon had a more streamlined way to be able to donate to Mastodon admins to pay for server costs. I imagine seeing some Stripe link in settings and being able to set up a small recurring donation.</p>
<h3>Here’s why I like Mastodon</h3>
<p>While those challenges complicate things, they don’t overshadow the brilliance of Mastodon and the protocol for me. One of those reasons is that it feels more intimate, just a small place with the people I follow. No one or thing unexpectedly forcibly getting injected into my home timeline.</p>
<p><strong>On Twitter, you have three groups of accounts: celebrities and other verified accounts, brands, and then just regular people. On Mastodon, you only have people</strong> (and with so many instances to choose from, no one can really squat on your desired username). No ads either. The Mastodon home timeline is always in reverse chronological order—not algorithmic or ranked like Twitter’s timeline is by default. This means your timeline is saner. It’s not filled with threads spewing the same nonsense that gets injected into your timeline by the algorithm. It’s not filled with ads.</p>
<p>And with the longer character limit, you can more easily converse with people or share your thoughts without losing much in translation or spending lots of time trying to reword things to fit logically in one or multiple posts.</p>
<p>Mastodon feels like the early days of Twitter, with people just sharing thoughts, not worrying about how to optimize for engagement. It feels more intimate, authentic, and close-knit. My only advice for those starting out on Mastodon is to boost posts you think others should see to help with discovery, and also, you can favorite your heart out knowing it doesn’t do unexpected things like injecting the post into others’ home timelines because there’s no algorithmic timeline.</p>
<p>As I mentioned earlier, Mastodon’s open-source software, open protocol, and strong API without limitation (as compared to Twitter) make it a dream for developers. I’ve been seeing this flurry of excitement from developers building Mastodon apps. I’m excited to see what else gets built on top of, or for, Mastodon and ActivityPub.</p>
<p>The challenge will then be how the Mastodon project and broader community deal with the huge influx of new users. Will they develop efficient product development processes to deal with the flood of feature requests, complaints, and associated chatter in a principled manner? Will there be enough people to push for great design?</p>
<p>So far, everything on Mastodon feels like a page out of early Twitter. Nothing bad about that; it’s easy for people to join and generally understand how things work. But shouldn’t it evolve to best embrace the unique affordances and constraints of Mastodon? What will it mean for future functionality to look, feel and act like the decentralized network it is? People designing for the official Mastodon project need to think less about Twitter and more about what it means to be Mastodon. Perhaps third-party Mastodon clients and forks can lead the way before they get adopted.</p>
<h3>An open web, owned by its users</h3>
<h3>Yes, another "bring back blogging and RSS"</h3>
<p>This is the part where I talk about my growing desire to have more control over, and own, my data and my online identity. I want to move away from relying too much on just a few large centralized tech companies when they control too much of my data. I think about worst-case scenarios. What happens if I get locked out of this account for a day, a week, for good? It’s with that mindset that I need more control, access to the raw data, and more.</p>
<p>That way of thinking is often a bit overkill and can lead you down a complex path (have you ever tried hosting your own email??), but 2023 is the year I begin to detach myself from large tech companies like Twitter and Google. And for the services I do rely on, I expect encryption. And it was nice to see Apple roll out iCloud Advanced Data Protection recently. I love Signal and ProtonMail. It gives me comfort knowing that even if my account was compromised, the attacker would also have to know a separate encryption key to get into my mailbox.</p>
<p>I’ve been running paulstamatiou.com for 17 years. First hosted from a Mac mini in my dorm room at Georgia Tech. Starting this site and continuing to maintain it has been one of the best things I’ve done. It gives me a space to tinker, write, share thoughts, show work, and publish photos.</p>
<p>I miss the days when if you wanted to have a space online, you had to make it yourself. Personal blogs were their own communities. The comments sections were helpful and thriving. They were hard to discover, but we got by. We had feed readers, blog rolls, Technorati, and trackbacks.</p>
<p>Every day, I would be excited to open my feed reader and see if anyone whose feed I subscribe to had posted anything new. Seeing that unread count badge on a favorite blog was like a little present.</p>
<p>In those days, you followed people. Sure there were a few big publications you might keep track of, but you didn’t really follow "developer blogs" or "design blogs." It was always just people’s personal blogs publishing whatever felt interesting to them. They had their own take and personality.</p>
<p>We’ve seemed to have lost a bit of that personality and authenticity. We’re living in a world where it often feels like everything is carefully curated and polished just so for engagement. This was well before we became far too accustomed to busy feeds, videos, threads, gamification, listicles... the constant need to be entertained and get a serotonin hit. Personal blogs offered a glimpse into the real lives and thoughts of their creators.</p>
<p>In recent years, we made way for the rise of personal newsletters. It was only after my inbox had become unmanageable from Substack and other newsletters that I started <a href="https://paulstamatiou.com/hello-rss/">using an RSS reader again</a>. A modern one that could also manage newsletters and declutter my inbox. But the type of content I long for is not there. (By the way: you can just add <code>.rss</code> to any Mastodon profile or search URL and get an RSS feed).</p>
<p>I’m hoping that the recent interest in Mastodon will get people to start thinking more about taking control of their data and online identity. Mastodon has a great shot at recreating that feeling of community that personal blogs used to have. It can be your own space.</p>
<p>I only ask that you don’t think of it as a Twitter replacement but as a new thing. A new way to communicate, connect and build communities. A decentralized product like Mastodon will have some learning curves, no doubt. But it’s a start. And it’s a start that’s not owned by a billionaire.</p>
<p>If you’ve read this far, thank you! You can follow me on Mastodon by copying my full username and pasting it into the search of your Mastodon website or app to find my profile and hit follow: <a href="https://stammy.design/@stammy">[object Object]</a></p>]]></description>
            <link>https://paulstamatiou.com/mastodon</link>
            <guid isPermaLink="true">https://paulstamatiou.com/mastodon</guid>
            <dc:creator><![CDATA[Paul Stamatiou]]></dc:creator>
            <pubDate>Thu, 05 Jan 2023 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Craft]]></title>
            <description><![CDATA[<p>After 10 years of working at large companies with thousands of employees, I recently joined a 10-person startup. It&#x27;s called <a href="https://a16z.com/2022/11/01/investing-in-rewind/">Rewind</a> and I am absolutely loving my new role for a lot of reasons. It&#x27;s a bit different from my previous roles: I’m a product designer but I also spend time building my designs in Xcode. I love having a hands-on route to directly affecting product quality.</p>
<p>Much of my career as a designer has led me to hold product and design quality in the highest regard. It&#x27;s not easy. I want to be proud of the things I ship and <a href="https://bryanhaggerty.com/blog/2012/11/proud_enough_to_put_your_name_on_it/">put my name on them</a> (<a href="https://www.folklore.org/StoryView.py?project=Macintosh&story=Signing_Party.txt&sortOrder=Sort+by+Date&topic=Apple+Spirit">see also</a>). That 10 year old post from Bryan Haggerty is still as true as ever:</p>
<blockquote>
<p>“With small teams, the output, whether it’s an app, web site or any other product, represents the people behind it and the tremendous amount of effort they expended to make it. And it’s common for those people to willingly put their name on it, <strong>taking accountability for what’s great and what needs to be improved.</strong>”</p>
</blockquote>
<p>I’ve worked on numerous projects with large teams where the work shipped felt like a string of excuses—a reflection of tight timelines, cut scope and endless constraints. It never feels great to ship something to real people that is not an accurate representation of the intent you and the team had.</p>
<p>As a designer I&#x27;m motivated not only by identifying and successfully solving problems for people through software, but also by the care, attention to detail and craft I&#x27;m able to put into it along with the team.</p>
<p>I want someone to use something I&#x27;ve created and feel that was intentional. That it not only had their exact needs in mind but went beyond to care about the details and have personality. <strong>This is a post about well-made, high-quality products and why shipping quality is hard.</strong></p>
<hr/>
<p>I’ve always been something of a hybrid designer and developer. I initially studied computer/electrical engineering when I went to college in 2004. Eventually I felt that was too far removed from the end user experience of the devices we use. I transitioned to a major that combined design and computer science. However, when I graduated I felt like I wasn’t great at either. I spent the 5 years after college working on several startups I cofounded before landing at Twitter in early 2013.</p>
<p>When I joined the Twitter design team I was designing in Photoshop. For things that demanded higher fidelity, I would dive into After Effects to make small UI videos—a far cry from the interactive mobile prototyping we take for granted today.</p>
<p>The next year I became immersed with interactive mobile prototyping. I fell in love with a Javascript animation library called Framer.js—it felt like a superpower. I could make fully interactive prototypes for web and mobile experiences that felt real (old examples <a href="https://paulstamatiou.com/twitter-video/">here</a> and <a href="https://photos.paulstamatiou.com/work/">here</a>).</p>
<p>Prototyping got me a step closer to what the actual product would feel like. It was my interactive canvas for testing out ideas and concepts rapidly. Prototyping dramatically elevated my design process, helped me think through implementation details, interactions, motion, and communicate concepts.</p>
<p>Of course, while high-fidelity visual designs and a complete interactive prototype can help you communicate your concept and get people excited, it won&#x27;t help the final product get built.</p>
<p>For that you need a lot more. You need to make your case for what the problem or opportunity is—most often validated with at least directional data and/or research insights—and why your specific solution could work. You need to ensure it weaves into broader company initiatives as well as goals for your team and org. And you need a plan to get your product out there in a timely manner along with ways you&#x27;ll further learn and validate your approach. An executive team won&#x27;t be thrilled to hear you want to spend a year building something based solely on a hunch.</p>
<p>That&#x27;s where the challenge of building quality products starts to creep in. <strong>The constant tension of shipping faster versus shipping better.</strong> Falling into a cycle of "Ship, then iterate" is a trap. It ends up being more <em><strong>shiterate</strong></em>. Things happen and that "fast-follow" V1.1 release or V2.0 you had imagined probably won&#x27;t. There&#x27;s always a new shiny initiative, re-org or new leadership hire that throws a wrench into things and changes all plans. Don&#x27;t rely on a future release to clean up today&#x27;s mess.</p>
<p>Having spent many years going through this constant quality versus speed tug-of-war I focused a lot of time and energy on product strategy as part of my design process. I crafted a story about our customers to our teams and leaders. I wrote a ton of internal documents; product briefs, design briefs, customer problems, product opportunities, vision, et cetera. I spent time evangelizing efforts, working on decks to show where we could go, how we could get there and what it could unlock, while addressing the opportunity cost as well as challenges like built-up tech and design debt.</p>
<p>But even that doesn’t ensure that the thing you&#x27;ve designed will result in the high-quality shipped solution you envisioned. There are a lot of reasons why shipping well-crafted, quality products is hard, especially on a large team.</p>
<h3>What is quality?</h3>
<h3>And why is it so hard?</h3>
<p>I often use the word quality when referring to apps, products and services I hold in a high regard but another word that often comes up in this context is <em>craft</em>. Craft, as in something that is handcrafted where something someone spent a lot of time on and maybe even embedded their own personal touches and personality in it. Often something handcrafted feels more premium.</p>
<p>There’s a reason high-end car manufacturers boast about their handcrafted cars. Something so premium that an individual person spent time obsessing over the details. Some even prominently display a plaque on the engine with the <a href="https://turbo.paulstamatiou.com/uploads/2022/11/mercedes-amg-engine-plaque.webp">signature of the engineer</a> that built it. This goes back to that quote earlier about putting your name on something and taking accountability.</p>
<p>Quality and craft are not just words designers toss around when referring to some veneer of polish adorned on top of a product with superficial visual design tweaks and unnecessary, over-the-top animations.</p>
<p>Quality is all-encompassing.</p>
<ul>
<li>It’s accessibility so that everyone can use it.</li>
<li>It’s performance and ease of use so it respects the user’s time and helps them accomplish their tasks when they need.</li>
<li>It’s reliability so they can feel good about having this tool in their pocket for when they need it.</li>
<li>It&#x27;s durability with designs and components that can scale to withstand future needs and uses.</li>
<li>It’s well-considered.</li>
<li>It’s the feeling that a lot of time and care went into creating the product: that someone has already thought of you.</li>
<li>Of course, it can also be a bit extra and bring delight in unexpected places and important moments.</li>
</ul>
<p>Apple gave a talk about the qualities of great design where they interviewed people on their thoughts around quality:</p>
<img src="https://turbo.paulstamatiou.com/uploads/2022/11/apple-wwdc-quality.webp" alt="Apple WWDC Quality" />
<small><a href="https://developer.apple.com/videos/play/wwdc2018/801/">The Qualities of Great Design</a> - WWDC</small>
<p>Quality happens throughout the entire project whether you&#x27;re cognizant of it or not. It happens when identifying the customer problem to solve, designing a solution, validating it, building it, maintaining it, and even when you sunset the product. A focus on quality drives a way of working in which you dynamically either embrace constraints when you need to or challenge them when you see an opportunity.</p>
<p>People hire services not just based on what they can do but how it makes them feel.</p>
<p>Quality has a direct relationship to that. Quality products can take your users from "I&#x27;m merely using this thing to accomplish a task" to "this is something I <em>love</em> using and I&#x27;m telling everyone I know about it."</p>
<p>I’m writing this article in a macOS app called Ulysses right now. I love it because it’s quality software. It&#x27;s approachable, <em>actually</em> easy to use, fast, and I can personalize it to my taste.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2022/11/ulysses-app-paulstamatiou.webp" alt="Ulysses app for macOS" />
<p>It makes me feel good about the work I’m doing. I could have written it in a myriad of other text editors filled with bells and whistles but I chose Ulysses because I know I can rely on it to let me focus on what I’m trying to write. Quality products make me excited to use them.</p>
<p>If we all generally agree that quality is a good thing, then why aren’t there more high-quality apps and services out there? <strong>Because quality is hard.</strong></p>
<h3>What affects quality?</h3>
<p>Lots of things can affect the quality of your product, especially on large teams, including culture, incentives, skills and tools. Here’s just a few that are top of mind:</p>
<ul>
<li>
<p><strong>Leadership, organizational support and incentives.</strong> Does the organization care about quality? What does quality mean to them? How does it tie into the career ladder, promotions and prioritization frameworks? Do they focus more on execution speed over quality?</p>
<p>Is quality baked into the normal product development process, or is it often relegated to low priority "polish" tickets that pile up. Will leadership pause a launch if the quality is below their bar? What is that bar?</p>
<p>If support for quality does not come from the top, it&#x27;s far too easy for ICs to skirt over issues and pay a little less attention to details they think their reporting chain won&#x27;t notice.</p>
<p>Do different roles (like engineering, product, design) have different motivations for getting their work done? This, again, ladders up to what the org thinks about quality.</p>
</li>
<li>
<p><strong>Culture around quality.</strong> To maintain a shared, company-wide understanding of the company&#x27;s specific stance is on quality, how does quality get rewarded, celebrated and prioritized? Is there a process in place for delaying a release and having a retro when the quality bar slips? Who decides when quality has slipped? Who&#x27;s accountable for addressing it?</p>
<p>Does everything need to have the same level of quality at the company? Are there certain things that need more or less? Unclear alignment around what deserves quality amongst teams can lead to issues.</p>
</li>
<li>
<p><strong>Trouble identifying issues.</strong> Do you have the right people with the right skills and motivations to flag quality-related issues? Do they have the right tools?</p>
<p>Focusing on quality is often thankless work. Tons of time can go into rigorously testing builds, logging issues, providing feedback and coming up with solutions given the constraints.</p>
<p>Does everyone have an eye and the time for design QA? For the items that are more visual/motion related, are the designers skilled enough at visual design to even know there are issues or be motivated enough to address them? Are there other designers they can rely on on the team for pixel-level details if that’s not their strength?</p>
</li>
<li>
<p><strong>Poor ticket/engineer fit.</strong> The onus is not just on designers to help identify and document issues to be addressed. What happens when a particular engineer picks up the next ticket and it involves a specific set of knowledge they may not have, for example like knowing about the nuances of animating collection views on iOS.</p>
<p>Does the engineering manager wait until there&#x27;s an engineer better suited to tackle this ticket? Does the assigned engineer compromise with the designer on a solution if this is too intricate to tackle for them? What resources does that engineer have at their disposal?</p>
</li>
<li>
<p><strong>Inadequate tooling for effective design/engineer pairing.</strong> Back when a designer and engineer might have worked in the same office with each other, they could sit down to iterate on a new build. They could easily try 10 or more different values for a specific animation, build and test together over the course of 30 minutes.</p>
<p>Contrast that with the new way of working remotely. The designer may feel less comfortable going back and forth suggesting small tweaks to engineering builds, so they only suggest a few iterations so as to not feel like they’re annoying the engineer too much. And these iterations will be less refined because the pairing iteration speed is so much slower. Do you send over ipa/apk files? Does the designer have the dev environment setup on their machine and pull the branch to build and test themselves? Or, worse, does the designer just have to wait a day or two to be able to provide feedback on a build when the code is reviewed and merged into an internal dogfood build they can easily access.</p>
<p>Relying on screenshots and video clips sent over Slack can only get you so far. Perhaps in the future there will be tools for this. I&#x27;d love something like high-fps, low-latency interactive VNC sessions for remotely controlling someone else&#x27;s Xcode simulator for example.</p>
</li>
<li>
<p><strong>Liberal use of "MVP" or "it&#x27;s just an experiment".</strong> Does the team use those terms to skirt around typical quality standards and ship something subpar? Does everything worked on, even experiments, demand the same care as a more mainstream release that goes out to all users?</p>
<p>That&#x27;s a slippery slope because it&#x27;s all too easy to simply ramp up that experiment to 100% of your users if it performs well, without addressing quality issues that were neglected prior to shipping to that initial set of users.</p>
<p>No one wants a slice of cake that is just a piece of the bottom layer. You need to have a taste of each layer with each bite, including the icing. So even if it’s not your entire vision, it has all the right pieces involved. Ditch the term MVP and use <a href="https://blog.asmartbear.com/slc.html">SLC (Simple, Lovable, Complete)</a>.</p>
</li>
</ul>
<p>Most companies struggle to prioritize small quality and “fit & finish” design issues. On their own, these tickets seem like they&#x27;ll have remarkably low impact for the product. How will fixing the alignment of this button help us have a better launch, higher customer retention or a more stable app? However, <strong>compounding effects come into play</strong> with this kind of work. One or two of them won’t make a difference. But when you’ve fixed a dozen or so? It’s noticeable.</p>
<p>Building that understanding into the way you work is key. But it&#x27;s not the singular solution. It still goes back to many of points above. Does your team have the skills and incentives to identify and adequately fix those issues? Does the organization continually reinforce and celebrate work that ladders up to quality, craft and great design?</p>
<p>I didn’t write this section aiming to get to some sort of grand revelation about how you can build great software with one simple trick. <strong>Quality is hard.</strong></p>
<p>I’m not saying designers, PMs and engineers should be holding up their projects for months to “get it right”. I&#x27;m saying that teams should be working in a way where everything is considered and there&#x27;s a framework for identifying, discussing and prioritizing quality-related issues so that quality is a bit less of a sisyphian task.</p>
<blockquote>
<p>“But the desire to ship quickly was counterbalanced by a demanding, comprehensive perfectionism. Most commercial projects are driven by commercial values, where the goal is to maximize profits by outperforming your competition. In contrast, the Macintosh was driven more by artistic values, oblivious to competition, where the goal was to be transcendently brilliant and insanely great.”</p>
<p>—<a href="https://www.folklore.org/StoryView.py?project=Macintosh&story=The_Macintosh_Spirit.txt">The Macintosh Spirit</a></p>
</blockquote>
<h3>Quality is a way of working</h3>
<h3>It&#x27;s not something you&#x27;ll get to later</h3>
<p>We&#x27;ve identified that quality is hard and that it&#x27;s tied to a whole slew of things from culture and leadership to experience and tools. Quality is the way you work. Focusing on quality doesn&#x27;t have to mean that suddenly your project scope has become bloated with a slew of tasks that will take 25% longer to complete. It can be prioritizing more <em>complete, well-considered</em> chunks of functionality (goes back to the SLC concept above).</p>
<p>What doesn&#x27;t work in my experience is marking tickets you can&#x27;t get to before your deadline as design debt, tech debt or polish to tackle later. Polish is an easy word to equate to design tickets but it&#x27;s an especially poor choice as most people tend to think it&#x27;s defined as optional, obsessive and unnecessary details.</p>
<p>I&#x27;ve been immersed in thinking about and working on quality for years at large companies. It&#x27;s insanely hard to change a company&#x27;s perception of quality and process, but here are a few things that help:</p>
<h3>Balance long-term and short-term design</h3>
<p>Build a working style that always pairs thinking about the long-term design direction of your surface area along with the short-term. By only thinking short-term it&#x27;s far too easy to design or build yourself into a corner, only too realize you&#x27;ve built a cluttered UI or relied on complicated interactions and flows. Doing so also helps you become a strong ally to your product partners so you can craft a story of where you see the product going and how it could potentially best address customer needs in the future.</p>
<p>I used to think doing long-term (so-called vision work) was bogus. Designers would get assigned to these "vision projects" by various executives, spend months on some explorations and a deck, only for the work to be archived in some internal wiki, never to be touched again. They tended to be run only by designers, not informing or consulting with adjacent roles and teams along the way.</p>
<p>As much as designers want to go off in a corner and come back with magical designs and a roadmap, this really needs to be a team effort, even if your stakeholders are more in the "inform" role of the DACI framework.</p>
<h3>Close the gap between design and engineering</h3>
<p>Bring design and engineering closer. There’s still a ton of onus on the designer to help illustrate and share their vision with their team. Sometimes designers are limited by what they can make with the tools at their disposal and their skills. If they can’t design or prototype at least a sliver of what’s in their head, how can they expect their engineering counterparts to not only build it but build it well? It may even limit the types of design solutions you explore if you&#x27;re unsure how to even communicate it. However, by building stronger relationships with your engineering coworkers you can try to bridge that gap more effectively.</p>
<p>For me, Figma is where initial hunches live; a starting point. Not final designs. it&#x27;s not until I start building and really using it that I get more signal to understand what aspects of the design feel good and which aspects don&#x27;t. That&#x27;s a big reason why I dislike teams that treat their visual designs as complete and "ready for handoff." Please, never treat design as something you just handoff to engineers. That&#x27;s a great way to devalue the contributions of the engineers on your team and lead to a worse product. Treat it more like a conversation between design and engineering.</p>
<p>Some larger teams have dedicated prototyper or design/UI engineering roles. That&#x27;s one way to help bridge this gap, though for me they always felt one-step removed from product design and I wanted to also be leading the design in addition to coming up with the final solutions. If you have these roles, it&#x27;s important to not just assign them from project to project merely to prototype something a team needs for a research study or other short-term need. Instead, have them paired up with design and research for 100% of the project.</p>
<p>It&#x27;s also important as a designer to know when to push on something and maintain your quality bar and when to compromise. That&#x27;s your superpower. Everyone will hate working with you if you hold a high quality bar but don&#x27;t know how to work within the context of your business goals and customer needs. Getting as close to the technical side will help you. Here&#x27;s a good post on this topic from an engineer&#x27;s perspective: <a href="https://www.joshwcomeau.com/career/effective-collaboration/">Effective Collaboration with Product and Design</a>.</p>
<p>Then there&#x27;s tooling that can help improve speed of iteration; making it faster for designers to receive and test builds from engineers (as mentioned in the previous section). And finally, provide resources for engineers to learn more of the intricacies of front-end development, UI and motion frameworks. This may be more important for companies that tend to hire more full-stack engineering roles.</p>
<p>Of course, all of this gets a lot easier if you&#x27;re a designer who can also code your designs.</p>
<h3>Determine what quality means for your team & set your quality bar</h3>
<p>Depending on the company, industry and team, quality will mean different things. For one product and customer type it may mean a huge focus on reliability and speed while for another it may be a focus on delight and attention to detail.</p>
<p>A shared understanding of what types of work meets and what type of work doesn&#x27;t meet your quality bar, along with executive support, can help with prioritization. Doing so can help realize the compounding effects of smaller quality and design tickets.</p>
<p>This entails understanding how a user-facing visual refinement is a very different type of ticket than something like a performance bug or crasher. If you only have one type of work queue, it&#x27;s very easy to only prioritize the bugs and crashers. But when do the other types of quality tickets get prioritized? Try to dedicate a certain amount of time to each type of work for each sprint. This goes back to the SLC concept: you want your slice of cake to be vertical so you can taste all the layers, including the icing (yes, I love this silly analogy).</p>
<h3>Don&#x27;t always jump to using existing patterns</h3>
<p>This is probably the most controversial one. In the design industry there&#x27;s a remarkable push behind design systems. They have a myriad of benefits including speeding up design and development time, making it easier to maintain accessibility, as well as evolve and maintain large surface areas in your product. But if design systems are not run well, they can hold you back.</p>
<p>Poorly run design systems can preclude valid design explorations in pursuit of consistency and efficiency; just using what&#x27;s already there.</p>
<p>For brand new products, don&#x27;t to be too eager to start on a design system. You often don&#x27;t know what this thing is yet. You don&#x27;t know where the product is going, what needs to scale, what the customer needs are, how they&#x27;ll react to your initial version or what the personality of the product will be.</p>
<p>But this familiarity with existing systems can get in the way of helping you tackle new kinds of problems. You may prematurely bucket it into a problem you&#x27;ve seen before. Design systems are just one of the tools at your disposal. Applying your design systems thinking (or any other patterns you&#x27;ve worked with before for that matter) all too eagerly may prevent you from noticing the obvious. That maybe there&#x27;s a different way of thinking about the problem at hand. Apple touches on this a bit in this video about <a href="https://developer.apple.com/videos/play/wwdc2018/802/">intentional design</a>.</p>
<p>A related tool I like to employ sometimes, especially to break out of my own personal design aesthetic and tendencies, is to ask myself, how would [another company] design this? I might think to myself "Airbnb loves to have these huge headers, bold colors, dynamic cards and sheets, so they may approach it like this." Then I&#x27;d mock that up.. and do the same with other companies. I may hate it, but it will get me thinking.</p>
<h3>Sunset or re-evaluate old functionality</h3>
<p>Incentivize and commit to sunsetting features that are no longer your core focus, have low usage, or are otherwise detrimental to your product. If you work on a product with millions of users, even low usage things will be sizable and may have secondary effects that are hard to gauge. This is hard, thankless work. It requires support from leadership to allow a team to focus on removing something instead of spending that time that could more directly move tangible metrics.</p>
<p>But without this rigor, your product could all too easily become cluttered, slow and become harder to maintain over the years.</p>
<h3>Use what you&#x27;ve built before you ship</h3>
<p>I&#x27;ve seen it happen all too often. You&#x27;re working on a project. You build a prototype and work with a researcher to get some initial qualitative feedback or you ship a small experiment to gather data. By the time the research insights have been finalized or the experiment data has had enough time to account for novelty, you don&#x27;t have much time left to explore significant refinements or alternative design directions. Your team is already on the hook to ship this before the end of the quarter or has tight timelines to get this code merged before the biweekly deadline to ship to Apple. So you end up compromising with a less-than-ideal refinement, even though you don&#x27;t think it&#x27;s the solution your users really deserve.</p>
<p>Always leave adequate time after gathering new insights to not only design refinements, but build them and live with them for a bit first. It&#x27;s too easy to compromise on quality in the face of existing timelines.</p>
<h3>Joining Rewind</h3>
<h3>Why going to a startup is the perfect fit for me</h3>
<p>Earlier this year I decided to leave my job, focus on my wedding and take a few months off. I had a lot of time to think about what I wanted to work on next. I wasn&#x27;t sure if I wanted to join another large company, a startup, or transition to contracting with a few companies.</p>
<p>One thing was clear though. I wanted a different kind of design challenge. Designing for mobile had started to feel boring. It felt so repetitive. The same constraints. It felt like I was just going around employing the same few patterns, especially when working on larger teams less interested in taking risks and trying new things.</p>
<p>It would be a bonus if I could find a company where I could more readily influence product quality by diving into the codebase myself. I had a strong desire for interesting work with a great team where I could be proud of what we built together. That&#x27;s what we all want right?</p>
<p>Dan Siroker happened to reach out to me around this time. Dan and I had crossed paths a decade ago in Y Combinator when he was starting Optimizely. We caught up and Dan showed me what he had been working on, complete with a live demo of Rewind. I was blown away by the ambition and concept. I immediately grokked it.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2022/11/rewind-app.webp" alt="Rewind for macOS" />
<p>Rewind is the search engine for your life. It&#x27;s a macOS app that fully utilizes the capabilities of Apple Silicon and macOS Ventura to record everything you see, analyze it and make it searchable in real-time. All while being private by design—everything is stored locally on your machine.</p>
<p>Rewind helps you out in those situations when you&#x27;re racking your brain try to remember where you saw something. Can&#x27;t find that tweet you know you saw once? Or wish you could go back 15 seconds to recover that long performance review you were writing before your browser crashed? You can search or rewind time. Once you&#x27;ve found what you&#x27;re looking for you can even copy text from it.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2022/11/rewind-app-1.webp" alt="Rewind app screenshot 1" width="3000" height="2147" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2022/11/rewind-app-2.webp" alt="Rewind app screenshot 2" width="3000" height="2147" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2022/11/rewind-app-3.webp" alt="Rewind app screenshot 3" width="3000" height="2147" />
<p>It&#x27;s the exact type of design challenge I was looking for. First, it&#x27;s a full-screen immersive app with no peers like it. There&#x27;s no playbook or existing design patterns for how to design something like this. Second, there&#x27;s a ton of privacy implications to ensure people feel safe using Rewind and know that they&#x27;re in control. And finally, since there&#x27;s no product quite like this, there&#x27;s a lot of hard product design and research iteration on the journey to find our specific product-market fit.</p>
<p>All this to say that Rewind was exactly the kind of team and company I was looking for. The product has the potential to change how we interact with computers.</p>
<p><strong>How does joining a startup relate to craft and product quality?</strong> Isn&#x27;t it harder for a small company to ship well-designed, high-quality software? Aren&#x27;t most startups busy scrambling to find PMF, scaling infra and putting out fires?</p>
<p>There&#x27;s no debating one aspect of startups compared to large companies with thousands of employees: startups are dramatically faster. Faster to make decisions, plan and build. You can talk about something in the morning then design and build it the same day. No more waiting until the next quarter.</p>
<p>But the main reason why I think it&#x27;s easier to influence quality on a smaller team is that I&#x27;m able to have a more general design role. I can be <a href="http://www.paulgraham.com/relres.html">relentlessly resourceful</a> and put the full extent of both my design and engineering skills to use. And the best unintended side-effect? I&#x27;m also learning more on the coding side as the talented engineers I work with provide tips and feedback on my code reviews.</p>
<p>I&#x27;ve only been at Rewind for a few months but this has been the exact kind of role I&#x27;ve been looking for for the last decade and I&#x27;m confident we&#x27;re going to build some great stuff.</p>
<hr/>
<h3>Quality is hard</h3>
<p>With the right team culture, process, tool, education, and incentives, achieving a higher level of product quality <em>should</em> be more attainable without dramatically impacting speed of execution. I&#x27;m not saying it&#x27;s easy. Quality will always be hard, but don&#x27;t you want to make something great?</p>]]></description>
            <link>https://paulstamatiou.com/craft</link>
            <guid isPermaLink="true">https://paulstamatiou.com/craft</guid>
            <dc:creator><![CDATA[Paul Stamatiou]]></dc:creator>
            <pubDate>Mon, 14 Nov 2022 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Revisiting the iPod]]></title>
            <description><![CDATA[<img src="https://turbo.paulstamatiou.com/uploads/2022/08/copyright-paulstamatiou_com-DSC05910-2000.jpg" alt="Apple iPod" />
<p>1,000 songs in your pocket.</p>
<p>You’ve probably heard that iconic marketing slogan before even if you never had an original iPod. Apple referred to the iPod as a "breakthrough digital device" when they announced it. The first iPod came at a time when the portable audio player landscape was.. nomadic (pun intended) at best.</p>
<p>MP3 players were already around when the iPod came out in 2001. Sales of early MP3 players were growing but they all had key limitations. You had to choose whether you wanted a smaller, flash memory player with extremely limited storage or a larger hard-drive based player.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2022/08/portable-audio-players-in-2000.jpg" alt="Various portable music players in ~2000" />
<small>Various portable MP3 and MP3 CD players in the early 2000s. Few were usable with just one hand on the go.</small>
<p>None of them were easy to use or elegant. They were often cluttered with buttons, had subpar software and were hard to navigate. There were also other options like MP3 CD Players and Sony MiniDisc players (I loved my <a href="https://www.minidisc.org/part_Sony_MZ-R70.html">MZ-R70</a>).</p>
<p><strong>The iPod was different.</strong> It was a sleek, shiny stainless steel and white device the size of a deck of cards. Its stellar industrial design turned heads. This was not just an audio player you used to play music. It said something about you the same way using a Mac vs a PC said something about you at the time. You were different; maybe a creative even. You valued well-crafted products.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2022/08/ipod-launch-graphic.png" alt="iPod launch graphic" />
<p>The iPod was a noteworthy device for a few reasons:</p>
<ul>
<li><strong>Size + Storage:</strong> While there were other devices like the Creative Nomad Jukebox and Archos Jukebox with 6GB drives, they were almost the size of CD players. With the iPod you didn&#x27;t have to choose between portability and storage. This was made possible by the iPod&#x27;s 1.8-inch hard drive, something Apple&#x27;s head of engineering first discovered from Toshiba while on a trip to Japan. Other players used traditional 2.5" notebook hard drives.</li>
<li><strong>Speed:</strong> The iPod used FireWire 400 instead of much slower USB 1.1 like competitive devices used at the time. You could load a CD onto your iPod in 10 seconds; about 30 times faster than other devices.</li>
<li><strong>Scroll wheel</strong>: This usefulness and simplicity of this cannot be overstated. I&#x27;ll dive into it more later.</li>
<li><strong>Elegant industrial design:</strong> As mentioned above, this thing is beautiful. Today we&#x27;d refer to it as a brick.. but it&#x27;s still a shiny brick.</li>
<li><strong>Anti-skip protection:</strong> The downside with hard-drive based mp3 players is they would skip when moved around. The iPod had 20 minutes of anti-skip protection thanks to its built-in 32MB flash memory buffer. This also had the benefit of increasing battery life to 10 hours by limiting how often the hard drive needs to spin up.</li>
<li><strong>iTunes + Auto-sync + Playlists:</strong> Apple made sure to make it known that the iPod with iTunes was the first "complete and seamless MP3 music solution." Using iTunes to manage your music and automatically sync it with your iPod was a dream compared to the clunky software required for other MP3 players. Notably, iTunes made it easy to create playlists and the iPod made them easy to play.</li>
<li><strong>Large backlit display:</strong> Featuring an LED-backlit LCD display with 160x128 resolution, the iPod could display six lines of text and song details at a glance.</li>
<li><strong>CD-quality sound:</strong> While it wasn&#x27;t a huge feature of the iPod, Apple boasted that the included headphones featured Neodymium transducer magnets to help you get enhanced frequency response to get the most out of the high-bitrate songs.</li>
<li><strong>White headphones</strong>: We expect it now with Apple devices, but at the time every other device came with black headphones and a black cord. Apple knew the iPod would live in your pocket and they needed a way to signal that you had one (and of course white to match the iPod itself). The white cord and earbuds became so popular Apple leaned into them for a whole <a href="https://www.youtube.com/watch?v=rgSQsu0yeH0">series of iPod dancing "silhouette" commercials</a>.</li>
</ul>
<img src="https://turbo.paulstamatiou.com/uploads/2022/08/copyright-paulstamatiou_com-DSC05925-3000.jpg" alt="Apple iPod" width="3000" height="2216" />
<p>All of these things combined made the iPod something the industry had to take note of. It wasn’t the most storage you could get in an MP3 player at the time<sup><a rel="footnote" href="#footnote-1" id="r1">1</a></sup>, it wasn&#x27;t the first MP3 player and it definitely was not the cheapest with it&#x27;s $399 price point at launch. But it was elegant, easy to use and when paired with iTunes, it was the complete package.</p>
<p>Using the iPod still wasn&#x27;t easy by today&#x27;s standards. First off, you had to have your own music library of MP3 files on your computer. The iTunes Music Store had not come out yet, nor were there any music streaming subscription services yet. So either you purchased them on some other website, pirated them from Napster, BitTorrent, Scour, IRC, Kazaa, LimeWire and their ilk or ripped them from a CD. Then you had to connect your iPod to your computer, fire up iTunes, sync your music, then disconnect it before you could play it.</p>
<p>But it was a different time. Managing your own music library was a burden to be proud of. People would boast about how many songs and gigabytes their library consumed and how they organized it. They were proud of the work they put into their libraries and cleaning up their audio file ID3 tags and customizing their WinAmp player.</p>
<p>Music piracy was an especially hot topic at the time. The iPod included no form of DRM and received some criticism that the iPod would only proliferate piracy. Anyone remember Apple&#x27;s <a href="https://www.youtube.com/watch?v=pleybGLgaEc">"Rip. Mix. Burn." ad campaign</a>? They showed the ease of ripping music to your Mac from CDs you owned. Apple also packaged the iPod itself with a sleeve that clearly said "Don&#x27;t steal music." on it.</p>
<p>Some industry critics lamented that Apple even bothered to enter the consumer electronics space; a space where products traditionally came with lower profit margins and stiff competition. The iPod was also Mac-only at launch. Would this turn people away or convince them to get a Mac? Eventually this was a non-issue as Apple quickly began supporting Windows PCs.</p>
<p>Here&#x27;s the iPod announcement in 2001:</p>

    <iframe width="560" height="315" src="https://www.youtube.com/embed/Mc_FiHTITHE?start=1279" 
    frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" 
    allowfullscreen></iframe>
  
<h3>Design</h3>
<p>While clear in hindsight, the iPod&#x27;s scroll wheel<sup><a rel="footnote" href="#footnote-2" id="r2">2</a></sup> was core to the success of the iPod. It flawlessly solved the problem of scrolling long lists of songs, adjusting volume and navigating menus on a small display that lacked touch capabilities. Combined with audible click feedback, it was a breeze to use.</p>
<p>In particular, it was easy to use with <em>one hand</em>. Not many MP3 players at the time were. You could raise the volume, skip a song, scrub through a song or navigate menus easily—even without looking at the screen.</p>
<p>In addition, when navigating menus there was a simple horizontal animation to help you understand whether you were drilling into or out of the menu. This was something iPhone OS 1 (it wasn&#x27;t called iOS until iOS 4) ended up doing as well when it came out years later.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2022/08/copyright-paulstamatiou_com-DSC05912-3000.jpg" alt="iPod close-up" width="2000" height="1463" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2022/08/copyright-paulstamatiou_com-DSC05883-3000.jpg" alt="iPod side view" width="2000" height="1059" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2022/08/copyright-paulstamatiou_com-DSC05917-3000.jpg" alt="iPod front view" width="2000" height="1462" />
<p>The iPod wasn&#x27;t the first time a portable device had a control like the scroll wheel. For years, Sony had some variation of their—failed if you ask me—"jog dial" on devices like PDAs. However, it always felt like some afterthought bolted to the side of their devices; not nearly as precise or quick to use. And of course, Apple got some inspiration from the B&O BeoCom phone.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2022/08/ipod-inspiration-braun-beocom.jpg" alt="iPod inspiration: Braun T3 transistor radio and Bang & Olufsen BeoCom 6000 phone" />
<small>Apple was inspired by the form of the 1958 Braun T3 transistor radio and the function of the 1998 Bang & Olufsen BeoCom 6000 phone, which utilized a wheel to provide quick access to phone book contacts and provided audible feedback while scrolling.</small>
<p>While iPods are long gone and all iOS devices are touch-screen now, some of what Apple learned with the scroll and click wheel evolved into the digital crown found on the Apple Watch.</p>
<p>It&#x27;s hard to imagine today what using an iPod in the early 2000s truly felt like. It was a dedicated device, singularly focused on helping you do one thing—play your favorite music—and do it well. It didn&#x27;t need to multitask or have any other complexity to function. It was simple, elegant and polished device. We don&#x27;t really have things like that today. Every mobile device is meant to be flexible, multitask and do just about anything for you, lending them to be more like a jack of all trades, master of none.</p>
<h3>Finding an iPod</h3>
<p>I have always admired the first iPod.<sup><a rel="footnote" href="#footnote-3" id="r3">3</a></sup> In 2002 I purchased the second-generation 10GB iPod. I was in the middle of high school and that was a hefty purchase for me.</p>
<p>The second-generation iPod was nearly identical to the first-generation iPod except for more storage options (10GB and 20GB) and minor physical changes (notably, a touch-sensitive wheel replaced the mechanical scroll wheel, which was prone to getting dirty and requiring cleaning).</p>
<p>I eventually dropped that iPod with headphones plugged in and it broke the headphone jack. I opened it up, soldered it back on and unfortunately sold it. I’ve missed it ever since.</p>
<p>Earlier this year I began my search for a second-generation iPod like the one I had. I thought about looking for a first-generation but honestly I did not like how they had a piece of white plastic near the ports instead of the metal backing and was concerned about the high probability of the mechnical scroll wheel having issues.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2022/08/copyright-paulstamatiou_com-DSC05881-3000.jpg" alt="My second-generation 20GB iPod" width="2000" height="1376" />
<p>If you decide to do the same<sup><a rel="footnote" href="#footnote-4" id="r4">4</a></sup>, I can offer a few suggestions. First, we are talking about a 20 year old device (older if you opt for a first-gen) so you should be concerned about the state of the battery and hard drive. It&#x27;s quite common to find people on eBay selling iPods where they&#x27;ve already replaced the battery, so that might be of interest if you don&#x27;t want to do the work yourself or have to deal with it later.</p>
<p>Of course, the vast majority of the early iPods you see for sale will have tons of scratches and maybe even some dings. That&#x27;s to be expected for such an old device, unless you plan on spending much more on a near-mint model; I even saw one selling a never-opened, sealed box iPod for $10k! However, since the front of the iPod is just plastic, a devoted owner can find specific polishing compound and significantly restore the faceplate to its former glory. It won&#x27;t be perfect (at specific angles you may still be able to see the original scratches) but you likely would not be able to tell from eBay pictures.</p>
<p>After some months of casual searching I finally found one on eBay in good condition with a newly replaced battery that wasn’t outrageously priced. I paid about $190 including shipping.</p>
<h3>Connecting and using the iPod</h3>
<p>A few days later my <a href="https://twitter.com/stammy/status/1549814701378490368?s=21&t=yaSATtU4zxfZqg8xuNvt_Q">new-to-me iPod arrived</a>!</p>

<blockquote>A Tweet embed was not displayed. Read this article in a browser to see it as intended.</blockquote>
<p>Would I even be able to connect this FireWire iPod to my modern M1-based MacBook Pro running macOS 12? Not too long ago Apple Music (née iTunes) stopped syncing iOS devices and that functionality was moved to the macOS Finder itself.</p>
<p>All I needed to do was find a way to connect FireWire 400 to Thunderbolt 3. This took quite a few adapters and dongles:</p>
<ul>
<li>Thunderbolt 3 to Thunderbolt 2</li>
<li>Thunderbolt 2 to FireWire 800</li>
<li>FireWire 800 to FireWire 400 (couldn’t find an Apple adapter, got one from <a href="https://amzn.to/3C2FoB5">elago</a>)</li>
<li>FireWire 400 6-pin to 6-pin Apple cable</li>
</ul>
<p>These dongles definitely add up in cost, though I got at least one of them used on eBay. In total, I paid just under $90 for all of these. I had another FireWire cable that would have worked but I was seeking an authentic Apple cable. All-in this iPod setup cost me about $280. Worth it? Absolutely.</p>
<p>Fortunately, it worked flawlessly after I connected everything. After a brief moment the iPod showed a "Do not disconnect" message and the Finder app in macOS displayed the iPod: both as an iPod and as a connected hard drive.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2022/08/copyright-paulstamatiou_com-DSC05941-2000.jpg" alt="iPod connected to my Mac with FW400" width="2000" height="1333" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2022/08/copyright-paulstamatiou_com-macOS-ipod-finder-syncing.png" alt="MacOS Finder connected to a 2nd generation iPod" width="2000" height="1463" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2022/08/copyright-paulstamatiou_com-macOS-ipod-finder-podcasts.png" alt="MacOS Finder connected to a 2nd generation iPod" width="2000" height="1463" />
<small>iPod connected to my Mac with FireWire 400 and accessed via Finder.</small>
<p>Selecting the iPod in Finder, you have the ability to sync music, podcasts and more. It&#x27;s pretty basic and just loads up audio files it detects from your main Apple Music or Podcasts apps. Of course these are only for actual files you have; not for any music from Apple Music&#x27;s streaming service for example. I selected a few podcasts and synced them. A few moments later I was listening to them on the iPod.</p>
<p>After syncing was complete, I ejected the iPod from Finder and removed the FireWire cable.</p>
<p>It took a moment to remember how to turn on the iPod. I had to turn off the Hold switch and press a button to wake it up. Then I navigated some menus to find a podcast to play. Scrolling line by line with the scroll wheel with its audible feedback was so satisfying. <strong>All the nostalgia came flooding back.</strong></p>
<p>Then I heard the tiny 1.8-inch hard drive whir to life. I can&#x27;t remember the last time I used a device with a spinning hard drive like this after so many years of using devices with SSDs. Though, at the same time I was a little bit paranoid about using a portable device like this with a spinning disk that felt so delicate.</p>
<p>Of course there’s no Bluetooth with the iPod so I found my AirPods Max 3.5” minijack to Lightning cable to connect them:</p>
<img src="https://turbo.paulstamatiou.com/uploads/2022/08/copyright-paulstamatiou_com-DSC05929-2000.jpg" alt="AirPods Max connected to an iPod" />
<small>AirPods Max, meet iPod.</small>
<h3>Impact</h3>
<p>There&#x27;s no need to state how influential the iPod went on to become: for Apple, for the industry, for pop culture and more. The <a href="https://www.moma.org/collection/works/89465">first iPod is even in the Museum of Modern Art</a> now. Some 450 million iPod devices have been sold.</p>
<p><a href="https://www.apple.com/newsroom/2003/04/28Apple-Launches-the-iTunes-Music-Store/">Apple unveiled the iTunes Music Store</a> about 1.5 years after the first iPod. It became dead simple to select a 128kpbs AAC song from their collection of 200,000 songs (today it&#x27;s 43 million) at launch, pay 99 cents to download it and then sync with your iPod to have on the go.</p>
<p>The easiest way to fight piracy was with convenience and Apple really showed how powerful a complete package could be: elegant portable audio device, great music library software and a robust integrated music store.</p>
<p>The iPod wasn&#x27;t the first MP3 player but it&#x27;s impeccable industrial design, novel software and overall execution made it iconic.</p>
<h3>What&#x27;s next?</h3>
<p>There&#x27;s a lot of other interesting early Apple devices<sup><a rel="footnote" href="#footnote-3" id="r3">3</a></sup> that I&#x27;d love to collect if I had the space but this iPod was the perfect start. I&#x27;m also a fan of the first-generation iPod Nano. If you&#x27;re looking to get a taste of iPod nostalgia that might be an easy place to start. It was flash-based and had a USB connection.</p>
<p>Though I&#x27;m really curious about the tiny <a href="https://twitter.com/Stammy/status/1552318317532254211">third-generation iPod Shuffle</a>. It was poorly received due to its over-minimalism and lack of controls on device (Apple pushed the use of remote buttons on the headphones cord along with VoiceOver navigation).</p>

    <iframe width="560" height="315" src="https://www.youtube.com/embed/mE_bDNaYAr8" 
    frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" 
    allowfullscreen></iframe>
  
<br><br><br><hr><br><h3>Footnotes</h3><p><a href="#r1">1</a><!-- --> A now-infamous comment about the iPod at launch was on the popular site Slashdot: “No wireless. Less space than a Nomad. Lame.”</p><p><a href="#r2">2</a><!-- --> The first-gen iPod had a mechanical scroll wheel while the 2nd-gen had a touch-sensitive scroll wheel. Later iPod generations called it the <!-- --><a href="https://en.wikipedia.org/wiki/IPod_click_wheel">click wheel</a><!-- --> when the menu/skip/etc buttons were merged into the wheel itself.</p><p><a href="#r3">3</a><!-- --> In addition to most early Apple products, I&#x27;d love to own a Macintosh Centris 650, Apple ][, Macintosh Color Classic, Macintosh SE, G4 Cube, iMac G4, QuickSilver PowerMac G4, PowerMac G4 MDD, Clamshell iBook G3 laptop, 12-inch and 15-inch Titanium PowerBook, eMac, iMac G3... the list goes on. I have fond memories of using several of these machines many years back.</p><p><a href="#r4">4</a><!-- --> There&#x27;s a <!-- --><a href="https://www.wired.com/story/ipod-modders/">whole community around iPod modding</a><!-- -->. People love to convert them to use SSDs instead of HDs, change the case and more. For example, the last generation iPod (the sixth-gen officially dubbed the iPod Classic, though you can also refer to all six generations as iPod Classics) can even be modified to add Bluetooth. I&#x27;m curious to look into converting mine to using an SD card for storage.</p>]]></description>
            <link>https://paulstamatiou.com/revisiting-the-apple-ipod</link>
            <guid isPermaLink="true">https://paulstamatiou.com/revisiting-the-apple-ipod</guid>
            <dc:creator><![CDATA[Paul Stamatiou]]></dc:creator>
            <pubDate>Sat, 06 Aug 2022 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Crypto design challenges]]></title>
            <description><![CDATA[<p><strong>It’s still early days in crypto.</strong> That’s what you’ll hear everywhere when you start digging into crypto and web3 today. For most new users this unfortunately feels a bit closer to the <a href="https://twitter.com/Stammy/status/1463516773420978181">wild west</a>. There are a myriad of situations where they might not know what&#x27;s happening and where they don&#x27;t trust the system, services or tools they&#x27;re using.</p>
<p>Early adopters face foreign terminology, complex UIs, unexpected and exorbitant fees, security issues, slow transactions, confusing errors, <a href="https://cryptoscamdb.org">scams</a> and more. That makes for one hell of an onboarding, even if you&#x27;re lucky enough to have a friend showing you the way.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2021/11/paulstamatiou_com-token-alert.png" alt="Token alert message" />
<small>A message like this is normal for advanced users, but can be confusing, scary and lacking guidance for newcomers.</small>
<p>This is the state of crypto today. That can work for now—early adopters are motivated enough to jump through hoops to try something new—but this won’t scale as billions of users join the crypto ecosystem in the coming years.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2021/11/paul-stamatiou-internet-crypto-adoption.jpg" alt="The state of crypto is like the Internet in 1998" />
<small>The state of crypto is like the Internet in 1998.</small>
<p>But this is all known; there are many new technologies and protocols vying to evolve, change or fix things. I’m most interested in the design side of things.</p>
<p><strong>Can we even design truly <em>great</em> experiences for common activities in crypto today?</strong> Does the underlying tech have to evolve significantly first? What&#x27;s the best we can do with today&#x27;s technological constraints?</p>
<p>The crypto users of tomorrow will have different motivations and expectations than the early adopters today. They won&#x27;t put up with clunky, confusing, unreliable, unsafe and expensive systems. Great design—for wallets, exchanges, identity, dApps, marketplaces, DeFi and more—will be the bridge to help get us there.</p>
<p>Everyone likes to say that in the future maybe crypto users won’t even know they’re using crypto; that the blockchain and complementary systems are just the technology powering everything behind the scenes. We can only get there if we <strong>design for trust</strong> and use that as a critical lens through which we analyze every aspect of the crypto experience today.</p>
<h3>Designing for trust</h3>
<p>So you might be thinking.. okay this is totally wrong and even the Bitcoin whitepaper established that cryptographic proof should be used instead of trust for decentralized systems. And that the ethos in the crypto community today is "Don&#x27;t trust, Verify."</p>
<p>Yea, that&#x27;s all true. But what I&#x27;m talking about is one level up than the blockchain itself. I&#x27;m talking about the interfaces people interact with to do what they need to do, which may happen to be directly on or indirectly related to the blockchain. It&#x27;s about elevating context and providing signals about their interactions so they can feel safer to make decisions about what actions to take and which actions to avoid.</p>
<p>Public blockchains like those that power Bitcoin and Ethereum are permissionless. Lack of trust, centralized servers and third parties is a feature. They&#x27;re entirely open networks where any participant or machine can see what&#x27;s happening. While this leads to a level of trust with the ability for anyone to track and verify all transactions, that’s where the trust ends.</p>
<p>As active web3 participants<sup><a rel="footnote" href="#footnote-1" id="r1">1</a></sup> we regularly interact with dApps, smart contracts and more that we should not simply trust by default. But there’s also a person&#x27;s trust of the blockchain itself. Ever had a transaction fail due to gas issues? Or new tokens you just sent to your wallet from your exchange not appear in a timely manner? Issues like this won&#x27;t inspire much confidence in crypto for new users.</p>
<p>A great crypto experience<sup><a rel="footnote" href="#footnote-2" id="r2">2</a></sup> designed for trust will help you make an informed decision by elevating all the information you need, especially if that information comes from multiple places. I’ll dive into that more a bit later.</p>
<div><p><strong>Current state of crypto</strong><br/>
<!-- -->I&#x27;ll be the first to admit that it&#x27;s easy to sit here and write about how I think crypto experiences today could be improved, especially while largely ignoring technical feasibility and challenges. It&#x27;s so early and it&#x27;s not easy building such expansive and composable decentralized infrastructure.</p><p>Unlike just about everything else we&#x27;ve come to expect with modern technology, popular blockchains like Ethereum are not instantaneous. In fact they&#x27;re slow and worse, expensive.</p><p>I mean if anything was possible, I don&#x27;t think anyone would think that the best way to store all their valuable assets would be in a little Chrome extension that injects JS into a website where malicious actors could <!-- --><a href="https://twitter.com/iam_preethi/status/1455523559070126083">trigger phishing prompts</a><!-- -->. It&#x27;s just the easiest way to quickly build things today.</p><p>Lots of crypto experiences are built around existing constraints. As usage, utility and demand increases in the future, we&#x27;ll be able to push on these constraints.</p></div>
<h3>What we can do today</h3>
<p>One of the reasons I&#x27;m so excited about web3 is that everything so desparately needs design help that almost any attention to detail anywhere in any common flow would be tremendously valued. <strong>It&#x27;s like getting in on the ground floor of helping define key interactions in browsers, email clients and other core tools during the formation of Internet.</strong></p>
<p>You can design how people interact with anything related to the blockchain: wallets, exchanges, dApps and more. You could have a lasting impact in a ridiculously fast growing space.</p>
<p>Crypto has been around for about a decade—long enough to prove there&#x27;s something here and see growth but still nascent enough that there&#x27;s plenty of things left to figure out, define and invent. How often do these opportunities come around?</p>
<p>But I digress..</p>
<p>Today, we can get very familiar with the technical constraints of crypto systems and design for trust and clarity over all touchpoints of someone&#x27;s journey. This article is in no way meant to be a complete overview of all design challenges in crypto. I wouldn&#x27;t be able to write that; this is just meant to highlight a few areas that have been top of mind for me.</p>
<p>There&#x27;s several high-priority areas to explore starting when someone first hears about crypto to learning about how and where to use it but I&#x27;m most interested in these:</p>
<ul>
<li>
<p><strong>Exchange experience & Onboarding</strong><br/>
As hundreds of millions of people interact with crypto for the first time, it&#x27;s very likely that their first experience will be with a centralized exchange where they can exchange their local fiat currency for their first Bitcoin, Ethereum, stablecoin or other crypto asset. There&#x27;s lots of responsibility and opportunity here to set new users up for success.</p>
</li>
<li>
<p><strong>Wallet experience</strong><br/>
For some, just holding crypto assets may be enough, but many will be drawn to all that web3 offers from various dApps to NFTs and more. A crypto wallet is the passport to web3 and making it clear how to set one up, become familiar with connecting to other services, dealing with transactions and more will be a key experience to get right.</p>
</li>
<li>
<p><strong>Web3 guidance & curation</strong><br/>
This is the discovery phase for slightly more advanced users that are now asking "What can I do with my crypto?" There are opportunities to help people discover what exists, what is safe to use and guide people along the way. It&#x27;s 1998 and people rely on AOL or the Yahoo! homepage to show them what&#x27;s out there. What&#x27;s the curated search engine for crypto?</p>
<p>There are a few projects in this space like <a href="https://rabbithole.gg/">Rabbithole.gg</a>, <a href="https://zapper.fi">Zapper.fi</a>&#x27;s Quests and <a href="https://Layer3.xyz">Layer3.xyz</a>, though I think most of them are a bit too complex or don&#x27;t yet do a great job yet on educating behind why someone would want to do a certain task. Another interesting one is <a href="https://context.app/feed/collectors">Context.app</a>, helping with NFT discovery.</p>
</li>
</ul>
<p>I also think there&#x27;s a huge opportunity around decentralized identity; I touch on that a bit in the next section.</p>
<h3>Exchange experience & Onboarding</h3>
<p>In the coming years, hundreds of millions of people will interact with cryptocurrency on-ramps—exchanges and similar services where they can receive their first cryptocurrencies and other crypto assets. For most people, this will be with a centralized exchange (CEX). Exchanges will be most people&#x27;s first time truly interacting with crypto. Exchanges will need to simplify, educate and guide these new users every step of the way.</p>
<p>Exchanges should explain the difference between different types of cryptocurrencies (including stablecoins), potential for volatility and potential for utility of each type. They should equip people with a basic understanding of security should they transfer their assets to a wallet outside the exchange.</p>
<p>But before all that, there&#x27;s a lot of opportunity to simplify the required KYC ("Know your customer") flows that require you to verify your identity. There&#x27;s nothing easy about these flows as they require a tedious process of uploading photos of your id. Even small enhancements like integrated camera flows instead of requiring switching to the camera app, letting you easily resume onboarding if you&#x27;re not in a place to do this yet (send me a reminder push notification in X hours) or letting you setup the rest of your account and upload your id when you can later would be welcomed.</p>
<p>At some point these people may want to do something more than just buy or sell their crypto. Exchanges can educate around dedicated, non-custodial wallets. Even small things like transferring Ether to a new wallet can be daunting. Exchanges can also begin to set the expectation that outside the exchange, transactions are usually not instant and that depending on the service, sometimes require significant fees and time.</p>
<p>I could go on and on. So much opportunity here.</p>
<h3>Wallet experience (Transactions)</h3>
<p>Wallets started out as only being responsible for managing and facilitating basic crypto asset transfers. Today they are responsible for a whole lot more. Modern wallets deal with showcasing NFTs, all sorts of tokens, dealing with complexities related to separate blockchains and Layer 2 assets, token swaps, connecting with dApps and more.</p>
<p>Wallets are a frequent and primary touchpoint for interacting with countless web3 services, protocols, other wallets and more. Designing for trust inside the wallet is of prime importance. There are no gatekeepers with decentralized services; just a lot of entities you&#x27;ll individually interact with. As such it’s important to make it clear exactly what’s happening each time you interact with another user, smart contract, dApp, et cetera.</p>
<p>A core part of all wallets is a way to list transactions. Too many wallets today treat this as a list of data without much thought about what it means for the user and within the context of trust.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2021/11/paulstamatiou_com-phantom-wallet2.png" alt="Phantom Solana Wallet (Chrome extension)" />
<small>Phantom Solana Wallet (Chrome extension)</small>
<img src="https://turbo.paulstamatiou.com/uploads/2021/11/paulstamatiou_com-metamask-wallet.png" alt="MetaMask Wallet (Chrome extension)" />
<small>MetaMask Wallet (Chrome extension)</small>
<p>Here are a few things I&#x27;ve been thinking about in regards to displaying transactions and assets:</p>
<ul>
<li>
<p><strong>Be hyper transparent around transaction status.</strong> We expect things today to be instant but the blockchain is one of the only pieces of modern technology that can feel very slow at times. We need to take great care in displaying transaction status. The average user should <strong>never have to visit Etherscan/Polygonscan/etc</strong> just to see how much time is left with their transaction. There should never, ever be any doubt in their mind about what&#x27;s happening to their money or transaction.</p>
<p>A basic "sending/pending" state is not enough. Can you imagine not having a progress bar when you were downloading an mp3 on dialup in the &#x27;90s?</p>
</li>
<li>
<p><strong>Make errors actionable.</strong> One of the most frustrating things is when a transaction fails. It&#x27;s annoying, sure, but with Ethereum transactions it also probably means you lost a lot of money in fees! Elevate as much of the error messaging and description as possible to the user. Suggest solutions the user can take if feasible, such as trying again but with more gas if that was the reason it failed.</p>
<p>Show me how much money I just lost on gas with this failed transaction. Don&#x27;t make me go to Etherscan to try to piece it all together; it can be rather confusing to discern on Etherscan with gas price, transaction fee, gas fee and gas usage, especially with EIP-1559.</p>
</li>
<li>
<p><strong>Show more context.</strong> Transaction data is far too cryptic today. Any way to add further context and humanize is needed. See if there&#x27;s ways to display social proof.</p>
<p>Who, what, where, when.. I received an NFT from an OpenSea contract, which I&#x27;ve used and trusted before. Or show that I swapped a token via Uniswap. Did I receive an NFT from a smart contract or another wallet? Show me a visual preview in the list of transactions, along with any indication of the other party (be it an OpenSea logo/name, or associated ENS name and avatar).</p>
<p>This can be taken much further, but may be better suited for future solutions where your wallet may be paired with a robust knowledge graph.</p>
</li>
<li>
<p><strong>Inform and put the user in control.</strong> Letting a user select how much gas to pay for a transaction is not enough. What other context can be provided to help them make a decision?</p>
<p>For example, if they are interacting with a smart contract to obtain an NFT and the contract has a ton of pending transactions, maybe the wallet could see how many NFTs are left by checking the contract&#x27;s remaining supply, see how many pending transactions would be ahead of them and try to roughly estimate how much gas may be necessary before the NFT supply runs out.</p>
<p>Or perhaps the wallet could see how many recent transactions with the smart contract with other wallets failed, potentially hinting that this contract should not to be trusted (like those scams where it tries to get people to visit a website) or has other issues.</p>
<p>Create first-class experiences around speeding up a transaction. If I have multiple pending transactions with the same smart contract, show me how this affects the queue and the position of each.</p>
<p>These may be contrived examples but the point remains. Approach this with a user focus, think about what people may need or want to know in the moment and try to bring it forward.</p>
</li>
<li>
<p><strong>Make transaction state global.</strong> Wallets today are not simple single-page apps. They often have multiple tabs or sheets, they could have various sheets and they can be closed or collapsed entirely. Most people will want to know the status of their pending transactions at all times, regardless of where they are in the wallet. Make it easy to see status from anywhere, including using actionable in-app toasts or browser/app push notifications when it makes sense.</p>
<p>A simple analogy might be a macOS menubar app like Google Drive. At a glance I can see that it&#x27;s busy syncing files or that it&#x27;s all done and at rest. I don&#x27;t have to go anywhere or do anything to see its state.</p>
</li>
<li>
<p><strong>Give me an "oh shit" undo/cancel button.</strong> It&#x27;s all too easy to make a mistake. Scenarios like trying to ape into a new NFT drop unfortunately mean that speed is the only way to have a chance.. but speed also means you might not be taking the time to think through your actions.</p>
<p>Did you accidentally approve a token on a contract you probably shouldn&#x27;t have? Unfortunately, scenarios like this happen more often than they should. Wallets need an emergency resources in times like this. Perhaps modern wallets could have a sort of emergency "oh shit" button.</p>
<p>A button like that may try to pay the necessary amount of gas to quickly cancel that pending transaction before it&#x27;s estimated to go through, or try evasive maneuvers like start moving your highest value tokens to a newly-created wallet on your behalf with extremely fast gas. I&#x27;d happily eat a huge gas fee if it meant saving much more valuable assets in an emergency.</p>
<p>These are just a few examples, but there are lots of ways to interpret designing experiences to <strong>guide users when things don&#x27;t go down the happy path</strong>.</p>
</li>
<li>
<p><strong>Show all assets across all networks/chains.</strong> A lot of things are being built on various blockchains and Layer 2 networks. With the exception of testnets, there&#x27;s no need to require switching between the Ethereum mainnet and Layer 2 networks like Optimism and Polygon. Just show everything together. It&#x27;s so annoying to hunt for your assets and forget what network they&#x27;re on. Modern wallets like <a href="https://rainbow.me/">Rainbow Wallet</a> do this today.</p>
<p>Furthermore, more wallets should support multiple blockchains such as Avalanche and Solana. This is a tremendous amount of engineering work, so it&#x27;s not to be taken lightly.</p>
<p>Why should we put the onus on new users to know the difference between various blockchains/Layer 2s and know what their wallet can and can&#x27;t support? It&#x27;s already hard enough to explain how to safely backup a seed phrase. This lets the people use whatever web3 service they want with minimal overhead.</p>
</li>
</ul>
<h3>Wallet experience (Security)</h3>
<p>And then there&#x27;s a whole realm of <strong>things related to wallet security</strong> that could be made easier to access, control and understand.</p>
<ul>
<li><strong>Make it easier to disconnect your wallet</strong> from connected apps and sites. Could a thoughtful implementation have preferences to enable automatically disconnecting after a certain time period, prompting you to disconnect older connections or only allowing a limited number of connections to be active at a time?</li>
</ul>
<img src="https://turbo.paulstamatiou.com/uploads/2021/11/paulstamatiou_com-metamask-connected-sites.png" alt="MetaMask connected sites UI" />
<small>Wallets tend to make their connected sites UI buried, with no education around when and why you may want to disconnect.</small>
<ul>
<li>
<p><strong>Introduce education and user controls for token approvals and token allowances.</strong> This one is for the more advanced users today but it really shouldn&#x27;t be due to the security implications. When interacting with a dApp that needs to access your tokens, you need to give the smart contract approval to use your tokens. Usually this allows unlimited use of all of your tokens and pose a risk where your tokens can be taken without further approval. It&#x27;s a best practice to remove token approvals for services you no longer trust or use. Similar to removing OAuth permissions on your accounts.</p>
<p>Services like <a href="https://revoke.cash/">Revoke.cash</a> and <a href="https://tac.dappstar.io/">Token Allowance Checker</a> exist for this purpose but this could be easier if part of the wallet experience. Some services like Zapper.fi have their own way to adjust allowances. Needless to say it could all be easier. You can read more about the topic here: <a href="https://kalis.me/unlimited-erc20-allowances/">Unlimited ERC20 allowances considered harmful</a>.</p>
</li>
<li>
<p><strong>Demystify common actions like connecting a wallet and signing a message.</strong> After you&#x27;ve used a few dApps, it becomes very common to see a lot of different dialogs you need to accept or confirm. This makes it all too easy for someone to absent-mindedly get into a habit of accepting these without quite understanding what&#x27;s happening.</p>
<p>Can modern wallets help educate customers about the risks associated with each action and provide ample recourse to undo them? Today, if you accidentally accept a dialog, most wallets don&#x27;t make it clear what you need to do to be safe, or if there is any risk from the action you took.</p>
<p>The team behind the <a href="https://walletconnect.com/">WalletConnect</a> protocol is working on a concept to merge "accept connection" and "sign message" that may only work for trusted apps and/or require strict restrictions.</p>
</li>
</ul>
<h3>What we can do tomorrow</h3>
<p>Dealing with existing technical constraints can definitely feel like we&#x27;re putting lipstick on a pig. If we put some of these shortcomings off to the side and consider a future wallet, things get a bit more interesting.</p>
<p>Here are a few potential areas of explore going forward:</p>
<ul>
<li>
<p><strong>Fix wallet addresses.</strong> Every crypto user deserves an easy way to reference their wallet. ENS is the current solution and it works (I love it and have several, including <code>stammy.eth</code>), but it&#x27;s not easy for a newcomer to setup, requires fees and has a small namespace where their ideal handle/domain is likely already taken.</p>
<p><strong>The next billion crypto users shouldn&#x27;t have to pay to make crypto usable.</strong> They shouldn&#x27;t have to deal with long addresses that could lead to huge issues like them losing funds. What&#x27;s the Gmail of wallet addressing? What if you could pick from several providers for a free shorthand address for your wallet? If you want pay for yourname.eth, thats fine. But that&#x27;s not for everyone. Could it be closer to email or ENS subdomains with providers you want to use or affiliate with like <code>stammy.exchange.eth</code> or <code>stammy@MyDAO</code>.</p>
</li>
<li>
<p><strong>Is wallet the right word?</strong> One challenge is that we’re designing for crypto as if it’s purely money (and maybe some NFTs) in a wallet. But the role of the wallet is growing and in the near future it will be so much more than that. Your crypto wallet can become your identity, your interests, your preferences, your knowledge graph, your communication. Perhaps we need a better word to describe its expanded role and control.</p>
<p>Websites are more frequently allowing you to "connect wallet" when often they mean just login. Connecting your wallet with your money can sound scary. Which brings me to the next point..</p>
</li>
<li>
<p><strong>Clarity & control around privacy and public assets.</strong> It takes some getting used to having all your assets publicly visible by anyone on the blockchain if they know your address. This is going to shock a lot of people when they first setup their wallet. Can you imagine paying a stranger for a coffee and them instantly being able to see all of your transactions and holdings? Creepy. But that&#x27;s what the blockchain enables.</p>
<p>Advanced users today get around this by maintaining multiple wallets, but surely we can&#x27;t expect everyone in the future to know how to do this on their own. Even then it&#x27;s not hard to track transactions if you accidentally transfer anything between the two wallets instead of using an exchange for that.</p>
<p>One partial solution is better wallet education and integration for supporting private-focused coins like Monero, Zcash and Mobilecoin. That&#x27;s fine for things that can be done privately, but you can&#x27;t exactly use those for other cryptoassets like NFTs or particular tokens. So what&#x27;s a more robust solution?</p>
<p>What if the wallet itself was safer by default? What if connecting your wallet to dApps was able to facilitate logging in, but by default did not show any assets. Depending on your permissions, the wallet could then allow exposing the wallet address where your assets actually live (potentially spread across multiple). Almost like Apple iCloud Private Relay for your wallet. I&#x27;m sure there are numerous technical and security feasibility issues with something like this, but I&#x27;m just trying to paint a picture of where we could aim in the future.</p>
</li>
<li>
<p><strong>Make it smarter, make it safer</strong>. Today “Connecting with wallet” is very convenient but very dumb. The dApp you connect to gets a unique identifier and some basic info about your holdings but not much else.</p>
<p><strong>How can we attach a knowledge graph to the wallet?</strong> A set of public and private preferences, a list of friends, a list of dApps you trust and how much, a list of blocked addresses, dApps and more. This graph data would ideally be a mix of public and private data stored off-chain.</p>
<p>Not only is this getting at a basic storage system for each wallet, it&#x27;s also getting at the start of a robust permissions system.</p>
<p>But the real super power of an approach like this? <strong>It can bootstrap all sorts of trust and security signals.</strong> You could see that 7 of your friends have used this smart contract before and didn&#x27;t report any issues, so you can trust it yourself too.</p>
<p>You could block or report a token as being a scam and it would instantly be hidden for your friends too. You could follow curated blocklists from entities you trust to make web3 safer for you. If anyone steals an NFT the community could blacklist it quickly enough that all NFT marketplaces could prevent any sale of that asset. There&#x27;s so much potential here. Companies like <a href="https://spruceid.com/">SpruceID</a> and <a href="https://idx.xyz/">idx</a> are exploring related things today.</p>
</li>
</ul>
<h3>What else?</h3>
<p>It&#x27;s such a promising time to be using web3 and especially working in web3. We haven&#x27;t even seen the killer apps of crypto that will bring waves of people into crypto.</p>
<p>This article was only meant to touch on a few areas where design help is especially needed, and from a design-only POV. I&#x27;m sure there are astounding technical challenges as well that may lead to varying alternative solutions. But it&#x27;s exciting to be here while it&#x27;s all getting figured out.</p>
<p>As a designer, I love to abstract complexity away from the user by relentlessly questioning what part of an interface is even necessary to present to the user and what we can automatically do for the user.</p>
<p>However, this will be one area we&#x27;ll have to be super careful about with crypto experiences. Crypto is different. It&#x27;s not like yet another Web 2.0 experience where abstracting things away (and likely putting that power back in the hands of the app/service). Web3 is about putting the user in control of their data and assets; giving them ownership, not taking it away.</p>
<blockquote>
<p>"Once understood, crypto is powerful in its simplicity. But it actually becomes more complicated the more you bury it under layers of abstraction. It’s clear to me now that the technology wants to be seen; it wants to be understood."</p>
<p>—<a href="https://thedefiant.io/crypto-wants-to-be-seen-op-ed-by-kayvon-tehranian/">"Crypto Wants To be Seen"</a></p>
</blockquote>
<p>With that, we&#x27;ll have to be careful about <strong>introducing thoughtful abstraction</strong>—simplifying and hiding complexity without diluting the essence of web3 or taking away control when it might be valued.</p>
<p>Examples of these types of decisions ahead might include:</p>
<ul>
<li>
<p>Do we hide that your wallet is non-custodial and introduce alternative recovery mechanisms? Or just do a great job at teaching people how to backup their key and understand the importance of that key.</p>
</li>
<li>
<p>Do we try to hide that there may be multiple Layer 2 networks you&#x27;re interacting with and automatically try to use the best network for the task at hand? Or focus on educating around what Layer 2 bridges do, the benefits of Layer 2 networks or other blockchains and provide transparency around where your assets live.</p>
</li>
</ul>
<p>These are the kinds of details we&#x27;ll have to figure out before we can get to that idealistic goal that everyone loves to talk about; that someday people won&#x27;t even know they&#x27;re using crypto. Is that even a goal? Or should we educate and empower people to embrace all that crypto and web3 have to offer? Of course, we&#x27;ll need to fix a few things first..</p>
<p>There&#x27;s a lot of noise in web3 today. It&#x27;s hard to know what technology, dApp or community is healthy and valuable. We need to build experiences that act as a great host to new users as if they had a web3 expert friend next to them guiding the way.</p>
<p>Maybe we can get there if we think about designing for trust. People trust other people and if web3 is all about decentralized networks, maybe we need to start tacking on more of those networks to the daily experience to help guide, secure and curate.</p>
<br><br><br><hr><br><h3>Footnotes</h3><p><a href="#r1">1</a><!-- --> I basically use the terms crypto and web3 interchangeably in this article but I realize there is nuance between the terms. Web3 tends to refer more towards the broader ecosystem and decentralized nature of how these systems work.</p><p><a href="#r2">2</a><!-- --> I reference "great experiences" often and I know it&#x27;s vague but there are so many things it can apply to: getting your first crypto, swapping tokens, connecting your wallet with a dApp, sending crypto to someone else, et cetera.</p><p><a href="#r3">3</a><!-- --> For the sake of simplicity, lets table the discussion of Layer 2 networks and alternative, faster blockchains like Solana. The current state of Eth gas is untenable and hopefully a multi-chain/L2 future full of composability can abstract away all the rough parts here. Even today the L2 experience is poor; I&#x27;ve watched friends click around for hours frantically trying to find their assets, forgetting what blockchain and L2 they had it stored on.</p><p><a href="#r4">4</a><!-- -->Another problem lies around proactively providing signals and controls to help users assess whether one of these entities can be considered trustworthy or not, but I&#x27;ll mention that in the next section.</p><p><a href="#r5">5</a><!-- -->Which thanks to ENS .eth domains it&#x27;s really not that hard to find someone&#x27;s wallet.</p>]]></description>
            <link>https://paulstamatiou.com/crypto-design-challenges</link>
            <guid isPermaLink="true">https://paulstamatiou.com/crypto-design-challenges</guid>
            <dc:creator><![CDATA[Paul Stamatiou]]></dc:creator>
            <pubDate>Wed, 24 Nov 2021 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[How I made $50K in 3 days with NFTs]]></title>
            <description><![CDATA[<link rel="preload" as="image" href="https://turbo.paulstamatiou.com/uploads/2018/01/copyright-paulstamatiou_com-cie1931-custom-chart.jpg"/><link rel="preload" as="image" href="https://turbo.paulstamatiou.com/uploads/2021/09/paul-stamatiou-crypto-mondrian-ranking.png"/><img src="https://turbo.paulstamatiou.com/uploads/2021/09/paul-stamatiou-CryptoMondrianDark-2000.webp" alt="Crypto Mondrian Dark NFT collection" />
<small>My code-generated NFT collection, <!-- --><a href="https://opensea.io/collection/cryptomondrian">Crypto Mondrian //DARK</a><!-- -->.</small>
<p>I first dabbled with cryptocurrency in 2011 when I wrote <a href="https://paulstamatiou.com/bitcoin-mining/">an article about mining Bitcoin</a> on AWS EC2 GPU clusters. My interest in crypto ebbed and flowed over the years before actively avoiding the space until earlier this year. It felt like there was a lot of noise and hype around volatile, speculative asset holding and not much innovation happening.</p>
<p>It wasn’t until a few months ago that I began to take a closer look at the state of crypto and see how much the landscape has evolved. The big thing for me was seeing how the blockchain has become programmable with smart contracts, little pieces of automatically-executing code running on the blockchain.</p>
<p>The new functionality afforded by smart contracts, along with the relative consumer ease of simply being able to connect your crypto wallet with any decentralized service and be able to quickly interact, has led to a flurry of new product developments. Most of these are categorized under the moniker dApps (decentralized applications that run on the blockchain or in a p2p capacity). A large chunk of dApps are in the so-called DeFi, or Decentralized Finance, space (yes, there&#x27;s lots of terms and abbreviations in the crypto space). I wrote a brief thread about <a href="https://twitter.com/Stammy/status/1417201411155120143">what I learned about crypto and DeFi</a> my first few weeks diving into it.</p>
<p><a href="https://ethereum.org/en/">Ethereum</a> was much more interesting to me now than Bitcoin. So much is being built on top of it with smart contracts and other <a href="https://coinmarketcap.com/tokens/views/all/">Ethereum-based tokens</a>. There are crypto-based games like <a href="https://axieinfinity.com/">Axie Infinity</a>, robust decentralized exchanges like Uniswap and Matcha.xyz, to communities and DAOs built around their own tokens like <a href="https://www.fwb.help/">FWB</a> and <a href="https://kong.land">Kong.land</a>. There&#x27;s far too much activity going on for me to accurately summarize the different types of innovation happening here and I&#x27;m definitely still learning myself.</p>
<p>NFTs are one particular realm of the crypto community that has been experiencing stratospheric growth over the last year. By now you’ve probably heard about them in some form. It could have been the news of digital artist <a href="https://www.theverge.com/2021/3/11/22325054/beeple-christies-nft-sale-cost-everydays-69-million">Beeple selling his NFT artwork for $69 million dollars</a>. Or maybe the news of Figma founder <a href="https://www.forbes.com/sites/alexkonrad/2021/03/18/figma-ceo-dylan-field-talks-cryptopunks-nft-beeple-metaverse/">Dylan Field selling a CryptoPunk NFT</a> for $7.5M.</p>
<p>NFTs are approaching mainstream status now—<a href="https://www.youtube.com/watch?v=oiN1_6pb_eE">Paris Hilton sold her own NFTs</a>, <a href="https://www.theblockcrypto.com/post/109655/jay-z-puts-a-cryptopunk-nft-as-his-twitter-profile-picture">Jay-Z bought a CryptoPunk</a> for $126k for his Twitter avatar and NBA player <a href="https://markets.businessinsider.com/news/currencies/steph-curry-nft-bored-ape-yacht-club-180000-ethereum-nba-2021-8">Steph Curry bought a $180k Bored Ape NFT</a> for his Twitter avatar and even Mila Kunis and Ashton Kutcher launching <a href="https://www.forbes.com/sites/nadjasayej/2021/07/26/is-stoner-cats-the-first-ever-nft-tv-show/">NFTs that unlock TV show episodes</a>.</p>
<p>One thing that stands out to me about crypto now, as opposed to the last time I was involved years ago, is that <strong>you can actually <em>do</em> stuff with your crypto now</strong>.</p>
<p>Before, it seemed like the most you could do was hold on to your crypto as an investment, sending it between wallets, or exchange it back to your local fiat currency. Now, people are able to spend their crypto.. largely on other crypto dApps or into the hands of creators with NFTs. And most of those people will continue investing in and building for crypto and decentralized services, so things continue growing and evolving.</p>
<p>However, all the press around NFTs reminds me of the hype around ICOs and speculative asset <em>hodling</em> of meme coins.. are NFTs just the latest example of a fleeting crypto fad?</p>
<h2>What are NFTs?</h2>
<h3>Digital art, collectibles, identity, tickets and more..</h3>
<p>I didn’t really get NFTs for a long time.. and honestly I don’t even know if I fully understand them now. Can’t someone just screenshot the NFT you paid a bundle for and have the same thing you have? That&#x27;s the common question you hear from anyone when they first hear about NFTs.</p>
<p>That&#x27;s like seeing <a href="https://photos.paulstamatiou.com/france/france-day-6/">the Mona Lisa in person</a>, taking a photo, turning that into a print on your wall and saying yours is worth the same. It&#x27;s not the original. With the public nature of NFTs on the blockchain, it&#x27;s easy for anyone to verify who owns it, who has owned it and when it first appeared. Anyone can look up your wallet address (or more recently ENS domain name if you set one up) to see what NFTs you own.</p>
<p>But let me take a step back for a moment..</p>
<p>NFTs are unique, non-fungible tokens on the blockchain. Regular cryptocurrency tokens like Ether or other <a href="https://coinmarketcap.com/tokens/views/all/">Ethereum-based ERC20 tokens</a> are fungible and can easily be traded and swapped for one another. They&#x27;re all the same thing.</p>
<p>By contrast, each NFT has a unique identifier allowing it to be paired with metadata that cannot be changed. While an NFT can be sold and transferred like any fungible token, each NFT has its own unique value and worth. This identifier also makes it possible to trace the ownership history for the NFT. It&#x27;s also possible to prove the scarcity of an NFT and know how many of a certain type exist and how many can exist.</p>
<p>Being able to programmatically prove ownership is where it gets interesting; NFTs can also be used like keys or digital tickets to unlock certain functionality, experiences, membership, events and so on.</p>
<p>And an NFT can never be taken from you. There is no middleman. This is not like <a href="https://slate.com/technology/2009/07/how-amazon-s-remote-deletion-of-e-books-from-the-kindle-paves-the-way-for-book-banning-s-digital-future.html">Amazon being able to remotely delete a Kindle book</a> you purchased because they want to. No one can take your NFT from your (non-custodial) wallet.</p>
<p>These traits of NFTs lead to some unique value propositions and capabilities. They can be used for digital art, content, collectibles and gaming but they can also be used for utilities like .eth domains like with the Ethereum Name Service or even tokenized real-world assets.</p>
<p>NFTs are status, identity, community, self-expression, access and more.</p>
<p>I could go on and get philosophical about the different ways NFTs provide value, but I&#x27;ll leave it at that. The value of an NFT always depends on what someone is willing to pay for it. The market always wins as they say; NFTs are no exception. Fortunately, now that market is open globally 24/7/365 and has a quick payment system. Not quite like the old days of trying to sell your Magic: The Gathering cards in person and not finding any buyers (just me?).</p>
<div><p>If you&#x27;d like to read up on NFTs more, I recommend checking out <!-- --><a href="https://ethereum.org/en/nft/">this NFT page on Ethereum.org</a><!-- -->, <!-- --><a href="https://opensea.io/blog/guides/non-fungible-tokens/">The OpenSea NFT Bible</a><!-- -->, <!-- --><a href="https://future.a16z.com/a-taxonomy-of-tokens-distinctions-with-a-difference/">Designing Internet-Native Economies: A Guide to Crypto Tokens</a><!-- -->, and <!-- --><a href="https://cdixon.org/2021/02/27/NFTs-and-a-thousand-true-fans">NFTs and A Thousand True Fans</a><!-- -->.</p></div>
<p>Even though NFTs have been around in some form since 2012 and then more media-focused from 2016, it&#x27;s still very early. I’m sure we’ll continue see a significant evolution of how they are used and how they are valued. Right now NFTs may get a bit of a mixed reputation due to the high level speculation on collectible assets and many buyers trying to quickly flip NFTs that are part of a limited set.</p>
<p>There are also private communities focused on investing in NFTs that have been growing, such as with <a href="https://pleasr.org/">PleasrDAO</a> and <a href="https://flamingodao.xyz/">Flamingo DAO</a>. While <a href="https://flamingodao.xyz/">Flamingo DAO</a> has done very well with their NFT investments so far, having experienced a 40X gain and <a href="https://twitter.com/litocoen/status/1432047312738660356">owning NFTs worth $1B+</a>, they take a longer view on what NFTs can provide:</p>
<blockquote>
<p>The growth of NFTs is just beginning, because NFTs represent the digitization and financialization of digital property and intellectual property. Trillions of creative works swirl around the Internet and are difficult to monetize, except through licensing models. NFTs hold out the hope of bringing back to the Internet an ownership economy. Creators can create, sell, and fractionalize ownership in their works, opening up a new chapter for creative endeavor. NFTs can be:</p>
<ul>
<li>fractionalized</li>
<li>combined into token sets</li>
<li>used as collateral for lending and stablecoin protocols</li>
<li>dynamic and interactive, incorporating outside data feeds</li>
</ul>
<p>Over the longer arc, NFTs hold out the hope of becoming increasingly financialized, interacting with other core blockchain-based financial primitives. They may prove to be a core primitive for decentralized identity solutions, and may increasingly serve as a cornerstone for monetizing emerging metaverses and other gaming platforms.</p>
<p>— <a href="https://docs.flamingodao.xyz/">What is Flamingo?</a></p>
</blockquote>
<p>Whatever your thoughts are on NFTs, it&#x27;s hard not to pay attention to what&#x27;s happening in the space. I very often think about how <a href="https://cdixon.org/2010/01/03/the-next-big-thing-will-start-out-looking-like-a-toy">the next big thing will start out looking like a toy</a> in the context of everything happening in crypto now, like the early days of the Internet.</p>
<h3>Common types of NFT projects</h3>
<h3>10k PFPs, collectibles, games and more</h3>
<p>With the basics out of the way, lets see what types of media-focused NFTs and cryptoart are common right now. First off, we have the very popular so-called “10k PFP” collections. These are sets limited to 10,000 media assets geared towards being used as a profile picture, usually because the image looks like some kind of being: human, alien or otherwise anthropomorphized entity.</p>
<p>There are the popular ones like CryptoPunks and <a href="https://boredapeyachtclub.com/">Bored Apes</a> and then there are the many derivative collections trying to capitalize on these types of sets. Owning an NFT from one of these collections has led to being a new sort of status and community.</p>
<p>There are interesting trading card-like NFTs like <a href="https://parallel.life/">Parallels</a> and gaming NFTs like <a href="https://zed.run/">Zed</a>. And then a section of the NFT space that I&#x27;ll just call experiments because I&#x27;m not sure what else to call them. Things like <a href="https://www.blitmap.com/">Blitmap</a>, <a href="https://collisions.substack.com/p/gimme-the-loot">Loot</a> and <a href="https://tunesproject.org/">Tunes Project</a> that test the waters of how certain types of NFTs can invite others to build on top of them. In this case of Loot, building a whole game ecosystem with characters, loot, music and more.</p>
<p>And of course, there&#x27;s a ton of NFTs that encompass all other forms of art. It has also been inspiring to see artists adapt to the new format and reap the benefits; getting paid more easily and generously than previously. There are computer-assisted artists making 2D and 3D creations by hand and there are all sorts of artists making digital versions of their hand-made creations. There&#x27;s even a painter <a href="https://opensea.io/collection/seasketch">selling NFT sketches</a> that come paired with an offer to unlock a physical painting, shipped to whoever owns the NFT during a particular time each year.</p>
<p>But there’s one type of NFTs that I became particularly fond of: <a href="https://en.m.wikipedia.org/wiki/Generative_art">generative art</a>. Generative art can be defined in many ways but at a high level it&#x27;s any art that was created in part or in whole with the artist being hands-off and having an automated computer system or program do the rest, leading to each creation being entirely unique.</p>
<p>One of the popular players in this space is <a href="https://artblocks.io/">Art Blocks</a>. This example below sold for 777 ETH (around $2.5M when it sold):</p>
<blockquote>
<p>Wow... just shocked. When I set this price (yesterday) I didn&#x27;t really expect it to sell this quickly. Thank you <a href="https://twitter.com/tylerxhobbs?ref_src=twsrc%5Etfw">@tylerxhobbs</a> for your fantastic work. I will certainly reinvest this in new and upcoming artists / donate a portion to charity. 🙏🤯 <a href="https://t.co/rbaJQ73D48">https://t.co/rbaJQ73D48</a></p>
<p>— Kevin Rose (@kevinrose) <a href="https://twitter.com/kevinrose/status/1430560685172297729?ref_src=twsrc%5Etfw">August 25, 2021</a></p>
</blockquote>

<h2>Making my NFTs</h2>
<h3>How I got inspired, built and listed them</h3>
<p>I knew I wanted to get involved with NFTs somehow. Over the past few months I had been seeing designers I follow experiment with and find success creating and selling their own cryptoart NFTs. Friends and family had been suggesting I do something with NFTs; I just didn’t know what.</p>
<p>I’m a designer and developer but my forte is definitely not the type of graphic and 3D design I had seen as being common with NFTs: detailed illustrations, 3D concepting/rendering and 3D animation. I didn’t want to design another collection of PFPs. It had to be something that I could feasibly write a simple program myself with regular web and mobile languages I already know.</p>
<p>I thought about picking up <a href="https://processing.org/">Processing</a>, which I had last touched in college more than a decade ago, and making some art out of things like <a href="https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life">Conway&#x27;s Game of Life</a> and other cellular automata. But I didn&#x27;t find that to be particularly aesthetically pleasing or how I could make it pleasing.</p>
<p>I began thinking about modern, abstract art I like, wondering if I could do a "crypto" take on that. I like geometric art and something with simple geometric shapes would be feasible for me to code with regular web/software technologies I already know. And hopefully by being heavily inspired by existing traditional artwork, these NFTs would might already feel familiar to viewers.</p>
<p>A few years ago I visited <a href="https://photos.paulstamatiou.com/amsterdam/">Amsterdam (my photoset)</a> and visited museums like the Stedelijk Museum of modern and contemporary art where I had seen lots of <a href="https://en.wikipedia.org/wiki/De_Stijl">De Stijl</a> pieces. Piet Mondrian&#x27;s compositions came to mind along with pieces by Gerrit Rietveld.</p>
<img src="https://turbo.paulstamatiou.com/p/2018/amsterdam/copyright-paulstamatiou_com-DSC1100-3000.webp" alt="" width="3000" height="2182" /><br /><br /><img src="https://turbo.paulstamatiou.com/p/2018/amsterdam/copyright-paulstamatiou_com-DSC1137-3000.webp" alt="" width="3000" height="2001" /><br /><br /><img src="https://turbo.paulstamatiou.com/p/2018/amsterdam/copyright-paulstamatiou_com-DSC1098-3000.webp" alt="" width="3000" height="2197" /><br /><br /><img src="https://turbo.paulstamatiou.com/p/2018/amsterdam/copyright-paulstamatiou_com-DSC1104-3000.webp" alt="" width="3000" height="2309" />
<p>I decided to try writing some code to generate Mondrian-inspired art that would be unique each time I ran it. But <strong>I wanted to make it feel like what crypto <em>feels</em> like to me</strong> at first glance. I think Mr. Robot, <a href="https://decrypt.co/79422/shadowy-super-coder-pack-315m-perks-ethereum-nft-devs">Shadowy super coders</a>, dark web, The Matrix, Blade Runner, Altered Carbon, Ready Player One.. <strong>lots of neon colors, glows and darkness</strong>.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2021/09/paul-stamatiou-crypto-vibes-moodboard-3000.jpg" alt="Paul&#x27;s moodboard of crypto vibes" width="2319" height="1948" />
<p>After I had a general idea of what I wanted to create, I thought about how to build it. I knew I wanted to do a limited set, something under 1,000. I figured 100 would be a nice way to get started and test the waters. Just enough that I would need to have whatever code I wrote be able to export directly to PNG. I didn&#x27;t want to hack around with taking screenshots for each of them.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2021/09/paul-stamatiou-crypto-mondrian-glow.png" alt="Paul&#x27;s moodboard of crypto vibes" width="2800" height="800" />
<small>The general vibe I was going for.. bright colors seeping into generous glows.</small>
<p>I decided to start by making a simple HTML page that used <code>canvas</code> and JavaScript to create the art and easily let me export the canvas. I had become familiar with canvas recently when making the <a href="https://stocketa.com">Stocketa</a> site:</p>
<blockquote>
<p>Spent a good chunk of the weekend building out the last bits of the new <a href="https://twitter.com/StocketaApp?ref_src=twsrc%5Etfw">@StocketaApp</a> website. Happy with how it&#x27;s turning out... will probably deploy later tonight Used Canvas to composite JPG frames (for smaller size) using PNG masks (for alpha) for Apple-like 3d scroll effect <a href="https://t.co/2OBNhIR3y8">pic.twitter.com/2OBNhIR3y8</a></p>
<p>— Paul Stamatiou (@Stammy) <a href="https://twitter.com/Stammy/status/1384509594991534082?ref_src=twsrc%5Etfw">April 20, 2021</a></p>
</blockquote>
<blockquote>A Tweet embed was not displayed. Read this article in a browser to see it as intended.</blockquote>
<p>After a Sunday afternoon of tinkering, I had a working concept. Every time the page loaded, a new random design would be created. I used the localStorage API to keep track of views and name each file for export, which I would simply do via a download button on the page. I was too eager to get this out and didn&#x27;t spend much time on additional code to automate things.</p>
<p>Much of the code revolves around randomly selecting the number of iterations to complete, what color palettes to use, modifying colors and the intensity of the glows. Some of them used color palettes of 3-5 colors I put together myself, while others I had the code pick from a random color and then find pentadic, tetradic or triadic colors to use or use varying alphas of a single color. Figuring out the colors took a decent chunk of time and I think there was still some room for improvement. I ended up having around 15 different color palettes I was having the code randomly select between at one point.</p>
<p>This is what it ended up being—a simple HTML page with a few hundred lines of JavaScript and a download button to export the canvas to a 4800x4800 PNG.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2021/09/paul-stamatiou-crypto-mondrian-chrome.png" alt="The single HTML file responsible for generating the artwork." width="1388" height="1304" />
<small>The single HTML file responsible for generating the artwork.</small>
<p>One issue I ran into and was with color profiles. Dealing with very saturated colors and lots of glows, I wanted to use the P3 color space instead of sRGB, which was the default color space/profile when exporting the contents of a canvas. This is something I became quite familiar with years back when writing <a href="https://paulstamatiou.com/building-a-windows-10-lightroom-photo-editing-pc/#the_display">my post about building a Lightroom PC</a>.</p>
<p><img src="https://turbo.paulstamatiou.com/uploads/2018/01/copyright-paulstamatiou_com-cie1931-custom-chart.jpg" alt="CIE1931 color space comparisons: ProPhoto RGB, Rec. 2020, Adobe RGB, DCI-P3, sRGB"/></p>
<p>Relying on sRGB meant some visible color banding that annoyed me. Unfortunately, it seemed like this was out of my control and it&#x27;s not yet possible to specify a color profile for canvas to use when exporting after a cursory investigation. It wasn&#x27;t a huge issue, so I moved on.</p>
<h3>Publishing PNGs as NFTs</h3>
<p>Now I had a pile of PNGs and needed to list them for sale as NFTs. This started out as a small project so I just wanted something very turnkey to manually list each piece. I already knew I wanted to use OpenSea. It&#x27;s hard to look at NFTs online and not come across them; something like 98% of all NFT trade volume flows through OpenSea.</p>
<p>The other nice thing about OpenSea is that there is no cost to the seller to mint each NFT. There&#x27;s a one time gas fee the first time you sell anything but I had done that a while back with another NFT that I&#x27;m not even sure how much that cost.</p>
<p>Minting an NFT is the process of putting your art/media and its associated metadata on the blockchain by creating a new, unique token (usually ERC-721 but there&#x27;s a newer format called ERC-1155 that supports both non-fungible and fungible tokens). In my case, I would be putting these on the Ethereum blockchain. It&#x27;s also possible to mint on other blockchains for lower costs, such as the <a href="https://rainbow.me/learn/a-beginners-guide-to-layer-2-networks">Ethereum-compatible sidechain Polygon</a>, or a faster blockchain, <a href="https://solana.com/">Solana</a>, but that&#x27;s outside the scope of this article. For now, we&#x27;ll stick with Ethereum. It&#x27;s currently the most popular for NFTs.</p>
<p>If I was doing a much larger NFT project, I would probably spend a bunch of time and money developing and deploying my own smart contract on Ethereum. NFTs are minted through a smart contract, small bits of code running on the blockchain itself. Owning your own smart contract gives you complete control over your NFT collection and doesn&#x27;t delegate any control over to a NFT marketplace. It just costs a lot to develop and deploy (for example, I tested deploying a simple smart contract and the estimated gas fees required to publish the smart contact to the Ethereum blockchain were around 0.25-0.35 ETH or ~$1,000).</p>
<p>This is a growing space so you&#x27;re at no shortage of options for how you want to publish your NFTs from <a href="https://niftykit.com/">Nifty Kit</a>, Bitski, Foundation, Rarible, Zora.co, UNifty.io, <a href="https://tryshowtime.com/">Showtime</a> and many more.</p>
<h3>Listing on OpenSea</h3>
<p>So I ended up sticking with OpenSea: easy to get started and no fees to mint NFTs, but they take a 2.5% cut on each sale. Other marketplaces like Foundation require you to pay gas to mint each NFT, which can get expensive quickly if you&#x27;re unsure your items will sell, with each item costing potentially around $100 of gas to mint.</p>
<p>There&#x27;s a bit of nuance to how OpenSea does things. They do so-called <em>lazy minting</em>. While you may need to pay an initial gas fee to list a new collection, each NFT listing does not require any fees. This works because the NFT is not actually minted yet. It gets officially minted once the buyer pays the gas fees to mint the artwork on the blockchain.</p>
<p>I created a new collection then began adding each NFT one by one; first adding the item, then marking it for sale at a set price. If I had a more complex set, I might have spent the time to add detailed metadata such as unique stats or traits of the individual NFTs to help people more easily filter and find what they&#x27;re looking for.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2021/09/paul-stamatiou-opensea-create-crypto-mondrian-3000.png" alt="OpenSea create Crypto Mondrian NFT interface" width="2702" height="2350" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2021/09/paul-stamatiou-opensea-sell-crypto-mondrian-3000.png" alt="OpenSea sell Crypto Mondrian NFT interface" width="2704" height="1600" />
<small><a href="https://opensea.io/collection/cryptomondrian">Adding and listing an NFT</a><!-- --> for sale on OpenSea.</small>
<p>When it came to pricing, I wasn&#x27;t really sure how to approach this. I started with the first few priced around $200, between Ξ0.05-0.065 (Ξ is the symbol for ETH, or ether). I wasn&#x27;t sure if these would sell at all and since I was manually uploading and listing each NFT, I started slow and released them in batches over a 3 day period. I listed the first three in a new <a href="https://opensea.io/collection/cryptomondrian">Crypto Mondrian //DARK</a> collection, Tweeted about it and then went out to dinner that Sunday evening.</p>
<p>Surprisingly, all 3 sold quickly. The next day, I released 20 more NFTs. Every few minutes I would hear the ding from my email app and then open my <a href="https://rainbow.me/">Rainbow Ethereum wallet</a> to see each new inbound ETH transfer from OpenSea.</p>
<blockquote>
<p>I&#x27;m blown away by the NFT community.. already sold 12 of my Crypto Mondrian //DARKs. 🤯 I just listed another 20: <a href="https://t.co/lPHCzp5spT">https://t.co/lPHCzp5spT</a> <a href="https://t.co/nOEb7zGfEq">pic.twitter.com/nOEb7zGfEq</a></p>
<p>— Paul Stamatiou (@Stammy) <a href="https://twitter.com/Stammy/status/1434923524754493443?ref_src=twsrc%5Etfw">September 6, 2021</a></p>
</blockquote>
<blockquote>A Tweet embed was not displayed. Read this article in a browser to see it as intended.</blockquote>
<p>I kept releasing in batches over a 3 day period at varying prices. As they started to sell I noticed people quickly listing theirs for sale at much higher prices so I experimented with increasing my prices.</p>
<p>It was interesting to see where the sales came from. While I think a good portion came from those that follow me on Twitter, I believe a large set of folks found me through various crypto community Discord and Telegram groups where my collection was eventually shared. I also saw lots of folks that purchased them ending up sharing the new NFTs they added to their collection with their own audiences. It was awesome to see it all come together.</p>
<p>By the end of day 3, all NFTs had sold (except #099 and #100 I wanted to keep for myself as a memento). To say that I was shocked that my Crypto Mondrian art was selling and selling well would be a huge understatement. The reaction far exceeded my expectations. The average sale price was around Ξ0.189, though that includes all sales (some of which were much higher like Ξ0.6-0.9) not just ones listed for sale by me directly.</p>
<p>My collection ended up being <strong>ranked #469 out of all NFT collections on OpenSea</strong> that week, and #132 in the Art category:</p>
<img src="https://turbo.paulstamatiou.com/uploads/2021/09/paul-stamatiou-crypto-mondrian-ranking.png"/>
<h2>Breaking down the sales</h2>
<h3>The grand total was Ξ14.085, just over $50,000 at the current ETH price</h3>
<img src="https://turbo.paulstamatiou.com/uploads/2021/09/paul-stamatiou-CryptoMondrianDarkCollection-3000.jpg" alt="All 100 Crypo Mondrian //DARK NFTs" width="3000" height="3000" />
<small><strong>All 100 <!-- --><a href="https://opensea.io/collection/cryptomondrian">Crypto Mondrian //DARK</a><!-- --> NFTs</strong></small>
<p>One interesting thing about certain NFT marketplaces like OpenSea is the ability for creators to specify a royalty percentage when listing their collection. This means that the creator will continually receive payment for any sale of their NFTs, even if they are not involved in the transaction and it is between two other users. This is amazingly creator-friendly. Currently, this is a feature of some individual NFT marketplaces, not actually part of any NFT standard.. yet.</p>
<p>That being said, I did set a 10% royalty on my Crypto Mondrian collection. OpenSea batches up the royalties and delivers them in a separate, single payment every few weeks.</p>
<p>Here&#x27;s a breakdown of the sales and royalties so far:</p>
<table><thead><tr><th>Payment received (minus 10% royalty and 2.5% OpenSea fees)</th><th>Number of sales</th></tr></thead><tbody><tr><td>Ξ0.0569</td><td>30</td></tr><tr><td>Ξ0.07</td><td>16</td></tr><tr><td>Ξ0.175</td><td>11</td></tr><tr><td>Ξ0.0875</td><td>11</td></tr><tr><td>Ξ0.35</td><td>6</td></tr><tr><td>Ξ0.306</td><td>5</td></tr><tr><td>Ξ0.131</td><td>5</td></tr><tr><td>Ξ0.219</td><td>4</td></tr><tr><td>Ξ0.0438</td><td>3</td></tr><tr><td>Ξ0.109</td><td>2</td></tr><tr><td>Ξ0.438</td><td>1</td></tr><tr><td>Ξ0.263</td><td>1</td></tr><tr><td>Ξ0.0788</td><td>1</td></tr></tbody></table>
<table><thead><tr><th></th><th></th></tr></thead><tbody><tr><td>Royalties accrued
(includes initial sales)</td><td>Ξ2.083</td></tr><tr><td>Grand total</td><td>Ξ14.085 ($50,417.96 @ current $3,579.55 ETH price)</td></tr></tbody></table>
<p>I&#x27;m extremely thankful and amazed at what was able to happen with this project, and the power of the crypto technology and community that enabled this to happen. It has been awesome to see creators quit their full-time jobs to pursue their passions, fueled by their newfound ability to quickly be able to earn a tremendous amount of money with NFT collections. It will be fun to see how this space evolves and what new types of things can be created using NFTs, even beyond art and collectibles.</p>
<p>On the other hand, it&#x27;s clear that a lot of people are interested in NFTs to be able to quickly flip them (often within hours or days of a purchase) and make a quick profit. As a creator, the first time I saw someone purchase my NFT and then immediately list it for 13x their purchase price.. that stung a bit. I get it though, and I have definitely been on the other side before. I wish there was a way to specify separate types of NFTs that might let me sell differently to those that enjoy the artwork vs those that are in it for the investment and speculation.</p>
<p>For example, I might sell an NFT at a discount if it meant the buyer would either not be able to sell it, or would not be able to sell it for some period of time. Not unlike a <a href="https://www.investopedia.com/ask/answer/12/ipo-lockup-period.asp">6-month IPO lock-up period</a> for employees.</p>
<h3>What&#x27;s next?</h3>
<h3>Just tinkering and learning</h3>
<p>I had a lot of fun diving into the world of NFTs lately. While I&#x27;m interested in continuing the journey with another collection, I won&#x27;t do anything unless it&#x27;s a slight evolution from what I just did with this set. Either a new style or something different (video? animated?).</p>
<p>I have been particularly interested in learning about smart contracts and would love to deploy a smart contract that is able to generate media completely on-chain. It&#x27;s been fun to watch all the smart contract experiments that <a href="https://twitter.com/dhof">Dom Hoffman</a> (creator of Loot, Blitmap, Vine..) has been tweeting out. As I wrote this, another interesting NFT experiment called <a href="https://mannys.game/about">Manny&#x27;s Game</a> was gaining popularity and had a unique set of rules.</p>
<p>But one thing seems to be certain with NFTs: creativity is valued highly. Being the second person to do something without evolving the format much won&#x27;t get you too far, especially in the future as the popularity of NFTs go up and down.</p>
<blockquote>
<p>Qualities to look for in NFTs on chain 🖼 good art 🌐 public domain 💻 open source 💎 unique 🤝 not anonymous 💗 healthy community ❌ not super markety 🧑‍🎨 committed artist 💸 you like it 💵 you can afford it 📉 ur cool if it goes down</p>
<p>— Dame.eth (@jacksondame) <a href="https://twitter.com/jacksondame/status/1437753067085107210?ref_src=twsrc%5Etfw">September 14, 2021</a></p>
</blockquote>
<p>But, of course, I have lots of work left on my other project <a href="https://stocketa.com">Stocketa</a>, where I recently added <a href="https://twitter.com/StocketaApp/status/1425456454316740612">basic crypto support</a>.</p>]]></description>
            <link>https://paulstamatiou.com/how-i-made-50k-in-3-days-with-NFTs</link>
            <guid isPermaLink="true">https://paulstamatiou.com/how-i-made-50k-in-3-days-with-NFTs</guid>
            <dc:creator><![CDATA[Paul Stamatiou]]></dc:creator>
            <pubDate>Sun, 12 Sep 2021 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Getting started with SwiftUI]]></title>
            <description><![CDATA[<link rel="preload" as="image" href="https://turbo.paulstamatiou.com/uploads/2021/06/paulstamatiou_com-swiftui-playgrounds-example.gif"/><p>It was just a year and a few months ago that I first began learning about and tinkering with Swift and SwiftUI. I followed tutorials and learned through lots of trial and error as I worked on my stocks tracker app, <a href="https://stocketa.com">Stocketa</a>. Picking up SwiftUI was one of the best decisions I’ve made.</p>
<p>SwiftUI is a massive advancement in making iOS development more accessible for all. I don&#x27;t consider myself a seasoned developer but I know enough to build somewhat polished prototypes and sites for my projects. I&#x27;ve tried to get into iOS development years ago with Objective-C and UIKit but it was just not for me.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2021/06/copyright-paulstamatiou_com-DSC05703-1500.jpg" alt="Xcode setup with SwiftUI live preview" />
<small>My Xcode setup. SwiftUI live preview on the right pane.</small>
<p>As a designer with many years of experience designing mobile interfaces, I always felt one step removed from the process and the final product. I could prototype a ton of stuff with web technologies and preview on mobile devices but it wasn&#x27;t the same. I&#x27;ve always wanted to design and build natively, with Apple&#x27;s own tools.</p>
<p>I love sweating the details of interactions and motion, but my ability to express myself and try out concepts using native devices and OS affordances always felt limited by my lack of knowledge of these tools. Sure, I could describe what I wanted to an engineer in many ways, but I wanted to build it myself.</p>
<p>There’s nothing quite like just doing it yourself, natively and SwiftUI has made this a reality for me. I&#x27;m here to share my enthusiasm and some resources so that it can be attainable for you too.</p>
<p>This is not meant to be a comprehensive guide or tutorial, but rather a brief reflection on my time with SwiftUI and some pointers on getting started.</p>
<h3>Stocketa & SwiftUI</h3>
<p>SwiftUI is not some beginner&#x27;s toy for getting into iOS development (though some long-time UIKit developers may say otherwise). <strong>You can make beautiful, full-blown, real iOS apps with all the motion, delight and flourishes you want.</strong> And this will only continue to improve as Apple invests more into SwiftUI in the coming years.</p>
<p>I have only had to use UIKit for a few minor things like getting more control over custom textfield designs and interactions. I&#x27;ve built custom bottom sheets, menus, onboarding flows and much more purely with SwiftUI. Here are some examples of what I&#x27;ve been able to build with SwiftUI:</p>

<blockquote>A Tweet embed was not displayed. Read this article in a browser to see it as intended.</blockquote>

<blockquote>A Tweet embed was not displayed. Read this article in a browser to see it as intended.</blockquote>

<blockquote>A Tweet embed was not displayed. Read this article in a browser to see it as intended.</blockquote>

<blockquote>A Tweet embed was not displayed. Read this article in a browser to see it as intended.</blockquote>

<blockquote>A Tweet embed was not displayed. Read this article in a browser to see it as intended.</blockquote>

<blockquote>A Tweet embed was not displayed. Read this article in a browser to see it as intended.</blockquote>

<blockquote>A Tweet embed was not displayed. Read this article in a browser to see it as intended.</blockquote>

<blockquote>A Tweet embed was not displayed. Read this article in a browser to see it as intended.</blockquote>
<h3>What is SwiftUI?</h3>
<p>Let me take a step back and explain what SwiftUI is in the first place and why I think it makes iOS development much more accessible to all.</p>
<p>SwiftUI is a framework for creating interactive user interfaces for iOS and macOS. It goes beyond just the visuals of how the interface looks and helps with everything from taps and gestures to accepting data input via things like text fields, color pickers and date pickers to working with your iPad&#x27;s trackpad pointer. And it does it in a way that, to me, feels very natural and fast.</p>
<p>It feels natural because <strong>SwiftUI code just feels like you&#x27;re writing some new type of HTML markup</strong>. It&#x27;s definitely way more than that, but when you&#x27;re just getting started it doesn&#x27;t feel foreign. You&#x27;re not trying to figure out what "super" means, what function overriding is or trying to grok what viewDidLoad() is for.</p>
<p>And it feels fast because you&#x27;re writing SwiftUI side-by-side with a live preview, so you see your changes as you type them. You don&#x27;t have to compile and send a build to your device or the simulator to get an interactive preview of your view.</p>
<p>SwiftUI was introduced two years ago with iOS 13 and brings a declarative style of programming for your user interface. The general idea is that all views of your app are based on the state of your data. Instead of telling a view exactly how and what you want it to do with imperative programming, with SwiftUI you tell it what you want and the view will react automatically based on the underlying data changing.</p>
<p>Want a circle to move across the screen when the user taps a button? You have a value on the object that it reacts to, along with an animation between the old and new value. This declarative style is similar to React web development too.</p>
<p>I&#x27;m flying through this but once you wrap your head around the declarative style it really just speeds up development.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2021/06/paulstamatiou_com-swiftui-playgrounds-example.gif" alt="SwiftUI example in Playgrounds"/>
<small>SwiftUI example in Playgrounds</small>
<h3>My SwiftUI first impressions</h3>
<p>It&#x27;s important for me to add the context here that my impressions of diving into iOS development with SwiftUI are based entirely on me being a designer, not an iOS developer already familiar with UIKit development. I&#x27;ve just been given keys to a Ferrari. Everything is amazing and I&#x27;m just happy to be in the driver&#x27;s seat and press that red engine start button. I have everything to finally build an iPhone app myself.</p>
<p>Contrast this viewpoint with, say, an existing iOS developer. My perception of the broader iOS developer community is that SwiftUI isn’t exactly universally loved. SwiftUI does not have feature parity with UIKit. The SwiftUI alternatives may not be as performant or may not be possible yet. It&#x27;s an entirely different way of crafting user interfaces and it has a few bugs here and there. I get that.</p>
<p>But SwiftUI is getting better every year and WWDC 2021 starts next week. With each iOS release we get more and more SwiftUI updates bringing us closer to parity. Swift 5.5 is coming soon and that brings lots of <a href="https://www.hackingwithswift.com/articles/233/whats-new-in-swift-5-5">very intriguing improvements like async/await</a> as well as <code>#if</code> for postfix member expressions (lets you do conditional view modifiers easily) that will be fun to explore.</p>
<p><strong>But I digress...</strong> my first impressions of developing with SwiftUI along with some of my current thoughts:</p>
<p><strong>SwiftUI live previews:</strong></p>
<ul>
<li>
<p><strong>First impression:</strong> Writing SwiftUI view code on one side of Xcode and then seeing the live, interactive preview of your interface is very slick and a fun way to learn as you figure out the ins and outs of SwiftUI.</p>
</li>
<li>
<p><strong>15 months in:</strong> SwiftUI Previews get extremely slow to load and refresh once you start having a larger app. They also get more complex as you have to do more work to manage the example data to use for the preview. Especially if you have certain things that rely on user state (such as a logged-in user from Firebase). And due to the static nature of the preview code, if you want to change a @State for example you have to resort to tricks like <a href="https://developer.apple.com/forums/thread/118589">wrapping the view</a>.<br/>
The key is to know what to use previews for. They can be very helpful for smaller subviews that work totally fine with static data. But it&#x27;s up to you if you want to spend the time to get it working well for more complex views. I tend to use it for smaller subviews and then just test on device for the rest.</p>
</li>
</ul>
<p><strong>On SwiftUI giving you native access</strong></p>
<ul>
<li>
<p><strong>First impression:</strong> SwiftUI gives you access to so much. Native UI components. Advanced gestures (of which you can use multiple at the same time!). The ability to animate virtually anything. The ability to use lots of views however you like, even applying a mask over them at once. Access to device things like gyroscope, accelerometer and haptics. The list goes on. It&#x27;s real, native app development and it&#x27;s great.</p>
</li>
<li>
<p><strong>15 months in:</strong> Yea this never gets old.</p>
</li>
</ul>
<p><strong>Building for native mobile vs Web</strong></p>
<ul>
<li>
<p><strong>First impression:</strong> Designing and developing natively for iOS feels so much faster and guaranteed compared to Web. There are only a few types of iOS devices so for the most part what you see on your device is exactly what someone will experience on their iPhone, down to the animations. You don&#x27;t have to worry about testing across many browsers and viewports compared to Web, nor worry about heavily optimizing file sizes.</p>
</li>
<li>
<p><strong>15 months in:</strong> You have to care about performance once your app does more. You&#x27;ll have to think about what thread you&#x27;re using else you may drop frames and introduce some scrolling jank. You&#x27;ll have to think about optimizing your views and heavily using sub-views to reduce what gets redrawn to the screen. You&#x27;ll have to care a bit about what functions do heavy computation and when.</p>
<p>But for performance with animations and masks, that&#x27;s still good. Most of the time when I drop some frames it&#x27;s due to some underlying data issue, not me doing something too crazy with lots of views, animations and masks.</p>
</li>
</ul>
<p><strong>SwiftUI&#x27;s modifier syntax</strong></p>
<ul>
<li>
<p><strong>First impression:</strong> Writing view code with all these chained modifiers (the .frame(), .foregroundColor() and other things chained under objects) is a bit funky and seems messy. Compared to web development where you actively try not to put too much style code in the view layout markup and abstract much of the styling out to a separate CSS file.</p>
</li>
<li>
<p><strong>15 months in:</strong> The way SwiftUI does things with modifiers is great but you need to get into the habit of abstracting commonly used groupings of modifiers into custom view modifiers (think of it like using a class in CSS.. kinda).</p>
</li>
</ul>
<p><strong>Working with a strongly typed language</strong>
While this is more about Swift than SwiftUI, you&#x27;ll run into it regardless: Swift is a strongly typed language.</p>
<ul>
<li>
<p><strong>First impression:</strong> It&#x27;s extremely annoying. I was dealing with non-stop warnings and errors that I wasn&#x27;t using the correct type when working with some data (Types are things like Bool, Int, Double as well as many other object types you can create). It was very confusing, especially trying to figure out why Optionals are a thing, how to unwrap them and so on.</p>
</li>
<li>
<p><strong>15 months in:</strong> I&#x27;m very comfortable now with Swift&#x27;s strong typing and really think it helps write faster, safer code. I&#x27;ll still run into various issues but most of the time it&#x27;s just Xcode looking out for me.</p>
</li>
</ul>
<h3>Learning SwiftUI</h3>
<p>It&#x27;s clear to me that SwiftUI is a powerful way to develop apps, especially for people with no prior iOS development experience. While there is always a learning curve with new frameworks and tools, especially code-based ones, SwiftUI is a fresh take on this with the Xcode live preview canvas that lets you see your UI as you&#x27;re writing it.</p>
<p>My goal with this article is share my high-level thoughts on SwiftUI and pointers on how to get started with some great resources that have helped me along the way. I hope to write a much more in-depth post about Stocketa and SwiftUI in the future.</p>
<h3>Where to start?</h3>
<p>I learned Swift and SwiftUI like I learn most things: a few tutorials to get the swing of things, then trying it out with my own project and all the trial and error that follows. Fortunately, SwiftUI has a ridiculously healthy and active developer community so there are always places to turn to for help.</p>
<p>Here&#x27;s the general flow you might follow while getting into SwiftUI:</p>
<ul>
<li>
<p><strong>Install Xcode or Playgrounds.app</strong>. While you&#x27;ll need Xcode to get the most out of SwiftUI and build a full app, there&#x27;s another option. Apple has a <a href="https://developer.apple.com/videos/play/wwdc2020/10643">MacOS and iPad app called Playgrounds</a> that&#x27;s perfect for prototyping and playing with Swift and SwiftUI.</p>
</li>
<li>
<p><strong>Get familiar with the SwiftUI basics.</strong> How to use frames, stacks and spacers to <a href="https://www.hackingwithswift.com/articles/217/complete-guide-to-layout-in-swiftui">lay things out in your interface</a>. Then how to use view modifiers to tweak visual elements of your designs.</p>
</li>
<li>
<p><strong>Dabble with basic interactions</strong> Advance to hooking up some button interactions with <code>@State</code> and bindings and trying built-in components like the ScrollViews, toggles and more.</p>
</li>
<li>
<p><strong>Play with animations.</strong> There&#x27;s lots of fun to be had with .transition() and .animation(). <a href="https://developer.apple.com/tutorials/swiftui/animating-views-and-transitions">Apple has a tutorial</a> on the basics too.</p>
</li>
<li>
<p><strong>Work with data and dive deeper into Swift.</strong> Up until now you could get pretty far with a minimal understanding of Swift itself but you&#x27;ll soon need to have a stronger grasp. Learning how to structure your models for objects, learn more about optionals and types, manipulating arrays, making network requests and so on.</p>
</li>
<li>
<p><strong>Getting better at manipulating data.</strong> At this point lots of your challenges will be around manipulating data and passing it around. Here you&#x27;ll probably face some decisions for your app. How do you store your data: do you use Apple&#x27;s Core Data, a SQLite library like <a href="https://github.com/groue/GRDB.swift">GRDB</a> or turn to a third-party solution like Firebase Firestore or <a href="https://realm.io">Realm</a>.</p>
</li>
</ul>
<h3>Resources</h3>
<p>Okay, now to the actual resources I&#x27;ve learned from and come to rely on for staying up-to-date with all things Swift and SwiftUI these days.</p>
<h3>Courses</h3>
<ul>
<li><strong><a href="https://developer.apple.com/videos/play/wwdc2020/10119">Apple WWDC Video: Introduction to SwiftUI</a></strong> — Start here and at least watch the first 10 minutes where it goes over SwiftUI layout basics. It pretty quickly starts going through states, interactions and gestures, which you might be better off learning more paced with some other resources if you&#x27;re just getting started.</li>
<li><strong><a href="https://developer.apple.com/tutorials/swiftui#swiftui-essentials">Apple: Introducing SwiftUI</a></strong> — Apple has their own tutorial for getting up to speed with SwiftUI, but if this is your very first time I personally don&#x27;t feel it&#x27;s that great and that following along with a video where things are described step by step might be better.</li>
<li><strong><a href="https://designcode.io/courses">Design+Code</a></strong> — This is where I started. Meng To and the team at Design+Code have several SwiftUI courses for all levels of experience. When I took the course there was only one and it was great for me to get a solid understanding of view layout basics.</li>
<li><strong><a href="https://cs193p.sites.stanford.edu/">Stanford CS193p - Developing Apps for iOS</a></strong> — Stanford has their own course covering SwiftUI, with all materials freely available online.</li>
<li><strong><a href="https://www.udemy.com/topic/swiftui/">Udemy SwiftUI courses</a></strong> — While I haven&#x27;t done any myself, there&#x27;s a lot of <a href="https://www.udemy.com/course/swiftui-masterclass-course-ios-development-with-swift/">highly-rated SwiftUI courses</a> on Udemy.</li>
</ul>
<h3>Hacking With Swift</h3>
<p>You can&#x27;t learn SwiftUI without coming across <a href="https://www.hackingwithswift.com/">Paul Hudson and his website Hacking With Swift</a>. It&#x27;s a goldmine of material and practically every Google search I had when I was getting started had one of his articles in the top results. I recommend subscribing to get access to more of his tutorials.</p>
<p>Aside from a plethora of articles, Paul also has several Swift-related books and two amazing, free courses that break down Swift and SwiftUI into bite-sized videos:</p>
<ul>
<li><a href="https://www.hackingwithswift.com/100/swiftui">100 Days of SwiftUI</a></li>
<li><a href="https://www.hackingwithswift.com/100">100 Days of Swift</a></li>
</ul>
<p>I dabbled with both but never fully finished them; I got too eager to start building my own project.</p>
<h3>Reddit</h3>
<p>There are a few solid sub-reddits I like to check occasionally to keep in the loop of things and sometimes share progress: <a href="https://reddit.com/r/SwiftUI">r/SwiftUI</a>, <a href="https://reddit.com/r/Swift">r/Swift</a> and <a href="https://www.reddit.com/r/iOSProgramming/">r/iOSProgramming</a>.</p>
<h3>Blogs</h3>
<ul>
<li><strong><a href="https://swiftwithmajid.com/">Swift with Majid</a></strong> by <a href="https://twitter.com/mecid">@mecid</a> — One of the first good Swift/SwiftUI blogs I found when just getting started. Lots of great articles written in an easy to digest way. Though some articles are definitely a bit advanced and not beginner friendly.</li>
<li><strong><a href="https://www.fivestars.blog/">Five Stars</a></strong> — An excellent resource from <a href="https://twitter.com/zntfdr">Federico Zanetello</a></li>
<li><strong><a href="https://peterfriese.dev/">Peter Friese</a></strong> — If you end up using Firestore for saving your data, Peter (who works on Firebase) has <a href="https://peterfriese.dev/swiftui-firebase-add-data/">some great tutorials</a> to get started.</li>
<li><strong><a href="https://www.swiftbysundell.com/">Swift by Sundell</a></strong> by <a href="https://twitter.com/johnsundell">@johnsundell</a></li>
<li><strong><a href="https://www.donnywals.com/the-blog/">Donny Wals</a></strong> — He also wrote a book on Core Data and a book on Combine.</li>
<li><strong><a href="https://swiftui-lab.com/">The SwiftUI Lab</a></strong> — Not as many recent posts these days but I read a few while learning.</li>
<li><strong><a href="https://sarunw.com/tags/swiftui/">Sarun Wongpatcharapakorn</a></strong></li>
<li><strong><a href="https://medium.com/tag/swiftui">Medium</a></strong> — I wish there was a better way to link to this, but there are some occasional good SwiftUI posts on Medium if you search by tag. <a href="https://betterprogramming.pub/search?q=swiftui">BetterProgramming</a> is one Medium publication to watch too.</li>
<li><strong><a href="https://www.vadimbulavin.com/">Yet Another Swift Blog</a></strong> — A bit more on the advanced side but some good Swift and SwiftUI topics here.</li>
<li><strong><a href="https://www.raywenderlich.com/3715234-swiftui-getting-started#toc-anchor-001">Ray Wenderlich</a></strong> — It&#x27;s not a blog, but a sort of professional developer subscription service. But they have plenty of free tutorials related to SwiftUI. My only gripe is that much of the content is written from the perspective of a developer trying out Swift/SwiftUI things, not as an overall beginner for mobile development. For example their intro to SwiftUI makes various references to UIKit development.</li>
</ul>
<h3>Newsletters</h3>
<ul>
<li>
<p><strong><a href="https://recreatecode.substack.com/archive?sort=new">Recreate Code</a></strong> — A newsletter with videos diving into using SwiftUI to build layouts of common UIs and apps from <a href="https://twitter.com/navdeep_ua">Navdeep Singh</a> and <a href="https://twitter.com/jsngr">Jordan Singer</a>.</p>
</li>
<li>
<p><strong><a href="https://www.avanderlee.com/">SwiftLee Weekly</a></strong></p>
</li>
<li>
<p><strong><a href="http://weekly.swiftwithmajid.com/">SwiftUI Weekly</a> by Majid Jabrayilov</strong></p>
</li>
<li>
<p><strong><a href="https://indiedevmonday.com/">Indie Dev Monday</a></strong></p>
</li>
<li>
<p><strong><a href="https://iosdevweekly.com/">iOS Dev Weekly</a></strong></p>
</li>
</ul>
<h3>GitHub & YouTube</h3>
<p>Whenever I&#x27;m really stuck on a problem and can&#x27;t find any relevant info on Google results, I usually turn to searching on YouTube and GitHub. I&#x27;m frequently surprised at what I&#x27;m able to find there that I wasn&#x27;t able to otherwise.</p>
<p>On GitHub you may find various examples apps showing the concepts you&#x27;re looking for. A few YouTube accounts that consistently have some SwiftUI content are <a href="https://www.youtube.com/channel/UC2D6eRvCeMtcF5OGHf1-trw">Code with Chris</a>, <a href="https://www.youtube.com/channel/UCbTw29mcP12YlTt1EpUaVJw">Sean Allen</a>, <a href="https://www.youtube.com/channel/UCK88iDIf2V6w68WvC-k7jcg">Rebeloper</a>, <a href="https://www.youtube.com/channel/UCsuV4MRk_aB291SrchUVb4w">Kavsoft</a> and of course <a href="https://www.youtube.com/channel/UCmJi5RdDLgzvkl3Ly0DRMlQ">Paul Hudson</a>.</p>
<h3>Tips from my experience</h3>
<p>So I just linked to a ton of resources. I wish there was one single thing I could recommend but for me I learned through a myriad of sources over time. Here are a few things I learned or wish I had known as I started getting the hang of Swift and SwiftUI:</p>
<ul>
<li>
<p><strong>Get inspired, find a project.</strong> I learn best when I have my own project to build instead of following tutorial after tutorial of a random app concept. If that&#x27;s you, it may be helpful to try to pick an area of interest and see if there&#x27;s a simple app you can build for it.</p>
<p>If you&#x27;re looking for app inspiration, or just want to discover new patterns or seek UIs to build yourself, I suggest continually checking the App Store and trying out lots of apps.</p>
<p>For me, that was a stock tracker app, <a href="https://stocketa.com">Stocketa</a>. (Which is currently in limited Testflight testing now as I continue development). I’ve been so impressed with what I’ve been able to accomplish purely with SwiftUI in this app.</p>
</li>
<li>
<p><strong>Learn a few Xcode shortcuts.</strong> I wish I had taken a bit more time to learn more about Xcode&#x27;s capabilities when I got started. There are so many handy shortcuts and settings that can make your life easier.</p>
<p>Read this post on <a href="https://peterfriese.dev/xcode-shortcuts/">Xcode shortcuts from Peter Friese</a>. Some of my faves:</p>
</li>
<li>
<p>Auto-indent code: <strong>⌃ (Control) + i</strong>.</p>
</li>
<li>
<p>Refresh the preview canvas: <strong>⌘ (Command) + ⌥ (Option) + p</strong>.</p>
</li>
<li>
<p>Open a file quickly: <strong>⇧ (Shift) + ⌘ (Command) + o</strong>.</p>
</li>
<li>
<p>Customize Xcode to make <strong>⌘ (Command) + d</strong> delete the current line.</p>
</li>
<li>
<p><strong>Building a custom bottom sheet is harder than it looks.</strong> Lots of app these days use nice, custom bottom sheets with varying capabilities. In SwiftUI we have the native <code>.sheet()</code> but you can&#x27;t control things like how high it opens. I built a few custom ones and they&#x27;re harder to get working flawlessly than you&#x27;d think. Especially if you want to be able to have multiple resting heights and seamlessly transition to scrolling with a single gesture when expanded.</p>
</li>
<li>
<p><strong>Use the <code>value</code> attribute for <code>.animation()</code></strong> for more control over when something animates. I use this everywhere. I only discovered it after filing a SwiftUI bug with Apple and the Apple engineer suggested using this for a particular issue I had.</p>
</li>
<li>
<p><strong>Use a view model.</strong> Eventually you&#x27;ll find yourself with increasingly more logic and functions in your views. It&#x27;s time to move that to a separate View Model file. An example would be a class that is an ObservableObject that your view uses. Read up on MVVM (Model-View-ViewModel) for more info on this architectural pattern.</p>
</li>
<li>
<p><strong><code>.mask()</code> is very useful.</strong> Especially if you&#x27;re using gradients to color certain elements or if you need to apply an alpha gradient on a view. You can also use stacks to use multiple elements in your mask.</p>
</li>
<li>
<p><strong>Customize SVG assets with "Template Image" render setting.</strong> Want to add an SVG to your Assets.xcsassets catalog and then be able to change its color directly in SwiftUI? You&#x27;ll need to set "Render As" to "Template Image" in Xcode.</p>
</li>
<li>
<p><strong>The <code>@AppStorage</code> property wrapper is your friend</strong> when you need to store tiny, non-vital local settings for the user. Out of the box it only supports a few value types, but you can <a href="https://lostmoa.com/blog/SaveCustomCodableTypesInAppStorageOrSceneStorage/">follow this guide on RawRepresentable</a> to store any type of data to it.</p>
</li>
<li>
<p><strong>The <code>resetTransaction</code> property of <code>@GestureState</code> can be handy</strong> to define the animation to use when a user releases their finger when doing a gesture (as opposed to applying a general animation for the entire view/object).</p>
</li>
<li>
<p><strong>Get to know the <code>.simultaneousGesture()</code> modifier.</strong> If you&#x27;re doing anything advanced with gestures, it&#x27;s helpful to know that SwiftUI can help you manage multiple gestures with this view modifier. There&#x27;s also <code>.highPriorityGesture()</code>.</p>
</li>
<li>
<p><strong><code>.contentShape()</code> is your friend if some views are not tappable</strong>. Every so often you&#x27;ll into a situation where you&#x27;re trying to make a view tappable (either inside a button or with <code>.onTapGesture()</code>) and only a certain part of the view will be tappable. By placing <code>.contentShape()</code> on this view, say after any padding or other visual modifications you have, you&#x27;ll make the entire area tappable.</p>
</li>
<li>
<p><strong>Disable interaction with <code>.allowsHitTesting(false)</code> when needed</strong>. This may come in handy when you&#x27;re doing more advanced things with gestures.</p>
</li>
<li>
<p><strong>Need more performance? Start by splitting your view into smaller sub-views.</strong> There are a lot of reasons why your app could see some slow downs or have some janky, frame-dropping behavior. But in my experience the best place to start is abstracting your larger views into smaller ones. SwiftUI updates a view whenever any part of the view state changes, so by splitting your view into a set of smaller views, you&#x27;re giving SwiftUI the ability to only update smaller views depending on what data changed state.</p>
</li>
<li>
<p><strong>Use <code>.compositingGroup()</code> to help with animation and rendering issues.</strong> This modifier basically applies view modifiers on the ancestor views before rendered. A bit hard to describe but in particular it&#x27;s helpful when dealing with opacity animations or shadows. And if the view doesn&#x27;t need to be interactive, there&#x27;s and <code>.drawingGroup()</code> which is similar but flattens your views and uses Metal rendering for increased performance.</p>
</li>
<li>
<p><strong>Consider caching slow functions with memoization.</strong> This only works for certain types of functions, but something worth knowing about. Here&#x27;s a <a href="https://www.hackingwithswift.com/plus/high-performance-apps/using-memoization-to-speed-up-slow-functions#manual-memoization">great article on memoization</a>.</p>
</li>
<li>
<p><strong>Core Data (storage) is not for everyone.</strong> I got it working in my early versions of Stocketa but then I wanted to have it sync with iCloud and found it to be slow and unreliable. The only answer was to do a lot of custom syncing another way. I moved to Firebase Firestore and was much, much happier (after figuring out how to best flatten my data structure a bit).</p>
</li>
<li>
<p><strong>If you just can&#x27;t get it to work.. quit Xcode.</strong> If you&#x27;ve tried everything and it should work but doesn&#x27;t, try quitting and reopening Xcode. Try "Clean Build Folder" in Xcode. Try clearing Xcode cache files (I like <a href="https://apps.apple.com/us/app/devcleaner-for-xcode/id1388020431?mt=12">DevCleaner.app</a> for this). If none of that works, maybe it&#x27;s Apple&#x27;s bug:</p>
</li>
</ul>

<blockquote>A Tweet embed was not displayed. Read this article in a browser to see it as intended.</blockquote>]]></description>
            <link>https://paulstamatiou.com/getting-started-with-swiftui</link>
            <guid isPermaLink="true">https://paulstamatiou.com/getting-started-with-swiftui</guid>
            <dc:creator><![CDATA[Paul Stamatiou]]></dc:creator>
            <pubDate>Wed, 02 Jun 2021 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Thoughts on email hosting]]></title>
            <description><![CDATA[<p>It happens to me all the time. I have some idea or other need and before I know it I&#x27;ve registered a few new domains. Eventually I may need to setup some email addresses on those domains. Then I need to decide if I really want to pay ~$5-6 per month to setup email by setting it up with Google Workspace Essentials (née G Suite), Fastmail, ProtonMail or their ilk.</p>
<p>Before you know it you have a handful of different email addresses on different domains for various needs and you&#x27;re paying $50+ per month for that privilege. And let&#x27;s be honest, most of these addresses get just a few emails per week, if any.</p>
<blockquote>
<p>There&#x27;s really no one that makes it easy to own/manage lots of email addresses.<br/>
I probably have 10 for various needs/projects, all on custom domains, and I love G Suite but it&#x27;s ~$6/mo per email. I use Fastmail for some too but it&#x27;s a hassle to setup/manage them all.<br/>
— Paul Stamatiou (@Stammy) <a href="https://twitter.com/Stammy/status/1372558128399708163?ref_src=twsrc%5Etfw">March 18, 2021</a></p>
</blockquote>
<p>It&#x27;s 2021. While email is becoming less and less the backbone of any new venture, it&#x27;s still a core and required piece of being an Internet citizen. It shouldn&#x27;t be this complex to manage and setup email for all of your domains.</p>
<p>There are definitely benefits to keeping all of our email accounts entirely separate:</p>
<ul>
<li>You want to separate business from personal.</li>
<li>You want each domain to have its own password and 2FA/security key setup for security. Not great if you have everything under one account or admin control — if one account gets hacked, they&#x27;re all hacked.</li>
</ul>
<p>While certain email providers can let you maintain separate user accounts together, they all seem to have the same sort of admin setup where an admin account can still control user accounts. That&#x27;s not quite what I&#x27;m looking for.</p>
<p>For something so common, it should be easy and not cost an extra $5 per month just to setup one more custom domain and a few addresses. I often don&#x27;t need all the assorted Google Workspace functionality, in fact I often prefer not having yet another Google account show up in the user account dropdown.</p>
<p>What I&#x27;m getting at is nothing novel: just easy and reliable turnkey email hosting. But a solution that is optimized for keeping accounts separate for security but somehow allowing for one account to pay for them. Similar to how you need to fetch an auth code to transfer a domain, perhaps you just need a payment code to setup billing.</p>
<p>You can go down the rabbit hole of self-hosting (<a href="https://thehelm.com">Helm</a> is an interesting solution here but I don&#x27;t want the server inside my house) and dealing with maintenance, deliverability issues and reliability. That&#x27;s not something I&#x27;m interested in.</p>
<p>There&#x27;s also a breed of services like <a href="https://migadu.com">Migadu</a> that offer one place for you to manage your domains and setup hosting for each. It actually seems exactly what I want, though I do have one concern about having one service, under the same login, manage everything for all email hosting for every domain I own. It just feels like it&#x27;s consolidating everything and making it dramatically easier for an attacker to gain access to everything in one go. It would be interesting if they had a way to have one payment account, but individual, 2FA logins for each domain (basically removing the notion of any sort of organization admin that can control all domains).</p>
<h3>What about email aliases?</h3>
<p>I&#x27;m holding off for an ideal solution like that but for now, there&#x27;s an adjacent set of solutions for slightly different needs. If you don&#x27;t absolutely <em>need</em> to have emails/domains kept separate and don&#x27;t mind mixing up the inbox, you can use email aliases.</p>
<p>Aliases let you send and receive email for another address on another domain, but all inside a different email inbox. So if your primary G Suite email is <code>yourname@domain.tld</code>, you can have an email alias that lets you send and receive email from that inbox for your other email account <code>nickname@otherDomain.tld</code>. There&#x27;s just one inbox though, but it&#x27;s up to you to filter and organize as you please.</p>
<p>This could be handy for emails/domains you have that are related: for example you may have a business domain and then a few emails on a different domain for the product owned by the business.</p>
<p>I recently discovered <a href="https://improvmx.com">ImprovMX.com</a> thanks to some replies to that tweet above. ImprovMX makes setting up email forwarding for any custom domain easy and I&#x27;ve used it for one of my domains so far. The only thing I don&#x27;t feel great about is that using this method, you&#x27;ll have to specify an SMTP server to send your email with and unfortunately that connection is password-only, no two-factor auth (even if 2FA was feasible you&#x27;d probably have to be asked with every email you send and email clients aren&#x27;t designed with that in mind).</p>
<hr/>
<p>Separately, someone also mentioned <a href="https://simplelogin.io">SimpleLogin.io</a>, which helps you make unique, temporary email address aliases. This is similar to how Sign in with Apple can hide your real email from the service if you enable the "Hide my email" setting. With SimpleLogin you can create all sorts of aliases that forward email to your real email, and completely hide your address. You can of course disable/delete the alias at anytime. I think I&#x27;ll be trying it out in the future when signing up for new things.</p>]]></description>
            <link>https://paulstamatiou.com/thoughts-on-email-hosting</link>
            <guid isPermaLink="true">https://paulstamatiou.com/thoughts-on-email-hosting</guid>
            <dc:creator><![CDATA[Paul Stamatiou]]></dc:creator>
            <pubDate>Sat, 20 Mar 2021 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Building]]></title>
            <description><![CDATA[<p>There’s no need to preface how wretched, horrible and hard 2020 was for all of us with the global pandemic and all that changed in the world. Most of us stayed home an insane amount and refrained from any kind of travel, domestic or international.</p>
<p>My girlfriend Katherine and I had plans for some big trips this year, which we of course shelved. In the past one of my most time-consuming hobbies was making really detailed photosets of my trips. Here&#x27;s one of my favorite: <a href="https://photos.paulstamatiou.com/africa/southern-serengeti-tanzania/">Southern Serengeti, Tanzania</a>.</p>
<p>I would spend months of spare time culling and processing thousands of captured shots and video clips then designing and building photosets around them. They were definitely a passion project, almost entirely for myself.</p>
<p>Over the last few years I was usually juggling 1 or 2 side projects: either writing some long article for this blog, or working on some large travel photoset. This year I didn&#x27;t feel strongly enough about any particular topic to deep dive into writing a long article about, nor did I have any travel photos to work on.</p>
<p>I felt the need to do or learn <em>something</em> to keep me occupied (which I even feel a bit weird about, I find it hard to just relax and do nothing). I had always been curious about Swift and SwiftUI but really thought that was an unattainable goal for me to be proficient at. I had very, very briefly dabbled with Objective-C development years back and was turned off by the whole thing. It was so confusing to me at the time.</p>
<p>In March I decided to spend some time diving into Swift and SwiftUI. After reading some cursory guides and tutorials, I needed a project to dive into. That&#x27;s how I learn best. I began working on a personal itch: having an easier, more approachable and elegant way to track my stock holdings. Since then I have probably spent 10-15ish hours per week for the last ~9 months learning and building my first real iOS app, <a href="https://stocketa.com">Stocketa</a> (Coming in 2021.. <a href="https://stocketa.typeform.com/to/gl6WWE">stay in the loop</a>).</p>
<p>It wasn’t all kittens and daisies. There have been many frustrating back-to-back days and weeks where I’ve been stuck on a problem or not been happy with a solution so I’ve redesigned and rebuilt entire features. I think I’ve rebuilt the holdings view of my app probably 4-5 times by now.</p>
<p>I really, really love building for iOS. I love being able to control the entire lifecycle of a product: idea, sketches, designs, coded and working on a real device with native iOS code.</p>
<p>I can spend an insane amount of hours on a particular animation or flow and get exactly to the intended fidelity and experience I’m aiming for.</p>
<p>Now this has me thinking that as long as I have some app that I’m working on as <a href="https://paulstamatiou.com/side-projects/">my main side project</a>.. I’m not so sure I’ll ever go back to spending months working on detailed photosets. While photosets are largely just for me, an app is a different beast entirely.</p>
<p>I can distribute and have others try out and hopefully find a recurring use for it. I’m not assuming my app or future apps will make me any money but there’s something nice about being able to share your work with others that they will be able to use with their own data, unlike my website where it’s a more defined one-way relationship.</p>
<p>But I digress, I’m sure I’ll find some lightweight way to share photosets in the future, but it likely won’t be to the level of care they have been in the past. Though I do plan to find time to pause working on the app to write about things I’ve learned and share more progress.</p>
<h3>Designing and developing</h3>
<p>Throughout the year all of this has had me thinking more about my career in the future.</p>
<p>When I went to college in 2004 I started out as an electrical engineering major. I grew up soldering and building little circuit boards so it felt like the natural thing to do. I was never really into software. Long story short, that changed for me and I became fascinated with the web, design and software world, eventually changing switching to a major that was a hybrid of design and computer science.</p>
<p>I graduated college not thinking I was a good designer <em>or</em> developer. I did both as needed with my first few jobs. They were startups, so wearing many hats is expected anyways.</p>
<p>I love working on design strategy, vision, visual design, interactions and motion just as much as learning how to setup a view model and pipe data through my app and having my designs come to life.</p>
<p>At times I feel like I’m hiding part of myself at my day job as I don’t really get to put all of my technical skills to use, aside from some interactive mobile prototypes (and I am trying to fit in more SwiftUI prototypes at work when I can).</p>
<p>This is not a dig at my employer or anything; just commentary on what I view as a slightly evolving landscape where development tools and frameworks have become so much more approachable that the definition of a "developer" is finally more accessible. This is a good thing! Designers that care so much about the end-to-end experience can now have greater control over the end result. I could have never been an iOS developer in the UIKit and Objective-C days.</p>
<p>I have no interest in going into full-time software engineering as a job. I don’t want to get caught up with process, semantics, code style and code reviews, I want to obsess over the (front-end) details and interactions until it’s right.</p>
<p>There are more and more design engineering roles these days but I feel like I would lose part of my autonomy as a designer in helping define the strategy, solution and experience. And some companies have design engineering roles that are much more on the engineering side where you’re going to be working in a production app. That’s definitely not me (please no UIKit!).</p>
<p>A common rebuttal to this is just "work at a startup!"—I am definitely jaded on that. Here’s a <a href="http://danluu.com/startup-tradeoffs/">good read</a> on the topic. I just think that the ROI is often so messed up with startups. Especially if you’re the first design hire and get to do all the fun and challenging 0-60 stuff. You’ll be putting in as much time and sweat as the founders but get 100x less compensation.</p>
<p>There&#x27;s nothing I need solved now, nor am I looking for a job (the opposite, I&#x27;m very happy at Twitter).. just wanted to share that I really love building, from design to polished app.</p>]]></description>
            <link>https://paulstamatiou.com/building</link>
            <guid isPermaLink="true">https://paulstamatiou.com/building</guid>
            <dc:creator><![CDATA[Paul Stamatiou]]></dc:creator>
            <pubDate>Thu, 31 Dec 2020 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[The Squire]]></title>
            <description><![CDATA[<p>I&#x27;m no stranger to keeping track of notes and documents across a myriad of apps, services and digital to-do lists. I use Notion, Apple Reminders app, Bear app, sometimes I use Ulysses, random plaintext TextEditor files and Google Docs.</p>
<p>But it really doesn&#x27;t matter what I do with my digital documents as I always end up having some pen and paper on my desk at all times to take notes, quickly sketch designs and manage more to-do lists. I usually rely on plain printer paper or a Moleskine notebook.</p>
<p>I was wandering around SoHo in Manhattan a few weeks ago when I went to a small boutique pen and stationery store ("Goods for the Study" on Mulberry St). I eventually came across the <a href="https://www.baronfig.com/tools/squire/metals?precious%20metals=stainless%20steel">BaronFig Squire</a> and it was by far the best pen I had tried out there.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2020/12/baronfig-squire-pen.jpg" alt="BaronFig Squire Pen" />
<small>Stainless Steel BaronFig Squire</small>
<p>First off, it&#x27;s a pricey pen. The stainless steel one I got is $95 but it starts at $55 for other metals and colors. But it has impeccable build quality: it&#x27;s a twist-to-open style pen and there is absolutely no wiggling or play in the mechanism. It&#x27;s also rather heavy which I appreciate. And finally the ink rolls out <em>very</em> smoothly, no matter what angle you&#x27;re using it at.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2020/12/baronfig-squire-pen-2.jpg" alt="BaronFig Squire Pen" />
<small>It has this subtle sword graphic along with their logo, though I wish it was blank.</small>
<p>It uses "Parker capless" style ink refills and I was readily able to find a few styles of compatible ink refills on JetPens.com: Schmidt P8126, Ohto Flash Dry PG-105NP, Uni SXR-600 Jetstream.</p>
<p>I purchased all of those refills looking for something slightly more fine but still ended up going back to the ink it came with (looked like a rebranded Schmidt P8126 anyways). My only complaint with it is that the default ink is ever so slightly too thick for my taste but I love how easily it comes out at all angles.</p>]]></description>
            <link>https://paulstamatiou.com/writing-baronfig-squire</link>
            <guid isPermaLink="true">https://paulstamatiou.com/writing-baronfig-squire</guid>
            <dc:creator><![CDATA[Paul Stamatiou]]></dc:creator>
            <pubDate>Mon, 21 Dec 2020 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Hello, RSS]]></title>
            <description><![CDATA[<p>It has been years since I’ve used RSS to keep tabs on interesting blogs I’ve found and websites I like. Social media took over and blogging went from being ubiquitous to being more of a novelty. Google shutdown FeedBurner 8 years ago; Google Reader was shuttered shortly after.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2020/10/copyright-paulstamatiou_com-DSC05584-1000.jpg" alt="Feedbin on my iPad Pro" />
<small>Feedbin on my iPad Pro</small>
<p>I used to follow a few hundred personal weblogs but eventually that number dwindled down as people stopped blogging. My consumption time naturally adjusted to focus on other sources like Twitter. Despite RSS standing for Really Simple Syndication, it couldn’t hold a candle to simpler and more interactive services… things everyone has like Twitter, Reddit, or even the Apple News app.</p>
<p>And then in recent years individual email newsletters became more mainstream with services like TinyLetter and Substack making it easy for people to build and reach their own community as well as monetize.</p>
<p>RSS has been considered dead to all but the most dedicated and loyal.</p>
<h3>Modern RSS readers</h3>
<p>It’s now almost 2021. Things I want to keep up to date with are now all over the place. My inbox is littered with various newsletters. I have to constantly manage Gmail filters (and remember to check them) for various subscriptions. While I get my fill of news and updates about interests from Twitter and some Reddit, I follow a lot and it’s easy to miss something.</p>
<p>This has been especially true in 2020 where there’s been enough political and pandemic news to dominate any platform. And beyond that, there are times when I want to step away from feeds of non-stop bad world news and go to a place that’s laser-focused on content from a few sources I’ve picked.</p>
<p>I decided to take a look at the current state of RSS readers in 2020. I was in for a surprise.</p>
<p><strong>RSS readers have evolved.</strong> That’s not even a good term for them now as they do so much more. They know that you get your news from multiple sources: email newsletters, Twitter, podcasts, YouTube and of course RSS too. They know that there’s often a deluge of updates you need help sifting through or that you need help keeping track of articles you find elsewhere.</p>
<p>I looked at what RSS readers were popular by checking out my website analytics. I’ve always seen Feedly and Newsblur in there as referrers, but have also started to see Inoreader as well. Feedly has a robust offering, and it was a product I used a bit many years ago. It has a higher price point than some other services but in the end I just didn’t like the design. It felt busy. Like another inbox I had to manage instead of a calm place I can go to relax, similar to firing up my Kindle. I felt the same way about Inoreader and others.</p>
<h3>Feedbin</h3>
<p>Then I found Feedbin. I very quickly knew this is what I had been looking for. First off, it&#x27;s not free. Feedbin is $5 per month. But on that note I don&#x27;t think any RSS readers with any unlimited email newsletter capability are free.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2020/10/copyright-paulstamatiou_com-feedbin-newsletter-address.jpg" alt="Feedbin Newsletter email address" />
<small>Feedbin has a custom email address to use for newsletters.</small>
<p>Newsletter functionality is easy to setup. In the settings you&#x27;ll find your own custom <code>@newsletters.feedbin.com</code> email address to use to subscribe to any newsletters you like.</p>
<p>There&#x27;s not much to the user interface but there&#x27;s attention to detail in a few places. I was pleasantly surprised to see that Feedbin has several Hoefler & Co typefaces to choose from. I then realized that Feedbin can even extract the full-text of any RSS post from the website directly, even when the feed only provides partial content.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2020/10/copyright-paulstamatiou_com-IMG0047.jpg" alt="Feedbin on my iPad Pro" />
<small>Feedbin theme and readability settings</small>
<p>Feedbin also has a browser bookmarklet so you can easily send any article you find anywhere on the web to Feedbin for reading later. I find myself using this quite a bit.</p>
<p>There&#x27;s also some basic "actions" functionality. Actions work very much like Gmail filters. You provide some basic search terms, specify what tags and feeds to look in and then how to act on it. Right now the set of actions is pretty limited: you can have posts marked as read or starred. There&#x27;s no way to entirely filter something out of a feed unfortunately. You can, however, setup push notifications for specific terms with <a href="https://feedbin.com/notifier">Feedbin Notifier</a>.</p>
<p>I use a few actions to star particular terms in high-volume feeds I follow. For example, I use it to search a few iOS-related subreddits for terms I care or am learning about (recently that was anything iOS 14 with Firebase) and star posts for me to browse through later.</p>
<p>That&#x27;s pretty much it. I use Feedbin every morning on my iPad Pro with my morning coffee. It&#x27;s a focused, dedicated place for me to catch up on a particular set of curated blogs, newsletters and news sources without getting distracted. And it helps unburden my inbox.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2020/10/copyright-paulstamatiou_com-IMG0050.jpg" alt="Feedbin Settings menu on my iPad Pro" />
<p>Feedbin only does a few things and I appreciate that it&#x27;s a relatively focused experience; not some overbearing tool. However, I do find myself wanting it to be a bit smarter in places.</p>
<p>I&#x27;d love to be able to tell it more generally what niche topics and phrases I&#x27;m interested in and have it more proactively prioritize these for me as well as learn as I engage with posts. I&#x27;d love to be able to apply those filters across links shared in Tweets from people I follow. And I&#x27;d like it to help me discover high-quality blogs about the topics I&#x27;m interested in.</p>
<p>I&#x27;d also like to be able to globally disable unread counts. I don&#x27;t want to have that kind of stressful inbox-like experience. I just want to be able to dip in and out as I please and not feel like I&#x27;m behind, as has always been my relationship with RSS readers in the past: an overbearing, incessantly incrementing unread counter.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2020/10/copyright-paulstamatiou_com-DSC05572-1000.jpg" alt="Feedbin on my iPad Pro" />
<small>Love my Heath mugs</small>
<p>Feedbin has an iOS app but there are lots of other RSS readers that let you log into your Feedbin account so you can maintain a synced consumption experience across devices. <a href="https://ranchero.com/netnewswire/">NetNewsWire</a>, <a href="https://reederapp.com/">Reeder</a> and <a href="https://www.goldenhillsoftware.com/unread/">Unread</a> are some of the popular ones.</p>
<p>If you follow any great blogs on the topics of iOS/SwiftUI development, design, software, startups or product development, I&#x27;d love to find more sites to subscribe to. Let me know on <a href="https://twitter.com/Stammy">Twitter</a> or <a href="https://paulstamatiou.com/contact">email</a>.</p>]]></description>
            <link>https://paulstamatiou.com/hello-rss</link>
            <guid isPermaLink="true">https://paulstamatiou.com/hello-rss</guid>
            <dc:creator><![CDATA[Paul Stamatiou]]></dc:creator>
            <pubDate>Sun, 18 Oct 2020 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Side projects]]></title>
            <description><![CDATA[<p>I have had some kind of side project for as long as I can remember. They have quenched my curiosity about new technologies and tools, kept my design and development skills fresh and often given me something to put out into the world.</p>
<p>Most of the time my side project has been this website. Redesigning it, debugging it, optimizing it, writing for it, shooting photos for it, editing photos for it, building out new functionality for it, managing servers and storage needs, et cetera.</p>
<p>For the last 6 months I have been working on a new side project (<a href="https://twitter.com/Stammy/status/1307353111896436739">thread</a>), a simple stocks-related app. It has helped me dive head-first into the world of Swift and SwiftUI, learn about Core Data, Cloudflare Workers, Sign In With Apple, TestFlight, Stripe Atlas, Firebase, Firebase Cloud Functions, Express.js, Hugo, Netlify and more. Not to mention that it has helped me sharpen my mobile, motion and visual design skills further.</p>
<p>Side projects give me a constraint-free creative outlet. I am the product manager, the researcher, the mobile designer, the web designer, the motion designer, the brand designer, the marketing designer, the mobile engineer, the backend engineer, the reliability engineer…</p>
<p>I can spend a month working on the animations of one view if I want. Everything is a blank canvas where I can try out different aesthetics, interactions, copy, motion and more. I can break as many design rules as I want. There are no gatekeepers or stakeholders.</p>
<p>I don&#x27;t set goals or deadlines for side projects—I fear they will start to feel like work then. It doesn&#x27;t matter it if takes me 4 weeks or <a href="https://twitter.com/Stammy/status/955482813825892352">4</a> <a href="https://twitter.com/Stammy/status/1186260455519600641">months</a> to write a blog post or even longer to <a href="https://twitter.com/Stammy/status/1034477412589830144">publish trip photosets</a> or ship an app. I’m just looking to make things the way I want.</p>
<p>Side projects keep me fulfilled on so many levels. I can’t imagine not having one on hand (well, ask me again when I have kids).</p>]]></description>
            <link>https://paulstamatiou.com/side-projects</link>
            <guid isPermaLink="true">https://paulstamatiou.com/side-projects</guid>
            <dc:creator><![CDATA[Paul Stamatiou]]></dc:creator>
            <pubDate>Mon, 05 Oct 2020 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Moving from Amazon S3 to Netlify]]></title>
            <description><![CDATA[<p>I recently began using <a href="https://www.netlify.com/">Netlify</a> for some of my side projects. Netlify is a modern web hosting provider that integrates a mix of offerings like a fast CDN and customizable build system. You specify how your website or project should be generated (ideal for static site generators like Jekyll) and all you do is run a git push when you&#x27;re ready to publish.</p>
<p>Netlify will automatically generate and deploy your site, optimize assets and images, provide access control and more. It also brings some desired functionality to static sites like <a href="https://www.netlify.com/products/forms/">built-in form handling</a> and server-side analytics.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2020/10/copyright-paulstamatiou_com-netlify-cd.png" alt="Netlify website settings" />
<small>Netlify website settings</small>
<p>While I was only using it for a basic landing page, I quickly began to admire how convenient it made the publishing process. Long story short, I moved this website to Netlify from my previous setup utilizing Amazon AWS S3 with CloudFront.</p>
<h3>My previous AWS S3 + Cloudfront setup</h3>
<p>I have been running this site for over 15 years now. The first few years I had a WordPress blog that I served on a bunch of devices ranging from a G4 Mac Mini in my dorm to a shared server and then to a VPS. Several years into that I wanted to change how I was publishing. I hated constantly updating the software due to security issues, keeping my VPS operating system and packages up to date and dealing with MySQL database backups (one of my early articles was about writing a bash script to save a <a href="https://paulstamatiou.com/how-to-bulletproof-server-backups-with-amazon-s3/">WordPress MySQL database dump to Amazon S3</a>).</p>
<p>I migrated my WordPress blog to Jekyll in late 2010 as part of my desire to simplify some of those performance and maintenance concerns. With Jekyll I had a site made up of fully static files and no database to worry about. I hosted my Jekyll site with Apache on an Ubuntu VPS for a while then landed on a Heroku setup with Rack::Static for a few years.</p>
<p>I eventually ended up <a href="https://paulstamatiou.com/hosting-on-amazon-s3-with-cloudfront/">hosting my site directly on S3 with CloudFront</a> and AWS Route53 for DNS. I favored this setup for its pure speed and lack of a real server I would have to manage in any capacity. Having everything on your site served at the edge directly from a CDN is a big deal. I remember receiving a few emails from readers outside the U.S. saying they noticed a performance boost on my site.</p>
<p>But the S3/CloudFront route felt like a hack. I relied on a Ruby gem to manually configure redirects (years ago I changed my permalink structure and have about a thousand redirects I need to keep around for old links) as well as invalidate CloudFront files each time I updated them. I also had to manage the site generation myself before deploying. Not a huge deal but it did mean I had to ensure I ran a few commands in the terminal in the correct sequence before deploying, and hanging around the terminal to ensure everything worked properly. I knew I needed to find a better solution when the gem I used for S3 deploys went into an unmaintained state.</p>
<h3>Why didn&#x27;t I migrate earlier?</h3>
<p>I first heard of Netlify several years ago. It seemed interesting but honestly I was not comfortable relying on a product from a relatively new startup for something as critical as hosting my sites.</p>
<p>Netlify the product kept getting better and Netlify the company kept growing, both in terms of employees, funding and customers. It was time to take a closer look.</p>
<p>At first glance I didn&#x27;t think Netlify was anything special. A hosting service that builds your site/app with a git hook before deploying was nothing new. And I did not even want that functionality at first. When I work on my long posts I commit to git dozens and dozens of times before publishing. I want my drafts backed up, but I also didn&#x27;t want to have to bother with a separate git branch for example.</p>
<p>Fortunately, there are several ways to manage your deploys with Netlify. Though for now I do have the default deploy-on-git-push behavior.</p>
<h3>Moving to Netlify</h3>
<p>The first step was authenticating my GitHub repository for this blog and seeing if Netlify could build it and deploy to a temporary site (Netlify issues you a subdomain of your choice on their <code>netlify.app</code> domain). This part took some trial and error with my Jekyll setup.</p>
<p>First, I needed to ensure all the Ruby gems I relied on were in my Gemfile so Netlify could install from that. I had to change a few things there. Second, I needed to find out how to get my SCSS and Coffeescript/JS generated. I figured I could just add the commands I usually run inline with the regular <code>jekyll build</code> command.</p>
<p>This part took some more trial and error. I couldn&#x27;t get it to run my Grunt (JavaScript task runner) commands. I used Grunt to compile, optimize and minify my SCSS, Coffeescript and JS files. For SCSS, I decided to move away from my Grunt setup and just use the <code>jekyll-sass-converter</code> Jekyll plugin to handle this for me easily. As for the Coffeescript, I used this as an opportunity to go back to JS files—something I had been wanting to do.</p>
<p>But that still left me with the task of how to concatenate and minify my JS files. Netlify has built-in asset optimization to do exactly this. It detects a series of <code>script</code> tags in your markup and bundles them all together to serve as one versioned file. This worked at first, then I realized that it wasn&#x27;t actually minifying the JS. I&#x27;m guessing it&#x27;s an issue on Netlify&#x27;s side after seeing someone else with the same issue, so I&#x27;ll have to revisit that later. For now I still have to compile the JS locally before deploying whenever I change it.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2020/10/copyright-paulstamatiou_com-netlify-asset-optim.png" alt="Netlify asset optimization settings" />
<small>Netlify asset optimization settings</small>
<p>The last thing I had to figure out was how Netlify handled redirects. There are two ways to configure redirects on Netlify, either with the <code>netlify.toml</code> config file or a separate plaintext <code>_redirects</code> file. I went with the latter as the format was similar to what I was using to manage URL redirects with the <a href="https://github.com/laurilehmijoki/s3_website">s3_website</a> gem. It only took a few find and replace all commands to the redirects file formatted properly.</p>
<p>I want to revisit the way I&#x27;m doing redirects (over 1,000+ for individual old articles when I changed my URL format years ago) and use a one-liner <a href="https://docs.netlify.com/routing/redirects/redirect-options/#placeholders">as described</a> in the documentation. Something like this:</p>
<pre><code class="language-plaintext"># I have lots of redirects like this for older posts
/2005/09/13/nero-7-announced    /nero-7-announced

# Will move to something like this
/:year/:month/:date/:slug  /:slug
</code></pre>
<p>At this point I had the site successfully building and deploying on Netlify. Here&#x27;s what my <code>netlify.toml</code> file looks like below. My setup is fairly basic so everything here can be controlled on the Netlify website as well.</p>
<pre><code class="language-bash">[build]
  publish = "_site/"
  command = "jekyll build"
[build.processing]
  skip_processing = false
[build.processing.css]
  bundle = true
  minify = true
[build.processing.js]
  bundle = true
  minify = true
[build.processing.html]
  pretty_urls = true
[build.processing.images]
  compress = false
</code></pre>
<p>The only thing left was updating the DNS to point to Netlify. To make this as smooth as possible I first logged into AWS and visited the Route53 dashboard to see all the DNS records attached to my domain. One by one I added the exact same DNS records to Netlify&#x27;s DNS. There there were quite a few records as I use both G Suite and Amazon SES on this domain.</p>
<p>I waited a while for Netlify&#x27;s DNS servers to add those rules and then I made the final change to update the DNS servers on the domain to point to Netlify&#x27;s DNS servers. Moments later the domain started loading my site on Netlify and then after that the SSL certificate was running.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2020/10/copyright-paulstamatiou_com-netlify-deploy-log.png" alt="Netlify dashboard showing a completed build and deploy." />
<small>Netlify dashboard showing a completed build and deploy.</small>
<h3>A note about media uploads</h3>
<p>While I migrated my blog to Netlify, I still keep my media assets hosted separately with S3 with CloudFront as I have for many years. I originally did this for a few reasons I mention on my <a href="https://paulstamatiou.com/about-this-website/#photos">About this website page</a>. The main one being that I don&#x27;t want ~30GB of media in my main git repository.</p>
<p>Netlify has a solution for this with their <a href="https://docs.netlify.com/large-media/overview/">Large Media feature</a> that uses Git LFS to store media, but I haven&#x27;t looked into that too much.</p>
<h3>Netlify first impressions</h3>
<p>I&#x27;m only a week into my new Netlify setup but I&#x27;m really loving it so far. Here are some of my initial thoughts:</p>
<ul>
<li><strong>Worry-free deploys:</strong> I&#x27;m coming around to this build system way of pushing git and knowing it will do everything it needs to build, optimize and deploy. I had something similar for my staging site back when I was writing on my iPad Pro and before I had my code-server VPS—each push would trigger AWS CodeBuild to deploy to a CloudFront distribution. Though that wasn&#x27;t a great experience for a staging server I was using for quick previews (having to wait a minute or more before the deploy is done), it&#x27;s fine for regular production deploys. I should also mention that with Netlify I can easily rollback to a previous deploy if needed.</li>
<li><strong>Built-in form handling:</strong> This was a really, really nice perk. With a static site hosted on S3 there was no backend that could accept any contact form POSTs; I had to use a hosted contact form from another service. Netlify has some magic attributes like <code>data-netlify="true"</code> you can apply to forms to get form handling and spam prevention.</li>
<li><strong>Asset optimization:</strong> I would love nothing more than to ditch all of my local asset pipeline management like concatenating CSS/JS files and minifying. Netlify handles this all for you (though as I noted I couldn&#x27;t get it to minify my JS for some reason but I&#x27;m sure that will be resolved soon).</li>
<li><strong>Server-side analytics:</strong> This is neat. Previously if I wanted server-side analytics I would have to enable S3/CloudFront logging and then use a tool (either paid or self-host) to read through the logs. While I don&#x27;t think I&#x27;ll use it forever as it&#x27;s rather pricey add-on at $9/month with far less functionality than dedicated analytics tools, it&#x27;s a great resource for seeing things like what bots are accessing or what 404s I may need to fix.</li>
</ul>
<img src="https://turbo.paulstamatiou.com/uploads/2020/10/copyright-paulstamatiou_com-netlify-analytics.png" alt="Netlify website analytics" width="2000" height="2174" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2020/10/copyright-paulstamatiou_com-netlify-analytics-2.png" alt="Netlify website analytics" width="2000" height="1748" />
<small>Netlify website analytics</small>
<ul>
<li><strong>Build times could be better:</strong> While it&#x27;s not a huge inconvenience, I do think build and deploy times could be faster, especially with the Pro plan that I&#x27;m on. It feels like they can vary between 1-4 minutes. Sometimes it goes by quickly and sometimes it takes more time between each file (maybe not cached?). I also think it must be running on some not-so-great hardware if it takes about 7.5 seconds to generate my jekyll site; something that takes 3.5-4 seconds on my MacBook Pro.</li>
</ul>
<h3>What&#x27;s next</h3>
<p>I&#x27;m trying to make it easier for me to write and publish articles, especially with my new focus on <a href="https://paulstamatiou.com/writing-more/">writing more</a> with these short-form posts. Netlify has been a huge help here by reducing some of the friction around deploys.</p>
<p>Other things top of mind for making it easier to publish include migrating away from Jekyll to a faster static site generator like <a href="https://twitter.com/Stammy/status/1307347164599922689">Hugo</a> and considering an admin front-end for my site generator like <a href="https://www.netlifycms.org/">Netlify CMS</a>.</p>
<p>For about a year now I have been using a <a href="https://paulstamatiou.com/about-this-website/#dev_env">Lightsail VPS running VSCode code-server</a> that I can access from any computer to write and deploy to my site. However, I&#x27;m now <a href="https://github.com/features/codespaces">trying out GitHub Codespaces</a>, which is basically the same thing.</p>
<p>I&#x27;m also exploring simplifying my local writing process by trying <a href="https://nova.app/">Nova.app from Panic</a> to have an all-in-one writing, dev and preview experience—no need to flip between 3 apps (Chrome, iTerm2, Atom). Though I wish I could figure out how to get a live browser preview with Live Reload working as mentioned on their homepage.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2020/10/copyright-paulstamatiou_com-coda-app-1500.jpg" alt="Nova.app native Mac code editor" />
<small>Nova, the native Mac code editor</small>]]></description>
            <link>https://paulstamatiou.com/moving-from-amazon-s3-to-netlify</link>
            <guid isPermaLink="true">https://paulstamatiou.com/moving-from-amazon-s3-to-netlify</guid>
            <dc:creator><![CDATA[Paul Stamatiou]]></dc:creator>
            <pubDate>Sun, 04 Oct 2020 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Writing more]]></title>
            <description><![CDATA[<p>I&#x27;m going to try something different and write more short-form posts here.</p>
<p>Over the years my focus has been increasing the quality of my articles. They&#x27;ve ended up becoming increasingly time-consuming to create. The same goes for my photosets, which also often require a bit of custom design and development in addition to the many hours photo culling and editing.</p>
<p>While that will not change and I thoroughly enjoy spending months of spare time sharing details about subjects and projects that interest me, there&#x27;s often a lot of stuff I would want to share here in between those ~annual, in-depth posts. These would be the types of posts that don&#x27;t really meet my quality bar to deserve my typical long-form post process and treatment.</p>
<p>I want to get back to what blogging felt like when I started in 2005. Back when posting a few sentences and publishing it within the same computing session was so easy and fun. Where expectations were low and it didn&#x27;t have to be perfect.</p>
<p>So I&#x27;m going to experiment with a section of my site for short little posts and updates. I want to share things I&#x27;m <a href="https://twitter.com/Stammy/status/1307353111896436739">learning with Swift and Swift UI</a>, how I&#x27;m thinking about certain design challenges with my side-projects, new products I&#x27;m using and more. I still plan to invest my time in long-form posts when it makes sense, but just want another outlet for different things.</p>
<p>As such, it felt like I would need to make a few layout changes for these posts to feel more casual and less refined. These short-form posts—which I don&#x27;t have a name for yet—have smaller text, a narrower layout and generally less stuff. As of now I have a little module on the homepage for these, but may change how and where I display these posts.</p>
<p>Let me know what you think via <a href="https://twitter.com/Stammy">Twitter</a> or <a href="https://paulstamatiou.com/contact">email</a> as I try this out. These new posts will be incorporated into my <a href="https://paulstamatiou.com/posts.xml">existing RSS feed</a> if you&#x27;d like to follow along there (I&#x27;ve been using <a href="https://ranchero.com/netnewswire/">NetNewsWire</a> for RSS feeds lately).</p>]]></description>
            <link>https://paulstamatiou.com/writing-more</link>
            <guid isPermaLink="true">https://paulstamatiou.com/writing-more</guid>
            <dc:creator><![CDATA[Paul Stamatiou]]></dc:creator>
            <pubDate>Sat, 03 Oct 2020 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Getting started with security keys]]></title>
            <description><![CDATA[<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-security-keys-DSC04276-2000.jpg" alt="" width="2000" height="1382" />
<small>A USB-C YubiKey 5C security key plugged into my ThinkPad X1 Carbon</small>
<p>Every week I come across another headline about how someone got hacked and within moments many of their online accounts had become compromised. These aren&#x27;t simple cases of bad actors using account credentials from large public data breaches and the unfortunate result of people using the same password across many websites.</p>
<p>These hacks, horror stories rather, are all the result of increasingly common attacks that gain access to a person&#x27;s phone number by exploiting vulnerabilities in phone carriers. More advanced attacks prey on <a href="https://www.cyberscoop.com/ss7-bitcoin-hack-positive-technologies/">SS7</a>, the old protocol underlying our cellular phone networks that lacks authentication. We more commonly hear about SIM card porting and SIM swapping attacks. In general, these attacks work by socially engineering your phone carrier to convince them you need a new SIM card as you lost your device or are upgrading it, or that you just want to switch carriers.</p>
<p>Today, many online accounts and services request your phone number to use as a form of account recovery as well as playing a role as a second factor in two-factor authentication via SMS text messages.<sup><a rel="footnote" href="#footnote-1" id="r1">1</a></sup> These attacks aim to get access to your phone number so the attackers can reset whatever accounts are tied to the number.</p>
<p>Attackers especially want to reset important accounts like your email account. From there they are often able to reset other accounts that might not be linked to your phone number. <strong>It&#x27;s a dangerous and all-too-quick sequence of events that can turn your life upside down in moments.</strong></p>
<p>Increasingly, the end goal is to gain access to a cryptocurrency account like Coinbase or to steal a high-profile Instagram account handle; methods that can quickly be used to get money.</p>
<p>Just take a look at these headlines:</p>
<ul>
<li><a href="https://www.nytimes.com/2019/09/05/technology/sim-swap-jack-dorsey-hack.html">Hackers Hit Twitter C.E.O. Jack Dorsey in a ‘SIM Swap.’ You’re at Risk, Too.</a></li>
<li><a href="https://medium.com/coinmonks/the-most-expensive-lesson-of-my-life-details-of-sim-port-hack-35de11517124">The Most Expensive Lesson Of My Life: Details of SIM port hack</a></li>
<li><a href="https://www.coindesk.com/hackers-stole-300k-blockchain-investor">Hackers Steal Over $300k From One of Blockchain’s Biggest VCs</a></li>
<li><a href="https://www.zdnet.com/article/wave-of-sim-swapping-attacks-hit-us-cryptocurrency-users/">Wave of SIM swapping attacks hit US cryptocurrency users</a></li>
<li><a href="https://www.vice.com/en_us/article/j5bpg7/sim-hijacking-t-mobile-stories?fbclid=IwAR2FM1sOJg7LALCsCMCAkUwgoxIyvhfwwE3Sjn7iyCxJLKcTJ-0F_01iJUg">‘I Lived a Nightmare:’ SIM Hijacking Victims Share Their Stories</a></li>
<li><a href="https://tonysheng.substack.com/p/sim-swap">Everybody is getting tragically sim swapped and you will too</a></li>
<li><a href="https://www.vice.com/en_us/article/vbqax3/hackers-sim-swapping-steal-phone-numbers-instagram-bitcoin">The SIM Hijackers</a></li>
<li><a href="https://www.vice.com/en_us/article/vbawv8/sim-swapping-hacking-victims-want-telephone-companies-protect-customers-edited">SIM Swapping Victims Who Lost Millions Are Pressuring Telcos to Protect Their Customers</a></li>
<li><a href="https://medium.com/@CodyBrown/how-to-lose-8k-worth-of-bitcoin-in-15-minutes-with-verizon-and-coinbase-com-ba75fb8d0bac">How to lose $8k worth of bitcoin in 15 minutes with Verizon and Coinbase</a></li>
<li><a href="https://www.zdnet.com/article/sim-swap-horror-story-ive-lost-decades-of-data-and-google-wont-lift-a-finger/">SIM swap horror story: I&#x27;ve lost decades of data and Google won&#x27;t lift a finger</a></li>
<li><a href="https://www.vice.com/en_us/article/d3jdbk/hackers-high-profile-instagram-accounts-hostage-ransom-bitcoin">Hackers Are Holding High Profile Instagram Accounts Hostage</a></li>
<li><a href="https://www.forbes.com/sites/zakdoffman/2019/10/07/fbi-issues-surprise-cyber-attack-warningurges-new-precautions/">FBI Issues Surprise New Cyber Attack Warning: Multi-Factor Auth Is Being Defeated</a></li>
<li><a href="https://www.nytimes.com/2019/01/27/opinion/2fa-cyberattacks-security.html">Two-Factor Authentication Might Not Keep You Safe</a></li>
</ul>
<hr/>
<blockquote>
<p>A technology that can give you everything you want is a technology that can take away everything that you have.</p>
<p>—Dan Geer, Security analyst</p>
</blockquote>
<p>I get freaked out every time I read one of those. As someone with a decent web presence, it feels like it’s only a matter of time before I become a victim of such an attack. While phone carriers have been working on making authentication better with efforts like <a href="https://www.verizon.com/featured/myzenkey/">Zenkey</a> (née Project Verify) and the <a href="https://krebsonsecurity.com/2018/09/u-s-mobile-giants-want-to-be-your-online-identity/">Mobile Authentication Taskforce</a>, I think it’s best to take things into your own hands now, especially when technologies like Zenkey rely on mass adoption from third parties.</p>
<p>I&#x27;ve been a bit paranoid about security for a while now. It began as a curiosity for interesting new tools and services from installing <a href="https://paulstamatiou.com/review-pgp-whole-disk-encryption-for-mac-os-x/">PGP WDE in 2008</a> to encrypt my Mac (before FileVault 2 offered full-disk encryption) to exploring newer tools and services like VeraCrypt and Tarsnap.</p>
<p>SIM attacks like these, often the result of social engineering, are not the only thing to be worried about these days. Online phishing has become incredibly advanced, be it from official-looking texts asking for account info (smishing), malicious phone calls scams (vishing), email spoofing, brand impersonation, website spoofing and more. Take a look at this one:</p>
<blockquote>
<p>Quick phishing demo. Would you fall for something like this? <a href="https://t.co/phONMKHBle">pic.twitter.com/phONMKHBle</a></p>
<p>— Mustafa Al-Bassam (@musalbas) <a href="https://twitter.com/musalbas/status/1038919152826757122?ref_src=twsrc%5Etfw">September 9, 2018</a></p>
</blockquote>
<blockquote>A Tweet embed was not displayed. Read this article in a browser to see it as intended.</blockquote>
<p>Paranoia is not entirely unwarranted with the plethora of these attacks today. It was with this mix of curiosity and fear that I began using hardware security keys two years ago. In a nutshell, <strong>security keys are little devices (typically USB, NFC or Bluetooth) that compute cryptography keys</strong> and serve as a more secure second factor<sup><a rel="footnote" href="#footnote-2" id="r2">2</a></sup> that only you can physically possess.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-security-keys-DSC04407-2000.jpg" alt="" width="2000" height="1400" />
<small>My assortment of Bluetooth, USB-A, USB-C, Lightning, NFC security keys</small>
<p>My evangelism of the benefits of these security keys amongst my friends has come up so often that I decided to write this beginner&#x27;s guide (albeit rather detailed) to security keys—a topic generally left to very tech savvy people—to accomplish a few things:</p>
<ul>
<li>Encourage people to take a closer look at their personal online security.</li>
<li>Explore what security keys are, understand the benefits and trade-offs, and see if security keys make sense for you.</li>
</ul>
<div><h3>Updates (Jan 2020)</h3><p>There have been quite a few updates—really good updates—in the security key world since I published this article in October 2019. I have updated the respective sections throughout this article, but also wanted to note them in one place here:</p><h3>Jun 2020</h3><ul>
<li><strong><a href="https://security.googleblog.com/2020/06/making-advanced-protection-program-and.html">Google has added WebAuthn support on iOS!</a></strong> This is huge news and something I&#x27;ve been waiting for. Now you can use USB, Lightning and NFC security keys in all Google login flows. Previously you could only use Bluetooth security keys via the Smart Lock app. The <!-- --><a href="https://www.yubico.com/blog/google-enhances-mobile-security-on-ios-with-yubikey-support-via-nfc-and-lightning/">Yubico post</a><!-- --> has additional context.</li>
</ul><h3>Jan 2020</h3><ul>
<li><strong><a href="https://9to5google.com/2020/01/14/iphone-google-security-key/">Google has updated the Smart Lock app for iOS</a></strong> to utilize the built-in security key present on modern iPhones, the Secure Enclave. This new functionality is equivalent to what modern Android devices like the Pixel 3 and 4 can do with their integrated Titan security chips. Unfortunately, we&#x27;re still waiting on Google to update their apps to fully support WebAuthn and allow logging in with USB, Lightning and NFC keys.</li>
</ul><h3>Dec 2019</h3><ul>
<li><strong>iOS 13.3 officially released and Safari gets FIDO2 WebAuthn support.</strong> This <!-- --><a href="https://www.yubico.com/2019/12/native-support-for-webauthn-and-fido-is-finally-here-on-iphones-and-ipads/">long-awaited update</a><!-- --> finally brings better WebAuthn support to iOS, starting with support in Safari for NFC, USB and Lightning security keys.</li>
<li><strong>Yubico Authenticator for iOS now <!-- --><a href="https://www.yubico.com/2019/12/yubico-authenticator-app-for-ios-now-supports-nfc/">supports NFC security keys</a><!-- -->.</strong></li>
</ul><h3>Nov 2019</h3><ul>
<li><strong>iOS 13.3 Safari introduces FIDO2 security key support!</strong> Wow, I didn&#x27;t expect to see this so soon. While still in beta and noted in the <!-- --><a href="https://developer.apple.com/documentation/ios_ipados_release_notes/ios_ipados_13_3_beta_2_release_notes">release notes</a><!-- -->, iOS 13.3 "supports NFC, USB, and Lightning FIDO2-compliant security keys in Safari" (and related Safari-powered view controllers that might be found inside apps). I can&#x27;t understate how great this news is for iOS users. Lack of proper iOS support was the largest issue facing security key adoption and convenience.</li>
<li><strong>YubiKey Bio:</strong> Yubico announced they are <!-- --><a href="https://www.yubico.com/2019/11/yubico-reveals-first-biometric-yubikey-at-microsoft-ignite/">working on a FIDO2 security key with an integrated fingerprint reader</a><!-- -->.</li>
<li><strong>Yubico Authenticator for iOS released.</strong> A lovely surprise with the release of Yubico Authenticator for iOS. This app lets you use your iPhone to access TOTP codes (not FIDO2) stored on your Lightning connector or NFC YubiKeys.</li>
<li><strong>OpenSSH to get U2F support.</strong> For those interested in easy native security key support with OpenSSH.</li>
</ul></div>
<h2>Security best practices</h2>
<h3>A few basics for improving your online security right now</h3>
<p>Before I dive right into talking about security keys, I thought it would be best to discuss a few security best practices: low-hanging fruit that go a long way for improving your security online. There&#x27;s a wealth of information on this topic across the web, so this is in no way meant to be an exhaustive list.</p>
<p>In addition, it really depends on a few things like what you are trying to protect, who might want it and where along the spectrum from convenience to security you would feel comfortable. Security folks would take this opportunity to talk about your personal <a href="https://en.wikipedia.org/wiki/Threat_model">threat model</a> to help assess what level of security paranoia and defenses are warranted for you. That could probably be it&#x27;s own article describing various routes to take and is fairly outside the scope of what I want to do with this article.</p>
<p>You can be on the <a href="https://www.bloomberg.com/news/features/2019-08-08/i-tried-hiding-from-silicon-valley-in-a-pile-of-privacy-gadgets?utm_medium=social&utm_content=businessweek&utm_source=twitter&utm_campaign=socialflow-organic&cmpid=socialflow-twitter-businessweek">supremely paranoid end of the spectrum</a> but it would just make simple daily tasks like checking email and browsing the web a chore, and most likely just increase the likelihood of locking yourself out of your accounts.</p>
<blockquote>
<p>Authentication is always a trade off between security and usability.</p>
<p>—Bruce Schneier, "<a href="https://www.amazon.com/Click-Here-Kill-Everybody-Hyper-connected-ebook/dp/B07BLMQKZK/ref=as_li_ss_tl?_encoding=UTF8&qid=1570905590&sr=8-3&linkCode=ll1&tag=paulstamatiou-20&linkId=8c5669b6a49248b08eebc13984483317&language=en_US">Click here to kill yourself</a>"</p>
</blockquote>
<ul>
<li>
<p><strong>Use a password manager, religiously.</strong> Make sure the sync works or opt for a hosted cloud solution. Pick a very strong master password for the password manager and remember it. Don&#x27;t use it for any other website or service. Backup the recovery key. Go through and change every online account password to something unique if it&#x27;s your first time setting up the password manager.</p>
<p>I use and love <a href="https://1password.com/">1Password</a> and pay for the cloud account but there are plenty of alternatives out there including DashLane, LastPass (some people avoid it due to a history of security incidents and their acquisition by LogMeIn), <a href="https://www.enpass.io/">Enpass</a> and open source options like <a href="https://bitwarden.com/">Bitwarden</a>.</p>
<p>Set up Two-Factor Auth for your password manager if available. This is separate from 2FA for your accounts it stores and is just 2FA for the password manager itself. For example, a 2FA-enabled cloud-hosted 1Password account will ask you for your second factor when adding 1Password to any new device.</p>
<p>Regularly take advantage of advanced password manager functionality that evaluates your accounts to see if they have been involved in any data breaches (1P calls this Watchtower) as well as informs you when you reuse passwords.</p>
</li>
<li>
<p><strong>Enable Two-Factor Authentication (2FA) wherever supported.</strong> Don’t enable SMS for your second factor if TOTP authenticator apps are an option.<sup><a rel="footnote" href="#footnote-3" id="r3">3</a></sup> Enable 2FA using an authenticator app for all supported sites (we’ll get to security keys later).</p>
<p>You can use an authenticator app like Google Authenticator, Microsoft Authenticator, <a href="https://www.yubico.com/products/services-software/download/yubico-authenticator/">Yubico Authenticator</a><sup><a rel="footnote" href="#footnote-4" id="r4">4</a></sup>, <a href="https://freeotp.github.io/">FreeOTP</a> (open sourced by Red Hat), <a href="https://github.com/andOTP/andOTP">AndOTP</a> (open source and has encrypted backups), <a href="https://duo.com/product/trusted-users/two-factor-authentication/duo-mobile">Duo Mobile</a> and <a href="https://authy.com">Authy</a><sup><a rel="footnote" href="#footnote-5" id="r5">5</a></sup>.</p>
</li>
<li>
<p><strong>Backup account recovery codes</strong> if they exist, especially for important accounts and email providers like 1Password, Google and Apple accounts.</p>
</li>
<li>
<p><strong>Remove your phone number as a recovery method for your email account.</strong> Ideally from all of your accounts, but we’ll get to that later.</p>
</li>
<li>
<p><strong>Add a passphrase/PIN for your mobile phone carrier.</strong> This passphrase would be requested from the carrier to authorize any SIM port. Or at least that’s the idea. Unfortunately, phone carriers have been known to be socially engineered into not asking for it and attackers have been known to have insiders at telephone companies to bypass this.</p>
</li>
<li>
<p><strong>Be a savvy web surfer.</strong> Much easier said than done, but lots of attack vectors are much closer to home than you might think. Keep your software up to date. Use an adblocker and/or DNS provider that can help keep you away from malware and phishing. (I have been testing out <a href="https://nextdns.io/">NextDNS.io</a> and liking it so far. It&#x27;s like a cloud-hosted <a href="https://pi-hole.net/">Pi Hole</a> if you don&#x27;t want to bother setting that up yourself.) More popular options include Google Public DNS (while not an explicit privacy/adblocker type of DNS provider it does <a href="https://developers.google.com/speed/public-dns/docs/security">protect against several types of attacks</a>), <a href="https://www.cloudflare.com/learning/dns/what-is-1.1.1.1/">Cloudflare 1.1.1.1</a> and <a href="https://www.quad9.net/">Quad9</a>.</p>
<p>Consider using a VPN when you are on an untrusted connection, but know that a VPN merely changes <em>who</em> you are trusting but doesn&#x27;t instantly make everything secure or private. Be skeptical of any browser extensions you install, links you click in emails, be careful when opening attachments and so on. Look for authentic website SSL certificates and correct domains when putting your credentials in a site. If your password manager can usually auto-fill in the details for a site but doesn&#x27;t one day, it could be that you&#x27;re not actually on the authentic site. So be sure to be suspicious if your password manager doesn&#x27;t seem to be working as intended.</p>
</li>
<li>
<p><strong>Revoke permissions for unused authenticated services.</strong> Go through your accounts like Google, Facebook and Twitter and revoke authenticated apps/integrations you no longer use or don&#x27;t recognize that have any kind of access to your account. There’s probably way more than you recognize due to past single sign on uses.</p>
</li>
<li>
<p><strong>Audit the authenticated devices linked to your Apple ID.</strong> Make sure you don’t have any old devices—maybe that you don’t use or no longer own—listed as devices in your account. And while we’re on the topic, make sure <a href="https://www.apple.com/icloud/find-my/">Find My iPhone</a> is enabled so you can remotely disable a lost device in a pinch.</p>
</li>
</ul>
<h3>Getting more advanced</h3>
<h3>More tips for the increasingly paranoid</h3>
<ul>
<li>
<p><strong>Secure your account with your domain name registrar.</strong> If you’re using email on a custom domain, ensure your domain name registrar is locked down with a strong password and two-factor auth using either an authenticator app or security keys. Remove any recovery phone number as well.</p>
<p>I’d recommend migrating your domains to something like Google Domains or AWS Route 53. Moving domains is easy. They offer strong 2FA solutions out of the box and I would trust them more than any other random registrar selling $5 domains.</p>
<p>This step is important because it’s another easy attack vector. Someone can socially engineer your registrar or mobile phone carrier (if linked), get access to your domain, change DNS MX records and then be able to receive password reset emails and take over other accounts.</p>
</li>
<li>
<p><strong>Consider how and if you want to backup your authenticator codes.</strong> After you’ve got all your accounts set up with two-factor auth using an authenticator app, you need to think about what might happen if you lose your phone. With an app like Google Authenticator, you will lose the codes if you have to get a new phone and restore from an iCloud backup. There are convenient options like Authy and 1Password that let you easily backup these codes and access from any device. There&#x27;s also AndOTP with it&#x27;s encrypted backup capability.</p>
<p>1Password has a <a href="https://support.1password.com/one-time-passwords/">really lovely integration</a> to also store these one-time password codes (and automatically paste them in when needed, depending on your app/extension/OS), but if you’re storing your second factor alongside your first, then you don’t really have two-factor authentication.</p>
<p>This solution is fine for most people, but this section is about being a bit more paranoid, so I would recommend not using the 1Password integration for your one-time password codes. Sure, you’re probably very screwed already in the unlikely event that someone gets access to your 1P database, but it’s even better if your most vital accounts require one more step by not having the OTP codes there.</p>
<p>The more extreme option is to manually keep track of the QR code or setup key provided when setting up 2FA for a TOTP authenticator on each account. Backing up these setup codes is a bit controversial and not recommended by the more hardcore security folks as it introduces another avenue by which you could be compromised if not securely stored. If you opt to backup your QR codes, you may want to store them outside of your password manager and in an encrypted manner. This could be on a service like Tarsnap, an encrypted Mac sparse bundle image or VeraCrypt volume. But now you have a new problem: how to securely store the passphrase or key for that service or volume.</p>
</li>
<li>
<p><strong>Don’t set a recovery email for your email accounts.</strong> Depending on your level of paranoia, you may opt to remove any recovery email addresses linked to your email accounts. The logic here is that every linked recovery email is another potential attack vector that could be used to gain access to your primary email account.</p>
<p>If this sounds like a bit too much to you and you’re worried about just locking yourself out of your account, you should at the least ensure that the recovery email account has a strong password and two factor authentication enabled. And ideally this account is with different email provider, not added or logged in on any of your devices and is only used for recovery.</p>
</li>
</ul>
<h3>Switch your carrier to Google Fi</h3>
<h3>If you want another safety net</h3>
<p>Even if you have done all you can to not link your online accounts to your phone number, there are always those services that just do not have two-factor authentication options beyond SMS. And that will always be a weak link in your security. You can do something like get a separate phone number that you only use for securing those accounts and don&#x27;t use for anything else. You could also create a separate Google Voice number for that purpose; the benefit being that it&#x27;s protected by your Google account&#x27;s 2FA.</p>
<p>Or you can move <strong>switch your mobile phone carrier to <a href="https://g.co/fi/r/NTP35E">Google Fi</a></strong>. I find this to be the simplest solution and have <a href="https://paulstamatiou.com/review-project-fi-by-google/">been using Fi for almost 4 years now</a>. The security benefit here is that your phone number is now protected by your Google account&#x27;s two-factor authentication, and is significantly less susceptible to social engineering attacks to gain account access.</p>
<p>I asked Google for more clarity on Fi security and was told the following. Basically, nothing is possible without access to the Google account already.</p>
<blockquote>
<p>[...] we check for the authentication of their account and if a user contacts us with an unregistered email ID then we ask them to confirm their identity by sending secret codes to the email ID which they claim that have been registered with Google Fi.</p>
</blockquote>
<h3>Enable Google Advanced Protection</h3>
<h3>Consider Advanced Protection for your Google accounts</h3>
<p>Google began offering something called <a href="https://landing.google.com/advancedprotection/">Advanced Protection</a> in late 2017. It offers enhanced security for those that might be at increased risk of targeted attacks. According to Google that includes journalists, celebrities, activists, business leaders, political campaign teams, firms dealing with cryptocurrencies and law firms. Fortunately, this functionality is available to anyone with a Google account and it brings some significant changes.</p>
<blockquote>
<p>Targeted attacks could be low volume, carefully crafted, phishing attacks, often personalized to individuals, and can be hard to distinguish from legitimate activity. This makes targeted attacks the hardest to protect against. The Advanced Protection Program is specifically designed to thwart targeted online attacks on Google accounts.</p>
<p>—<a href="https://support.google.com/a/answer/9378686?hl=en&visit_id=637018522450242142-4228392704&rd=2&ref_topic=9376233">Google</a></p>
</blockquote>
<p>First, Advanced Protection <em><strong>requires</strong></em> that you use security keys. It won&#x27;t let you enable it until you pair two security keys to ensure you have a backup key. The main benefit here being that security keys prevent phishing. Google accounts with AP enabled also bring stringent changes like:</p>
<ul>
<li>Very strict account access rules for your emails and Google Drive files. This means you won&#x27;t be able to use your Google account outside of native Google apps, except for a select list of trusted third-party applications like Apple Mail, Apple Calendar, Apple Contacts and Mozilla Thunderbird.</li>
<li>App passwords are no longer supported</li>
<li>Exhaustive Gmail scans to catch phishing messages and attachments containing malware.</li>
<li>No recovery code. That’s right. If you don&#x27;t have access to your password and one of your security keys, there is no way back in. You must go through the recovery process, which is much more rigorous and includes various delays on purpose. They may ask recovery questions like what month and year you first opened the Google account.</li>
<li>Enhanced web browsing safety when signed into Google Chrome. Google will alert you if it detects you downloading a file it thinks is unsafe according to its <a href="https://safebrowsing.google.com">Safe Browsing</a> policies.</li>
<li>And finally, I feel like Advanced Protection is more suspicious of activities and will aggressively prevent logging in if it thinks something is astray. I recall trying to test it out and logged in and out of my account on various devices and different IPs on VPNs and it was quick to prevent access.</li>
</ul>
<p>Google Advanced Protection may be overkill for some people but it&#x27;s a good segue into security keys and how they can help enhance your online security.</p>
<hr/>
<div><h3>Further reading</h3><p>As I mentioned earlier, there&#x27;s a wealth of security-related information, guides and research available online. I just wanted to provide a few starting points in this section. However, one area that deserves a mention is considering so-called privacy-first applications, services and providers. They are typically open source programs or services from companies that are very transparent about every facet of their practices related to user privacy, data handling and dealing with authorities.</p><p>You might have heard of some of the common privacy-first solutions: DuckDuckGo instead of Google, ProtonMail instead of Gmail, Firefox/Tor Browser instead of Chrome, various Linux distros instead of Windows 10 (at least run <!-- --><a href="https://www.winprivacy.de/english-home/instructions-1/">W10Privacy</a><!-- -->), Signal instead of SMS/WhatsApp and so on.
<strong><a href="https://www.privacytools.io/">PrivacyTools.io</a></strong> is an amazing resource covering a slew of privacy-first applications, services/providers, tools and more. I particularly enjoyed <!-- --><a href="https://www.privacytools.io/providers/">the page</a><!-- --> about the fourteen eyes, key disclosure laws and warrant canaries.</p></div>
<h2>What are security keys?</h2>
<h3>The small hardware devices to enhance your online security.</h3>
<p>Security keys are inexpensive, little hardware devices that use public-key cryptography to securely authenticate the website to the key. Maybe you&#x27;ve seen them around; these security tokens tend to look similar to regular USB memory sticks. Compared to using an authenticator app (also known as a TOTP code generator) as a second factor for 2FA, security keys (also called external or roaming authenticators) are a preferred and more secure option.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-DSC04558-2000.jpg" alt="" width="2000" height="1555" />
<small>USB-C security key plugged into a Pixel 3 Android phone.</small>
<p>When you go to log into a website where you have registered a security key as your second factor, you are first prompted for your username and password and then for the key. Usually this means plugging in and touching a special touch sensitive area of the key (for USB keys), but could also mean bringing the key closer (NFC) or pairing and pressing a button on the key in the case of Bluetooth security keys.</p>
<p>Okay, sounds easy enough.. but a bit more of a hassle to keep another device handy, right? So what’s so great about these security keys?</p>
<p>It’s no coincidence that Google requires hardware security keys as the second factor method for Google accounts with Advanced Protection enabled. Google themselves pushed for their employees to use security keys and they saw that it <a href="https://krebsonsecurity.com/2018/07/google-security-keys-neutralized-employee-phishing/">entirely neutralized phishing attacks</a> on all of their 85,000+ employees.</p>
<p>Compared to TOTP authenticators, <strong>the key benefit of using a security key is that they are immune to phishing attacks</strong>.<sup><a rel="footnote" href="#footnote-6" id="r6">6</a></sup> This is partially due to the fact that the origin/domain of the website is taken into account when you register your key. If you fall for a credential phishing email and went to log into a look-alike fake website, verification would fail, even if you thought the website was real.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-security-keys-DSC04226-2000.jpg" alt="" width="2000" height="1292" />
<small>YubiKey 5C Nano plugged into my <!-- --><a href="https://www.amazon.com/s/ref=as_li_ss_tl?k=thinkpad+x1+carbon&crid=30FOTLWWW9BYZ&sprefix=thinkpad+x1+c,aps,138&ref=nb_sb_ss_i_1_13&linkCode=ll2&tag=paulstamatiou-20&linkId=a2628e36a6cf0de399fadef734369ca7&language=en_US">ThinkPad X1 Carbon</a></small>
<h2>Security key history</h2>
<h3>FIDO, U2F, CTAP, WebAuthn.. where did it come from?</h3>
<p>But first I wanted to briefly dive into the history of security keys over the last few years. For the purpose of this article, I want to refer to these hardware authenticators and security keys as just security keys. You may have seen them referred to as FIDO U2F, CTAP, FIDO2 and WebAuthn. It’s all very confusing and even the newer overarching and correct term (FIDO2) doesn’t quite roll off the tongue.</p>
<p>You may be thinking, wait a minute, I used hardware tokens years before this. And you’re not wrong. Code generating hardware tokens like RSA SecurID have been around since the early <strong>2000s</strong>. They would continually display newly generated codes on their LCD display: codes that would often be <em>appended</em> to a password when logging in.</p>
<p>Then there were USB security keys in <strong>2007</strong> that would identify themselves to the computer as standard USB HID keyboard input devices and as such, not require any special drivers. When pressed, they would input a one-time password string comprised of things like counters, timers and random values. The one-time password would then be verified by the server based on a shared state (like the usage counter and device id) between the server and key.</p>
<p>While those keys sound a lot like the keys we have today, their implementation is quite a bit different and they are still susceptible to phishing and man-in-the-middle attacks.</p>
<p><strong>Fast-forward to 2012.</strong> Google and Yubico collaborated on a hardware security key based on public-key cryptography. This eventually became known as U2F (Universal 2nd Factor) and became part of the FIDO Alliance (Fast IDentity Online), an organization initially founded by PayPal, Lenovo and other companies to work on a passwordless authentication protocol.</p>
<p><strong>In 2014</strong>, Google officially <a href="https://fidoalliance.org/google-launches-security-key-worlds-first-deployment-of-fast-identity-online-universal-second-factor-fido-u2f-authentication/">shipped FIDO U2F support</a> in their Chrome browser. The next few years brought better security key hardware, increased support from large, mainstream websites like GitHub, Facebook and Dropbox, as well as increased support from browser vendors.</p>
<p><strong>Now, in 2019,</strong> we have the <a href="https://fidoalliance.org/fido2/">FIDO2</a> project. It recognizes the growing need to enable easy and secure multi-factor authentication experiences across both desktop and mobile devices to further the FIDO Alliance&#x27;s goal while making strong authentication more accessible. FIDO2 consists of two distinct parts: a client API called WebAuthn (an official W3C standard created in collaboration with the FIDO Alliance) and an API for hardware authenticators.</p>
<p>FIDO2 = WebAuthn + CTAP</p>
<p>The first part, <a href="https://www.w3.org/TR/webauthn/">WebAuthn</a> (short for Web Authentication), is essentially the client/browser JavaScript API that allows websites to create and use credentials based on public keys, which may come from hardware authenticators. It’s huge news that this is now a W3C standard so that every browser manufacturer can begin developing and supporting it. WebAuthn is the core link between the website server—frequently referred to as the Relying Party—and the browser.</p>
<p>The second part helps define the link between the browser and the external authenticator device. This protocol is called the Client to Authenticator Protocol, or just CTAP.<sup><a rel="footnote" href="#footnote-7" id="r7">7</a></sup> This aids in all the particulars of how various hardware authenticators communicate with the browser, such as via USB, Bluetooth Low Energy and NFC.</p>
<h2>What is passwordless?</h2>
<h3>What is this passwordless thing all about?</h3>
<p>One thing I keep hearing about with respect to authentication these days is passwordless auth. Honestly, it just seems like a buzzword.. so what exactly is <em>passwordless</em>? I&#x27;ll briefly describe the premise here and why it&#x27;s not the focus of this article.</p>
<p>One of the primary goals of the FIDO Alliance at its inception was to provide "open and free authentication standards to help reduce the world&#x27;s reliance on passwords." So far in this article when talking about FIDO1 I have only mentioned Universal 2nd Factor (U2F), which eponymously refers to enhancing two-factor authentication by using hardware security keys as a second factor.</p>
<p>FIDO U2F became well-known, in no small part to strong support from Google and subsequent integration into the Chrome browser. And well, U2F is comparatively easy to understand for people already familiar with two-factor auth... you just use a key you plug in as your second factor. Easy enough.</p>
<p>FIDO1 also contained a spec for something called UAF, Universal Authentication Framework. Its original goal was to provide a passwordless authentication solution employing biometrics. Similar to U2F, UAF utilizes public-key cryptography to authenticate with each service.</p>
<p>The difference is that UAF does not require any password. The browser asks the user to complete their previously registered authentication gesture, such as tapping their finger on a fingerprint reader or typing in a PIN.<sup><a rel="footnote" href="#footnote-8" id="r8">8</a></sup> As such, it&#x27;s called passwordless since no password is actually sent across the network. The authentication is done with the standard challenge-response auth as part of public-key cryptography.</p>
<p>Okay, so what about FIDO2? FIDO2 brings WebAuthn, which essentially merges the capabilities of U2F and UAF into one API that can be accessed by any supported browser or OS. People utilizing FIDO2 for two-factor auth with a security key as their second factor now have the ability to use a broader set of authenticators, such as internal platform authenticators like fingerprint readers and facial biometrics built into their devices. And finally, FIDO2 provides various passwordless authentication formats into the same system: passwordless single-factor or multi-factor.<sup><a rel="footnote" href="#footnote-9" id="r9">9</a></sup></p>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-DSC04602-2000.jpg" alt="" width="2000" height="1381" />
<small>Android supports built-in platform authenticators like fingerprint readers. Here&#x27;s <!-- --><a href="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-android-biometrics.png">an example flow</a><!-- -->.</small>
<p>All of this work is done to make passwords obsolete...why?</p>
<p>Passwords have several notable issues. Strong passwords are hard to memorize, they take time to type, many people still use the same password for all of their accounts and it&#x27;s easier to be phished with just a password. And of course, should anyone get access your password, they can just use it right away to log in.</p>
<p>But these seem like relatively solved issues today, right? We have robust password managers and we have two-factor authentication. The thinking behind passwordless is that those are just workarounds to an ancient authentication system that should be re-imagined with the latest technology we have at our disposal today.</p>
<p>We already have a taste of what FIDO2 brings today with enhanced authenticator support: you can use Touch ID on your MacBook Pro in Chrome, the fingerprint reader on your Windows 10 device via Windows Hello or even use the Pixel 3 Android phone itself as an authenticator, storing credentials inside its Titan M security chip and more. And you can imagine that in the future smart watches could begin to function as authenticators too: Apple already lets you use your Apple Watch as a proximity-based authenticator to unlock your Mac.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-security-keys-DSC04296-2000.jpg" alt="TouchID working with WebAuthn in Google Chrome" width="2000" height="1333" />
<small>TouchID working with WebAuthn in Google Chrome</small>
<p>The passwordless vision is compelling but feels quite a few steps away. First, barely any websites even support passwordless authentication flows.<sup><a rel="footnote" href="#footnote-10" id="r10">10</a></sup> Second, passwordless functionality requires storing data like display name and relying party name on the security key itself—something that doesn&#x27;t happen when simply using your security key as a second factor. This is called a resident key credential and this data takes up space. Modern <a href="https://support.yubico.com/support/solutions/articles/15000014219-yubikey-5-series-technical-manual#FIDO2mfqz6r">YubiKeys only have storage room for 25 resident keys</a><sup><a rel="footnote" href="#footnote-11" id="r11">11</a></sup> for use with such passwordless auth. Sure that might be a moot point if we all end up using internal platform biometric authenticators<sup><a rel="footnote" href="#footnote-12" id="r12">12</a></sup> for everything, but biometrics aren&#x27;t a flawless<sup><a rel="footnote" href="#footnote-13" id="r13">13</a></sup> solution:</p>
<blockquote>
<p>Biometrics are easy, convenient, and when used properly, very secure; they&#x27;re just not a panacea. Understanding how they work and fail is critical to understanding when they improve security and when they don&#x27;t.</p>
<p>—<a href="https://www.schneier.com/blog/archives/2009/01/biometrics.html">Bruce Schneier</a>, Security expert</p>
</blockquote>
<hr/>
<p>The very compelling counter-argument is that, well, <a href="https://www.troyhunt.com/heres-why-insert-thing-here-is-not-a-password-killer/">people just know how to use passwords</a> and not everyone understands (or cares!) about security. We&#x27;ve finally made some headway on getting people to use two-factor authentication.</p>
<p>It&#x27;s for those reasons that I would like to focus on the here and now: learning about the benefits of hardware security keys and how you can begin using them <em><strong>today</strong></em> with many services you already use.</p>
<h2>Security keys vs. auth apps</h2>
<h3>Are security keys really any better than TOTP code generator apps for 2FA?</h3>
<p>Before I go into detail about how security keys work and their benefits, it might make sense to talk a bit about the issues with using authenticator apps for two-factor auth.</p>
<h3>TOTP risks</h3>
<h3>Why authenticator apps aren&#x27;t perfect</h3>
<p>Even though they are a vastly preferred second factor compared to SMS, authentication with TOTP (Time-based One-Time Password) has some risks and inconveniences compared to security keys employing public-key cryptography.</p>
<ul>
<li>
<p><strong>Lack of phishing prevention.</strong> A huge issue with TOTP is that there is no inherent replay attack protection. You could still fall victim to a fake website (or real one being proxied via <a href="https://breakdev.org/evilginx-2-next-generation-of-phishing-2fa-tokens/">man-in-the-middle like with Evilginx 2</a> and <a href="https://github.com/drk1wi/Modlishka">Modlishka</a>) looking exactly like a website you visit and supply your password and TOTP codes to them. The attacker or bot can then log into the real website as you and still be within the TOTP time limit.</p>
</li>
<li>
<p><strong>TOTP employs a shared secret.</strong> With TOTP, the website has a secret key it provides to you. This is the key your authenticator app uses for initial setup. The TOTP authenticator then generates a hash with the secret key and the current time. The website does the same thing on its end, using the same secret key it has, and compares the two.</p>
<p>The issue is that the user and the relying party website share and store the same key. Unless the website followed the <a href="https://tools.ietf.org/html/rfc6238#section-5">security recommendation in the TOTP spec</a> to encrypt the secret key and only decrypt when in use to limit exposure in memory, it’s possible an attacker could generate TOTP codes for any account.<sup><a rel="footnote" href="#footnote-14" id="r14">14</a></sup></p>
</li>
<li>
<p><strong>Manual code entry.</strong> A significant and frequent annoyance with TOTP codes is that you have to manually type in the code each time: not to mention open your phone, then open the authenticator app. There are, however, methods of simplifying this with desktop authenticator apps, especially with password managers like 1Password automatically copying and pasting it in for you, but you don&#x27;t really want to have your password manager also store OTPs.</p>
</li>
<li>
<p><strong>Backing up TOTP authenticators is a hassle.</strong> Lose your phone where you had the only setup of Google Authenticator? You will need to proceed to account recovery for every account you had in there, which may go through an SMS (hopefully you’ve disabled this already!) or email reset flow. That’s annoying.</p>
<p>There are some modern solutions to backing up and syncing your authenticator app in the cloud like Authy, using the OTP integration in 1Password or managing andOTP encrypted backups. But that’s up to you to decide if those routes are for you as they have some downsides. You can also decide if you prefer to backup the TOTP setup secret key or QR code, but it would need to be stored securely as to not introduce another attack vector.</p>
<p>But I digress, my point here is that backing up your authenticator is yet another thing to think and worry about with TOTP.</p>
</li>
</ul>
<h3>Security key benefits</h3>
<h3>No shared secret, phishing prevention and much more</h3>
<p>On the other hand, security keys work in a very different manner and avoid many of the issues inherent with TOTP authenticators. Security keys are based on public key cryptography, meaning there is <strong>no shared secret</strong> between the user and the website. The benefit here is that even if a website was breached and an attacker gained access to a user&#x27;s public key, they would not be able to do anything with it.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-security-keys-DSC03266-2000.jpg" alt="" width="2000" height="1511" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-security-keys-DSC04416-2000.jpg" alt="" width="2000" height="1400" />
<small>My <!-- --><a href="https://paulstamatiou.com/gear/camera">90mm macro lens</a><!-- --> was a great investment and was used thoroughly in this post.</small>
<p>In addition, security keys are designed to make it impossible to get the private key out of the security key itself as cryptographic functions are computed locally on the device and never exposed to the computer.</p>
<ul>
<li>
<p><strong>Bulletproof phishing protection.</strong> The largest benefit of security keys is that they entirely thwart phishing attempts unlike TOTP authenticators. The exact domain name of the website is taken into account when the security key is registered. Even if the user willingly tried to log into a fake phishing site, the security key authentication would not work as the domain would differ. There&#x27;s also support for token binding which furthers this protection, though I&#x27;m not sure it is widely supported yet.</p>
</li>
<li>
<p><strong>Security keys prevent replay attacks.</strong> Security keys are designed to never expose private keys outside of the hardware. However, should they somehow be cloned, they contain a <a href="https://www.w3.org/TR/webauthn/#sign-counter">signature counter</a>. The WebAuthn spec says the security key should provide an incremental counter to the relying party on each successful authentication. Should the value not match the last known value, the authentication should fail. I say should because this is not a strict requirement for WebAuthn and it doesn&#x27;t appear to be common yet.</p>
<p>In addition, security keys and the relying parties utilize a challenge-response authentication flow to ensure single use and further prevent replay attacks.</p>
</li>
<li>
<p><strong>Built-in user presence required.</strong> One of the core features of security keys from the beginning has been that they require user presence before the key can do any cryptographic operations. All security keys require you to prove your presence by physically touching a capacitive touch sensor (or button for Bluetooth keys). This prevents remote takeovers as the user has to prove their physical presence to the device. Newer FIDO2 keys support user verification where you need to provide a PIN or a biometric gesture like a fingerprint tap (like with the <a href="https://www.yubico.com/2019/11/yubico-reveals-first-biometric-yubikey-at-microsoft-ignite/">upcoming YubiKey Bio</a> with integrated fingerprint reader) if configured as such.</p>
</li>
<li>
<p><strong>No typing in codes.</strong> And after you tap the key, that’s it. There’s no more work to do, you’re already logged in. However, this assumes you already have the key plugged in your machine and don’t have to fish it out of your pocket or bag.</p>
</li>
<li>
<p><strong>Easy to backup.</strong> Backing up a security key is easy—just buy spare security keys and register them on each service!</p>
</li>
<li>
<p><strong>Privacy as default.</strong> And finally, since security keys generate unique public/private key pairs for each website, it is impossible for anyone to know what sites are registered to your security key. Even if your key is stolen, there is no way to know what websites it is used with, or any associated data.<sup><a rel="footnote" href="#footnote-15" id="r15">15</a></sup></p>
</li>
</ul>
<h2>Types of security keys</h2>
<h3>How many keys do you need? How much do they cost?</h3>
<p>That’s a long way of saying that security keys are a terrific option to increase your online security. Now we can go into some more actionable info: basics about the security keys themselves, how many you need and what kind.</p>
<p>You’ll need to buy some security keys of course before you can get started. FIDO2 and WebAuthn paint a vivid picture of the future of authentication from supporting more types of authenticators—from numerous internal biometric sensors to more types of mobile devices—to supporting passwordless authentication flows.</p>
<p>As I mentioned earlier, external security key authenticators are the easiest to incorporate into your daily life today compared to passwordless auth. It won&#x27;t be perfect though: there are still some inconveniences and support issues associated with using security keys for your two-factor auth that I’ll dive into later.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-security-keys-DSC04371-2000.jpg" alt="" width="2000" height="1309" />
<h3>How many do I need?</h3>
<p>Yes, you need to purchase your security keys and they are not free. This is quite different than past solutions like SMS and TOTP authenticator apps. But it’s a small price to pay for enhanced security and phishing prevention. Security keys come in many varieties (USB-A, USB-C, NFC, Bluetooth LE and most recently, Lightning connector) to interface with computers and mobile devices.</p>
<p>There are benefits to using only one security key, but having multiple keys to rely on as your second factor is ideal.</p>
<ul>
<li>
<p><strong>Purchase two or more keys if</strong> you want to rely entirely on security keys—and fully disable SMS and TOTP authenticator apps where possible—you will want at least 2 keys so that you can have a backup key. That being said, most services let you program many keys so there is not much harm in having a few more (unless they are too easily misplaced or haphazardly stored and fall into the wrong hands). You may also find it handy to have small "nano" keys that always stay plugged in your computer.</p>
<p>You will need at least two keys if you want to consider enabling Google Advanced Protection on your account.</p>
</li>
<li>
<p><strong>Purchase one key if</strong> you want to test it out. There is still a strong benefit to just using one security key as a second factor in addition to a TOTP authenticator app as your backup. By relying on your security key to authenticate as much as possible, you’ll still receive the strong phishing protection that comes with security key usage.</p>
</li>
</ul>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-security-keys-DSC03398-2000.jpg" alt="" width="2000" height="1317" />
<small>YubiKeys are pretty durable. I&#x27;ve had this one on my keychain for a year and a half now. I have heard people say the USB-C version is less durable than the USB-A version but I haven&#x27;t had any issues myself.</small>
<h3>How much do they cost?</h3>
<p>Depending on feature set and durability, security keys range in price from around $10 all the way to $100+.</p>
<ul>
<li>
<p><strong>Entry-level:</strong> At the entry-level, we have security keys that cost something like $12 <a href="https://www.amazon.com/HyperFIDO-Mini-U2F-Security-Key/dp/B01LZO0WE9/ref=as_li_ss_tl?keywords=HyperFIDO+Mini&qid=1567903903&s=gateway&sr=8-3&linkCode=ll1&tag=paulstamatiou-20&linkId=db94e571a3fbbd74d3715286bdedfdd6&language=en_US">HyperFIDO Mini</a>, $20 for a <a href="https://www.amazon.com/Yubico-Security-Key-USB-Authentication/dp/B07BYSB7FK/ref=as_li_ss_tl?ie=UTF8&linkCode=ll1&tag=paulstamatiou-20&linkId=b7110c9a034fd051693d5ce694d6bbbc&language=en_US">Yubico Security Key</a> and the open source <a href="https://solokeys.com/">SoloKey</a>.</p>
<p>These cheaper keys tend to be strictly for authentication via one protocol only and won&#x27;t support additional protocols and software customization that pricier keys have—which is totally fine. Some keys in this price range may only support FIDO U2F and not the latest FIDO2 spec (aside from the model by Yubico). This means you can&#x27;t use them for new WebAuthn passwordless functionality if that matters to you.</p>
</li>
<li>
<p><strong>Mid to top tier:</strong> The main players in this space are Google (with the <a href="https://store.google.com/product/titan_security_key_kit">Google Titan Security Key bundle</a> as well as the <a href="https://store.google.com/product/titan_security_key">just-released USB-C version</a> that is similar to the Yubico 5C) and Yubico with their latest YubiKey 5 series offerings like <a href="https://www.yubico.com/product/yubikey-5ci">the flagship $70 YubiKey 5Ci</a> featuring dual USB-C and Apple Lightning connectors.</p>
<p>At this level you start to see more durable keys with better build quality, as well as support for many applications in addition to FIDO U2F and FIDO2<sup><a rel="footnote" href="#footnote-16" id="r16">16</a></sup>, such as Yubico OTP, Smart Card, OATH and OpenPGP. But most of these probably mean very little to you unless you&#x27;re a developer.</p>
</li>
</ul>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-iphone11pro-DSC04719-2000.jpg" alt="" width="2000" height="1224" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-security-keys-DSC03357-2000.jpg" alt="" width="2000" height="1575" />
<small><strong>Left:</strong> YubiKey 5Ci (Lightning connector) with iPhone 11 Pro <strong>Right:</strong> Titan Security Key bundle</small>
<ul>
<li><strong>Advanced & specialized:</strong> At the high-end there are devices that do much more than just U2F authentication and have robust, integrated password managers and cryptocurrency wallets. Trezor and Ledger both offer models in the $50 to $120+ range.</li>
</ul>
<hr/>
<p>I should also mention that there is a slowly growing category of devices not listed above that will become more important in the future as passwordless auth expands: external FIDO2 biometric authenticators. These devices are full-fledged FIDO2 security keys but also contain a biometric sensor like a fingerprint reader.</p>
<p>The fingerprint reader comes in handy for local user verification (instead of a PIN) for multi-factor passwordless auth. For example, like this Feitian BioPass authenticator. But I can&#x27;t <a href="https://www.zdnet.com/article/google-launches-titan-security-keys-but-recommends-keys-from-chinese-firm-with-military-links-in/">vouch for that brand</a> and don&#x27;t know if it requires special fingerprint drivers like similar models do. But I digress, this doesn&#x27;t matter right now, especially as I&#x27;m focusing on two-factor auth security key uses.</p>
<p><strong>Update (Nov 2019):</strong> Yubico has since announced that they are working on <a href="https://www.yubico.com/2019/11/yubico-reveals-first-biometric-yubikey-at-microsoft-ignite/">YubiKey Bio</a>, a security key featuring an integrated fingerprint reader that has no battery and requires no additional drivers or software to function. Unfortunately, it appears that this first biometric security key from Yubico is only USB-A.</p>
<h2>Compatibility issues</h2>
<h3>A look at what supports WebAuthn</h3>
<p>There are two pieces to successfully adopting security keys: support for FIDO U2F or FIDO2 WebAuthn from websites you use and the same support on the browsers and devices you wish to use to access those websites or apps.</p>
<p>Both have been a bit confusing for various reasons. Take website support of FIDO U2F or FIDO2 WebAuthn for example. A website may support one of those and let you register your security key, but it&#x27;s up to the site&#x27;s specific two-factor auth implementation to determine whether you will be allowed to register multiple security keys and/or use security keys as your only type of second factor. One reason is that that website&#x27;s accompanying mobile app may not support security key login and they don&#x27;t want to have to explain this trade-off to users.</p>
<p>Spotty browser support has been a big issue over the years. This really comes down to the devices you use, as well as their current state of support for security keys. While security keys come in many flavors spanning USB-A, USB-C, NFC, BLE and Apple Lightning connector, just because the port fits into your device doesn&#x27;t mean it will work everywhere on your device.</p>
<p><strong>Support for security keys is by no means ubiquitous across devices, operating systems and browsers and websites.</strong> Things have gotten much, much better over the years and really, the only real rough patch lies with iOS. I&#x27;ll dive into a brief description of the current support landscape right now, but one way to keep up to date on WebAuthn support status is by checking <a href="https://caniuse.com/#search=webauthn">CanIUse</a>.</p>
<hr/>
<div><h3>Windows - Great support</h3><p>You can use any USB security key on Windows 10 with Google Chrome, Mozilla Firefox, Brave and Microsoft Edge.</p><p>Windows 10&#x27;s Hello authentication system also supports FIDO2 security keys and currently the Edge browser has WebAuthn integration to access additional Hello-supported authentication methods such as PIN and biometric readers.</p></div>
<div><h3>Linux - Great support</h3><p>USB security keys should be fully supported by any modern Linux distro as well as a browser like Chrome, Chromium and Firefox. However, <!-- --><a href="https://support.yubico.com/support/solutions/articles/15000006449-using-your-u2f-yubikey-with-linux">certain distros may require you to manually tinker</a><!-- --> with the udev device management subsystem to enable browsers to interact with security keys.</p></div>
<div><h3>ChromeOS - Great support</h3><p>Supports USB security keys. Certain Chromebooks also feature their own integrated Google H1 CR50 security chip so you don&#x27;t even need an external security key, but I believe they only operate as a FIDO U2F+CTAP1 key.</p></div>
<div><h3>macOS - Great support</h3><p>While security keys are fully supported on Chrome and Firefox for macOS, Safari has lagged behind and not had support for a while. Fortunately, <!-- --><a href="https://developer.apple.com/documentation/safari_release_notes/safari_13_release_notes">Safari 13</a><!-- --> shipping with macOS 10.15 Catalina brings FIDO U2F and FIDO2 WebAuthn support.</p><p>If you&#x27;re not on Catalina yet, you&#x27;re able to put it to use with the <!-- --><a href="https://developer.apple.com/safari/technology-preview/">Safari Technology Preview</a><!-- --> now, but it does appear to entirely lack basic UI to show when a site is requesting key access. Chrome also supports biometrics with WebAuthn, letting you access TouchID on TouchID-sporting hardware like the MacBook Pro and MacBook Air. No FaceID support and no word if that will happen.</p></div>
<div><h3>Android - Great support</h3><p>Android support for security keys is in a great state, and that&#x27;s no surprise with Google&#x27;s push for U2F, and now WebAuthn, since the beginning. Chrome and Firefox enjoy full FIDO2 support and this means you can easily opt to use USB, Bluetooth and NFC security keys, along with any integrated biometrics such as your device&#x27;s fingerprint reader. (However, Brave browser and Firefox Focus did not appear to have functioning security key support at the time I wrote this.)</p><p>In addition, the Android OS itself is <!-- --><a href="https://fidoalliance.org/android-now-fido2-certified-accelerating-global-migration-beyond-passwords/">FIDO2 certified</a><!-- -->. The OS-level integration means that browsers and other apps only need to make an API call to trigger Android&#x27;s robust auth flow that handles everything.</p><img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-android-fido2-auth-protocols.png" alt="" width="4670" height="2300" /></div>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-DSC04469-2000.jpg" alt="Using a USB-C security key on a Pixel 3" width="1999" height="1390" />
<small>Using a USB-C security key on a Pixel 3</small>
<div><h3>iOS - Great support (Updated 2024)</h3><p><strong>Update 2024:</strong> Things have come a long way and you&#x27;re no longer at a disadvantage using a security key with iOS.</p><hr/><p>The state of security key support on iOS <em>used</em> to be utterly horrible. The native Safari browser didn&#x27;t support any kind of web authentication. The only option was to use a special Lightning connector security key and a different browser that had security key support baked in (Brave for iOS).</p><p>The only other way to work around it was with custom solutions employing Bluetooth security keys. Google lets people use security keys on iOS by redirecting to a separate app called Google Smart Lock that can pair with Bluetooth security keys—an annoying, one-off and clunky solution only for Google services.</p><p><strong>Fortunately, things have changed for the better.</strong> They&#x27;re still not great, but they&#x27;re on the right track. As of December 2019, Apple released iOS 13.3 which brought Safari support for WebAuthn using USB, NFC and Lightning connector FIDO2 security keys.</p><p>Even though Safari supports WebAuthn now, this does not mean that everything on iOS will. Many apps are in need of software updates to let you use security keys. Since iOS had no security key support for ages, it&#x27;s likely that many apps just incorrectly assume that iOS as a whole can&#x27;t interface with security keys and won&#x27;t even let iOS users provide their security key. Gmail is one such example: both the iOS app and website in Safari won&#x27;t let you use a USB, NFC or Lightning connector security key yet. <strong>Update (Jun 2020):</strong> Google now supports USB, NFC and Lightning connector security keys for WebAuthn on iOS!</p><p>This is also the current state of support for the aforementioned YubiKey 5Ci Lightning connector security key. It only works with a small set of apps and browsers like 1Password, LastPass, Safari and Brave browser.</p><img src="https://turbo.paulstamatiou.com/uploads/2019/10/copyright-paulstamatiou_com-safari-iOS-webauthn-prompt.png" alt="" /><p><strong>A note about NFC keys</strong>
Don&#x27;t modern iPhones have NFC? Can&#x27;t we use that along with NFC security keys for authentication?</p><p>Fortunately, the short answer is yes! Unfortunately, this was literally only possible until late in 2019 with iOS 13 bringing full read/write NFC support to devices like the iPhone 7 and newer. And then it wasn&#x27;t available to consumers until iOS 13.3 brought NFC key support into Safari in December 2019.</p><p>In the past iOS provided read-only NFC access on iPhones. You might have seen some examples of NFC security key authentication on iPhones in the past (in case you&#x27;ve seen the LastPass integration advertised). Those solutions have also been proprietary (sound familiar?) and required custom integration with the YubiKey Mobile SDK as they did not use FIDO U2F or FIDO2/WebAuthn, but instead used the proprietary YubiKey OTP. That was the only option at the time because FIDO U2F and FIDO2 require NFC read-write access to function, which iOS did not allow at the time.</p><p>Safari does now support the use of NFC keys and it&#x27;s a great and easy experience. App and other browser developers (looking at you Chrome!) will still need to <!-- --><a href="https://www.yubico.com/2019/09/yubico-ios-authentication-expands-to-include-nfc/">manually add support for this functionality</a><!-- -->. <!-- --><a href="https://www.yubico.com/2019/12/yubico-authenticator-app-for-ios-now-supports-nfc/">Yubico Authenticator for iOS</a><!-- --> was recently updated to support NFC keys so you can also use the key for TOTP code generation purposes in addition to WebAuthn. However, NFC is not a perfect solution with mixed support: current iPads and older iPhones don&#x27;t have the necessary NFC hardware.</p><p><strong>Update (Jun 2020):</strong> Google now supports NFC security keys for WebAuthn on iOS, so if you&#x27;re primarily using a security key for Google products and services, now is a great time to consider an NFC key.</p></div>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-iphone11pro-DSC04715-2000.jpg" alt="" width="2000" height="1319" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-iphone11pro-DSC04691-2000.jpg" alt="" width="2000" height="1467" />
<small><strong>Left:</strong> iPhone 11 Pro + YubiKey 5Ci Lightning connector security key <strong>Right:</strong> Using the 5Ci withBrave browser for iOS</small>
<h2>Buying your keys</h2>
<h3>NFC, BLE, USB-C, oh my! What to choose?</h3>
<p>Hopefully you now have enough context about the compatibility landscape to help you make an informed decision about what security keys to purchase given your mobile and desktop computing needs today.</p>
<p>If every type of security key was well-supported everywhere, you would probably just want a USB-C key for your computer and NFC key for your mobile devices. Holding your NFC key up against your phone for a moment is such an easy task compared to plugging anything into the USB-C port—dramatically easier than using a Bluetooth key that constantly needs to be charged, uses an archaic Micro-USB port and has to be paired.</p>
<p>But that would be too easy. Unfortunately, we&#x27;re stuck with a not-so-great matrix of varied security key support across devices, operating systems and browsers. Below I&#x27;ve put together some personal security key recommendations depending on what mobile device you use. I focused on mobile devices as the differentiator as desktop support is already fantastic for any USB key.</p>
<div><h3>New users</h3><p>For those that want to test the waters first</p><p>If you&#x27;re not sure if you want to fully commit to security keys right now but want to give it a try, I&#x27;d recommend starting off with an affordable, no-frills USB-A key like the Security Key by Yubico. It&#x27;s perfect for letting you try out web authentication flows on your desktop computer easily. Even having one key would still provide benefit of protecting you from phishing attempts while serving as just an extra second factor authentication method alongside your current TOTP/authenticator app.</p><p>Just note that this model cannot be used with desktop and mobile Yubico Authenticator apps to store TOTP secrets and function as an authenticator app for services that don&#x27;t support security keys yet. Those are reserved for higher-end "YubiKey" series keys from Yubico.</p><ul>
<li><strong>Security Key:</strong> The basic $20 Yubico key — <!-- --><a href="https://www.amazon.com/Yubico-Security-Key-USB-Authentication/dp/B07BYSB7FK/ref=as_li_ss_tl?crid=3H4MU5SVEIRSE&keywords=yubico+security+key&qid=1571597480&sprefix=yubico+secu,aps,136&sr=8-4&linkCode=ll1&tag=paulstamatiou-20&linkId=299655a54943ab8b7ee619f38ddfafd0&language=en_US">Amazon</a><!-- --> · <!-- --><a href="https://www.yubico.com/product/security-key-by-yubico/">Yubico</a></li>
</ul></div>
<div><h3>Recommendation for iOS users</h3><p>Lightning, NFC, USB keys & limitations</p><p>If you use iOS today, your best bet it to use either an NFC key or a Lightning connector key. Unfortunately, while Yubico has announced that they will release an NFC key that is also USB-C in Q1 2020, it&#x27;s not out yet. Until then, I would recommend the YubiKey 5Ci that is both Lightning connector and USB-C.</p><p>A dual USB-C and Lightning connector YubiKey will also be handy if you need to use this on an iPad as current iPads do not have any NFC hardware. An NFC key may prove to be more convenient if you only plan to use it with your iPhone.</p><ul>
<li>
<p><strong>YubiKey 5Ci:</strong> Dual Lightning connector and USB-C FIDO2 security key. — <!-- --><a href="https://www.amazon.com/Yubico-YubiKey-5Ci-Authentication-Connectors/dp/B07WGJ1DNJ/ref=as_li_ss_tl?keywords=yubikey+5ci&qid=1576867933&sr=8-3&linkCode=ll1&tag=paulstamatiou-20&linkId=0d65ce40f347351fc00d663e8dc3de43&language=en_US">Amazon</a><!-- --> · <!-- --><a href="https://www.yubico.com/product/yubikey-5ci">Yubico</a></p>
</li>
<li>
<p><strong>YubiKey 5 NFC:</strong> NFC/USB-A key. FIDO2 & multi-protocol — <!-- --><a href="https://www.amazon.com/Yubico-YubiKey-USB-Authentication-Security/dp/B07HBD71HL/ref=as_li_ss_tl?crid=186W2NOH2ZGVF&keywords=yubikey+5+nfc&qid=1569293897&s=gateway&sprefix=yubikey+5,aps,146&sr=8-1&linkCode=ll1&tag=paulstamatiou-20&linkId=e6f0cc0e64c05a151414335b37964685&language=en_US">Amazon</a><!-- --> · <!-- --><a href="https://www.yubico.com/product/yubikey-5-nfc">Yubico</a></p>
</li>
<li>
<p><strong>YubiKey 5C:</strong> USB-C FIDO2 & multi-protocol security key — <!-- --><a href="https://www.amazon.com/Yubico-YubiKey-Factor-Authentication-Security/dp/B07HBCTYP1/ref=as_li_ss_tl?keywords=yubikey+5c&qid=1569291833&s=gateway&sr=8-3&linkCode=ll1&tag=paulstamatiou-20&linkId=4f4719146c331ef33155e74b8dadcc47&language=en_US">Amazon</a><!-- --> · <!-- --><a href="https://www.yubico.com/product/yubikey-5c">Yubico</a></p>
</li>
</ul><h3>For Google users</h3><p>Of course, it&#x27;s not that easy. If you use Google services, you will need a Bluetooth key<!-- --><sup><a rel="footnote" href="#footnote-17" id="r17">17</a></sup><!-- --> as they have not yet updated to take advantage of Safari&#x27;s WebAuthn support nor implement their own into Chrome for iOS. And then your best bet is to also get a USB-C key for desktop use.</p><p>Unfortunately, no <em>great</em> Bluetooth keys exist. They all seem mediocre<!-- --><sup><a rel="footnote" href="#footnote-19" id="r19">19</a></sup><!-- --> in terms of design, durability, usability and lacking FIDO2 support. And then there&#x27;s the fact that many of these keys, like ones by Feitian and Thetis, are made in China. Paranoid security folks avoid them due to concerns around untrustworthy firmware.</p><p>The Bluetooth key I&#x27;m linking to here is Google&#x27;s Bluetooth Titan Security Key. These keys are essentially rebranded Feitian keys loaded with Google&#x27;s own firmware. These keys seem to be only FIDO U2F keys, not the latest FIDO2, so there is no WebAuthn passwordless support.</p><p>Up until recently, the Titan Key was only sold in a bundle, but Google recently began selling them separately, along when they announced their new USB-C key. <!-- --><a href="https://store.google.com/product/titan_security_key">Google&#x27;s new USB-C Titan key</a><!-- --> is created by Yubico but is neutered and lacks the flagship Yubico features I would have expected: support for multiple protocols (mainly to be able to use Yubico Authenticator) and full FIDO2 support. As such, I recommend the YubiKey 5C<!-- --><sup><a rel="footnote" href="#footnote-20" id="r20">20</a></sup><!-- --> instead.</p><p>If these options are limiting for you and the services you wish to use won&#x27;t work with a Bluetooth key on iOS (at this time that&#x27;s most things not Google), there is one fallback: adding an authenticator app as another second factor to use for these scenarios.</p><p><strong>Update (Jun 2020):</strong> <!-- --><a href="https://security.googleblog.com/2020/06/making-advanced-protection-program-and.html">Google now supports WebAuthn for iOS</a><!-- --> with USB, NFC and Lightning connector security keys! This is huge news and means you no longer have to rely on sub-par Bluetooth security keys. As such I am removing my recommendation for Bluetooth security keys.</p><p>That being said, Chrome for iOS does not yet support WebAuthn but Google has been making great progress lately between this update and their recent Google Smart Lock update, so a Chrome for iOS update can&#x27;t be too far away.</p></div>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-DSC04644-2000.jpg" alt="" width="2000" height="1225" />
<small>There&#x27;s no way around it: Bluetooth security keys are annoying.</small>
<div><h3>Recommendation for Android users</h3><p>Use whatever you like, Android is the best.</p><p>If you use Android, you can basically do whatever you want: support for all sorts of keys across Android is great. Personally, I would just recommend going for multiple USB-C keys (assuming your desktop computer is also USB-C).</p><p>I tend to prefer the smaller form factor keys over the slight convenience benefit of a larger NFC key, but that really comes down to personal preference. When the NFC version of the YubiKey 5C comes out, I would recommend that over the USB-A version shown below.</p><ul>
<li>
<p><strong>YubiKey 5C:</strong> USB-C key. FIDO2 & multi-protocol — <!-- --><a href="https://www.amazon.com/Yubico-YubiKey-Factor-Authentication-Security/dp/B07HBCTYP1/ref=as_li_ss_tl?keywords=yubikey+5c&qid=1569291833&s=gateway&sr=8-3&linkCode=ll1&tag=paulstamatiou-20&linkId=4f4719146c331ef33155e74b8dadcc47&language=en_US">Amazon</a><!-- --> · <!-- --><a href="https://www.yubico.com/product/yubikey-5c">Yubico</a></p>
</li>
<li>
<p><strong>YubiKey 5 NFC:</strong> NFC/USB-A key. FIDO2 & multi-protocol — <!-- --><a href="https://www.amazon.com/Yubico-YubiKey-USB-Authentication-Security/dp/B07HBD71HL/ref=as_li_ss_tl?crid=186W2NOH2ZGVF&keywords=yubikey+5+nfc&qid=1569293897&s=gateway&sprefix=yubikey+5,aps,146&sr=8-1&linkCode=ll1&tag=paulstamatiou-20&linkId=e6f0cc0e64c05a151414335b37964685&language=en_US">Amazon</a><!-- --> · <!-- --><a href="https://www.yubico.com/product/yubikey-5-nfc">Yubico</a></p>
</li>
</ul></div>
<div><h3>About nano-sized keys</h3><h3>Tiny keys for frequent use</h3><p>Nano-sized security keys are made to be remarkably low-profile and meant to remain in a USB port. They&#x27;re so small that they&#x27;re even a bit annoying to remove—and you&#x27;re likely to lose them if you do.</p><p>They&#x27;re intended for keeping in computers, or <!-- --><a href="https://www.yubico.com/product/yubihsm-2">even servers</a><!-- -->, where security key functionality will be used frequently and ease-of-access to touch the key is important. I find having one plugged into the USB port on my desktop&#x27;s monitor to be very handy: only a short distance to tap it when I need to login. But this will especially be handy for those doing more with their security keys than just two-factor auth, like using it for PGP and SSH keys.</p><p>It&#x27;s up to you to decide if you would feel comfortable using a nano key in a laptop you travel with where there is a risk of the two being stolen together, compared to a stationary desktop computer.</p><ul>
<li><strong>YubiKey 5 Nano:</strong> Extremely compact USB-A FIDO2 key — <!-- --><a href="https://www.amazon.com/Yubico-YubiKey-USB-Authentication-Security/dp/B07HBDX2CM/ref=as_li_ss_tl?keywords=yubikey+5+nano&qid=1570503136&sr=8-3&linkCode=ll1&tag=paulstamatiou-20&linkId=4cfafa6e7365091c6f27277c028e64ee&language=en_US">Amazon</a><!-- --> · <!-- --><a href="https://www.yubico.com/product/yubikey-5-nano">Yubico</a></li>
<li><strong>YubiKey 5C Nano:</strong> Extremely compact USB-C FIDO2 key — <!-- --><a href="https://www.amazon.com/Yubico-YubiKey-Factor-Authentication-Security/dp/B07HBTBJ5S/ref=as_li_ss_tl?keywords=yubikey+5c+nano&qid=1570503018&sr=8-3&linkCode=ll1&tag=paulstamatiou-20&linkId=387702a17d99cbfce290324e5306664e&language=en_US">Amazon</a><!-- --> · <!-- --><a href="https://www.yubico.com/product/yubikey-5c-nano">Yubico</a></li>
</ul></div>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-security-keys-DSC03311-2000.jpg" alt="" width="1999" height="1145" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-security-keys-DSC04348-2000.jpg" alt="" width="2000" height="1370" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-security-keys-DSC03372-2000.jpg" alt="" width="2000" height="1334" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-security-keys-DSC04350-2000.jpg" alt="" width="2000" height="1444" />
<small>Nano-sized keys live in the USB port of your computer, ideal for cases where they will be used frequently.</small>
<h3>An ode to Yubico</h3>
<p>I really love Yubico security keys. It&#x27;s no surprise that one of the original companies pushing for strong authentication online knows the importance of high quality, durable hardware. I’ve never had any issues with Yubico build quality and their higher-end YubiKey series supports a robust feature set that&#x27;s customizable with software. It costs a premium but you can trust it and they are known to do recalls if they suspect there are any issues that could affect security (they replaced one of my older 4C keys).</p>
<p>If I had to nitpick, their software (YubiKey Personalization Tool, YubiKey Manager, Yubico Authenticator) isn&#x27;t simple or well-designed.</p>
<p>There is, however, one significant criticism about Yubico keys from security folks in the industry. It&#x27;s that Yubico&#x27;s keys are closed source, preventing developer community-sourced verification of secure code along with the ability to update and modify the device however the owner wishes. For customers that fall in that camp, there are open source options like <a href="https://solokeys.com/">SoloKeys</a>.</p>
<hr/>
<p><strong>Hopefully that all made some sense!</strong> If you&#x27;re still not sure what you need, it might be worth checking out <a href="https://www.yubico.com/quiz/">this quiz</a> from Yubico to help you find the right security key for your needs.</p>
<h2>Registering your keys</h2>
<h3>Using security keys for two-factor auth</h3>
<p>So you&#x27;ve purchased a security key or a few and are ready to set things up.. great! Each security key you own must be registered with each service you wish to use it on such as Google, 1Password, Facebook, GitHub, et cetera.</p>
<p>You&#x27;ll register each key one by one. Usually navigating to the website&#x27;s settings page related to two-factor auth and finding a button to add a key. This assumes you&#x27;ve already setup two-factor auth. Then when prompted you plug your key in and tap it. Depending on the website you may be prompted to type in a name for each key. This step is vital as it helps you identify which key to remove from the service in the event you lose that key and have multiple registered on the same service.<sup><a rel="footnote" href="#footnote-22" id="r22">22</a></sup></p>
<p>And that&#x27;s pretty much it. Once a key is registered with a service, the next time you log in <sup><a rel="footnote" href="#footnote-23" id="r23">23</a></sup> it&#x27;s as easy as touching your security key when prompted after entering your username and password.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-1password-security-key.png" alt="" width="2028" height="1478" />
<p>That&#x27;s generally how two-factor authentication with security keys works but these things differ from website to website depending on how they&#x27;ve implemented things. For example, you may be prompted for a code from an authenticator app instead (if you have one added as a second factor option) and are in a browser that does not support FIDO U2F or FIDO2 WebAuthn.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-security-keys-DSC04317-2000.jpg" alt="YubiKey 5Ci plugged into a MacBook Pro" width="2000" height="1944" />
<small>YubiKey 5Ci plugged into a MacBook Pro</small>
<p>You can check to see if the websites and services you use support security keys by taking a look at <a href="https://www.dongleauth.info/">DongleAuth.info</a>. It&#x27;s also easy enough to search the settings pages of the websites you use for any mention of security keys for two-factor authentication.<sup><a rel="footnote" href="#footnote-24" id="r24">24</a></sup></p>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-firefox-security-key-prompt.png" alt="" width="935" height="696" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-mac-chrome-use-security-key-webauthn.gif" alt="" width="800" height="527" />
<small>Different browsers will display varying prompts requesting you to touch your security key. <strong>Left:</strong> Windows 10 Firefox <strong>Right:</strong> Chrome for macOS <strong>Not pictured:</strong> Safari 13 for macOS Catalina (while it has experimental WebAuthn support, it shows no UI to prompt for a key yet)</small>
<h3>Setting up Google Advanced Protection</h3>
<h3>Google&#x27;s strongest, security key-required security program</h3>
<p>I mentioned the benefits of Google Advanced Protection <a href="#enable-google-advanced-protection">earlier in this article</a>. It is designed to help thwart targeted attacks by requiring the use of security keys, in addition to numerous enhanced security measures.</p>
<p>Signing up for <a href="https://landing.google.com/advancedprotection/">Advanced Protection</a> follows the same process I mentioned above: enable two-factor auth, register and name two security keys and you&#x27;re ready to go.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-google-advanced-protection-setup.png" alt="" width="1300" height="926" />
<small>Chrome will ask to see detailed info about your key during the key registration process.</small>
<p>Advanced Protection has some aggressive requirements: you must register at least two security keys, you can&#x27;t add any TOTP authenticator apps as a second factor and there&#x27;s no recovery code. You can however add an approved Android device as an authenticator. Google requires having two keys with Advanced Protection so that one can operate as a spare should you lose one.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-google-advanced-protection-setup-2.png" alt="" width="800" height="977" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-google-advanced-protection-setup-3.png" alt="" width="800" height="977" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-google-advanced-protection-setup-4.png" alt="" width="800" height="977" />
<div><h3>Use G Suite? You&#x27;ll have to enable it first.</h3><p>If you use the enterprise G Suite for your email, you may not have the option to even enable the Advanced Protection Program until your administrator has turned it on. If you run G Suite for yourself, you can read about <!-- --><a href="https://support.google.com/a/answer/9378686?hl=en">enabling the beta here</a><!-- -->.</p><img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-enable-gsuite-adv-protection.png" alt="" width="1680" height="1169" /></div>
<h3>What about regular Google accounts?</h3>
<h3>If you&#x27;re not ready to make the jump to Advanced Protection</h3>
<p>If you just want to test the waters a bit with security keys and don&#x27;t think enabling Advanced Protection is for you at this time, you can always just register keys as part of any Google account&#x27;s regular 2-Step Verification settings.</p>
<p>The process for adding a key is similar to the Advanced Protection flow from above but you just navigate to <strong>Google Account → Security → 2-Step Verification → Add Security Key</strong>.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-add-security-keys-google-account.png" alt="" width="1566" height="1315" />
<p>With regular Google accounts, you&#x27;re free to mix second factor authentication types from SMS to authenticator apps and even other phones using <a href="https://support.google.com/accounts/answer/7026266?co=GENIE.Platform%3DAndroid&hl=en">Google 2SV phone prompts</a>. Of course, I strongly advise against using SMS at all.</p>
<h3>1Password</h3>
<p>If you use the hosted option for 1Password password manager, adding your keys is a simple process as well. Just log into 1Password.com, click your name in the corner then navigate to <strong>My Profile → More Actions → Manage Two-Factor Authentication → Add a Security Key</strong>.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-1password-register.png" alt="" width="1688" height="1395" />
<p>You can add as many keys as you like. However, the current 1Password implementation does not yet allow you to remove the authenticator app as a second factor. Since people often use 1Password on their mobile devices in addition to their desktop computers, they would likely only support security key-only authentication once every 1Password mobile app offered security key support.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-1password-register-2.png" alt="" width="1688" height="1395" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-1password-register-3.png" alt="" width="1688" height="1395" />
<p>Only the 1Password iOS app <a href="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-1password-ios-use-security-key.png">supports physical security keys</a> at this time and via a custom Yubico Mobile SDK integration only supporting the new and expensive Lightning connector YubiKey 5Ci.. so definitely not for everyone just yet.</p>
<p><strong>Update (May 2020):</strong> 1Password for iOS now <a href="https://support.1password.com/security-key/">supports NFC security keys</a>, though only the YubiKey 5 NFC for now it seems.</p>
<p><strong>Will 1Password ask for my security key every time?</strong></p>
<p>Adding a security key does not mean that 1Password will ask for it every single time you need to open 1Password to log into an account: something that likely happen many times throughout the day for you. 1Password only really asks for your security key when adding your 1Password account to an untrusted device like a new browser or desktop app.</p>
<h3>Fastmail</h3>
<p><a href="https://ref.fm/u21963120">Fastmail</a> is a popular non-Google email service that has supported security keys for years now. It also lets you entirely remove SMS, recovery codes and authenticator apps if you so wish. Setup is trivial as well: <strong>Settings → Password & Security → Two-Step Verification → Add Verification Device → Set Up Security Key.</strong></p>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-fastmail-security-key-setup.png" alt="" width="1402" height="1160" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-fastmail-security-key-setup-2.png" alt="" width="1402" height="1160" />
<h3>Facebook</h3>
<p>Of course, you can register your security keys with your social accounts like Facebook as well. The process is the same: find the two-factor auth section in the account settings then add and name each of your security keys.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-fb-key-register.png" alt="" width="1453" height="1130" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-fb-key-register-2.png" alt="" width="1453" height="1130" />
<h3>Registering keys on other services</h3>
<p>If you have any questions about how to set up your security keys on other services, Yubico maintains a <a href="https://www.yubico.com/works-with-yubikey/catalog/">well-documented section</a> on their site for just about every supported service.</p>
<h3>What about mobile?</h3>
<h3>It&#x27;s easy on Android, less so on iOS..</h3>
<p>By now you&#x27;ve registered your security keys and figured out how to log back in with them on your desktop browser. But how do you login on your mobile devices with security keys?</p>
<p>As I mentioned in the Android section earlier, it&#x27;s a breeze. The operating system itself (well, Google Play Services technically) supports FIDO2 so any website or app should trigger this authentication activity view, giving you numerous authentication options such as with NFC, USB and Bluetooth keys.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-DSC04478-2000.jpg" alt="" width="2000" height="1491" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-DSC04498-2000.jpg" alt="" width="2000" height="1607" />
<small>Using your security key on Android just works. (Pictured: Pixel 3 + YubiKey 5C USB-C key)</small>
<p>It&#x27;s not the same with iOS. You&#x27;re out of luck if your main browser is Chrome for iOS as it does not have support yet. While iOS 13.3 brought support for USB, NFC and Lightning keys to Safari, not all apps and services have taken note yet.</p>
<p>If you use a Google account on your iPhone or iPad, however, you do have another option. Google has a separate authentication app called <a href="https://apps.apple.com/us/app/google-smart-lock/id1152066360?mt=8&at=1000lMp4">Google Smart Lock</a> for this purpose. You log into all of your Google accounts in the Smart Lock app—it supports Bluetooth security keys—and it can redirect you back to the app you came from to complete your authentication. This works for native Google apps as well as apps utilizing Google login.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-iphone11pro-DSC04735-2000.jpg" alt="Using a Bluetooth security key on iOS with Google Smart Lock." width="2000" height="1243" />
<small>Using a Bluetooth security key on iOS with Google Smart Lock.</small>
<p>It&#x27;s not a perfect solution but you don&#x27;t have much of a choice for Google apps and services on iOS right now. Even attempting to log into Gmail in Safari does not let you use a security key directly in Safari; instead it tries to redirect you to Google Smart Lock.</p>
<p>Having to install a separate app just to use your security key is a hassle. Then you add on to that some general Bluetooth security key woes: having to pair the key, having to keep your security key charged at all times, having to carry around a MicroUSB cable around to keep the key charged, having the key&#x27;s button always accidentally get pressed in your bag and drain the battery. Annoying.</p>
<p>However, I&#x27;m hoping that in the first few months of 2020 we&#x27;ll begin to see more apps and services update to support security keys, at least via utilizing SFSafariViewController to take advantage of the existing WebAuthn implementation.</p>
<h3>Bonus: Pixel 3 as a security key</h3>
<h3>Take advantage of the integrated Titan M security chip</h3>
<p>This probably isn&#x27;t what you have in mind right now when you think about a security key. For most of this article I&#x27;ve been talking about external hardware authenticators that you plug into your computer or mobile device. But they don&#x27;t always have to be separate from your device.</p>
<p>More and more devices have integrated security chips, some Google Chromebooks even have an integrated "H1" chip that can be used for FIDO U2F auth. These integrated security chips may go by various names like secure element, TPM and Apple&#x27;s Secure Enclave, but the gist is generally the same. They are secure cryptoprocessors that have a secure boot process and microkernel to completely isolate itself from the rest of the hardware. Much like USB security keys, the system cannot access the secrets stored on the security chip: the chip itself just runs computations. Now, with WebAuthn and initiatives like this Google solution I&#x27;m about to describe, there are more ways for these chips to be used for web authentication.</p>
<p>But I digress... the Pixel 3 has a "Titan M" security chip that can be used to store your cryptographic keys for second factor authentication. This is similar to how an external security key is used to generate a unique public/private key pair for auth. When you go to Google account settings to add another second factor for 2-Step Verification, it will display a prompt to add your Android device if it recognizes that your Google account is logged in and supported. While it supports any Android device running Android 7+, it&#x27;s only the Pixel 3 (and I&#x27;m guessing the new Pixel 4 can do the same) that features this enhanced protection. (<strong>Update January 2020:</strong> Google has <a href="https://9to5google.com/2020/01/14/iphone-google-security-key/">updated the Smart Lock app for iOS</a> to enable similar functionality for iOS users.)</p>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-google-add-pixel3-security-key.png" alt="" width="1390" height="996" />
<small>Adding the Pixel 3 as a second factor to a Google account.</small>
<p>It&#x27;s important to note that this is not the same type of phone prompt you may have seen in the past where your phone receives a login request notification via the cloud. This new implementation is quite novel: it&#x27;s local proximity based, and as such it requires Bluetooth to be enabled on both devices. Also, Google was able to get this working entirely without requiring Bluetooth pairing, which is always a hassle. They developed an extension to WebAuthn that introduces <a href="https://www.youtube.com/watch?v=ktN88Vnmnns">pairing-less secure communication</a> between your computer and the mobile device.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-iphone11pro-DSC04771-2000.jpg" alt="" width="2000" height="1371" />
<p>When you log into your Google account, it will communicate with your phone locally via Bluetooth. Similar to an external security key, user presence is required in the form of a physical press. Google had the security chip hardwired to the Pixel 3&#x27;s volume down button. As such, not even malicious software running on the phone would be able to control the Titan M chip on its own.</p>
<h3>Why does it ask for a PIN?</h3>
<h3>Set a PIN to enhance user verification on your FIDO2 key</h3>
<p>If you&#x27;re using a FIDO2 security key you may have been prompted at some point during the registration process or elsewhere to set or enter a PIN for the key. This was confusing to me the first time it happened, especially when I was using my key as a second factor.</p>
<p>Of course, there is a reason for this. But first, I&#x27;ll go ahead and say that for the purpose of using the key as a second factor only, you don&#x27;t <em>need</em> to set a PIN.</p>
<img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-set-fido2-pin.png" alt="Setting a FIDO2 key PIN in YubiKey Manager" width="822" height="634" /><br /><br /><img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-google-security-key-pin-request.png" alt="Chrome for macOS prompting for the PIN" width="939" height="763" />
<small><strong>Left:</strong> Setting a FIDO2 key PIN in YubiKey Manager <strong>Right:</strong> Chrome for macOS prompting for the PIN.</small>
<p>The PIN is there to enable a form of multi-factor authentication for passwordless authentication flows. We&#x27;re not quite there yet as not many services support passwordless functionality, but the modern security keys support it. FIDO2 keys have the ability to store username and password credentials directly on the key, via FIDO2 resident credentials.</p>
<p>This is a significant change to how things were done with FIDO U2F where it was not possible to know which services had been registered with the key. Now with resident credentials it&#x27;s possible for someone to ask the key to list out what domains it has been registered on or just what accounts exist on the key for a given domain. As such, you need a way to add a stronger user verification step to limit that access. In this passwordless world, your FIDO2 hardware key can require user verification with a PIN that is local and stored directly on the key itself, or it can require something like a biometric gesture if the device has such sensors/readers and was configured that way.<sup><a rel="footnote" href="#footnote-25" id="r25">25</a></sup></p>
<p>But wait, I thought this was supposed to be <em>passwordless</em>.. why do I need to set and remember a PIN? Yubico has the reasoning here:</p>
<blockquote>
<p>A PIN is actually different than a password. The purpose of the PIN is to unlock the Security Key so it can perform its role. A PIN is stored locally on the device, and is never sent across the network. In contrast, a password is sent across a network to the service for validation, and that can be phished. In addition, since the PIN is not part of the security context for remotely authenticating the user, the PIN does not need the same security requirements as passwords that are sent across the network for verification. This means that a PIN can be much simpler, shorter and does not need to change often, which reduces concerns and IT support loads for reset and recovery. Therefore, the hardware authenticator with a PIN provides a passwordless, phishing-resistant solution for authentication.</p>
<p>—<a href="https://www.yubico.com/2018/08/10-things-youve-been-wondering-about-fido2-webauthn-and-a-passwordless-world/">Yubico</a></p>
</blockquote>
<h3>Final words of advice</h3>
<h3>Keeping track of your keys</h3>
<p>If you&#x27;re like me you probably have quite a few websites you will be using your security keys with. If you have more than a few security keys it may be handy to make a spreadsheet of each key you own and each service it is registered on (or in your password manager, add a note for each login about what keys are registered with each service.</p>
<blockquote>
<p>Done. Now I’ll just have to wait for banking hours when I lose my other u2f keys and lock myself out of my accounts 😂 <a href="https://t.co/kC2NmX8TTa">pic.twitter.com/kC2NmX8TTa</a></p>
<p>— Paul Stamatiou 📷 (@Stammy) <a href="https://twitter.com/Stammy/status/1029772096862208001?ref_src=twsrc%5Etfw">August 15, 2018</a></p>
</blockquote>

<p>This is particularly handy if you store any of your keys at separate locations for safekeeping and need to know which ones to register on new services when you get a hold of them next.</p>
<p>Which brings me to my next point, if you have more than one security key, you should keep the spare somewhere safe. That could be a trusted friend or family member&#x27;s house, it could be your place of work, a <a href="https://www.nytimes.com/2019/07/19/business/safe-deposit-box-theft.html">bank safe deposit box</a>, et cetera. Unless you think you could be targeted, this is likely just to prevent you from misplacing the spare security keys at your place.</p>
<div><link rel="preload" as="image" href="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-yubikey-disable-otp-mode.png"/><h3>Pro tip: Disable Yubico OTP mode</h3><p>There&#x27;s one common annoyance with the default YubiKey configuration: accidentally tapping the button on a YubiKey will make it begin spewing out a large string of random characters each time. Contrary to popular belief, this is <em>not</em> related to actual FIDO/FIDO2 functionality. It&#x27;s a mode specific to YubiKeys for another type of authentication that you probably won&#x27;t be using: Yubico OTP.</p><p>This is distinct from the TOTP you already know about for generating app codes, and different from using your YubiKey to store TOTP secrets. Here&#x27;s <!-- --><a href="https://developers.yubico.com/OTP/OTPs_Explained.html">more detail about Yubico OTP</a><!-- -->.<!-- --><sup><a rel="footnote" href="#footnote-26" id="r26">26</a></sup></p><p>The point here is that having a long string accidentally get inputted into whatever application or document you were working on will drive you crazy. It happened to me one time when I was working in <!-- --><a href="https://paulstamatiou.com/building-a-windows-10-lightroom-photo-editing-pc/">Adobe Lightroom</a><!-- --> as I reached over to plug in a USB SD card reader and accidentally tapped the YubiKey in the other USB port.. and let me tell you, Lightroom went crazy and interpreted every keystroke as a command. It took me a while to undo that mayhem.</p><p>Needless to say, I disable Yubico OTP mode on every YubiKey I own. Fortunately, it&#x27;s very easy. Install the <!-- --><a href="https://www.yubico.com/products/services-software/download/yubikey-manager/">YubiKey Manager app</a><!-- --> and uncheck OTP mode:</p><img src="https://turbo.paulstamatiou.com/uploads/2019/09/copyright-paulstamatiou_com-yubikey-disable-otp-mode.png"/><small>On the Interfaces tab uncheck OTP and save.</small></div>
<h2>FAQ</h2>
<h3>Because this is entirely more complex than it should be</h3>
<h3>What is a security key?</h3>
<p>Security keys, security tokens, U2F keys, roaming authenticators, platform authenticators—whatever you want to call them—are hardware authenticators that run public-key cryptography operations in a manner that is entirely isolated from the rest of mobile device or computer. There are two general classes of security keys: internal platform authenticators and external roaming authenticators.</p>
<p>Platform authenticators are integrated inside of a device. They may take the form of an integrated security chip accessible by software for the purpose of web authentication, such as the security chip in the Pixel 3, or biometrics devices like fingerprint readers and facial recognition sensors.</p>
<p>This article has primarily been about other variant: roaming authenticators. These are the little external hardware authenticators you connect to any device (via Bluetooth LE, NFC or USB) to carry out your authentication needs. They communicate with your computer via FIDO CTAP (Client to Authenticator Protocol).</p>
<h3>In one sentence, why is a security key better than an authenticator app for two-factor authentication?</h3>
<p>There are several reasons (view the keys vs TOTP section above), but the main one is that security keys prevent phishing by using public-key cryptography that verifies the domain you&#x27;re attempting to authenticate with is the same one you originally registered your key with.</p>
<h3>What services and browsers support WebAuthn?</h3>
<p>See the compatibility section above. For the most part, support is great across Windows, Linux, ChromeOS, macOS and Android. iOS is getting there with recent Safari support for USB, NFC and Lightning connector security keys. However, many iOS apps and browsers still need to catch up.</p>
<p>As for what websites support FIDO2 WebAuthn (and the earlier FIDO U2F) for two-factor auth, it&#x27;s probably easiest to just log into the website and poke around the security and two-factor auth sections. You can also check <a href="https://www.dongleauth.info/">DongleAuth.info</a> or the <a href="https://www.yubico.com/works-with-yubikey/catalog/">Yubico catalog</a>. FIDO2 WebAuthn also supports passwordless functionality but the vast majority of websites do not support that at this time.</p>
<h3>How often do I need use my security key?</h3>
<p>This depends on the exact implementation for each website, but for the most part: not that often. Most services only prompt for your security key if you are using an untrusted browser or device. For example, after logging in the service will mark your browser as trusted for 30 days, or until you log out. However, if the service thinks something is weird like you are logging in from a different IP in another country or you&#x27;re in a new browser, you will need to do the full two-factor auth login with the security key.</p>
<p>For mobile apps like Gmail, it seems to not automatically expire the trusted client status. You only need to present the security key the first time you add your Google account to the phone.</p>
<p>Whether this means you should carry around your security key with you at all times is up to you. But if you&#x27;re traveling, I would definitely take it. And a second key as a backup (assuming you still have a spare somewhere else safe) that you store in a different place while traveling. This is similar to how I travel with SD cards when on photography trips. I keep a set of SD cards on me and a duplicate set of SD cards (or imported to my computer if traveling with one) at my lodging, until I&#x27;m able to get home and <a href="https://paulstamatiou.com/storage-for-photographers-part-2/">load it on my NAS</a>.</p>
<h3>What happens if I lose my security key?</h3>
<p>You just log in with your spare security key and remove the security key you lost from the account. Easy.</p>
<p>To get more specific: This depends on the service, but it&#x27;s almost certainly the case that you have several other second factors you can use to login with (be it backup security keys or TOTP authenticator apps) or that you have a recovery method configured (email reset or recovery code). Since you are still able to log into your services, you just need remove the lost security key from your account. That&#x27;s why naming the key something specific, like the model name of the key, is handy to help you figure out which key to remove from the account.</p>
<p>Removing the lost security key also protects you in case you happen to lose your remaining second factor key(s) or do something like accidentally wipe a phone that had your only TOTP authenticator app that wasn&#x27;t backed up. If that happened, the service would still think you have your second factor handy and would prevent login. Of course, depending on the service and how you configured it, it might still allow recovery.</p>
<h3>What happens if <em>someone else</em> gets access to my security key?</h3>
<p>The short answer here is that you&#x27;re still protected. Someone can&#x27;t use your security key to log in as you wherever you have it registered as your second factor. For one, it&#x27;s a <em>second</em> factor. They would still have to know your username and password. Second, they would have to know what websites you have your key registered with. And they cannot get that from the security key—it doesn&#x27;t even exist in the key. This gives you enough time to remove the key from your account when you notice it&#x27;s lost or stolen.</p>
<p>The more complicated answer emerges if we begin talking about newer FIDO2 functionality intended for passwordless authentication. FIDO2 resident key credentials are a way of storing the username along with other data on the actual security key itself. When the server requests a credential from the client and only provides the origin to the key, the key has to know which resident (on the key) credential to provide. If there are multiple resident credentials for that website, it must provide a way for the user to select which credential to use.</p>
<p>Needless to say, the security key itself needs to have this info locally for this functionality and as such, there is a way for someone with access to your security key to list out the saved resident credentials.</p>
<p>However, it&#x27;s important to note that this can be safeguarded with an optional user verification step requiring a PIN or biometric (PIN is more well-supported today). This only applies to services utilizing resident key credentials, which seems like it&#x27;s only going to be single factor passwordless and not multi-factor passwordless configurations that have that extra verification step.</p>
<p>And finally, it seems like the ability to list out all resident key credentials is nascent, with only <a href="https://support.yubico.com/support/solutions/articles/15000027138-yubikey-5-2-3-enhancements-to-fido-2-support">Yubico starting to offer this ability</a>.</p>
<p>But for the most part, unless part of a highly targeted attack, chances are anyone that found the key would think it&#x27;s a broken USB memory stick. Or if they know what it is, they could start using it themselves for their own U2F/etc needs and it would work just fine. You should be more concerned about attackers stealing your info online. Using a security key as intended is your best defense there.</p>
<h3>Can I log into my Mac, Windows PC or Linux computer with my security key?</h3>
<p>Support for using your security key to log into your computer is varied and in most cases will require a Yubico brand YubiKey, not a regular security key from another provider that lacks certain functionality.</p>
<p>Support for Windows login has had some ups and downs over the years but it just became officially supported with the new <a href="https://www.yubico.com/2019/10/yubico-login-for-windows-now-generally-available/">Yubico Login for Windows</a>. Unfortunately, setting it up <a href="https://support.yubico.com/support/solutions/articles/15000028729-yubico-login-for-windows-configuration-guide">seems quite involved</a>. It used to work with YubiKey 4 series keys alongside a Windows program called YubiKey for Windows Hello but that <a href="https://support.yubico.com/support/solutions/articles/15000006472#enableCCID">was deprecated</a> and Yubico then pointed customers to a much older implementation called <a href="https://www.yubico.com/wp-content/uploads/2016/06/Windows-Login-YubiKey-Configuration_en.pdf">YubiKey Windows Logon</a>.</p>
<p>MacOS users can <a href="https://support.yubico.com/support/solutions/articles/15000006478-getting-started-with-the-yubikey-on-macos">use certain YubiKeys</a> to log into their computers, but installation is definitely left to advanced users. And the story is the same with Linux: it&#x27;s possible but challenging to configure the <code>pam_u2f</code> module properly.</p>
<h3>Why does my YubiKey print out a bunch of random characters when I tap it?</h3>
<p>If you tap your YubiKey—this only applies to YubiKeys— while your cursor is focused on any sort of input field, it may spew out a ton of seemingly-random characters. It&#x27;s triggering a proprietary feature called Yubico OTP that is unrelated to standardized FIDO2/WebAuthn stuff. You can easily <a href="#pro-tip-disable-yubico-otp-mode">disable Yubico OTP mode</a> on your YubiKey.</p>
<h3>What else can security keys do?</h3>
<p>Yubico brand YubiKeys feature a variety of technologies beyond FIDO U2F and FIDO2 capabilities, including: PIV/Smart Card, OpenPGP, OATH-HOTP/OATH-TOTP and Yubico OTP. You can manually configure your key to store ssh keys, GPG private keys, sign your git commits and more. It was also recently announced that <a href="https://marc.info/?l=openssh-unix-dev&m=157259802529972&w=2">OpenSSH will be receiving support for U2F</a>, enabling your security key to be your keypair.</p>
<p>Personally, I find one of the more intriguing YubiKey uses is using it for TOTP code generation. This is handy for websites that don&#x27;t yet support FIDO U2F or FIDO2 security keys but do support TOTP authenticator apps. Once configured, the YubiKey can store up to 32 credentials. They are accessible by plugging in your key and opening up the desktop or Android Yubico Authenticator app. Yubico has hinted that iOS app is on the way (<strong>Update:</strong> <a href="https://apps.apple.com/us/app/yubico-authenticator/id1476679808">Yubico Authenticator for iOS is out now</a> and supports the YubiKey 5Ci and NFC keys).</p>
<h2>What&#x27;s next?</h2>
<h3>A recap and look at the future of web authentication</h3>
<p>Today we learned about improving your online security through several facets from using a password manager, removing your phone number from your online accounts and then migrating to security keys to protect against phishing attacks. However, being diligent about your online security and using security keys won’t protect you from every attack vector. If everyone began using security keys overnight, attackers would focus all their efforts on other attack vectors.</p>
<p>Not everyone needs the most paranoid level of security. It&#x27;s always a trade-off between security and convenience. The more paranoid you get, the more likely you are to just lock yourself out of accounts.</p>
<p>On top of that, we need more sites to treat security keys as first class citizens. I can&#x27;t even use multiple security keys on Amazon AWS yet and that&#x27;s the place you would think would need it the absolute most. Why can&#x27;t I opt out of SMS entirely on every service? Why don&#x27;t more services let me only allow security keys as my <em>only</em> type of second factor?</p>
<p>As much as I want to evangelize how great security keys are today, lets face it— they&#x27;re kinda annoying. You have this new device—probably several—to keep track of now. I don&#x27;t expect everyone reading this post to go out and start using security keys right away. We shouldn&#x27;t have to go through this much trouble to be a bit safer online.</p>
<hr/>
<p>The goal post with FIDO2 lies one step beyond what I&#x27;ve talked about here today about using these security keys as a second factor for two-factor authentication. The vision is around using devices you already have—phones with face scanning cameras, laptops with fingerprint readers, maybe even smart watches one day—to help authenticate you on websites securely.</p>
<p>The hope is that authentication may happen as <em>passwordless</em> but I really think that is a hard concept for people to grok after decades of being primed on how passwords work. I&#x27;ll be keeping a keen eye on this space over the next decade.</p>
<h3>Recap</h3>
<h3>Because this was long and complex</h3>
<ul>
<li>
<p><strong>Seemingly everyone is getting hacked today.</strong> SIM port and SIM swap attacks involve someone taking over your phone number, typically by socially engineering your mobile phone carrier. With access to your phone number, attackers can rely on your various online accounts having your phone number added as a two-factor auth method with SMS. Attackers can then begin gaining access to every such account (or via your email) and wreak havoc on your digital and financial assets.</p>
<p>These attacks are becoming more common. If part of a targeted attack, it may not even matter if you have a PIN/passphrase set with your mobile carrier.</p>
</li>
<li>
<p><strong>Don&#x27;t use SMS for two-factor auth.</strong> Google has shown that utilizing SMS as a second factor is still beneficial (compared to not having two-factor authentication at all) for automated attacks using stolen credentials, such as from data breaches. However, SMS is horrible for targeted attacks.</p>
<p>But, in an abundance of caution, it is highly recommended to remove phone numbers and SMS recovery methods from every account where possible. Enable two-factor authentication everywhere and start with using an authenticator app/TOTP code generator for the second factor instead of SMS.</p>
</li>
<li>
<p><strong>You can increase your online security in a number of ways.</strong> There are numerous other <a href="#security-best-practices">security precautions and best practices</a> one can follow depending on their threat model and comfort with increased inconvenience for enhanced security. The first and most highly-recommended is using a password manager, like 1Password. Further down the line, you may want to switch your mobile carrier to <a href="https://g.co/fi/r/NTP35E">Google Fi</a> and <a href="#enable-google-advanced-protection">enable Google Advanced Protection</a> for your Google accounts.</p>
</li>
<li>
<p><strong>Using a security key for two-factor auth prevents phishing.</strong> These tiny little devices are secure cryptoprocessors that utilize public-key cryptography to generate unique key pairs for every website. The website stores the public key while the private key remains isolated on the security key, inaccessible to even malware running on the machine.</p>
<p>Security keys take the origin/domain of the website into account and will not allow successful authentication, even if the user is tricked into using it on a look-alike phishing site. This is something that authenticator/code generator apps cannot do. There are <a href="#security-keys-vs-auth-apps">other benefits too</a>.</p>
</li>
<li>
<p><strong>Security keys are just one part of the larger FIDO2 vision.</strong> Security keys live under an umbrella called FIDO U2F and a newer (and backwards compatible with FIDO) FIDO2 moniker. FIDO2 introduces a browser Web Authentication API along with a modern protocol for communicating with hardware called CTAP2. FIDO2 leads the way to a simpler and stronger online authentication with support for more devices, including biometrics already integrated into devices, as well as strong passwordless single-factor and multi-factor auth.</p>
</li>
<li>
<p><strong>Security key support is getting better</strong>—both websites that support it as well as browsers/devices—but it&#x27;s not ubiquitous. It&#x27;s not the best user experience today. You shouldn&#x27;t have to carry around a separate device just to be safe online. WebAuthn aims to change that. But for now, security keys—combined with strong online security best practices—are a great way to fortify your regular online activities.</p>
</li>
</ul>
<br><br><br><hr><br><h3>Footnotes</h3><p><a href="#r1">1</a><!-- --> Of course, there are other ways to get your SMS two-factor codes—such as being phished via an official-looking text message to relay an SMS code.</p><p><a href="#r2">2</a><!-- --> And recently, much more with modern "passwordless" functionality that I&#x27;ll dive into later.</p><p><a href="#r3">3</a><!-- --> Despite my entire pre-amble about SMS, it largely <!-- --><a href="https://security.googleblog.com/2019/05/new-research-how-effective-is-basic.html">does help thwart mass attacks</a><!-- -->, as reported by Google. SMS as 2FA can still prove beneficial for automated bots trying to log into sites with your password from a data breach, but does not help much in the face of targeted attacks. This act of trying out stolen credentials on various sites is called credential stuffing.</p><p><a href="#r4">4</a><!-- --> This is a separate functionality that YubiKeys have in addition to typical U2F usage. It can function as a TOTP code generator once a security key is plugged into the device (they have desktop and mobile apps).</p><p><a href="#r5">5</a><!-- -->And about authy: ​​Authy brings convenient multi-device support to the table. Accounts in Authy are encrypted with a passphrase and should be safe even if access is gained to your Authy account. Accessing the app can also be protected via PIN/fingerprint/FaceID. They have, however, had security incidents in the past that scared a lot of folks away.</p><p><a href="#r6">6</a><!-- --> Well.. when it comes to security, it&#x27;s wise to never say never. DNS hijacking is the one attack vector that comes to mind. <!-- --><a href="https://fidoalliance.org/fido-technote-the-growing-role-of-token-binding/">Token binding</a><!-- --> solves this but does not seem widely implemented. The same goes for security key counter checking..</p><p><a href="#r7">7</a><!-- --> FIDO U2F keys were part of the previous version of CTAP, so now they are labeled as CTAP1 under FIDO2. CTAP1 is backwards compatible with the latest FIDO2 CTAP2 protocol. Yea, there’s a lot of nuance in here..</p><p><a href="#r8">8</a><!-- --> I say authentication but this part is user verification, not authentication. The difference is the user is proving itself to the particular device instead of the website.</p><p><a href="#r9">9</a><!-- --> If you want to see an example passwordless auth flow, look at <!-- --><a href="https://www.slideshare.net/FIDOAlliance/webauthn-and-security-keys-126400301">this slide deck from Yubico/Google</a><!-- --> (Start at slide 30).</p><p><a href="#r10">10</a><!-- --> Microsoft.com is the only one that comes to mind.</p><p><a href="#r11">11</a><!-- --> SoloKey, the first open source FIDO2 security key, <!-- --><a href="https://github.com/solokeys/solo/issues/156">supports up to 50 resident keys</a><!-- -->.</p><p><a href="#r12">12</a><!-- --> And if your computer doesn&#x27;t have internal biometrics you can use for this purpose, you don&#x27;t have many options. There aren&#x27;t really any good CTAP2 devices on the market yet that include fingerprint readers. Update (Nov 2019): Yubico has announced that they are <!-- --><a href="https://www.yubico.com/2019/11/yubico-reveals-first-biometric-yubikey-at-microsoft-ignite/">working on YubiKey Bio</a><!-- -->, the first biometric YubiKey that integrates a fingerprint reader for multi-factor auth purposes and does not require any batteries or custom drivers. This makes it ideal for enhancing user verification with biometrics (you can do old PIN-based too) when using passwordless auth. Unfortunately, it seems like this first device is only USB-A, not USB-C.</p><p><a href="#r13">13</a><!-- --> And for United States residents, you could be compelled to provide your <!-- --><a href="https://www.wired.com/2013/09/the-unexpected-result-of-fingerprint-authentication-that-you-cant-take-the-fifth/">biometrics to unlock a device</a><!-- --> and not invoke the Fifth Amendment, unlike a password.</p><p><a href="#r14">14</a><!-- --> They would still need your password but could try credential stuffing from any public data breach and hope to get lucky. Or if you had any malicious software running on your machine when you register a new authenticator, the provided secret key could be captured. I’m really getting into the weeds here, but in general having any shared secret can be seen as another potential attack vector.</p><p><a href="#r15">15</a><!-- -->However, this gets complicated as FIDO2 brings new functionality called resident key credentials. This makes it possible to locally store the additional user data required to make passwordless authentication function, but also introduces the ability to list the stored credentials on the security key. Fortunately, there are ways to <!-- --><a href="https://support.yubico.com/support/solutions/articles/15000027138-yubikey-5-2-3-enhancements-to-fido-2-support">protect against this</a><!-- --> with additional user verification.</p><p><a href="#r16">16</a><!-- --> Unfortunately, Google&#x27;s Titan keys do not support FIDO2 functionality at this time.</p><p><a href="#r17">17</a><!-- --> I have yet to come across another service that has an iOS app that allows it to utilize paired Bluetooth security keys like Google Smart Lock does.</p><p><a href="#r18">18</a><!-- --> Unless you are okay with using Brave browser along with the YubiKey 5Ci.</p><p><a href="#r19">19</a><!-- --> The Google Titan Bluetooth key is frustrating to use as there&#x27;s no way to turn it off completely and it always turns itself on and blinks forever when in my bag or pocket, eventually draining itself so you need to have a Micro-USB cable handy.</p><p><a href="#r20">20</a><!-- --> Yubico also has FIPS versions of their keys that meet certain compliance requirements for special needs but they do not support FIDO2 (yet) so I would not recommend unless you know you need a FIPS 140-2 key.</p><p><a href="#r21">21</a><!-- --> Technically the Google Titan Bluetooth key also has NFC but it&#x27;s not FIDO2.</p><p><a href="#r22">22</a><!-- --> I go into more detail about this "what happens if I lose my key" scenario in <!-- --><a href="#faq">the FAQ below</a><!-- -->. This assumes you were able to log back into the website with your backup/spare key (or other form of second factor.. went through an account recovery flow) and want to prevent it from being used by an unauthorized person that finds it (this would be hard as they wouldn&#x27;t know what account/username was registered to it.. but I go into detail about this in the FAQ too) or prevent you from getting locked out in the future.</p><p><a href="#r23">23</a><!-- --> A few caveats: it may not be the next time you log in if the service has you marked as using a trusted client. This depends on the service and how they categorize trusted clients. It could depend on a time period, different IP/location, new browser, et cetera.</p><p><a href="#r24">24</a><!-- --> Most websites that support security keys today tend to only support FIDO U2F and not FIDO2 WebAuthn. But that&#x27;s fine for two-factor auth purposes. You&#x27;re still accomplishing what we came here to do with this article: enhance your online security, prevent phishing.</p><p><a href="#r25">25</a><!-- --> Adding an enhanced, local user verification step like this to your passwordless single factor makes it passwordless MFA (multi-factor authentication).</p><p><a href="#r26">26</a><!-- --> There&#x27;s also some, arguably paranoid, concern that you can be tracked across multiple accounts and websites by using Yubico OTP mode as part of the string used contains the device identifier of your key.</p>]]></description>
            <link>https://paulstamatiou.com/getting-started-with-security-keys</link>
            <guid isPermaLink="true">https://paulstamatiou.com/getting-started-with-security-keys</guid>
            <dc:creator><![CDATA[Paul Stamatiou]]></dc:creator>
            <pubDate>Mon, 21 Oct 2019 00:00:00 GMT</pubDate>
        </item>
    </channel>
</rss>