<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Mike Bifulco</title>
        <link>https://mikebifulco.com</link>
        <description>Resources for modern software designers and developers.  Tips and walkthroughs on using developer tools like React, node, and javascript.</description>
        <lastBuildDate>Wed, 03 Jun 2026 18:51:15 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>All rights reserved 2026, Mike Bifulco</copyright>
        <item>
            <title><![CDATA[CSS Tips Part 2 - text-wrap: pretty will make your text feel intentional]]></title>
            <link>https://mikebifulco.com/posts/text-wrap-pretty-for-subtle-visual-balance</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/text-wrap-pretty-for-subtle-visual-balance</guid>
            <pubDate>Thu, 30 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Go beyond balance. Learn how text-wrap: pretty improves readability, reduces awkward breaks, and makes your UI feel more polished.]]></description>
            <content:encoded><![CDATA[
## Part 2: A Slightly Smarter Wrap

In the last post, we talked about `text-wrap: balance` and how it makes headings feel cleaner and easier to read.

Where `balance` is perfect for making your headings feel cleaner and a little easier to read, `pretty` is here to make paragraphs feel _just right_.

In short: `text-wrap: pretty` helps make sure the last sentences in paragraphs don't end up with an orphaned word or two on their last line.

## What is text-wrap: pretty?

`text-wrap: pretty` is a newer CSS value that tells the browser to avoid awkward line breaks when wrapping text.

Instead of just filling lines as efficiently as possible, the renderer uses an algorithm to make better decisions about where lines should break, rather than the default behavior, which uses the "play it as it lies" approach you're probably familiar with.

Fundamentally, it means fewer orphaned words at the end of paragraphs, and fewer cases where multiple consecutive lines have hyphenated breaks.

It is subtle, but the end result is a lot more like hand-laid typography from the golden age of print.

### Why this matters: Better UX

Reading is not just about words. It is about flow.

When a line breaks in an awkward place, your brain has to do a tiny bit of extra work. That cost is small, but it adds up across a page.

Good typography removes friction.

This ties directly into a few UX principles:

- **Cognitive load**: Cleaner line breaks reduce micro-interruptions while reading
- **Orphan prevention**: Avoiding a single word stranded on its own line keeps the reader's eye moving naturally
- **Aesthetic usability effect**: Cleaner text feels easier to use, even if nothing else changed

Most people will never point at your site and say “nice line breaks.”

But they will feel the difference.

### Pretty vs Balance

These two are easy to confuse, but they solve different problems:

- `text-wrap: balance` → makes lines similar in length (great for **headings**)
- `text-wrap: pretty` → avoids awkward breaks (great for **paragraph text**)

## See it in action

On desktop, drag the slider to narrow the column. On mobile, tap the toggle and adjust width to compare — watch what happens to the last line of each paragraph.

<TextPrettyDemo />

<br />

## How to use it: CSS

```css
p {
  text-wrap: pretty;
}
```

That is it.

Like `balance`, this is one of those rare features that gives you a real UX improvement for almost no effort.

## How to use it: Tailwind

Tailwind now supports this as well:

```html
<p class="text-pretty">Your text here</p>
```

If you already adopted `text-balance` for headings, this pairs nicely with it.

## Can I use it yet?

In general, yes. According to [Can I Use](https://caniuse.com/wf-text-wrap-pretty), it is supported by most major browsers. The good news is that the fallback is harmless: the text will wrap as it normally would without the property.

So: go for it! Use this rule where it makes sense in your page designs. There's essentially no downside.

## Related Reading

- [W3C CSS Text Module Level 4: text-wrap](https://www.w3.org/TR/css-text-4/#text-wrap) official specification
- [Chrome Developer blog: Text Wrap Pretty](https://developer.chrome.com/blog/css-text-wrap-pretty)
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Optimizing Your Next.js Site's Fast Origin Transfer and ISR Reads]]></title>
            <link>https://mikebifulco.com/posts/reduce-nextjs-bandwidth-with-link-prefetch</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/reduce-nextjs-bandwidth-with-link-prefetch</guid>
            <pubDate>Mon, 09 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Next.js Link prefetching quietly burned through 15 GB of bandwidth on my Vercel-hosted blog. Here's how I fixed it.]]></description>
            <content:encoded><![CDATA[
## A quiet problem I almost missed

I got one of those automated emails from Vercel that made me stop and read it twice.

My personal blog, a mostly static site with no video and lazy-loaded images, had already used more than **15 GB of outgoing bandwidth** for the month. That was roughly three quarters of Vercel's free tier, and the reset was still weeks away.

<Image
  publicId="posts/reduce-nextjs-bandwidth-with-link-prefetch/vercel-email"
  alt="A screenshot of the Vercel email showing a warning about hitting tier limits"
  caption="Wuh oh - work up to an email from Vercel warning about hitting tier limits"
/>

Traffic here is steady, but not especially high. Something didn't add up.

So I did what I probably should have done sooner and opened the analytics dashboard.

## It turned out nothing was wrong

The bandwidth wasn't coming from bots, scraping, or hotlinking. It was coming from **Fast Origin Transfer**, which in Vercel's world is largely driven by prefetching.

Specifically, Next.js `<Link>` prefetching.

By default, every `<Link>` on the page prefetches its destination as soon as it enters the viewport. That's a reasonable default for many apps. Navigation feels instant, and most of the time you never think about it.

On my homepage, though, there are a lot of links visible right away. Post summaries link to articles and tags. The footer includes a long list of tag pages. There are navigation links, social links, and related content.

Altogether, more than **sixty links** were prefetching their target pages the moment someone loaded the homepage. On every visit.

## How Next.js Link prefetching actually works

The short version is that the `<Link>` component in Next.js has a `prefetch` prop that defaults to `true`. In production, any link that enters the viewport automatically fetches the page it points to in the background.

This became more noticeable for me after upgrading to **Next.js 16**, which made prefetching behavior more aggressive by default. The framework is smarter about what it fetches now, but on pages with lots of links, the volume of background requests can still add up quickly. On Vercel, those requests are metered as **Fast Origin Transfer**.

The detail that made this fix viable for my site is that **hover prefetching still happens** even when viewport prefetching is disabled. When someone hovers a link, Next.js will still fetch what it needs before the click.

That means you can keep most of the perceived performance benefit without eagerly downloading dozens of pages that may never be visited.

One important caveat: this behavior depends on which router you're using. On the **Pages Router**, `prefetch={false}` disables viewport prefetching but still allows hover prefetching. On the **App Router**, `prefetch={false}` disables both. If you want hover-only behavior there, you'll need to call `router.prefetch()` yourself on mouse enter.

## The changes I made

Rather than touching every `<Link>` by hand, I added a small wrapper component that flips the default to no viewport prefetching.

```tsx
// src/components/Link/Link.tsx
import type { ComponentProps } from 'react';
import NextLink from 'next/link';

type LinkProps = ComponentProps<typeof NextLink>;

/**
 * Custom Link wrapper.
 * Defaults prefetch to false to reduce background bandwidth usage.
 */
const Link = ({ prefetch = false, ...props }: LinkProps) => {
  return <NextLink prefetch={prefetch} {...props} />;
};

export default Link;
```

Then I updated imports across the site to use this wrapper instead of next/link directly.

```diff
- import Link from 'next/link';
+ import Link from '@components/Link';
```

For the small set of links people are most likely to click, primarily the main navigation, I opted back into prefetching explicitly.

```tsx
<Link href="/newsletter" prefetch>
  Newsletter
</Link>
```

That keeps the interface feeling fast where it actually matters.

## The results

The number of background prefetch requests dropped immediately. Instead of sixty-plus fetches on every homepage visit, only a handful of intentional ones remained.

Based on early numbers and bundle sizes, I'm seeing something in the range of a 40 to 60 percent reduction in bandwidth usage. That's the difference between flirting with Vercel's free tier limits and staying comfortably under them.

| Metric               | Before            | After                   |
| -------------------- | ----------------- | ----------------------- |
| Viewport prefetch    | All visible links | Primary navigation only |
| Hover prefetch       | Yes               | Yes                     |
| Background bandwidth | ~15 GB/mo         | Estimated 6-9 GB/mo     |

## When this is worth doing

This pattern makes sense if:

- You have pages with lots of visible links, like homepages or tag indexes
- Your pages prefetch non-trivial JavaScript bundles or data
- You're on Vercel's free or Pro tier and paying attention to bandwidth
- You've noticed Fast Origin Transfer climbing without an obvious cause
- You recently upgraded to Next.js 16 and saw a usage spike

It's probably not worth the effort if:

- Your pages have very few links
- Navigation speed matters more than bandwidth for your use case
- You're already prefetching intentionally and have bandwidth to spare

## Trade-offs, honestly

The main downside is that the first click to a non-prefetched page might be slightly slower.

In practice, I haven't noticed it. Most people hover before clicking, and hover-triggered prefetching still kicks in. The perceived speed is nearly identical.

The wrapper component adds a small abstraction, but it also gives me a single place to control this behavior site-wide. If Next.js changes their defaults again, and they will, I only have one file to update.

## Follow-up: another important change

After reviewing more of my analytics in PostHog, I realized I was getting _loads_ of traffic from crawlers and bots that were trying to visit arbitrary page numbers on my site by appending them to the URL:

```markdown
https://mikebifulco.com/page/117
https://mikebifulco.com/page/9
https://mikebifulco.com/page/28
```

In an attempt to make my site more friendly to people who somehow got a link to a page that didn't exist, I had set up a server-side redirect that would redirect to the first page -- this redirect was _also_ triggering ISR reads each time it ran.

The change I made here was obvious in retrospect: visit a page that doesn't exist? 404. No additional checks, just the basics. No more ISR reads.

## What I took away from this

- Sensible defaults aren't universal
- Prefetching is powerful, but it isn't free
- A small wrapper component can save real money
- It's worth occasionally checking what your framework is doing on your behalf

This is the kind of issue that only shows up when you've been running your own site for a while. Nothing was broken. It was just quietly inefficient.

## You're not the only one

Once I started digging into this, I realized how common the problem is. There are long-running threads full of developers hitting the same wall: unexpected bandwidth spikes, climbing Fast Origin Transfer costs, and confusion about what prefetch actually does.

If you're dealing with this too, these are worth reading:

- [Next.js prefetching and Vercel high Fast Data Transfer](https://community.vercel.com/t/nextjs-prefetching-and-vercel-high-fast-data-transfer/9154)
- [How to reduce fast origin transfer](https://community.vercel.com/t/how-to-reduce-fast-origin-transfer/23551)
- [Please allow to globally disable prefetching](https://github.com/vercel/next.js/discussions/24009)
- [`<Link>` prefetching behavior](https://github.com/vercel/next.js/discussions/60581)

If you've run into similar surprises, I'm always curious to hear about them. You can find me on [Bluesky](https://bsky.app/profile/mikebifulco.com) or [Threads](https://threads.net/@irreverentmike).
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Patching NPM Dependencies with pnpm patch]]></title>
            <link>https://mikebifulco.com/posts/patching-npm-dependencies-with-pnpm-patch</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/patching-npm-dependencies-with-pnpm-patch</guid>
            <pubDate>Tue, 11 Nov 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Learn how to patch NPM dependencies with pnpm patch to fix issues with your project.]]></description>
            <content:encoded><![CDATA[
## Introduction

Sometimes a third-party package breaks, and you can't wait for a PR to make its way into a release. Fortunately, `pnpm patch` makes it dead simple to hotfix packages locally while keeping your version control clean.

Recently, we needed to patch the [`@payloadcms/storage-uploadthing` package](https://www.npmjs.com/package/@payloadcms/storage-uploadthing) to fix a bug with image loading, so that we could continue to use it as our image hosting provider for [Craftwork](https://craftwork.com)'s implementation of [Payload CMS](https://payloadcms.com).

Here's how we handled it, using `pnpm patch`.

### What is pnpm patch?

[`pnpm patch`](https://pnpm.io/cli/patch) is a tool provided by the pnpm package manager that allows you to patch packages locally—and commit those changes cleanly. It works by creating a patch file that contains the changes you want to make to the package. You can then apply the patch file to the package using `pnpm install`.

## The process

Patching a package is a three-step process:

1. Track down the bug
2. Create a patch file
3. Apply the patch file to the package

Let's go through each step in detail.

### Step 1: Track down the bug

In our case, we tracked the bug down by making changes to the `handleUpload` function in `@payloadcms/storage-uploadthing`. You can do this in two ways:

1. Dig into `node_modules/@payloadcms/storage-uploadthing/src/...` directly
2. Or, clone the repo and search from there if you want to keep your project folder clean

We worked directly inside `node_modules` to validate the fix quickly. One thing to keep in mind here is that running `pnpm install` will overwrite your changes to the package -- which is eactly why we need to use `pnpm patch` to create a persistent patch!

### Step 2: Make a Local Fix

Once you've got a fix in mind, try it out directly in your project. You will do this by making temporary edits right inside the installed version of the package within your IDE.

<Aside type="note">
  In our case, the fix for `@payloadcms/storage-uploadthing` involved some minor changes:

  - the `handleUpload` function wasn't setting a `url` field based on the UploadThing API's response, so our Payload db didn't have any image URLs stored.
  - the `disablePayloadAccessControl` setting was commented out, which caused payload to store _local_ image URLs instead of UploadThing's public URLs.
</Aside>

Once we saw that this fix solved the issue in development, it was time to commit it to source control using `pnpm patch`.

### Step 3: Create a Persistent Patch with pnpm patch

<Image
  publicId="posts/patching-npm-dependencies-with-pnpm-patch/patch-process-1"
  alt="A screenshot of the terminal showing the output of the `pnpm patch` command"
  caption="The `pnpm patch` command opens the dependency's code in a temporary directory for you to edit."
/>

To preserve your fix and commit it to source control:

1. run: `pnpm patch <package-name>`. This opens the dependency's code in a temporary directory for you to edit.
2. Reapply the fix in the temporary folder.
3. Test it - do everything you would typically do to make sure the fix works: test functionality, run linters and test suites, etc.
4. To complete your patch and ready it for addition to source control on your project, run: `pnpm patch-commit <package-name>`

That saves the patch to your repo, and pnpm will re-apply it automatically every time you install dependencies. It also modifies your `package.json` to reference the patched version.

This will add a new entry to your `package.json` like this:

```json
"@payloadcms/storage-uploadthing": {
  "patches": {
    "@payloadcms/storage-uploadthing": "patch/@payloadcms/storage-uploadthing.patch"
  }
}
```

...as well as a file in your project's `patches` directory that represents the patch itself, in git diff format. This file type is a little difficult to read. You can re-open your patch file in your code editor to see the changes. Your changes will also be reflected in your `pnpm-lock.yaml` file.

This will cause pnpm to apply the patch every time you install dependencies.

### If you need to edit your patch

This is one part of the workflow that leaves a bit to be desired - if you need to edit your patch later, the best workflow I've found is to remove the patch from your project by running: `pnpm patch-remove <package-name>`, and then start a fresh patch by running: `pnpm patch <package-name>` (and going through these steps again).

You _can_ edit the `.patch` file directly, but it's finicky. In most cases, it's easier to remove and re-create the patch.

### Closing the loop with the package maintainer

Your dependency is now patched, and you can commit it to source control to use. This can help provide evidence to open source maintainers that the fix is needed, and that it works. It's good practice to [open a pull request](https://github.com/payloadcms/payload/pull/14250) to the package maintainer with your fix so that they can review it and merge it into the main branch.

### When it's time to remove the patch

Once there is an upstream fix in place, you can remove the patch from your project by running: `pnpm patch-remove <package-name>`.

This will remove the patch from your `package.json` and the `patches` directory, and you can then commit the changes to source control.

Remember that this doesn't automatically update the dependency in your project to the latest version - you'll still need to use `pnpm install` to do that.

---

## Why this process is useful

- You don't need to wait on library maintainers to merge PRs to get your fix into your project
- Your fix lives in version control, so teammates and CI builds stay in sync
- It's a fast, repeatable way to patch packages without publishing a fork

## Not using pnpm?

If your team is using a package manager other than pnpm, there are other options that are very similar:

- for `yarn` you can use [`yarn patch`](https://yarnpkg.com/cli/patch)
- for `bun` you can use [`bun patch`](https://bun.com/docs/pm/cli/patch)
- for `npm` you can use [`npx patch package`](https://www.npmjs.com/package/patch-package)
- if you're using ruby's `bundler`, you're in the wrong place, and you have my sympathies.

The specifics of each of these options are very similar, but vary slightly - refer to the docs linked above for a walkthrough of each.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[CSS Tips - text-wrap:balance will make your sites feel better]]></title>
            <link>https://mikebifulco.com/posts/text-wrap-balance-will-make-your-designs-better</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/text-wrap-balance-will-make-your-designs-better</guid>
            <pubDate>Mon, 23 Dec 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Improve readability with text-wrap: balance. Learn how this simple CSS property creates visually balanced text for better user experience and design polish.]]></description>
            <content:encoded><![CDATA[
## A Quick Win with text-wrap: balance

Here's a ludicrously simple tip to make your website more readable: use the `text-wrap: balance` CSS property. It's one line of CSS, but it makes a noticeable difference in how text appears, especially for headings.

### Why Use text-wrap: balance?

When text breaks across multiple lines, it often creates uneven line lengths, which can feel awkward to read. The `text-wrap: balance` property ensures that text lines are balanced, creating a more visually pleasing and readable layout.

Take a look at these two versions of a heading:

**Before:**

### What is text-wrap: balance?

`text-wrap: balance` is a CSS property designed to improve the visual balance of text that spans multiple lines. By default, when a block of text wraps onto a new line, the lengths of those lines can vary significantly, creating uneven and sometimes awkward breaks.

With `text-wrap: balance`, the browser automatically adjusts the wrapping of text so that the lines are as close to equal length as possible. This makes the text easier to read, and looks great - particularly for headings, short paragraphs, and blockquotes.

### Key Points:

- **Purpose**: Ensures evenly distributed line lengths in multi-line text.
- **Use Case**: Best suited for headings, short paragraphs, or any text that benefits from visual balance.
- **Compatibility**: Works on most modern browsers and gracefully falls back to default text wrapping behavior where unsupported.

By enhancing the balance of text, this property helps to create a polished and professional design with minimal effort.

## See text-wrap: balance in action

Here's a quick side by side example of a heading before and after using `text-wrap: balance`:

<heading className="text-3xl font-bold text-purple-700">
  This is a heading that doesn't have the rule applied; text will break onto a
  new line unevenly
</heading>

<br />

And by contrast -

<br />

<heading className="text-balance text-3xl font-bold text-purple-700">
  This is a heading that will feel nicely balanced if it spills onto a new line
</heading>

(Note: you may need to resize your browser window to see the difference)

## How to use it: CSS

One little line of CSS does the trick:

```css
h1,
h2,
h3,
h4,
h5,
h6 {
  text-wrap: balance;
}
```

## How to use it: Tailwind

Recent releases of Tailwind have built-in support for `text-wrap: balance`. You can start using it with the `text-wrap-balance` class.

```
<h1 class="text-wrap-balance">
  This is a heading taht will feel nicely balanced if it spills onto a new line
</h1>
```

### Browser Support

According to Can I Use, `text-wrap: balance` is supported by approximately 90% of browsers. While there are exceptions (e.g., IE11, Opera Mini, and some niche mobile browsers), the fallback is harmless: the text will wrap as it normally would without the property.

### Why It Matters

Legibility and readability are critical for user experience. There's even a psychological principle-the [Aesthetic Usability Effect](https://mikebifulco.com/newsletter/aesthetic-usability-effect) - that suggests people perceive more attractive designs as easier to use. Balancing your text lines is a subtle but effective way to make your site look polished and professional.

## Try It Today

Improving the look and feel of your site doesn't have to involve a complete overhaul. Small changes like text-wrap: balance can make a big difference. Add it to your site, and give your visitors a better reading experience-one balanced line at a time.

<details>
  <summary className="text-lg font-bold inline ml-4 cursor-pointer text-pink-600">
      Video Transcript
  </summary>

[00:00:00] **Mike Bifulco:** Hey, what's up friends. This is Mike from tiny improvements. I have a ludicrously simple tip for you.

[00:00:03] That's going to make your sites look better with one line of CSS. And I cannot believe how easy this is, which is why I'm making a video about it.

Side by side Demo: Single post

[00:00:10] **Mike Bifulco:** What we're looking at here is my website. I've made a change. That is exactly one line of CSS between this and the version you're about to see.

[00:00:16] And I think the change is tremendous. Take a look at this.

[00:00:21] Again, version one. Version two.

[00:00:23] Version one. Version two. Version one. How to set up self healing, URLs, and next JS for better. SEO. Version two, how to set up self healing, URLs, and next JS for better SEO. I think that's a little more readable. Don't you?

[00:00:38] Maybe he doesn't pronounce enough here. Let's look at a more detailed example.

Side by Side example: Lots of posts

[00:00:41] **Mike Bifulco:** this is my newsletter page, where I list off many newsletters that I've written in the past.

Subscribe to 💌 Tiny Improvements

[00:00:45] **Mike Bifulco:** If you're watching this and you don't subscribe already I would love it if you did. I write a weekly newsletter called tiny improvements with product tips for startup founders, product builders, and indie hackers, based on my experience, building startups in the past and currently building my startup Craftwork, which is a Y [00:01:00] Combinator backed startup.

Looking at the change

[00:01:00] **Mike Bifulco:** now let's take a look at this change here.

[00:01:02] It's much more pronounced when you see it multiple times.

[00:01:04] So, what we're looking at is CSS change that brings balance to text when it breaks across lines. And that is almost exactly what the change is. It is CSS, text balance.

[00:01:14] If I pull this up on the Chrome for developers site, you can see from my pal, Adam Argyle, a super straight forward tutorial on what this thing looks like.

[00:01:24] And the change is pretty easy to see when it's animated like this. Although it's a little hard to describe what's happening is the balanced version is trying to make the text break into lines that are roughly evenly sized.

[00:01:33] So it has a lot more visual balance. It's a little easier to parse because your eyes and jumping from one line to the next isn't quite as far of a distance on the balanced version versus the unbalanced version. It also works with Arabic text, right to left left to right. It doesn't matter.

[00:01:46] There are some limitations here.

[00:01:48] This balance rule works on up to six lines, which means that if you apply it to everything, it won't work for long paragraphs, for example. But the nature of this rule really applies to headings. This is more or less the way that this should be applied [00:02:00] and I'll show you how I did it on my site.

[00:02:01] Next.

Implementation details in Next.js with Tailwind

[00:02:01] **Mike Bifulco:** This is what you have to do to make this thing happen on your site, where you're implementing headings. You need to add a text balance rule to it. This has done with tailwind. So it's applying the text wrap, colon balance CSS property to my headings. And this component happens to apply to all the headings on my site. So it was super easy to do, but if you had to do it somewhere else, it would look something like this. Const balanced, heading. Equals. Return H one style equals there you go.

[00:02:31] Tax rate balance. This would do it. If you need to do it, one-off for some reason, but you could also apply this to block quotes. Like the Google article explained. So const balanced block quote equals tax wrap balance, or in tailwind land, you could do. Class name equals text balance, not work just as well.

[00:02:51] Matter of fact, let's go do this for the block quote on my site too.

[00:02:53] I have this. Lovely block quote, component that I use to render block quotes on my site. And I think it's a reasonable thing [00:03:00] to add text balance here as well. So we're going to do that and that will improve the aesthetics of my site. That's super nice. It's very subtle. People may never notice that this happens, but it should make it so that when your title's going to a second line, the look that much nicer, pretty cool, right? I thought so.

## Can I use it yet though?

[00:03:13] **Mike Bifulco:** Last thing I know what you're thinking. Is this something that I can actually use yet? Well, the good news is pretty much, yes. According to can I use this is used by almost 90% of browsers on the internet, which is fantastic. My apologies to people who use IE 11 opera mini UC browser for Android QQ, browser, Baidu browser, or Caio S browser.

[00:03:32] You're going to have to wait a little bit longer to see nice titles on my site, but in the meanwhile, the fallbacks. All back scenario for this is that your text will rep as it used to, if you're using this rule. So I consider this relatively safe to use.

[00:03:44] It's also already supported by tailwind, which is fantastic.

[00:03:47] I think you should go add this to your site and give it a shot. Legibility and readability are really important for user experience. And there's this thing called the aesthetic usability effect that the better looking your site is the better looking your product is.

[00:03:58] The more people will [00:04:00] inherently like it. It's a scientifically proven thing that, the better looking something is the more people put value in it.

[00:04:05] So why not? I don't want line change like this.

[00:04:07] That gets you some real wins for free.

[00:04:09] All right.

[00:04:09] That's a quick tip. I hope it's helpful for you until next time.

[00:04:12] My name is Mike Bifulco. This is a tiny improvements. Give them hell out there.

[00:04:15] ​

</details>
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Content creation workflow: my writing process]]></title>
            <link>https://mikebifulco.com/posts/content-creation-workflow-my-writing-process</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/content-creation-workflow-my-writing-process</guid>
            <pubDate>Sun, 22 Dec 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Learn how I write and publish content on my Next.js site using Markdown and MDX, and a custom content creation workflow.]]></description>
            <content:encoded><![CDATA[
## My writing workflow

I have worked diligently to develop a writing workflow that keeps me productive and focused on writing, rather than getting hung up on the tools I use to write.

### A little about me

I'm Mike Bifulco, a software engineer and designer. I work as CTO and Cofounder of [Craftwork](https://craftwork.com) (Y Combinator S23), and I publish a weekly newsletter called Tiny Improvements to a focused audience of startup founders, product builders, and indiehackers.

I have worked in developer relations and content creation since about 2017, and have been publishing content on [mikebifulco.com](https://mikebifulco.com) since 2019.

Along the way, I've learned a lot about how to write and publish content, and I've developed a workflow that keeps me productive and focused on writing, rather than getting hung up on the tools I use to write.

My site is built with Next.js, and I use Markdown (and something called MDX) to write posts.

Sharing my work online has created endless connections and opportunities for me; if I had never hit the `publish` button on my work, I would not be where I am today.

### Why workflow matters

Time and time again, I've seen aspiring writers, devrel-ists, and content creators waste weeks, months, and sometimes years trying to get everything _just right_ before they share their work with the world. That is a waste of time, and it's a shame.

Regardless of who you are, the tools you use, and what you're writing about, landing on a workflow that works for you is the first step to getting started.

If the work you're creating is good, you've got a great foundation to stand on. Sharing your expertise and knowledge with your community starts there - the rest is just details.

## How I publish content on my Next.js site with Markdown and MDX

For all content on my site, my authoring workflow looks like this:

### Write in Markdown

<Image
  publicId="posts/content-creation-workflow-my-writing-process/writing-screenshot"
  alt="A screenshot of my IDE with a Markdown file open"
  caption={
    <span>
      writing new posts looks a whole lot like{' '}
      <a href="https://mikebifulco.com/posts/self-healing-urls-nextjs-seo">
        this
      </a>
      .
    </span>
  }
/>

1. I write in [Markdown](https://daringfireball.net/projects/markdown/). This makes it easy to write without distraction, and keeps my writing process focused on _what_ I should be saying, rather than how it looks.
1. I create a file for each new post in [the source code for my site](https://github.com/mikebifulco/blog) under the `src/data/newsletters` directory, as a single `.mdx` file with a small amount of frontmatter (title, desctiption, tags, slug, and a cover image).

### Every article needs a cover image

<Image
  publicId="posts/content-creation-workflow-my-writing-process/figma"
  alt="A screenshot of a Figma file with a cover image for an article"
  caption={
    <span>
      <a href="https://mikebifulco.com/newsletter/open-sourcing-my-design-system">
        I use Figma
      </a>{' '}
      to create cover images for all of my articles.
    </span>
  }
/>

1. For every article, I create a `1200 x 630px` cover image in [Figma](https://mikebifulco.com/newsletter/open-sourcing-my-design-system). This is the image you'll see on social media sites when a link to my articles is shared. Any other images included in the body of a post are created the same way, and are generally the same size.
1. I use [Squoosh](https://squoosh.app) to compress and optimize any included images, and then upload them to [Cloudinary](https://cloudinary.com) as `.webp` files.

### Commit, merge, and publish

<Image
  publicId="posts/content-creation-workflow-my-writing-process/pull-request"
  alt="A screenshot of a pull request for this very post in GitHub"
  caption="This is what a pull request looks like for this very post."
/>

1. When I'm done writing and ready for a newsletter to go live on my site, I commit the changes to a new branch, and open a pull request _to myself_ to merge the changes into the `main` branch. This generates a preview build of the new page on Vercel, where I can check out the changes and make sure everything looks good before merging.
1. After the PR is merged, Vercel automatically builds the site and deploys the changes, and the article is live in a few minutes.

## After I publish: sharing my work

**The most critical part of this process is sharing my work with the world.**

Once a post goes live, I run off to social media and start _sharing my work_ with the world - on Bluesky, on Threads, on LinkedIn, and on Reddit. The ins and outs of that process is a whole other article, but I'll say this: it's just as important as _actually publishing something_.

## Go hone your process

Here's the thing: this is _my_ workflow - it works great for me, because I built it around my own preferences and needs. As you're designing your workflow for publishing, take advantage of the things your brain likes.

Is it easier for you to write in Notion? Great! Start there. Is Markdown a pain in the butt? Skip it and use something that you like better. There's no right anwers here - the only thing that matters is that you actually get over the hump and _publish something_.

Once you've published something, you can iterate from there.

Good luck!
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Migrate from next-sitemap to the Next.js App Directory's sitemap]]></title>
            <link>https://mikebifulco.com/posts/migrate-from-next-sitemap-to-app-directory-sitemap</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/migrate-from-next-sitemap-to-app-directory-sitemap</guid>
            <pubDate>Sat, 23 Nov 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[This post walks through the process of migrating from the next-sitemap library to the Next.js App Directory's sitemap.]]></description>
            <content:encoded><![CDATA[
## Transitioning from next-sitemap to Next.js's Built-in Sitemap.xml and Robots.txt APIs

In this post, I'll walk you through the process of migrating from the next-sitemap npm package to using Next.js's built-in API for generating sitemap.xml and robots.txt files. This transition not only simplifies our codebase but also leverages the capabilities of Next.js to enhance our SEO strategy.

### Why Migrate?

The [next-sitemap npm package](https://github.com/iamvishnusankar/next-sitemap) was a great tool for generating sitemaps, but as Next.js has evolved, it has introduced built-in support for sitemap and robots file generation. This change allows for a more streamlined approach, reducing dependencies and improving maintainability.

Admittedly, I have also been a bit of a laggard in updating my site to the new app directory - this is actually the _very first_ use of App Router on this site!

## What is a sitemap?

A sitemap is a file that lists all the URLs on your site, helping search engines discover and index your content. It provides a roadmap for search engine crawlers to navigate your site and understand its structure. They're also used by other services like Google Search Console to understand your site's structure. If you haven't used Google Search Console, it's an invaluable resource for measuring your site's search engine performance.

I've written at length about the value of SEO, including the [SEO tools I used to grow my sites to 20k+ visitors/month](https://mikebifulco.com/posts/seo-tools-for-new-projects).

## What is a robots.txt file?

The robots.txt file is a configuration file used to instruct web crawlers (like Googlebot) on how to crawl your site. It allows you to specify which pages should be indexed and which should be excluded, helping control the visibility of your content to search engines. In this case, we're using robots.txt to stop search engines from indexing URLs that we don't want to show up in search results, like Next.js API routes, and other pages that are generated dynamically.

## Removing the next-sitemap dependency

The first step is to remove the next-sitemap dependency from your project:

1. remove `next-sitemap` from your package.json file - make sure to check both `"scripts"` and `"devDependencies"`, and remove it from both places.
2. run `npm install` (or `yarn install` or `pnpm install`) to update your lockfile
3. delete your `next-sitemap.config.js` file if it exists
4. **Important:** If you have `sitemap.xml`, `sitemap-0.xml`, etc. files in the `/public` directory of your repo, delete any that exist. Next won't generate a sitemap file if these are already there - and it can be tricky to debug!

Side note: [`next-sitemap`](https://www.npmjs.com/package/next-sitemap) was a fantastic tool, and served me for quite a long time. I'm super thankful to the maintainers for their work on the package - it filled an important need for a _very_ long time!

## Generating a sitemap.xml file with Next.js

Next.js has a great built-in API for generating sitemaps and robots files. We'll use this API to generate our sitemap.xml and robots.txt files. The API is simple to use and allows for customization of the sitemap and robots file generation process.

There are a couple choices for [creating a sitemap with Next.js](https://nextjs.org/docs/app/api-reference/file-conventions/metadata/sitemap#generating-a-sitemap-using-code-js-ts):

1. **Write and maintain the XML for your sitemap yourself** - this may be okay for really small sites, but you will need to add an entry to this file for _every_ page you want search engines to know about. This quickly becomes cumbersome for sites with dynamic content, or even just a lot of pages.
2. **Use Next.js's built-in API to generate the sitemap.xml file** - I am going to opt for the built-in API because my site has hundreds of pages published, and I don't want to have to maintain a sitemap file with an entry for every single page.

### Configuring the sitemap.xml file

Create a new file in the App directory called `sitemap.ts`:

```tsx
import type { MetadataRoute } from 'next';

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  return [
    // TODO: one entry for every page you want search engines to know about
  ];
}
```

This file is where you will add an entry for every page you want search engines to know about. The goal is to return an array of objects of the following type:

```tsx
type SitemapFile = Array<{
  url: string;
  lastModified?: string | Date;
  changeFrequency?:
    | 'always'
    | 'hourly'
    | 'daily'
    | 'weekly'
    | 'monthly'
    | 'yearly'
    | 'never';
  priority?: number;
  alternates?: {
    languages?: Languages<string>;
  };
}>;
```

A couple things to note here, from the [sitemap spec](https://www.sitemaps.org/protocol.html#xmlTagDefinitions):

1. The `url` property is required and should be the full URL to the page you want to include in the sitemap.
2. The `changeFrequency` property is optional and can be one of the following values: `always`, `hourly`, `daily`, `weekly`, `monthly`, `yearly`, or `never`. This is a _hint_ to search engines about how often the page is likely to change. Google and other search engines may choose to use different values than you specify if it becomes clear that your page changes at a different rate than you specify.
3. The `priority` property is "The priority of this URL relative to other URLs on your site." It is an optional property and can be any number between 0 and 1. If you don't include it, it will default to 0.5 for every page. I recommend setting this to 1 for your homepage, and cascading it down to 0.5 for other pages, depending on their relative importance to your site. It may not actually influence search engine behavior - and it's not a guarantee that a page will rank higher just because it has a higher priority - but it is a useful hint for search engines.
4. `alternates.languages` is a feature of Next.js that allows you to specify alternate versions of your page in different languages. This is useful if you have a blog post that is published in multiple languages, and you want to include all of the versions in your sitemap. I only publish in English (_en este momento!_), so I haven't tested this yet, and it isn't included in this tutorial.

### Populating your sitemap.ts file

#### Static pages

For static pages on my site, I opted for a semi-manual approach to adding them to the sitemap. I created an array of strings that represent the routes I want to include in the sitemap, and then mapped over that array to create the sitemap entries.

```tsx
// Define your static routes
const routes: string[] = [
  '', // home page
  '/about',
  '/integrity',
  '/newsletter',
  '/podcast',
  '/posts',
  '/tags',
  '/work',
  '/shop',
];

// Create sitemap entries for static routes
const staticRoutesSitemap = routes.map((route) => ({
  url: `${baseUrl}${route}`,
  lastModified: new Date(),
  changeFrequency: 'weekly' as const,
  priority: route === '' ? 1 : 0.8,
}));
```

When run, this will generate an array of sitemap entries for each of the routes in the `routes` array - note that the homepage has a priority of 1, and all other pages have a priority of 0.8.

#### Dynamic pages

For pages that are generated dynamically, or hosted by your CMS, the process isn't too different. You will need to fetch the URL of each page you want to include in the sitemap, and then create a sitemap entry for each one. In my case, I have 3 different sources of dynamic content:

1. Newsletters: these are dispatches of my newsletter [💌 Tiny Improvements](https://mikebifulco.com/newsletter), which I send out every week.
2. Blog posts: these are the blog posts I publish on this site (you're reading one right now!).
3. Tags: These are metadata tags I use to categorize my blog posts and newsletters issues. I generate a list of all tags on the site, and then map over that list to create a sitemap entry for each one.

I write all my site content in [`MDX`](https://mdxjs.com/docs/what-is-mdx/), and save them as files in my site's repo under the `src/data/` directory.

I used a utility function to grab all of the newsletter issues, blog posts, and tags from the `src/data/` directory, and then mapped over each one to create a sitemap entry. For newsletters, that looks like this:

```tsx
// this is a helper function used across my site.
// replace with whatever is needed to fetch from the CMS you use
const newsletters = await getAllNewsletters();

// create a sitemap entry for each newsletter
const newslettersSitemap = newsletters.map((newsletter) => ({
  url: `${baseUrl}/newsletter/${newsletter.slug}`,
  lastModified: new Date(newsletter.frontmatter.date),
  changeFrequency: 'weekly' as const,
  priority: 0.8,
}));
```

The same pattern is used for blog posts and tags.

## Sitemap.ts: The complete file

```tsx
import type { MetadataRoute } from 'next';

import { getAllPosts } from '@lib/blog';
import { getAllNewsletters } from '@lib/newsletters';
import { getAllTags } from '@lib/tags';
import { BASE_SITE_URL } from '@/config';

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  const baseUrl = BASE_SITE_URL;

  const newsletters = await getAllNewsletters();
  const newslettersSitemap = newsletters.map((newsletter) => ({
    url: `${baseUrl}/newsletter/${newsletter.slug}`,
    lastModified: new Date(newsletter.frontmatter.date),
    changeFrequency: 'weekly' as const,
    priority: 0.8,
  }));

  const posts = await getAllPosts();
  const postsSitemap = posts.map((post) => ({
    url: `${baseUrl}/blog/${post.slug}`,
    lastModified: new Date(post.frontmatter.date),
    changeFrequency: 'weekly' as const,
    priority: 0.8,
  }));

  const allTags = await getAllTags();
  const tagsSitemap = allTags.map((tag) => ({
    url: `${baseUrl}/tags/${tag}`,
    lastModified: new Date(),
    changeFrequency: 'weekly' as const,
    priority: 0.5,
  }));

  // Define your static routes
  const routes: string[] = [
    '', // home page
    '/about',
    '/integrity',
    '/newsletter',
    '/podcast',
    '/posts',
    '/tags',
    '/work',
    '/shop',
  ];

  // Create sitemap entries for static routes
  const staticRoutesSitemap = routes.map((route) => ({
    url: `${baseUrl}${route}`,
    lastModified: new Date(),
    changeFrequency: 'weekly' as const,
    priority: route === '' ? 1 : 0.8,
  }));

  // combine all the sitemap entries into a single array
  return [
    ...staticRoutesSitemap,
    ...newslettersSitemap,
    ...postsSitemap,
    ...tagsSitemap,
  ];
}
```

### Testing your sitemap

Fire up `next dev` and navigate to `/sitemap.xml` - you should see your sitemap! Make double and triple sure that your sitemap has an entry for every single page you want search engines to know about. You may also want to check that it _updates_ correctly by adding a new page and checking that it appears in the sitemap.

<Aside type="warning">

If it doesn't seem like your sitemap is updating correctly, **remember to check your `/public` directory for sitemap.xml files** that may have been generated by `next-sitemap`, and delete them!

</Aside>

## Creating a robots.txt file

Next up, robots.txt. This is a _very_ similar process - we will follow the [docs for robots.txt](https://nextjs.org/docs/app/api-reference/file-conventions/metadata/robots) from Next.js.

This is a deceptively important file for your website's SEO. It is a really good idea to familiarize yourself with the [robots.txt file format](https://www.robotstxt.org/robotstxt.html), and to understand the meaning of each rule you set.

### Disallow everything for non-production environments

**🚨 Important: ** If you are running a non-production environment, you will need to add a check to your robots.ts file to disallow all requests. This is because non-production environments often have URLs that you don't want search engines to index - it would be bad news if Google decided that a deploy preview of your site should rank higher than your production site!

### Robots.ts: The complete file

Much like static pages for the sitemap, you will need to add an entry for every path you don't want search engines to index.
In my case, I have a reverse proxy in front of my site that handles analytics and logging with PostHog, and I don't want search engines to index those URLs.
You'll see that handled below with `noIndexPaths`.

```tsx
import type { MetadataRoute } from 'next';

import { BASE_SITE_URL } from '@/config';

const noIndexPaths = [
  '/ingest', // posthog's reverse proxy
  '/ingest/*', // posthog's reverse proxy
];

export default function robots(): MetadataRoute.Robots {
  // 🚨 IMPORTANT: if this is not a production environment, disallow all requests
  if (
    // Vercel-specific environment variable. Please check the docs for your hosting provider!
    env.VERCEL_ENV !== 'production' ||
    // for a generic node environment
    process.env.NODE_ENV !== 'production'
  ) {
    return {
      rules: [
        {
          userAgent: '*',
          disallow: '*',
        },
      ],
    };
  }

  return {
    rules: [
      {
        userAgent: '*',
        disallow: '/api/', // Next.js API routes
      },
      {
        userAgent: '*',
        disallow: '/_next/', // Next.js build output
      },
      {
        userAgent: '*',
        disallow: '/public/', // static files like css, images, fonts. This one's up to you!
      },
      ...noIndexPaths.map((path) => ({
        userAgent: '*',
        disallow: path,
      })),
    ],
    sitemap: `${BASE_SITE_URL}/sitemap.xml`,
  };
}
```

A few important callouts here: `BASE_SITE_URL` is a variable I set in my site's config, and it is the full URL to the root of my site (`https://mikebifulco.com`). You will need to replace it with the actual URL of your site.

## Deployment checklist

Now that everything's done, make absolutely sure you've got everything configured correctly. Here's a quick checklist I used to verify that my new sitemap and robots.txt were set up correctly:

```md
**Before going live**, verify that:

- robots.txt
  - [ ] visit `/robots.txt` and verify that it exists
  - [ ] check that there is an entry for your sitemap that contains a full URL, including the protocol (`https://`)
  - [ ] read through the disallow rules to make sure they make sense for your site. If you're using next.js, this will include `/_next/` at a minimum, and possibly `api/` and `public/` if don't want those directories indexed.
- sitemap.xml
  - [ ] visit `/sitemap.xml` and verify that it exists
  - check that it contains the correct entries for all:
    - [ ] static pages
    - [ ] dynamic pages (newsletters, blog posts, tags)

**While testing deploy previews of your site**, verify that:

- [ ] your sitemap is being generated correctly
- [ ] your robots.txt is being generated so that it **disallows all requests** in deploy previews

**After going live**, check that:

- [ ] your sitemap is being picked up and read by [Google Search Console](https://search.google.com/search-console)
- [ ] use something like the [Ahrefs Webmaster Tools Site Audit](https://ahrefs.com/signup?plan=awt&return=website-checker) to scan your site and verify that it is indexed correctly and that there aren't any issues.
```

And that's it! You've successfully migrated from the next-sitemap library to Next.js's built-in sitemap and robots.txt APIs.

## See the code changes I made to my site

If you're curious to see the code changes I made to my site to implement this, you can [view the diff on GitHub](https://github.com/mbifulco/blog/pull/894/files).
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[The results of my PostHog AB Test are in!]]></title>
            <link>https://mikebifulco.com/posts/posthog-ab-test-results-are-in</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/posthog-ab-test-results-are-in</guid>
            <pubDate>Mon, 30 Sep 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[I dive into the data from my PostHog AB Test and show you how to interpret the results.]]></description>
            <content:encoded><![CDATA[
In this video from my Tiny Improvements series, I'm diving into product analytics to improve newsletter signups on my personal site. Join me as I share my engineering process, from discovering a bug with my old provider to setting up an A/B test with PostHog to find the best-performing newsletter signup form. Despite fewer-than-hoped signups, I've gathered key insights to refine my strategy. Plus, a sneak peek into my next steps, like redesigning the signup popup and enhancing site SEO. If you're a startup founder or indie hacker, you’ll find plenty of actionable tips here!

## See the code changes I made in this video

Code changes for this video are available in this pull request are available at [mbifulco/blog#856](https://github.com/mbifulco/blog/pull/856)

## Timestamps for this video

00:00 Product Analytics for Engineers
01:18 The Results are in!
04:09 Code review in Next.js
04:49 I switched from VS Code to Cursor
05:50 Looking at the variant that won
06:31 Ship a variant directly from PostHog
07:30 A surprise I didn't see coming
08:05 What we did and what's next
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[How I found a missing change on my next.js site with PostHog]]></title>
            <link>https://mikebifulco.com/posts/posthog-helped-me-find-a-bug</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/posthog-helped-me-find-a-bug</guid>
            <pubDate>Mon, 02 Sep 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[I tackle a significant drop in my newsletter subscribers. Join me as I dive into the data using PostHog, identify and fix critical errors, and ultimately switch from ConvertKit to Resend.]]></description>
            <content:encoded><![CDATA[
In this video, I discuss my recent efforts to improve the product analytics experience on my website. Over the past two weeks, I addressed a sign-up issue by switching to a new email service and implementing AB testing on my newsletter forms. I analyzed the results, but discovered a bug that prevented complete data collection. I walk through identifying the problem, show the fixes I made, and reset the experiment to gather accurate data. I also encourage viewers to check out the open-source code for my site and invite feedback and questions.

## See the code changes I made in this video

Code changes for this video are available in this pull request are available at [mbifulco/blog#840](https://github.com/mbifulco/blog/pull/840)

## Video Timestamps

00:00 Introduction and Recap
00:44 Analyzing AB Testing Results
02:32 Sponsorship Shoutout
03:01 Deep Dive into Data Analytics
05:41 Fixing Implementation Bugs
08:33 Resetting and Restarting the Experiment
10:28 Conclusion and Next Steps
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Unlocking A/B Testing with PostHog: Improving Newsletter Signups]]></title>
            <link>https://mikebifulco.com/posts/ab-testing-with-posthog-to-fix-conversions</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/ab-testing-with-posthog-to-fix-conversions</guid>
            <pubDate>Mon, 19 Aug 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Optimizing signups by testing, trusting statistics, and fine-tuning UX using data from PostHog]]></description>
            <content:encoded><![CDATA[
## Test, trust the data, and optimize your site for better results

In this video, I dive into A/B testing with PostHog to boost newsletter signups on my site. I walk you through my process-from identifying issues with signups, switching email platforms, to experimenting with different UX elements. I'll show you how to set up and run A/B tests, and explain why trusting the data is crucial for making smart, data-driven decisions. If you're a developer or UX enthusiast, this video will help you refine your own website's user experience.

The code for my site is available on github - you can see the Pull Request for the changes associated with this video here: https://github.com/mbifulco/blog/pull/832

## Watch the first two episodes in this series:

1. [Product Analytics for engineers: Debugging a conversion problem on my next.js site](https://mikebifulco.com/posts/debugging-a-conversion-problem-on-my-nextjs-site)
2. [Fixing the bug behind my Conversion Problem](https://mikebifulco.com/posts/fixing-my-conversion-problem)

## Video Timestamps

- 00:00 Introduction and Series Overview
- 00:35 Identifying the Signup Problem
- 00:59 Switching to Resend
- 01:11 Exploring AB Testing
- 01:19 Sponsorship by PostHog
- 02:11 Website Elements and Hypotheses
- 04:07 Implementing AB Tests
- 05:03 Setting Up PostHog Experiments
- 07:20 PostHog Implementation Details
- 08:31 Testing and Analyzing Results
- 10:52 Tell me what you think!

<details>

  <summary>

    <b>Transcript</b>

  </summary>

[00:00:00] **Mike Bifulco:** Hello, and welcome back to tiny improvements. My name is Mike And since we last talked, I've been working on a problem on my website. This is the third video in a series that I'm doing on trying to get people, to sign up for my newsletter.

[00:00:11] If you're new here, I read a weekly newsletter called tiny improvements.

[00:00:13] That is meant for product developers, startup founders, indie hackers, people who are interested in building products. Where I share the things that I've learned, building products that companies like Google and Stripe and Microsoft, and more recently building a venture capital backed startup I'm co-founder of a company called Craftwork. We went through Y Combinator last summer. And so this is my way of giving back. I'm trying to give away the things that I know for free, because I've been really lucky in my career.

[00:00:34] And I want you to be as lucky as I have been. So since you're here, let's talk about where we've been in the first video. I discovered that I had a problem with signups and people weren't subscribing. I was using convert kit for my newsletter at the time and was having some sort of mystery problem with signups.

[00:00:47] So I added a bunch of telemetry to show me when signups were happening and to try and detect failures from that experience, I found that. I was getting some mystery failures with convert kit in my implementation of my newsletter signup form. And that's [00:01:00] what led me to what I did in the second video, which is where I replaced convert kit with Resend.

[00:01:03] So now I use Resend email platform for both sending my newsletters and getting people to sign up for my mailing list. That's been really nice so far. In this video I'm exploring the next thing I wanted to get into, which is AB testing stuff on my site.

[00:01:16] So let's take a look at that and see what that actually means in practice.

## Sponsored by Posthog

[00:01:19] **Mike Bifulco:** Hey, all this video series is sponsored by PostHog. After seeing my first video, they reached out about a sponsorship, which is really cool.

[00:01:25] And frankly, I'm flattered to see it. I was planning on making these videos either way and that's because I really enjoy PostHog. I also really enjoy building products and seeing things improve over time. . I wouldn't take a sponsorship from something that I don't believe in and don't use, I hope you're enjoying this series and I hope you're learning something.

[00:01:39] If you're really into it, it might also be worth giving. PostHog a shot. One of my favorite things about the platform is that they're free tiers, unbelievably generous. You can get a whole lot out of PostHog for free before paying anything to decide if it's worth it for you.

[00:01:50] There's also a self host option. If you want to go that route and PostHog also has a ton of open source software, which means you can have influence over the product itself.

[00:01:58] I think that's really amazing. And the team has been [00:02:00] super responsive so far. So if you want to check it out, go to PostHog dot com slash Mike Bifulco. There'll be a link in the description. It will let them know I sent you and it means a lot to me.

[00:02:09] Thanks so much. I hope you enjoy the rest of the video.

[00:02:11] Okay, this is my site and this is one of the things that I'm interested in testing to see if I can make a difference in the amount of people signing up.

[00:02:17] When you visit my site, read one of my newsletters or any of the articles on my site. There's a bunch of things that are made available at the top of the pages, a cover image and a title things you're probably used to seeing, I have this nice dynamic. Table of contents, which is really helpful I also record audio versions of some posts, which is why we see this podcast embedded here. if we scroll through the post, when you get towards the end of it, a couple of things happen.

[00:02:36] This pop-up, that just flew in from the left is a thing called polite pop. This is where the first call to action typically comes for someone to subscribe to my newsletter. I've got a couple of hypotheses on how we can do better here. What I want to do is test the copy.

[00:02:48] That's rendered here to see if there's maybe a different treatment, that we can show. To people to get them more compelled to sign up. I might also choose to remove this. It kind of is just an ag and I think people are really well-trained to just dismiss pop-ups and [00:03:00] try and get them out of their face.

[00:03:01] And it's a little bit of a rude experience while you're on a site. I see loads of people coming to my site and clicking this. No thanks button. I've got tons of telemetry on that. That may not be long for this world.

[00:03:09] The other thing that I see, and I think this is worth testing straight away is at the bottom of each post.

[00:03:14] I have this giant banner, which is this big striking thing that says ship products that matter. And I really like this. This is something I workshopped for awhile, trying to come up with a slogan or phrase, something that was sort of attention grabbing. That's supposed to give people a reason to sign up.

[00:03:28] However, I think what I've done here is I built something that is so different from everything else. That's that seen on my site that. By the time you get down here, as you scroll down and you get this great big dark banner that appears, it's pretty obvious that the article is over and then I'm not giving you any more value here. And so what I want to test is if I can replace this with something that's a little more subtle.

[00:03:47] So maybe not a giant banner like this, but something that says, Hey, I write this cool newsletter. I think you might like it. Please subscribe. And maybe Tiki into people's psychology a little bit to keep them reading on the page. watching back some replays of people visiting the site. [00:04:00] It's pretty common to see someone get to about here and go away.

[00:04:02] And if they leave before they get down here, I've lost. So. we're going to try a couple of things here and that's. Where AB testing comes in.

## A-B Testing in PostHog

[00:04:08] an AB test is exactly what it sounds like. I have version a version B and sometimes C D E F a number of different versions of one bit of user experience that I want to test against each other to see how they perform. The idea here is to see that if I do this versus that is one going to get me more people signing up for my newsletter or not.

[00:04:24] **Mike Bifulco:** And we can kind of test some hypothesis from there. Now there's some really important statistics involved in how this works. What I really like is that when you collect data, the math will tell a story. And if you're willing to trust the math and listen to what the statistics say, you can probably make a good data driven decision to move yourself from doing well, to doing better and incremental change over time will do really well.

[00:04:46] But you have to be comfortable with trusting what the statistics say. And let me be the first to tell you that there's a lot to learn about that, and it can be really counter-intuitive. I am far from a statistics expert. I have learned a lot of mathematics in my life.

[00:04:57] You have to learn to trust the statistics. [00:05:00] And so that's what we're going to try to do here. Let me get off my high horse. Let's talk about this. So this is my first experiment is called newsletter banner treatments. So you give it a name, which is a human readable thing, and then our feature flag key.

[00:05:10] So this is the key that we'll use programmatically to make decisions based on this experiment. So I gave it newsletter banner treatments as the key. The description here again is a human readable thing. It's meant for me when I go review these later on to see what this experiment was all about.

[00:05:23] So I may fill this in with more detail, but the idea is I want to test different UX presentations of the newsletter banner that appears at the bottom of articles. To see which one performs best.

[00:05:32] By default PostHog will give you a control, which is the fallback value. So the control is meant to be in scientific method speak.

[00:05:39] That means the thing that we know how it performs and the baseline for the experience right now, that's that big dark banner that I show on my site that I was just showing you that people sort of. Seem to scatter away from. I'm running two tests against that in this case. So I'm going to test a simple implementation and a hero implementation. Those are bits of UI that I've built alternatives for.

[00:05:58] And I'll show you what they look like. [00:06:00] So if I come through and I hit, continue on this experiment, we'll see that PostHog does a little bit of thinking. And it goes to do some give me some numbers on roughly what this would look like. And what I want to check is my newsletter subscribed event.

[00:06:11] So I'm hoping to see more of these newsletter subscribed things happening. With one variant of this versus the other, they'll probably all perform slightly differently. We're going to pick the one that wins out of the three. So. I've picked the event that I want to use. If I go to the next page here, what I get is the goal for the experiment.

[00:06:28] So this now shows me everything in one view. What it's saying at the very top is this is a draft. I haven't actually started it yet. By results are not significant, meaning I haven't collected enough data to make a decision. And the feature flags name is here.

[00:06:39] Down here, we get implementation details from PostHog, which is literally code snippets that you can use in your application. So you can switch through these and see what they look like.

[00:06:47] There's react native there's no, there's Ruby, all kinds of stuff in here. What's really cool is they show you exactly how to do this. So you load the feature flag using the feature flags name. If you have a user ID, like an email address, if someone's logged in, you can pass that [00:07:00] into, they always get a consistent experience per user. And then you make a decision based on what comes back. So the feature flag will say for this person render a simple one. It might come back and say for this person render a hero one and you do different things based on that. So what I'll do is I'll hit launch on this thing, It'll sort of thing for a second and go live and I'll, show you what the implementation looks like, next.

[00:07:20] Okay, implementation time. So I'm using post hogs library called PostHog JS.

[00:07:26] Thanks sports, some really nice react components, which I'm using in this implementation here. So this experiment name, newsletter, banner treatments is what we just saw on the site. These are the three different experiment variants.

[00:07:35] So these are the things that the experiment will tell me to render for different users. And we'll collect data on that. And I'm using a thing called PostHog feature, which is a react component exported by post hog, which takes in the name of the flag. As well as the part of the experiment to match.

[00:07:50] So what this is saying is we're going to do this with the newsletter experiment. So if it comes back and says control, we're going to render this thing, the fancy component, which is the newsletter banner that's currently shown on [00:08:00] the site with the dark background.

[00:08:01] I've created two other variants. The simple one here is based on a fairly standard tailwind component library. And this one called hero is one that I was using on other pages on my site, but wasn't consistently showing on the bottom of articles.

[00:08:13] now I'm taking all three of these things. And for about a third of users, I'll show each one of these and we'll track. How many of them convert to newsletter subscriptions over the next. Week or so, and we'll see what comes back.

[00:08:23] Next thing to see is what this looks like in the browser, because PostHog also provides some tools for you to be able to poke around with these and make sure it works well before you roll it out to your users.

## PostHog's A-B Testing tools in the browser

[00:08:31] **Mike Bifulco:** All right back here on post-talk and here's what I want to show you.

[00:08:35] from any page on PostHog, you can get to this handy thing called toolbar. If I click into this, this gives me the ability to launch a PostHog specific toolbar within the context of my site. So it doesn't really fancy injection of content. And it renders PostHog using what I believe is a Chrome extension.

[00:08:50] And so if I click on this, it's going to load my local host, which I've told is where I'm running my site. This is what the tool bar looks like.

[00:08:55] Typically you'll see it. Like this, when it first comes up and we're really interested in this [00:09:00] feature flags. Functionality here. So there's a bunch of things here. You can do actions and heat maps and all kinds of stuff like that. But let's take a look at feature flags first. I'm going to navigate to one of my newsletters, the most recent one, we were just checking this out and I'm going to scroll to the bottom and I'm going to go to this feature flags thing here and already something looks different, This is not the banner that was showing before. And this is a sign that my experiment is working. you can see here, I can manually override the experiments that I'm seeing personally in development.

[00:09:25] And as I toggle through these, I get three different presentations. this one might look familiar. This is the hero one I had before. This is the simple implementation that I wanted to take a look at. And then here's the control implementation. the important thing to test here is we're trying to test things that could produce the same output against each other. When users come to this page, I want to make sure they can submit this form and get the output that I want from each of them, which is that newsletter subscribed event.

[00:09:46] So from this control one, This is a newsletter subscription form. First name and email address is exactly what we want to see the simple form, same thing. First name, email address, and then the hero form. Once again, first name and email address. So. [00:10:00] All the primitives are here. I have three different variants of this thing.

[00:10:03] The next thing to do is to set this live and just record some traffic for awhile. there are some statistical minimums. We have to get a certain amount of users interacting with each one of these, to be able to say whether it worked or not. And the next part is just waiting. So we're going to spin this up on PostHog.

[00:10:17] We're going to collect some data over the next week or two, however long it takes, and then we'll start to make some decisions based on that and go into the next step from there.

[00:10:23] So that's all there is to it. It's a little bit of implementation. It's a little bit of work to set up the three different variants, but now I need to trust the statistics. I need to listen to what comes back from post-hoc as the experiment runs. And tweak my site design based on the data that comes back. My guess is it'll probably take about two weeks for this to come back with meaningful results. But lucky for me, I can run a couple of experiments in parallel, as long as the two different experiments don't interfere with each other. I can probably still draw a valid conclusion from it. So over the next week or so I'll watch this and I'll see what happens.

## What do you think?

[00:10:52] **Mike Bifulco:** If you've been hanging on for the whole series so far, I'm really curious what you think of this.

[00:10:55] Is this something you would find useful for your site? Do you have an idea of experiments you'd like to run? Do you have [00:11:00] questions about this stuff?

[00:11:01] I spent a bunch of my career working in design and user experience. So this sort of thing is a process that I really enjoy, but I can understand that it might be frustrating too, especially if you just want to get to results.

[00:11:10] If you have questions for me, feel free to drop them in the comments. . Your ideas are always welcome here. There's no criticism too big or too small. I'd love to hear what you're thinking. Thanks so much. My name is Mike bi-fold co this is tiny improvements and we'll catch up for the next one.

</details>
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Fixing the sign-up problem on my site using PostHog Product analytics]]></title>
            <link>https://mikebifulco.com/posts/fixing-my-conversion-problem</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/fixing-my-conversion-problem</guid>
            <pubDate>Tue, 13 Aug 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[In part two of my product analytics journey, I tackle a subscriber drop, dive into PostHog data, fix key errors, and switch from ConvertKit to the developer-friendly Resend.]]></description>
            <content:encoded><![CDATA[
Watch [Product Analytics for engineers: Debugging a conversion problem on my next.js site using @PostHog](https://youtu.be/4nWcB1a8M1s) on YouTube

Thanks so much to PostHog for sponsoring this video and supporting my work! Give it a whirl over at https://posthog.com/mikebifulco and tell 'em I sent you!

## Summary

In part two of my adventure with product analytics, I tackle a significant drop in my newsletter subscribers. Join me as I dive into the data using PostHog, identify and fix critical errors, and ultimately switch from ConvertKit to Resend – a more developer-friendly email platform.

Along the way, I'll show you how I integrated tRPC into my Next.js site for a type-safe API, created hooks for better data management, and set use posthog to chase down the root of the bug.

Whether you're a startup founder or an indie hacker, you'll find valuable insights to improve your product. Plus, transparency is key – this video is sponsored by PostHog, but all opinions are genuinely mine. Let's build something great together!

## Video Timestamps

00:42 ConvertKit Stats

01:06 Subscription Form

02:45 Sponsored by Posthog

03:16 Resend broadcasts

03:36 tRPC

03:54 tRPC Demo

04:43 Subscription form code walkthrough

06:27 useNewsletterStats

07:33 What I'm seeing in posthog

08:37 What's next

09:45 Next PostHog tests

10:11 What do you think I should do next?

10:31 Wrap up

## Links

- Watch part 1 of this series: [Product Analytics for engineers: Debugging a conversion problem on my next.js site using @PostHog](/posts/debugging-a-conversion-problem-on-my-nextjs-site)
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Product Analytics for engineers: Debugging a conversion problem on my next.js site]]></title>
            <link>https://mikebifulco.com/posts/debugging-a-conversion-problem-on-my-nextjs-site</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/debugging-a-conversion-problem-on-my-nextjs-site</guid>
            <pubDate>Mon, 05 Aug 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[This video dives into the process I used to diagnose and debug a conversion problem on my personal website using Posthog, a powerful product analytics tool.]]></description>
            <content:encoded><![CDATA[
Watch [Product Analytics for engineers: Debugging a conversion problem on my next.js site using @PostHog](https://youtu.be/4nWcB1a8M1s) on YouTube

## Summary

I've been experiencing a problem with my personal website, mikebifulco.com, where my newsletter sign-ups have mysteriously plummeted. In this video, I take you through the process of diagnosing and debugging this issue using Posthog, a powerful product analytics tool.

We'll start by taking a look at the site, identifying potential problem areas, and then diving into the code. I'll show you how I implement Posthog to track user interactions and gather valuable insights. We'll explore how to handle form submissions, track events, and use Posthog’s features to pinpoint what's going wrong.

Throughout the video, I'll share my thought process, hypotheses, and the steps I take to experiment and test different solutions. If you've ever had a non-bug issue in production, this video is for you. Let's get to the bottom of this conversion rate mystery together!

You might be interested in this video if you want to learn about debugging and optimizing website performance, especially using tools like Posthog. Relevant technologies and subject areas include React, Next.js, form handling, product analytics, serverless functions, and conversion rate optimization.

## Video Timestamps

0:00 Product Analytics for engineers: Debugging a form conversion rate problem on my website with Posthog

01:05 Site walkthrough

01:30 Are people annoyed by the popup?

02:53 Long form article pages

04:02 Looking at the code

05:20 Dive into the code

07:13 Newsletter form refactor

10:45 Serverless function for newsletter subscribe

12:26 The results in Posthog

13:29 What we did, and what's next

14:43 Why Posthog and product analytics are helpful

15:41 Epilogue: We learned something! Next steps...

## Links

- Watch [Product Analytics for engineers: Debugging a conversion problem on my next.js site using @PostHog](https://youtu.be/4nWcB1a8M1s) on YouTube
- Part 2 of this series: [Fixing the sign-up problem on my site using PostHog Product analytics](/posts/fixing-my-conversion-problem)
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Your tastes will always outpace your skill, and what to do about it]]></title>
            <link>https://mikebifulco.com/posts/your-tastes-will-always-outpace-your-skill</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/your-tastes-will-always-outpace-your-skill</guid>
            <pubDate>Sun, 28 Jul 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Powerful advice gleaned from a quote by Ira Glass - your taste will always outpace your creative abilities.]]></description>
            <content:encoded><![CDATA[
Watch [The SECRET you need to hear about the difference between Taste and Skill](https://youtu.be/Ym6HQopqe-4) on YouTube

## Summary

Mike discusses how important it is for creatives, especially those building startups and indie projects, to understand this gap and use it as motivation.

If you're on this journey, it is to your benefit to draw from a broad array of influences, and relate it to your creative output.

In addition to the critical step of building your chops by practicing your craft, gathering inspiration from others who excel in the field is a game changer. This is borrowed from my extensive experience in building software. and a career spent learning about the critical role of good design.

If you're aiming to produce better and more user-friendly products, this video offers valuable guidance and inspiration to help you along your creative journey.

## Video Timestamps

0:00 Ira Glass on Beginners
05:35 Mobbin
06:03 Wrap up
06:31 💌 Tiny Improvements, my newsletter

## Links

- Watch [The SECRET you need to hear about the difference between Taste and Skill](https://youtu.be/Ym6HQopqe-4) on YouTube
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Seed your Supabase database with this simple pattern]]></title>
            <link>https://mikebifulco.com/posts/seed-your-supabase-database</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/seed-your-supabase-database</guid>
            <pubDate>Tue, 23 Jul 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Learn how to seed your Supabase database with this simple pattern.]]></description>
            <content:encoded><![CDATA[
## Introduction

When working with Supabase, you may need to seed your database with initial data. This is a common task when setting up a new develper environment, or when you need to populate your database with predictable sample data for testing purposes. In this post, I'll show you a simple pattern for seeding your Supabase database using TypeScript.

## Prerequisites

This post assumes you have a [Supabase](https://supabase.com) project set up and a basic understanding of TypeScript. If you're new to Supabase, you can follow the [official documentation](https://supabase.io/docs/guides) to get started.

Although my site is built with [tRPC](https://trpc.io/), [Drizzle ORM](https://orm.drizzle.team/) and [Next.js]https://nextjs.org/, this pattern can be adapted for other frameworks, libraries, and databases.

### Seeding the database with sample data using Faker

This example uses a library called [Faker](https://fakerjs.dev/) to generate fake data. Faker is a popular library for generating random data such as names, addresses, and phone numbers. You can install it using your package manager of choice:

```bash
# note that faker is installed as a dev dependency
pnpm install faker -D
```

## Setting up the seed data

For this example, we will use a simplified Drizzle ORM Database schema with two tables - `chefs` and `recipeTypes`. Here's what the schema might look like:

```ts
// schema.ts

// ...other tables and imports above
export const chefs = createTable('chefs', {
  id: serial('id').primaryKey(),
  name: varchar('name', { length: 256 }).notNull(),
  email: varchar('email', { length: 256 }).notNull(),
  phone: varchar('phone', { length: 256 }),
  address: text('address'),
});

export const recipeTypes = createTable('project_type', {
  id: serial('id').primaryKey(),
  name: varchar('name', { length: 256 }).notNull(),
  description: text('description'),
});

export const recipes = createTable('recipes', {
  id: serial('id').primaryKey(),
  name: varchar('name', { length: 256 }).notNull(),
  description: text('description'),
  recipeTypeId: integer('recipeTypeId').references(recipeTypes.id),
  recipeChefId: integer('recipeChefId').references(chefs.id),
});
```

I try to keep my seed data organized in a `src/db/seed` directory. Each file in this directory contains seed data for a specific table in the database. For example, if you have a `chefs` table and a `recipeTypes` table, you would create two files: `chefs.ts` and `recipeTypes.ts`.

Here's an example of what the directory structure might look like:

```bash
src
└── db
    ├── seed
    │   ├── chefs.ts
    │   ├── recipes.ts
    │   ├── recipeTypes.ts
    │   └── seed.ts   // this is where we collate all seed data and insert into db
    ├── db.ts          // exports the db instance from Drizzle
    └── schema.ts      // database schema de  ition
```

## Creating seed data

This script will stick data into the `chefs`, `recipes`, and `recipeTypes` tables. To keep things neatly organized, each table is represented by its own file. Each of these files exports a function that seeds the data for that table, which is of the type:

```tsx
type SeedFunction = () => Promise<string>;
```

The string returned by each `SeedFunction`'s promise is a message that will be logged to the console when the seeding is complete. I use this to keep track of how many rows were inserted into the database.

### For tables with predefined data

The simplest option is tables with predefined or hand-written data. For these, I more-or-less hand-write objects to stick into the database. Here's an example of how to the `recipeTypes` table:

```tsx
import db from '../db';
import { recipeTypes } from '../schema';
import type { SeedFunction } from '../seed';

type RecipeTypeRow = {
  name: string;
  description: string;
};

// note the export: we will use this later
export const RecipeTypes: SeedFunction = {
  Breakfast: { id: 1, name: 'Breakfast', description: 'Breakfast recipes' },
  Lunch: { id: 2, name: 'Lunch', description: 'Lunch recipes' },
  Dinner: { id: 3, name: 'Dinner', description: 'Dinner recipes' },
} as const;

const seedRecipeTypes = async () => {
  // convert the object to an array of values
  const data = Object.values(RecipeTypes);

  await db.from(recipeTypes).insert(data);

  return `${data.length} Recipe types seeded successfully`;
};
```

Some things to note in the above code:

- We're creating an array of objects with predefined data for the `recipeTypes` table.
- We're inserting the predefined data into the `recipeTypes` table using the `db.from(recipeTypes).insert(data)` method.
- The `return` statement at the end of the function is a string, which will be logged to the console when seeding this table is complete.
- the `RecipeTypes` object is exported so we can use it in other seeding functions.

### Generating data with Faker

For tables that can use randomized data, a slightly different approach is used with the [Faker.js](https://fakerjs.dev/guide/) library, which can generate many different types of randomized data.

Here's how to populate the `Chefs` table with a list of fake chefs:

```tsx
import faker from 'faker';

import db from '../db';
import { chefs } from '../schema';
import type { SeedFunction } from '../seed';

type ChefRow = {
  name: string;
  email: string;
  phone: string;
  address: string;
};

const seedChefs: SeedFunction = async () => {
  // generate random data for 10 people to stick into the chefs table
  const data: ChefRow[] = Array.from({ length: 10 }, () => ({
    name: faker.name.findName(),
    email: faker.internet.email(),
    phone: faker.phone.phoneNumber(),
    address: faker.address.streetAddress(),
  }));

  await db.from(chefs).insert(data);

  return `${data.length} Chefs seeded successfully`;
};
```

### Seeding related data

If you have tables with relationships, you can seed related data by using the `id` of the parent table. For example, if you have a `recipes` table that has a foreign key to the `recipeTypes` table, you can seed the `recipes` table with the `id` of the `recipeTypes` table.

Here's an example of how you might seed the `recipes` table with related data:

```tsx
import db from '../db';
import { recipes } from '../schema';
import type { SeedFunction } from '../seed';
import { RecipeTypes } from './recipeTypes';

type RecipeRow = {
  name: string;
  description: string;
  recipeTypeId: number;
};

const seedRecipes: SeedFunction = async () => {
  const data: RecipeRow[] = [
    {
      name: 'Pancakes',
      description: 'Delicious pancakes',
      // use the id from the RecipeTypes object we exported earlier
      recipeTypeId: RecipeTypes.Breakfast.id,
      // since it can be any chef, we'll just use the first one
      recipeChefId: 1,
    },
    {
      name: 'Spaghetti',
      description: 'Classic spaghetti',
      recipeTypeId: RecipeTypes.Dinner.id,
      recipeChefId: 2,
    },
    {
      name: 'Roast chicken',
      description: 'Juicy roast chicken',
      recipeTypeId: RecipeTypes.Dinner.id,
      recipeChefId: 3,
    },
    {
      name: 'Sandwich',
      description: "Good ol' ham & swiss",
      recipeTypeId: RecipeTypes.Lunch.id,
      recipeChefId: 4,
    },
  ];

  await db.from(recipes).insert(data);

  return `${data.length} Recipes seeded successfully`;
};
```

## Seed the database

Now that we have a script written for each table in the database, we we need to run them each in a specific order, as some tables may depend on others. I keep a file called `seed.ts` which to run each of the seeding functions in the correct order.

```tsx
import seedChefs from "./chefs";
import seedRecipes from "./recipes";
import seedRecipeTypes from "./recipeTypes";

const seedDb = async () => {
  // note: this function assumes we're starting with an empty database

  console.log("Seeding database...");

  console.log("Adding independent data...");
  const res = await Promise.allSettled([
    seedRecipeTypes(),
    seedChefs(),
    // add more independent seeding functions here
    // these will run in parallel
  ]);

  res.forEach((result) => {
    if (result.status === "rejected") {
      console.log("Error seeding database:", result.reason);
    } else {
      console.log(result.value);
    }
  });

  console.log("Adding related data...");
  const dependentTasks = [
    seedRecipes,
    // add more dependent tasks here, they will run in this order
  ];
  for (const task of dependentTasks) {
    try {
    const result = await task();
    console.log(result);
    } catch e {
      console.log("Error seeding database:", e);
    }
  }

  console.log("Seeding complete!");
};

seedDb()
  .then(() => {
    console.log("Seeding complete!");
    process.exit(0);
  })
  .catch((err) => {
    console.error("Error seeding database:", err);
    process.exit(1);
  });
```

You can run this script using your package manager of choice, by adding an entry to `package.json`:

```json
{
  "scripts": {
    // ...etc
    "seed": "tsx --env-file=.env src/db/seed/seed.ts"
    // ...etc
  }
}
```

Then, run the script using:

```bash
pnpm run seed
```

This will seed your database with the sample data you've defined. Note that we're using `Promise.allSettled` to ensure that all the seeding functions run in parallel. This can be useful if you have a large amount of data to seed. It will also catch any errors that occur during seeding and log them to the console.

`Promise.allSettled` returns an array of promises that are settled (either fulfilled or rejected). This allows you to handle each promise individually and log any errors that occur. It is different from `Promise.all`, which will reject the entire promise chain if any of the promises are rejected - you may want to use `Promise.all` if you want to stop seeding if any of the promises fail.

When run, your script should output something like this:

```bash
Seeding Database...
Adding independent data...
3 Recipe types seeded successfully
10 Chefs seeded successfully

Adding related data...
10 Recipes seeded successfully
Seeding complete!
```

## Adapt this pattern to your needs

This is a simplification of the pattern I use in my projects to seed my Supabase database. You can adapt this pattern to suit your needs by adding more tables, more data, or more complex relationships between tables. The key is to keep your seed data organized and to use a consistent pattern for seeding your database.

I use this to reset my database to a known state when I'm working on new features, and to set up my test environment with fresh, predictable data. It's a simple pattern, but it's been incredibly useful for me in my projects.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[SEO for Devs: Own your work with canonical tags]]></title>
            <link>https://mikebifulco.com/posts/own-your-work-with-canonical-tags</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/own-your-work-with-canonical-tags</guid>
            <pubDate>Fri, 12 Jul 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Canonical tags are a powerful tool to help search engines understand which version of a page is the original one. This can help you avoid duplicate content issues and ensure that your content gets the credit it deserves.]]></description>
            <content:encoded><![CDATA[
## Canonically Speaking: Own Your Work

You've gone through the trouble of planning, outlining, and writing an article - the product of hours (or sometimes days) of work. After publishing your work on your own site, you take the time to cross-post it on Hashnode, Medium, Dev.to, and Reddit, to get more eyes on it.

Great news: your work is a success! You're racking up likes and upvotes, and people are leaving thoughtful comments.

Some time later, you open up an incognito window, and do a Google search for your article, and it pops up!

...but wait, why is the top result Medium, and not `yourgreatwebsite.com`?

It sounds like it's time you learned about the `canonical` tag, its value for SEO, and why it matters if you're trying to build a brand for yourself, or for a product you're working on.

## What is a Canonical Tag?

The **canonical tag** is a specially formatted `<link />` tag in HTML which lets you specify the "canonical" or original version of the content on a given page. The Google crawler and other search engines use these in combination with a few other signals to determine which domain "owns" the content being shown.

In other words: **canonical tags tell search engines which URL should be considered the official home of whatever is on that page**.

### Syntax for the Canonical tag

Canonical tags go in the `<head>` section of an html page, and they look like this:

```html
<head>
  <!--
    you'll probably have a bunch of other stuff here,
    like title, stylesheet, and meta tags.
  -->
  <link rel="canonical" href="https://www.yoursite.com/some-article" />
</head>
```

**Important:** Your page should have _only one_ canonical tag. Adding more than one can have negative or unintended effects on your search rankings!

### Some great reasons to use Canonical Tags

When your work is posted in multiple places online, canonical tags tells search crawlers which version should be considered the authoritative source.

If you cross post and don't use a canonical tag, it can lead to your poor search rankings _everywhere_ for your work. This means that even if you get a boost initially from sharing on Hashnode, Medium, or Dev.to, it can actually _hurt_ your chances to rank well in the long run.

In theory, this means that the signals search crawlers use to rank your articles (like backlinks and traffic statistics) should be attributed to the original source on your site. That's great news, because more backlinks and clicks through to your work _should_ increase visibility on search engine results pages (SERPs).

### Another benefit: Protection Against Content Theft

Eventually, your high-traffic articles will copied and republished without your permission by spammy content aggregator sites looking to build traffic for themselves.

By having a canonical tag _on your site_ from the start, and having it indexed by search engines, you ensure that these spam sites don't win by stealing your content. The canonical tag helps search engines recognize your original work and prioritize it in search results.

---

## Implementing Canonical Tags on your site

Thankfully, it's not particularly complicated to add canonical tags to your site. The long and short of it is that you need to add a `<link>` tag to the `<head>` section of your HTML pages, specifying the canonical URL of the content.

As an example here's a simple, step-by-step guide to implementing canonical tags in a Next.js site using the pages router:

### Create a New Next.js project

If you haven't already, you can create a new Next.js project by running the following commands in your terminal:

```bash
npx create-next-app@latest my-nextjs-site
cd my-nextjs-site
```

### Install the Next.js Head Component

Next.js provides a built-in `<Head />` component to help you manage the `<head>` section of your HTML. You don't need to install anything additional for this; it's already included with Next.js.

_A word of caution:_ Using a `<Head />` tag on any page in your site gives you a way to add content to the `<head />` section rendered on the final page. This is super convenient, but that also makes it easy to unintentionally include more than one of these puppies per page -- and you don't want to do that.

### Add the Canonical Tag to Your Pages

Adding the tag to a single page is straightforward - toss it between `<Head>` tags, and make sure the `href` attribute has the _exact_ same URL as this page will. **If your site pages have a trailing slash `example.com/hello/`, make sure to include it!**

```jsx
import Head from 'next/head';

export default function Home() {
  return (
    <div>
      <Head>
        <title>My Next.js Site</title>
        <link rel="canonical" href="https://www.yoursite.com/" />
      </Head>
      <h1>Welcome to My Next.js Site</h1>
    </div>
  );
}
```

You can add the canonical tag to other pages in the same way - just make sure to replace the href value with the correct, specifc URL for each page.

### Set the Canonical URL for article pages

For more complex sites, especially those with pages generated from Markdown or a CMS, you'll likely want to set the canonical URL dynamically. Here's a simplified example of how you might accomplish this using `next/navigation`:

```jsx
import Head from 'next/head';
import { useRouter } from 'next/navigation';

export default function BlogPost() {
  const router = useRouter();

  // ƒor https://example.com/articles/my-good-article,
  // this will contain something like "/articles/my-good-article"
  const path = router.asPath;

  /*
    Dynamically set the canonical URL - this needs to be an absolute URL
    so make sure to include the domain
    For example, if your site is https://www.yoursite.com
    and the path is /blog/my-post, the canonical URL would be
    https://www.yoursite.com/blog/my-post
  */
  const canonicalUrl = `https://www.yoursite.com${path}`;

  return (
    <div>
      <Head>
        <title>Blog Post Title</title>
        <link rel="canonical" href={canonicalUrl} />
      </Head>
      <h1>Blog Post Content</h1>
    </div>
  );
}
```

### Verify the Implementation

After adding canonical tags, it's essential to verify their implementation. You can use tools like [Google's URL Inspection Tool](https://support.google.com/webmasters/answer/9012289?hl=en) in Search Console to check if your pages are being indexed correctly with the canonical tag.

<Image
  publicId="posts/own-your-work-with-canonical-tags/google-search-console"
  alt="Google Search Console showing the URL Inspection Tool"
  caption="Use Google's URL Inspection Tool to verify that your pages are being indexed correctly with the canonical tag"
/>

By following these steps, you'll ensure that search engines recognize your original content, helping you build your personal brand and protect your work from content theft.

## Bonus points: set canonical URLs in places where you crosspost

Many community blogging platforms contain tools that will let you set a canonical URL on your posts. This is a step you should absolutely take when it is available - it's a way to explicitly tell crawlers that if they're crawling your article on some other site, they should consider your original site the owner.

In other words, when you post on Dev.to, you should add metadata to your post _there_ to indicate that it was _originally_ posted on `yoursite.com`.

<Image
  publicId="posts/own-your-work-with-canonical-tags/canonical-dev-to"
  alt="A recent post of mine on Dev.to showing that it is a crosspost"
  caption="If you do it right, dev.to will point right back to your original article"
/>

### FWIW: Adding canonical tags with Next.js App router

If your Next.js app is built using the App Router, implementation is slightly different, but also pretty straightforward. Next provides an API called [Dynamic Metadata](https://nextjs.org/docs/app/building-your-application/optimizing/metadata) on each page, which slurps up the output of a function called `generateMetadata` on your pages, and sticks the result in nicely formatted tags in the `<head />` of your document.

To add a canonical tag with this method, you'll do something like this:

```tsx
import type { Metadata, ResolvingMetadata } from 'next';

type Props = {
  params: { id: string };
  searchParams: { [key: string]: string | string[] | undefined };
};

export async function generateMetadata(
  { params, searchParams }: Props,
  parent: ResolvingMetadata
): Promise<Metadata> {
  // read route params
  const slug = params.slug;

  return {
    metadataBase: new Url('https://yoursite.com'), // Next will use this to make complete URLs from relative paths
    alternates: {
      canonical: `/articles/${slug}`,
    },
  };
}

export default function Page({ params, searchParams }: Props) {
  /* etc */
}
```

### Setting a canonical URL on Dev.to

To [set the canonical URL of a post on Dev.to](https://dev.to/p/editor_guide#front-matter), add `canonical_url` to the frontmatter of your post:

```md
---
title: Hello this is a post
canonical_url: https://yoursite.com/article/some-article`
---
```

### Setting a canonical URL on Medium

To [set the canonical URL of a post on Medium](https://help.medium.com/hc/en-us/articles/360033930293-Set-a-canonical-link), you'll use the three dot button `...` on your post and select "This story was originally published elsewhere" from the menu

### Setting a canonical URL on Hashnode

In the Hashnode editor, there's a helpful menu under _Draft Settings_ for "Are you republishing?", where you can [specify your post's canonical URL](https://support.hashnode.com/en/articles/6556971-how-to-set-a-canonical-link).

### Setting a canonical URL on LinkedIn

LinkedIn _desperately_ wants you to use their "write an article" feature to share long form content on their site. In my opinion, this is a bad idea - **LinkedIn articles do not support canonical tags** -- and IMO, this means they're trying to take credit for your work.

Instead, just share a link to your article in a regular post - it may not do as well in their feed algorithm, but at least there they'll honor your canonicals.

## Protect your work and boost your SEO with canonical tags

All told, this is a tiny amount of work to protect your IP, send search traffic your way, and build your brand. It's one of those things that many devs overlook. Building SEO traffic for your site has compounding value over time - and learning the fundamentals goes a long way.

Now get out there and add `<link rel="canonical">` to your articles, before I claim them as my own 😘

## More reading on SEO

I have [written _gobs_ about SEO for developers](https://mikebifulco.com/tags/seo) - if you liked this article, you may want to out these as well:

- [How to set up self-healing URLs in Next.js for better SEO](https://mikebifulco.com/posts/self-healing-urls-nextjs-seo)
- [3 Tiny Tips for better SEO](https://mikebifulco.com/newsletter/tiny-tips-for-better-seo)
- [SEO tools I used to grow my sites to 20k+ visitors/month](https://mikebifulco.com/posts/seo-tools-for-new-web-projects)
- [The correct semantic HTML for adding subtitles to h1 tags](https://mikebifulco.com/posts/semantic-html-heading-subtitle)
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Add Structured Data to your Next.js site with JSON-LD for better SEO]]></title>
            <link>https://mikebifulco.com/posts/structured-data-json-ld-for-next-js-sites</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/structured-data-json-ld-for-next-js-sites</guid>
            <pubDate>Thu, 25 Apr 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Structured Data can be added to your site tell Google and other search engines what type of content is on each page using a metadata format called JSON-LD.]]></description>
            <content:encoded><![CDATA[
<small>

_note: This post is inspired by an article that my pal Josh Finnie wrote, showing [how he added JSON-LD to his Astro.js site](https://www.joshfinnie.com/blog/adding-json-ld-to-my-blog/): If you're an Astro-naut - give that a read. It's great!_

</small>

## SEO is the growth hack you're overlooking

Many devs overlook the value of SEO for their work.

I've long contended that learning a little bit about SEO can go a long way. It's in your best interest to configure your site so that Google, Duck Duck Go, and Bing know what your site is about, and what you're expert on.

In this brief tutorial, I'll share some information about Structured Data and JSON-LD, and how you can add it to your Next.js site to improve your site's SERP (Search Engine Results Page) presentation, with just a little bit of code and configuration.

## What is JSON-LD?

**JSON-LD (JSON Lightweight Linked Data format) is a metadata format** which can be added to your site to tell Google and other search engines what type of content is on each page. This can help search engines understand your content better, and can lead to better search results for your site. In reality, JSON-LD is _just_ a specific format for JSON which is human readable, and is meant to describe the content on a page in a way that search engines can understand. You can read more about it here: [https://json-ld.org/](https://json-ld.org/)

JSON-LD looks like this:

```json
{
  "@context": "https://json-ld.org/contexts/person.jsonld",
  "@id": "http://dbpedia.org/resource/John_Lennon",
  "name": "John Lennon",
  "born": "1940-10-09",
  "spouse": "http://dbpedia.org/resource/Cynthia_Lennon"
}
```

### What is Structured Data?

**Structured Data is a set of search-engine specific JSON-LD templates** that search crawlers look for to understand more about the information you're sharing online. It is _optional_ for your site, but can help bring more traffic to your site by increasing the chances that your site will show up in search results.

Adding the _right_ type of Structured data to your site means that when your pages come up in someone's search results, the search engine can display more information about your site, like reviews, ratings, and other rich snippets. Ever seen a recipe or a product review in a search result? That's because of structured data.

<Image
  publicId="posts/structured-data-json-ld-for-next-js-sites/apple-cobbler"
  alt="A search result featuring apple cobbler recipes, with a star rating, time to complete, a short ingredients list, and a photo"
  caption="Structured Data can help your site show up in search results with rich snippets like this one"
/>
<br />

### Types of Structured Data

There are many types of Structured Data you can embed on your site - [Google Search Central has a list of structured data features](https://developers.google.com/search/docs/appearance/structured-data/search-gallery) which that is worth a good look. Some examples of Structured Data include:

- **Article**: For news, blog, and other article pages
- **Events**: Showcases events like concerts, festivals, and other happenings
- **FAQ**: Make your FAQ page more discoverable
- **Product**: Details and information about a product you're selling
- **Recipe**: Ingredients, cook time, and other details about a recipe
- **Review Snippet**: A review of a product, service, or other item
- **Video**: For pages that showcase video content

Each of these formats are slightly different in content, but they use JSON-LD to describe the content in a way that search engines can understand. By way of example, this is the Structured Data for a post on my site about a livestream I did demonstrating [how to build a site with Astro, TypeScript, and React](https://mikebifulco.com/posts/live-astro-content-driven-website-rebuild):

```html
<script type="application/ld+json">
  {
    "@context": "https://schema.org",
    "@type": "VideoObject",
    "name": "Rebuilding an open source content-rich site with Astro, TypeScript, and React",
    "description": "A YouTube live coding stream, learning to build content-driven sites with the Astro Web Framework.",
    "thumbnailUrl": "https://i.ytimg.com/vi/wyJYInvZya8/hqdefault.jpg",
    "uploadDate": "2024-03-23T00:00:00.000Z",
    "contentUrl": "https://www.youtube.com/watch?v=wyJYInvZya8",
    "embedUrl": "https://www.youtube.com/embed/wyJYInvZya8",
    "duration": "PT1M33S"
  }
</script>
```

Not too bad, right? This JSON-LD tells Google that this page is a video, and gives Google some information about the video, like the title, description, and thumbnail. In theory, if someone searches for the title of the video, Google might show this video in the search results, with a thumbnail and a link to the video.

Once you've got Structured Data embedded on your site, you can verify that it's working using [Schema.org's Structured Data Testing Tool](https://validator.schema.org/):

<Image
  publicId="posts/structured-data-json-ld-for-next-js-sites/schema-org-validator"
  alt="Schema.org's Structured Data Testing Tool showing that my video structured data is valid"
/>

Similarly, you can use [Google's Rich Results Test](https://search.google.com/test/rich-results):

<Image
  publicId="posts/structured-data-json-ld-for-next-js-sites/rich-results-test"
  alt="Google's Rich Results Test showing that my video structured data is valid"
/>

If you want to poke around yourself, check out the [results for the video example above](https://search.google.com/test/rich-results/result?id=K92cqPpaYa6TcdmYuVrIzQ).

Pretty cool! So - now let's talk about how it's done.

## Adding Structured data to your Next.js site with JSON-LD

My site is built with Next.js - the articles you read here are written in an extension of Markdown called [MDX](https://nextjs.org/docs/pages/building-your-application/configuring/mdx), and the site is statically generated.

When I publish an article that features a YouTube video, I add frontmatter to the MDX file for the article that contains the ID of the video, and then I use that ID to generate the JSON-LD for the video.

Again, for the page above, that looks like this:

```mdx
---
title: 'Rebuilding an open source content-rich site with Astro, TypeScript, and React'
excerpt: A YouTube live coding stream, learning to build content-driven sites with the Astro Web Framework.
date: 2024-03-23
tags: [video, nextjs, typescript, astro]
coverImagePublicId: posts/live-astro-content-driven-website-rebuild/cover
slug: live-astro-content-driven-website-rebuild
youTubeId: wyJYInvZya8
---

OpenApi.tools is an Open Source yada yada yada
```

Google provides an npm package called [schema-dts](https://www.npmjs.com/package/schema-dts) which contains types and helpers for generating JSON-LD. Start by installing this package:

```sh
npm install schema-dts
# or with pnpm
pnpm install schema-dts
# or with yarn
yarn add schema-dts
# or with bun
bun add schema-dts
```

Then, import the package and use it to generate a typed variable to contain a VideoObject's schema:

```tsx
import type { VideoObject, WithContext } from 'schema-dts';

let videoStructuredData: WithContext<VideoObject> | undefined = undefined;
```

<small className="text-xs">

**Shout out** to redditor [/u/AdrnF](https://www.reddit.com/r/nextjs/comments/1ccr79j/comment/l172n31/) for the tip. I didn't know this npm package existed!

</small>

Next, we'll need to populate this variable with the appropriate data for the schema. In my case, I'm using the `youTubeId` from the frontmatter to generate the JSON-LD for the video, like this:

```tsx
let videoStructuredData: VideoStructuredData | undefined = undefined;

if (youTubeId) {
  videoStructuredData = {
    '@context': 'https://schema.org',
    '@type': 'VideoObject',
    name: title,
    description: excerpt,
    thumbnailUrl: `https://i.ytimg.com/vi/${youTubeId}/hqdefault.jpg`, // this is the thumbnail for the video straight from youtube
    uploadDate: new Date(date).toISOString(),
    contentUrl: `https://www.youtube.com/watch?v=${youTubeId}`, // this is the URL for the video on youtube
    embedUrl: `https://www.youtube.com/embed/${youTubeId}`, // this is the URL for the video embed on youtube
    duration: 'PT1M33S', // this is the duration of the video

    /*
        note that I'm not using the entire VideoObject schema here, but
        you could add more fields if you wanted to, like interactionStatistic
        and regionsAllowed:
      */

    // interactionStatistic: {
    //   '@type': 'InteractionCounter',
    //   interactionType: { '@type': 'http://schema.org/WatchAction' },
    //   userInteractionCount: 0,
    // },
    // regionsAllowed: ['US'],
  };
}
```

Once this object is created, I serialize it to a string and add it to a `<script>` tag on the page - depending on when and where you generate it, you can stick this in the `<head>` of your page, or right in the body of the document, like I do:

```tsx
// snip -

return (
  <>
    {videoStructuredData && (
      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{
          __html: JSON.stringify(videoStructuredData),
        }}
      />
    )}
    <article>{/* page content goes here */}</article>
  </>
);
```

When the page is generated, you can inspect the source and see the JSON-LD embedded in the page - as in the example above.

You can double-check that your Structured data is valid using one the [Schema.org Structured Data Testing Tool](https://validator.schema.org/) before publishing by copy/pasting the generated HTML for your pages into the "code snippet" tab. Once you're happy with it, you can publish your article and you're good to go!

Job done. Google's crawler will see this JSON-LD and use it to understand the content on your page better, and you'll be on your way to better search results.

## Embed your Structured data server-side for best results

Embedding this information on in your articles in Next.js only takes a few steps, but it's critical that you do this _server-side_ to give google the best chances of seeing it. I'm using the Next.js `/pages` directory for my site -- articles are generated statically using `getStaticPaths` and `getStaticProps`, which means that the JSON-LD is generated at build time.

If you use the _App Router,_ you'll want to make sure that you embed your JSON-LD using a React Server Component (RSC), not using a client-side script.

If you're using a CMS, you'll want to make sure that the JSON-LD is generated when the page is statically rendered, and not when the page is loaded in the browser.

## Challenges with structured data

It's worth mentioning here that even if the schema validators can read your JSON-LD, it doesn't guarantee that Google will use it in search results. Google's search algorithms are complex, and they use many signals to determine what to show in search results.

I've been tweaking the implementation of Video structured data on posts like the one above, because the Google Search Console has been showing me that the structured data is valid, but it's not showing up in search results as a video:

<Image
  publicId="posts/structured-data-json-ld-for-next-js-sites/search-console-hates-me"
  alt="Google Search Console showing that my video structured data is valid, but not showing up in search results"
  caption="Google's crawler thinks my video isn't the main content of the page."
/>

There's still some work to do here, but I'm confident that with some more tweaking, I'll be able to get this working. If you know more about this, I'd love to hear from you! Drop me a line on [Threads @irreverentmike](https://threads.net/@irreverentmike) or email me <a href="mailto:hello@mikebifulco.com">hello@mikebifulco.com</a>.

These rules are always changing, and keeping up with them is a fulltime job in itself. Nonetheless, adding structured data to your site is a good practice, and can help your site show up in more search results -- even if you can't control exactly how it shows up.

## Keep adding Structured Data to your site

Now's your turn - go give it a shot. You may want to start with something like the [Profile Page](https://developers.google.com/search/docs/appearance/structured-data/profile-page) structured data format, or by adding one for [Articles](https://developers.google.com/search/docs/appearance/structured-data/article) to your posts.

For the amount of effort required, the payoff is worth it. Every little SEO boost you build into your site pays off in the long run. Think of it as an investment in the passive value of your content - the more you can do to make your content discoverable, the more likely it is to be found.

## Resources on SEO and Structured Data

As I mentioned above, this tutorial was inspired by [Josh Finnie's article on adding JSON-LD to his Astro.js site](https://www.joshfinnie.com/blog/adding-json-ld-to-my-blog/). Josh is a great developer and a good friend, and I recommend you check out his work.

I've written a few articles on SEO that you may find helpful:

- [3 Tiny tips for better SEO](https://mikebifulco.com/newsletter/tiny-tips-for-better-seo)
- [How to set up self-healing URLs in Next.js for better SEO](https://mikebifulco.com/posts/self-healing-urls-nextjs-seo)
- [SEO tools I used to grow my sites to 20k+ visitors/month](https://mikebifulco.com/posts/seo-tools-for-new-web-projects)
- [How to reset your Open Graph embed on LinkedIn, Twitter, and Facebook](https://mikebifulco.com/posts/reset-your-open-graph-embeds-on-linkedin-twitter-facebook)

And here are some tools that can help you get started with Structured Data:

- [Google's Structured Data Testing Tool](https://search.google.com/structured-data/testing-tool)
- [Google's Rich Results Test](https://search.google.com/test/rich-results)
- [Schema.org's Structured Data Testing Tool](https://validator.schema.org/)

If you found this helpful I'd love it if you shared the article with a friend.

I'm also keen to hear from you. Drop me a line on [Threads @irreverentmike](https://threads.net/@irreverentmike) or email me <a href="mailto:hello@mikebifulco.com">hello@mikebifulco.com</a> if you think I missed anything, or if you have any questions!
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Rebuilding an open source content-rich site with Astro, TypeScript, and React]]></title>
            <link>https://mikebifulco.com/posts/live-astro-content-driven-website-rebuild</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/live-astro-content-driven-website-rebuild</guid>
            <pubDate>Sat, 23 Mar 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[A YouTube live coding stream, learning to build content-driven sites with the Astro Web Framework.]]></description>
            <content:encoded><![CDATA[
OpenApi.tools is an Open Source and community-driven list of high-quality, modern tools for OpenAPI that we've been maintaining over at APIs You Won't Hate for the past few years, and it's overdue for a rebuild.

🔧 In this session, I'll be using Astro.build to recreate the openapi.tools site, with a focus on building a highly performant, maintainable, and SEO-driven experience for the next version. If i'm lucky, we'll even get into building some fun new features to help our community find the right tools for their use case with OpenAPI

I'll be building with:

- Astro: https://astro.build
- Hosting through @VercelHQ
- Visual Studio Code
- TypeScript
- React.js
- Markdown
- Fathom analytics @FathomAnalytics
- PostHog @PostHog
- Tailwind CSS @TailwindLabs

📅 Mark your calendars and join me at 10am EST for an insightful journey through the intersection of design and development. If you dig SEO and markdown, or you're a React developer, JavaScript enthusiast or TypeScript pro, or you've been curious about what Atsro brings to the table, you'll enjoy this one!

Don't miss out on this opportunity to learn, create, and connect. Be sure to subscribe and click the notification bell to stay updated on this and more exciting content from Craftwork.

For additional resources like my newsletter for founders and product builders, 💌Tiny Improvements, visit my website at https://mikebifulco.com/newsletter
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Using Satori and Next.js to generate dynamic images]]></title>
            <link>https://mikebifulco.com/posts/live-coding-satori-og-images-nextjs</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/live-coding-satori-og-images-nextjs</guid>
            <pubDate>Sat, 27 Jan 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[A YouTube live coding stream where we explore how we use a variety of dynamic images with Next.js using Satori.]]></description>
            <content:encoded><![CDATA[
Join me for an exciting live stream where we dive into the world of design and development at Craftwork! 🎨💻

🔧 In this session, we'll explore how we use a variety of image templates to elevate our software's appearance. From stylized portraits of our talented team members to vibrant paint swatches and eye-catching Open Graph (OG) preview images for our website, we'll unveil the secrets behind our visual magic.

🖌️ We'll kick things off by using the power of Figma, our design tool of choice, to craft stunning templates. Then, we'll dive deep into the development side, where we'll transform these designs into dynamically generated images. How? With the incredible Satori library and the magic of Edge Functions on Next.js, brought to you by the team at @VercelHQ .

I'll be building with:

- Satori & Next.js from @VercelHQ
- Figma
- Visual Studio Code
- TypeScript
- Tailwind CSS @TailwindLabs

📅 Mark your calendars and join us on Jan 27th at noon EST for an insightful journey through the intersection of design and development. Whether you're a React developer, JavaScript enthusiast, TypeScript pro, designer, or simply curious about UX and tech, this livestream is for you!

Don't miss out on this opportunity to learn, create, and connect. Be sure to subscribe and click the notification bell to stay updated on this and more exciting content from Craftwork.

See you there! 🚀🎉
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Configuring Resend Broadcasts for newsletters on my Next.js website]]></title>
            <link>https://mikebifulco.com/posts/live-coding-resend-broadcasts-nextjs</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/live-coding-resend-broadcasts-nextjs</guid>
            <pubDate>Sat, 20 Jan 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[A coding livestream where integrate Resend's new Broadcasts feature into my next.js site to use for sending newsletters.]]></description>
            <content:encoded><![CDATA[
## Notes about today's Livecoding stream

This is a YouTube Livestream, where I'll be working on integrating Resend Broadcasts into my next.js site to use for sending newsletters. Resend released a new set of features this week that makes it easier to send mail to large audiences.

I'll be building with:

- Resend
- Next.js
- TypeScript
- Vercel
- Tailwind CSS

With Substack recently catching headlines for their boneheaded content moderation policies, lots of creators and developers have been looking at other tools for managing their mailing lists. Between Beehiiv, ConvertKit, Ghost, Mailchimp, and some of the other usual suspects, there are many options to choose from.

Let's take a look at Resend's new API to see how it works, and if it's a good fit for my workflow!

## Don't forget to subscribe

If you're interested in more content like this, please subscribe to my **[YouTube channel - @mikebifulco](https://www.youtube.com/@mikebifulco?sub_confirmation=1)!**
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[How to set up self-healing URLs in Next.js for better SEO]]></title>
            <link>https://mikebifulco.com/posts/self-healing-urls-nextjs-seo</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/self-healing-urls-nextjs-seo</guid>
            <pubDate>Sat, 02 Dec 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Set up self-healing URLs with the App Router in Next.js for better SEO, accessibility, and usability]]></description>
            <content:encoded><![CDATA[
<small>

_note: This post is inspired by a great video from YouTuber Aaron Francis: [Make self-healing URLs with Laravel](https://www.youtube.com/watch?v=a6lnfyES-LA). For all my PHP homies - go check that video out. It's great!_

</small>

<Image
  publicId="posts/self-healing-urls-nextjs-seo/demo"
  alt="A demo of a self-healing URL made in Next.js"
  caption="Ever wonder how Amazon and Medium create self-healing URLs?"
/>

Building sites with human-readable URLs is helpful for a few reasons: it gives users a better understanding of what they're getting when they click on a link to your site, it's better for SEO, and it's more accessible (screen readers can read out the URL to the user and they can understand where they are on the site). It's also just a nice thing to do for your users... by way of example, these two URLs _feel_ dramatically different:

`https://example.com/posts/c61sca0`

vs

`https://example.com/posts/how-to-set-up-self-healing-urls-in-nextjs-for-better-seo`

The first one is a bit of a mystery box. You have no idea what you're going to get when you click on it. The second one is much more descriptive, and _hopefully_ the contents of the page match the URL.

...but, what happens if you change the title of the post? The human-readable URL is now misleading. If you're using a static site generator like Next.js, you can use the file system to create self-healing URLs that will always point to the correct page, even if the title changes.

Or, what if you're managing a larger site, where it's possible that two posts may have the same title?

These are both issues that self-healing URLs are attempting to solve.

## What are self-healing URLs?

**Self-healing URLs are URLs that allow for human-readable text, but also include a unique identifier that will always point to the correct page**, even if the human-readable text changes, or gets removed entirely.

In this post, we'll learn **how to set up self-healing URLs in Next.js.** This is something used on sites like Amazon and Medium to make sharing links a little more robust. These are URLs that allow for human-readable text, but also include a unique identifier that will always point to the correct page, even if the human-readable text changes, or gets removed entirely.

Here's the URL-pattern we're to build: `https://example.com/posts/${POST_TITLE}-${POST_ID}`.

Ultimately, we'll use the `id` of a post to identify which content to render on a page, and we'll use the `title` of the post to create a human-readable portion in the URL. As long as the URL ends with a hyphen followed by the `id`, we will redirect to the correct page, with a nicely formatted, human-readable URL.

## Self-healing URLs in Next.js with the App router

To create self-healing URLs for blog posts with the [Next.js App router](https://nextjs.org/docs/api-reference/next/router), we'll start with a fresh react app from the cli:

```bash
# with npm
npx create-next-app

# or, with yarn
yarn create next-app

# or, with pnpm
pnpm create next-app
```

Give your project a name, and select the options you want to use. I used all the defaults for this example:

```
✔ What is your project named? … next-self-healing-urls-app-router
✔ Would you like to use TypeScript? Yes
✔ Would you like to use ESLint? Yes
✔ Would you like to use Tailwind CSS? Yes
✔ Would you like to use `src/` directory? Yes
✔ Would you like to use App Router? (recommended) Yes
✔ Would you like to customize the default import alias (@/*)? No
```

You'll also need to install the `slugify` package, which we'll use to create a URL-safe slug from the post's title:

```bash
npm install slugify

# or, with yarn
yarn add slugify

# or, with pnpm
pnpm add slugify
```

### Set up dynamic routing

We'll need to add a few files to the default setup. Using the App directory, create the following directories and files:

```
app
├── posts
│   └── [slug]         // note that this is a _folder_ called [slug]. This is how dynamic routes are set up in the app router
│        └── page.tsx  // render one post
├── not-found.tsx      // this will render if someone tries to visit a post page with an id that doesn't exist in the url
├── sitemap.ts         // generate a dynamic sitemap with the _correct_ canonical URL for each post
└── utils
    └── post.ts        // types and helper functions to load posts and format URLs
```

Let's start with `post.ts`. This file contains a type definition and helper functions to load posts and format URLs.

```ts
import slugify from 'slugify';

export type Post = {
  userId: number;
  id: number;
  title: string;
  content: string;
};

export const getAllPosts = async () => {
  // fetch all posts from an example API.
  // this is just a placeholder, replace with your own data
  // shout out to https://jsonplaceholder.typicode.com/ - what a great service!
  const postsResponse = await fetch(
    'https://jsonplaceholder.typicode.com/posts'
  );
  const posts = (await postsResponse.json()) as Post[];

  return posts;
};

export const getPostById = async (id?: string | number) => {
  if (!id) {
    throw new Error('No ID provided');
  }

  if (typeof id === 'string') {
    id = parseInt(id);
  }

  const allPosts = await getAllPosts();

  const post = allPosts.find((post) => post.id === id);

  if (!post) {
    // we'll use a try/catch block around this function later
    // to redirect if a post doesn't exist with this id,
    // so make sure to throw an error here.
    throw new Error('Post not found');
  }

  return post;
};

/**
 * Converts input to a URL-safe slug
 * @param {string} title - the title of the post
 * @returns {string} a URL-safe slug based on the post's title
 */
const titleToSlug = (title: string) => {
  const uriSlug = slugify(title, {
    lower: true, // convert everything to lower case
    trim: true, // remove leading and trailing spaces
  });

  // encode special characters like spaces and quotes to be URL-safe
  return encodeURI(uriSlug);
};

// given a post, return its slug
export const getPostSlug = (post: Post) => {
  return `${titleToSlug(post.title)}-${post.id}`;
};

// given any slug, try to extract an id from it
export const getIdFromSlug = (slug: string) => slug.split('-').pop();
```

### Generate a sitemap with the correct canonical URL for each post

Let's talk SEO for a moment: Google (and other search engines) use your site's sitemap file to understand the structure of your site. This helps them index your site more accurately, and it helps them understand which pages are the most important. Next.js supports static and dynamic sitemap generation, which you can read about in their [docs on sitemap.xml](https://nextjs.org/docs/app/api-reference/file-conventions/metadata/sitemap). Your sitemap should contain the canonical URL for every page in your site.

When Google and other search engines crawl your site, they use the Sitemap as an address book, and then visit each page found in the sitemap to analyze the content on the page, and deciding how to rank it in search results. If the URL in the address bar doesn't match the URL that Google has indexed for that page, it can cause problems with SEO. For example, if you have a page with the URL `https://example.com/foo/bar/some-url-here`, but Google has indexed the page as `https://example.com/foo/bar/some-other-url-here`, Google will think that you have two pages with the same content, and it will penalize you for duplicate content.

This is where the **canonical tag** comes in. The [canonical tag](https://ahrefs.com/blog/canonical-tags/) is a special bit of metadata that you can add to your page's `<head>` tag, which is used to tell search engines which URL is the _original URL for the content onthat page_. Ideally, the canonical URL for our blog posts should _exactly_ match the pattern we've set up for our self-healing URLs: `https://example.com/posts/${POST_TITLE}-${POST_ID}`. This is the URL that we want Google to index for each post. We'll do that by making sure we use this URL in our sitemap, and by adding a canonical tag to each post page.

A canonical tag looks like this:

```html
<link rel="canonical" href="https://example.com/foo/bar" />
```

So, this is what sitemap.ts looks like:

```ts
import { MetadataRoute } from 'next';

import { getAllPosts, getPostSlug } from '@/utils/posts';

export default async function sitemap(): MetadataRoute.Sitemap {
  const allPosts = await getAllPosts();

  let urlPrefix = 'http://localhost:3000';
  if (process.env.NODE_ENV !== 'production') {
    urlPrefix = 'https://example.com';
  }

  return allPosts.map((post) => ({
    url: `${urlPrefix}/posts/${getPostSlug(post)}`, // https://example.com/posts/this-is-a-post-1
    lastModified: new Date(), // ideally, this is the last modified date of the post
    changeFrequency: 'daily', // this will be used to determine how often pages are re-crawled
    priority: 0.7, // the priority of this URL relative to other URLs on your site
  }));
}
```

Now, if you run your app and visit `https://localhost:3000/sitemap.xml`, you should see a sitemap that includes an entry for each post, with the correct canonical URL specified.

### Setting up page.tsx: where the magic happens

In the file `app/posts/[slug]/page.tsx`, we use the [Next.js App Router's `generateStaticParams` function](https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes#generating-static-params) to generate URLs for all posts. This function is called at build time, and it returns an array of objects that contain the `slug` for each post. The `slug` is used to generate the URL for each post page.

Then, in the server function which renders the post page, we check whether the current URL's readable portion matches the post's actual slug. If not, we redirect to the correct URL.

We also use the [Next.js App Router's `generateMetadata` function](https://nextjs.org/docs/app/next-script#generating-metadata) to generate metadata for each post. This function is called at build time, and it returns an object that contains the `title` and `alternates` for each post. The `alternates` object contains the `canonical` URL for each post, which is used to tell search engines which URL is the correct one for each post. **This is critical for SEO purposes** - it helps Google verify that when your page loads, the URL in the address bar matches the URL that Google has indexed for that page.

```tsx
import { Metadata, ResolvingMetadata } from 'next';
import { isRedirectError } from 'next/dist/client/components/redirect';
import { notFound, redirect, RedirectType } from 'next/navigation';

import {
  getAllPosts,
  getIdFromSlug,
  getPostById,
  getPostSlug,
  Post,
} from '@/utils/posts';

// generate URLs for all posts
export async function generateStaticParams() {
  const posts = await getAllPosts();

  return posts.map((post) => {
    const slug = getPostSlug(post);

    return {
      slug,
    };
  });
}

type PostPageParams = {
  params: {
    slug: string;
  };
};

export default async function Post({ params }: PostPageParams) {
  const id = getIdFromSlug(params.slug);

  let post: Post;
  try {
    post = await getPostById(id);
    const correctSlug = getPostSlug(post);

    // check whether the current URL's readable portion matches the post's actual slug
    if (correctSlug !== params.slug) {
      // if not, redirect to the correct URL
      const redirectUrl = `/posts/${correctSlug}`;
      await redirect(redirectUrl, RedirectType.replace);
    }
  } catch (e) {
    // this is a hack to make redirects work from within a try/catch block
    // shout out to @jeengbe on github for the tip
    // https://github.com/vercel/next.js/issues/49298#issuecomment-1537433377
    if (isRedirectError(e)) {
      throw e;
    }

    // if the post doesn't exist, return the "not found" 404 page
    notFound();
  }

  // make your post look nice IRL
  return <div>My Post: {params.slug}</div>;
}

export async function generateMetadata(
  { params }: PostPageParams,
  parent: ResolvingMetadata
): Promise<Metadata> {
  // read route params
  const id = getIdFromSlug(params.slug);
  // fetch data
  const post = await getPostById(id);

  return {
    title: post.title,
    alternates: {
      canonical: `https://example.com/posts/${params.slug}`,
    },
  };
}
```

Another important note - _entire_ component is rendered server-side - visitors to this page won't see any content flash on screen if they enter an incorrect URL. This is huge for page performance and SEO purposes, and has traditionally been challenging while using Static Site Generation.

Instead of a screen flash, your users get a great experience: they can try to load an incorrect URL, and as long as the URL ends with a hyphen followed by the `id`, they'll be redirected to the correct URL seamlessly, like magic. If the URL doesn't match the pattern, they'll be redirected to the 404 page.

### Not Found: a 404 page for posts that don't exist

In `app/not-found.tsx`, create a 404 page that will render if someone tries to visit a post page with an id that doesn't exist in the url. [Next provides a `notFound` function](https://nextjs.org/docs/app/api-reference/functions/not-found) that will return a 404 page. We used this in page.tsx to return a 404 page if the post doesn't exist. You'll want to make this page look nice and include some helpful text, but for the sake of this example, we'll keep it simple:

```tsx
/*
  redirect to this page by calling the `notFound` function from the App Router in a page's server function:
  import { notFound } from 'next/navigation';
*/

export default function NotFound() {
  return <div>Not Found</div>;
}
```

## Try it out!

That should do it! run `yarn dev` to start the server, and navigate to `http://localhost:3000/posts/1` - you'll see it _automatically_ redirect to a better URL.

<Image
  publicId="posts/self-healing-urls-nextjs-seo/demo"
  alt="A demo of a self-healing URL made in Next.js"
/>

Nice!

Head over to `http://localhost:3000/sitemap.xml` and check out the nicely formatted sitemap, with the correct canonical URL for each post. Now your web app, your readers, _and_ Google are all on the same page. 🔥

## To do: update your redirects when a post's title changes

To be completely thorough there's one more thing we should probably do: if a post's title changes, you should add an entry to your redirects file to redirect the old URL to the new one. Even though this is a self-healing URL, it's still a good idea to add a redirect for the old URL, just in case someone has bookmarked it, or if someone has shared it on social media. This will also help Google understand that the old URL is no longer the correct one, and that it should index the new URL instead.

This is a bit more challenging, but it's worth it.

Because making this work is dependent on your specific setup, I'm not going to include a code example here, but I'll give you a few pointers:

- In your CMS, when a post is saved, check whether the title has changed. If it has, add an entry to your redirects file to redirect the old URL to the new one.
- It's a good to make sure that you don't accidentally create a redirect loop. If the new URL for a given path is the same as any of the prior URLs, don't add a new redirect, and remove any existing redirects for that path.
- You may need to kick off a rebuild of your site to make sure that the new redirect is picked up by your app. If you're using Vercel, you can use their [API to trigger a rebuild](https://vercel.com/docs/api#endpoints/deployments/redeploy-all-deployments) when a post is saved.

## Summary: self-healing URLs in Next.js

In this post, we learned how to set up self-healing URLs in Next.js. We used the App Router to generate URLs for all posts, and we used the App Router's `generateMetadata` function to generate metadata for each post. This function is called at build time, and it returns an object that contains the `title` and `alternates` for each post. The `alternates` object contains the `canonical` URL for each post, which is used to tell search engines which URL is the correct one for each post. **This is great for SEO purposes** - it helps Google verify that when your page loads, the URL in the address bar matches the URL that Google has indexed for that page. It also has usability benefits: if your post's title ever changes, the URL will magically update itself to match the new title. Additionally, people who visit your page while using a screen reader will have a better experience, because the URL will always match the content on the page.

Not too shabby!

## Get the code

You can find the code for this tutorial on [GitHub at mbifulco/next-self-healing-urls-app-router](https://github.com/mbifulco/next-self-healing-urls-app-router). If you enjoyed this post, please consider giving it a star ⭐️ on GitHub!

## PS: What about using the Next.js Pages router?

This post _started_ as a tutorial for using the Next.js Pages router to create self-healing URLs, but I ran into a few issues that would make it really challenging to recommend going down this path if you're using the pages router (which is actually what [mikebifulco.com uses](https://github.com/mbifulco/blog)!). For that reason, I think **this is a feature you should only add if you're using the App Router**. I'm including the draft of my original post here [in a gist](https://gist.github.com/mbifulco/daf23aed0d827ec6317962691cb9cd0d) in case anyone wants to take a stab at it. If you figure it out, please let me know!
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Acquired: Costco podcast summaries, generated using a GPT/LLM tool]]></title>
            <link>https://mikebifulco.com/posts/acquired-costco-podcast-llm-summaries</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/acquired-costco-podcast-llm-summaries</guid>
            <pubDate>Tue, 17 Oct 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[I built a tool for summarizing podcasts Using Open AI's GPT and transcription APIs. This is a sample of its output for an episode of the Acquired podcast about Costco's history and business.]]></description>
            <content:encoded><![CDATA[
## What is this thing?

The podcast [Acquired has a fantastic episode on the history of Costco's business](https://www.acquired.fm/episodes/costco). It's a tremendous episode, and you should add it to your queue... but it's also 3 hours long. After lisrtening to it, I wanted to talk about the episode with my teammates. Knowing they all wouldn't likely have the the time to listen to the whole show, I built a tool with OpenAI's Whisper API and GPT4 to summarize the show for them

This post is a sample summary of the episode for a few different personas, generated by LLM tools that I cobbled together. I wrote a bit about it in an issue of my newsletter Tiny Improvements, called

## Executive Summary:

This podcast analyzed the story of Costco, one of the largest and most successful warehouse clubs in the world with revenues of more than $230 billion.

Key Highlights:

- Costco's success is rooted in its unique model that has stripped away the complexities of traditional retail and focuses on providing high-quality goods at low prices. It has also benefited from its membership model, which encourages customer loyalty and provides a steady stream of revenue.
- The company was founded as Price Club in 1976 and pivoted towards the consumer market in the 1980s. It merged with Costco in 1993, and the combined entity became a hit with consumers in North America and beyond.
- Costco's growth has been driven by its keen focus on operational efficiency and a commitment to its core values. The company prioritizes serving its members, treating its employees well, being honest in its business practices, and rewarding its investors.
- The company continually looks for ways to keep operating costs low and pass the savings on to customers. This has led to Costco's successful strategy of having a limited number of products (SKUs), allowing the company to negotiate better deals with suppliers and streamlining operations.
- Costco's approach to growing its business has been defined by discipline and long-term vision. The company emphasizes incremental improvements and sustainability over explosive growth, and this has allowed Costco to steadily increase its market share without compromising on its core principles.

### Points for a Technical Executive (CTO):

- Costco has embraced technology to streamline operations, improve efficiency and support its growth. Most notably, the company has invested in warehouse automation technologies to reduce costs and improve efficiency.
- However, Costco's approach to e-commerce has been slower than other retailers, reflecting the company's emphasis on its brick-and-mortar operations.

### Points for an Operations Executive (COO):

- Costco's operational efficiency is central to its business model, with the company continually looking for ways to reduce costs and pass the savings on to customers.
- The company's decision to limit the number of products (SKUs) it sells has allowed it to streamline operations and negotiate better deals with suppliers.
- Costco's emphasis on retaining employees and promoting from within is also key to its success, helping to ensure consistent service and build a strong company culture.

### Points for a Growth Executive (CBO):

- Costco's growth has been driven by its unique membership model, opening of new stores domestically and internationally, and the introduction of new product categories.
- Even as it expands, the company has remained committed to its core business model of selling high-quality goods at low prices.
- Costco's decision to limit the number of SKUs it sells, and thus avoid the 'paradox of choice', has also helped to drive customer loyalty and repeat purchases.

### Related Reading or Listening:

- 'Made in America' by Sam Walton
- 'The Everything Store: Jeff Bezos and the Age of Amazon' by Brad Stone
- 'The Costco Craze: Inside the Warehouse Giant' documentary by CNBC.
- 'Margin of Safety' by Seth Klarman.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Add custom fonts to Next.js sites with Tailwind using next/font]]></title>
            <link>https://mikebifulco.com/posts/custom-fonts-with-next-font-and-tailwind</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/custom-fonts-with-next-font-and-tailwind</guid>
            <pubDate>Mon, 17 Apr 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Learn how to add custom fonts to your Next.js app using next/font and Tailwind CSS. Improve user experience without sacrificing performance.]]></description>
            <content:encoded><![CDATA[
## Adding custom fonts to your website is a typical requirement for most web projects

By default, Next.js sites will add small set of fonts that you can use for your sites (in addition to the default fonts for a given browser). That can be useful to get started quickly, but for most custom site designs, you'll need to add custom fonts and typefaces that fit your site's brand and design guidelines.

In this tutorial, you'll learn how to **add custom fonts to your Next.js site using the `next/font` package and Tailwind CSS**. There's a few configuration steps needed to load fonts from Google Fonts using `next/font`, generate CSS variables for each font, and then use those variables to create custom font families in your Tailwind config.

With this setup, you'll be able to easily use your custom fonts throughout your Next.js app using Tailwind's utility classes.

### SEO Benefits of using custom fonts correctly on your Next.js site

In addition to improving the user experience, implementing custom fonts on your website can also have a [positive impact on your Lighthouse scores](https://web.dev/patterns/web-vitals-patterns/fonts/) and SEO. However, it's important to implement custom fonts carefully to avoid performance issues. Using too many or too large font files can slow down your site's loading time and hurt your Lighthouse performance score. Additionally, using custom fonts in a way that affects the visual stability of the page can result in lower scores for Core Web Vitals, which can impact your SEO. So, it's important to strike a balance between using custom fonts to enhance the design and ensuring that they don't negatively impact performance or user experience.

### About next/font

[`next/font` is an npm package](https://nextjs.org/docs/api-reference/next/font) developed by Vercel, which provides an easy way to load fonts in your Next.js app, while maintaing performance, and minimizing [Cumulative Layout Shift (CLS)](https://web.dev/optimize-cls/). It uses the Font Loading API to asynchronously load local font files stored in your repo, or from popular font providers such as Google Fonts, Typekit, and Fonts.com. The package also generates optimized font subsets to reduce the amount of data transferred over the network, and it provides a convenient way to generate CSS variables for each font, which can be used to create custom font families in your [Tailwind config](https://tailwindcss.com/docs/configuration). This makes it easy to use custom fonts throughout your Next.js app with minimal configuration.

## How to: Add multiple custom fonts to your Next.js site with Tailwind CSS

There are several ways to load custom fonts into your next.js app. If you're using a Google Fonts as your custom font provider, you can use the `next/font/google` package to load fonts from Google Fonts. The process is slightly different for loading font files that are stored locally in your repo, but the basic steps are the same:

### Load custom fonts from Google Fonts

In `_app.jsx/tsx`, load your the fonts you need from `next/font/google`, but use the `variable` configuration prop, which you will use to generate a definition for a CSS `--var` for each font:

```tsx
import { Barlow_Condensed, Inter } from 'next/font/google';

const barlowCondensed = Barlow_Condensed({
  weight: '700',
  subsets: ['latin'],
  variable: '--font-barlow-condensed',
});
const inter = Inter({
  subsets: ['latin'],
  variable: '--font-inter',
});
```

### Load custom fonts from a local file

This next example shows how you would load a font from a local file. It also showcases another feature of the `next/fonts` library - you can map font weights to different files as needed. This also applies for font _styles_ (italic, bold, etc).

In `_app.jsx/tsx`, load your the fonts you need from `next/font/local` using the syntax below. Note that in this case, font files in my repo are also being hosted in `/public/fonts` directory. Again, make sure to use the `variable` configuration prop, which you will use to generate a definition for a CSS `--var` for each font:

```tsx
import localFont from 'next/font/local';

const grosa = localFont({
  src: [
    {
      slug: '../../public/fonts/Grosa/Grosa-Regular.woff2',
      weight: '500',
      style: 'normal',
    },
    {
      slug: '../../public/fonts/Grosa/Grosa-Medium.woff2',
      weight: '600',
      style: 'normal',
    },
    {
      slug: '../../public/fonts/Grosa/Grosa-Bold.woff2',
      weight: '700',
      style: 'normal',
    },
  ],
  variable: '--font-grosa',
});
```

### After loading custom fonts, generate CSS variables for each font

Then, in that same `_app.tsx` component - pass the generated variables into the wrapper class. This will make that variable available to any child of that element in the DOM (in other words, your whole app):

```tsx
export default function MyApp({ Component, pageProps }) {
  return (
    <main
      className={`${inter.variable} ${barlowCondensed.variable} ${grosa.variable}`}
    >
      <Component {...pageProps} />
    </main>
  );
}
```

Behind the scenes, next is generates unique css classes for each font permutation. These classes do one thing: they define a [css custom property](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties) (sometimes called a css variable) for each font.

By adding the resulting CSS classes to the root of your Next.js app, these variables are made available to any child of the `App` component - essentially all pages and components on your site.

<Image
  publicId="posts/custom-fonts-with-next-font-and-tailwind/classes"
  caption="is a screenshot from Chrome Browser tools for Craftwork.com, which is built using this setup"
  alt="screenshot of chrome browser tools showing the resulting CSS classes"
/>

### Use these variables your Tailwind config to create font families

Up to this point, we've loaded our custom fonts into our Next.js app, and we've made those fonts available to our entire app using CSS variables. Now, we need to tell Tailwind how to use these variables, by assigning them to specific font-family classes.

In your Tailwind config, add an entry to your `theme.extend`, to create a new font family that uses the google fonts you just imported - that will look something like this:

```tsx
// tailwind.config.js
export default {
  theme: {
    extend: {
      fontFamily: {
        "barlow-condensed": "var(--font-barlow-condensed)", // note: you can call the left side of this whatever you want - barlow-bold or title-font or foo-bar, this is what you'll use in your Tailwind css classes to use this font
        "inter-medium": "var(--font-inter)", // note: the bit that goes inside the var() function is the same variable name we defined in app.tsx
      }
    }
  }
```

Then, whenever you want to use the fonts you've added, ask for that font-family in your tailwind classnames by prefixing the font-family with "font-", like this:

```tsx
const myComponent: React.FC = () => (
  <p className="font-barlow-condensed">
    This should be rendered with the Barlow font family
  </p>
);

export default myComponent;
```

That should do the trick!

If you're wondering where these steps came from, it is essentially a combination of the instructions provided in [Next's docs for Font Optimization](https://nextjs.org/docs/basic-features/font-optimization). My team is using this very configuration setup for our Next.js site on [Craftwork.com](https://craftwork.com) to load custom fonts both locally and from Google Fonts, and it's been working great.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Building in public: 400 subscriber milestone report for my newsletter]]></title>
            <link>https://mikebifulco.com/posts/building-in-public-growth-report-400-readers</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/building-in-public-growth-report-400-readers</guid>
            <pubDate>Thu, 06 Apr 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Tiny Improvements has seen 350% growth in the last 6 months. This is my reflection on that growth, and tips for anyone interested in writing a newsletter.]]></description>
            <content:encoded><![CDATA[
## Growing feels great

It feels a little wild to say this, but I'm a few days away from hitting 400 Subscribers to my weekly newsletter, [Tiny Improvements](https://mikebifulco.com/newsletter). I started writing to share my expertise with the world, and to try to pay forward some of my luck and privilege to anyone who might benefit from it.

I've been writing about startups, building products, design, and React for a few years now, and it feels like the newsletter has really hit its stride lately.

In the past 6 months, I've grown by 350%, and landed about half a dozen sponsored newsletters. It's been really encouraging to see people enjoying what I have to say - and I have gotten some amazing feedback along the way.

## The basics: what I've learned so far

For my friends who may be interested in doing something like this, here's my advice: write on a dependable, regular cadence, publish your newsletters for SEO-driven growth, and don't be afraid to share your work.

## Growth comes in phases

<Image
  publicId="posts/building-in-public-growth-report-400-readers/growth-chart"
  alt="a chart showing the growth of Tiny Improvements since its launch in May of 2020"
/>

This chart shows a few important milestones in the story behind Tiny Improvements:

- **0-34** readers: May 2020, when I first announced I was writing
- **34-50** readers: December 2020, months later, after I sent my second dispatch
- **88-143** readers: July - Nov 2022, I started writing weekly
- **143-215** readers: November 9th - Dec 1 2022, I [Got laid off from my Job @ Stripe, and went viral](https://mikebifulco.com/newsletter/leaving-stripe-going-viral)
- **215-215** readers: December 2022 - Jan 2023: Flatlined! Turns out I introduced a bug to my site that prevented anyone from subscribing. lol.
- **215-394** readers: This brings us to today! Steady growth from steady writing, half a dozen sponsorships, and some promising deals coming my way.

## What's next?

I'll be writing more about my [experience as a founder](https://mikebifulco.com/newsletter/building-a-startup-in-2023-90-day-report), and sharing the lessons and challenges I will no-doubt run into as we grow. I've also got some ideas for short multi-segment posts/tutorials that I'd like to share, like more about [design for developers](https://mikebifulco.com/tags/design), and [networked note-taking](https://mikebifulco.com/newsletter/unlock-productivity-with-networked-note-taking).

Finally, on the business front, I'm hoping I'll be able to start working with sponsors who I think will really connect with my readers - I'm hoping to build relationships with some of the devtools companies which I really love, to see if there are opportunities to work together. I want to really come through for the people who have supported me (if you're reading this, that's you!), and I want to make sure that I'm only working with companies that I think will really benefit my readers.

By the way - if you're interested in [sponsoring Tiny Improvements](https://mikebifulco.com/sponsor), let's talk!

And of course, I'm looking forward to 400, and then 500 readers, and then anything to come after that!

## You should probably subscribe to Tiny Improvements

If you're interested in startups, building products, design, or React, I think you might really like [💌 Tiny Improvements](https://mikebifulco.com/newsletter).
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Steps I take to fix stubborn TypeScript errors in VS Code]]></title>
            <link>https://mikebifulco.com/posts/typescript-vscode-error-fix-last-resort</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/typescript-vscode-error-fix-last-resort</guid>
            <pubDate>Wed, 15 Feb 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Sometimes fixing a TypeScript or eslint error in VS Code can feel impossible. Here's what I do when I have exhausted all my resources.]]></description>
            <content:encoded><![CDATA[
## I'm new to TypeScript.

I've been using TypeScript to build software for my new company, [Craftwork](https://craftwork.com). I've been pretty open about the fact that I'm new to TypeScript, and have been blissfully writing non-type-safe javascript code since somewhere around 2005.

Of course, that's all changing.

This new project is built with [create-t3-app](https://create.t3.gg), a framework for building TypeSafe apps with Next.js and TRPC. Out of the box, t3 is configured with some sensible (and fairly strict) settings for both eslint and TypeScript's tsconfig.

If you're familiar with TypeScript, Eslint, and tsconfig you may want to skip ahead to [My last resort to fix TypeScript errors in VS Code](#my-last-resort-to-fix-typescript-errors-in-vs-code).

### ESLint in a nutshell

If you're not familiar, _eslint is a **linter**_ - a tool that will help you identify and fix code quality and formatting issues in your code.

ESLint is a popular linter for JavaScript, and it can also be used with TypeScript. It provides a wide range of configurable rules that you can use to enforce consistent code style and identify potential bugs. ESLint is highly extensible, which means you can customize it to fit your specific needs. For example, you can use it to enforce your team's coding standards, or to catch common mistakes that TypeScript can't detect on its own.

### tsconfig in a nutshell

When you're working on a TypeScript project, `tsconfig.json` is a configuration file that allows you to specify how the TypeScript compiler should behave when it compiles your code.

The purpose of `tsconfig.json` is to provide a single source of truth for your TypeScript project's configuration. It allows you to specify options such as the target version of JavaScript you want to generate, the module system you want to use, the paths to your project's source files, and many other settings.

One of the main benefits of using `tsconfig.json` is that it allows you to enforce a consistent set of rules across your project. You can use it to enforce specific compiler options, which helps to ensure that your code is consistent and that everyone on your team is using the same settings. `tsconfig.json` also allows you to configure your project's build pipeline, so you can easily automate the process of compiling and bundling your TypeScript code.

Additionally, `tsconfig.json` allows you to take advantage of features like incremental compilation, which can significantly improve the speed of your builds by only compiling the parts of your project that have changed since the last build.

## How TypeScript works in VS Code

There are a few steps required to set up TypeScript to work with VS Code. If you haven't done this yet, you should follow the instructions on VisualStudio.com to get started: [TypeScript in Visual Studio Code](https://code.visualstudio.com/Docs/languages/typescript).

When you open a TypeScript file in VS Code, the TypeScript language server will start in the background. The language server is a separate process that provides language features like IntelliSense, code navigation, and code refactoring. It also provides the ability to run TypeScript code in the editor. Because TypeScript has _many_ options and plugins, the language server uses the `tsconfig.json` file in your project to determine the rules it should use to compile your code.

VS Code needs to determine which version of TypeScript to use, so it will look for a `package.json` file in your project. If it finds one, it will use the version of TypeScript specified in the `devDependencies` section. If it doesn't find a `package.json` file, it will use the version of TypeScript that is bundled with VS Code.

---

## My last resort to fix TypeScript errors in VS Code

Sometimes, when I'm working on a TypeScript project, I'll get an error in VS Code that I can't figure out. I'll check and double-check against articles and tutorials online, or ask my hyper-smart TypeScript friends ([Sean Rogers, everyone](https://seanrogers.dev/)), and despite doing everything I can think of to address the problem, sometimes I just can't get the error to go away.

Here's what I do when I find myself in this situation:

### Make sure VS Code is using the correct version of TypeScript

Sometimes VS Code's TypeScript process doesn't use the right version of TypeScript for the project I'm working on. For me, this seems to happen after updating TypeScript versions, or when switching between projects that use different versions of TypeScript.

To check which version of TypeScript VS Code is using, open the Command Palette (Ctrl+Shift+P on Windows, or &#8984; on a Mac) and type `TypeScript: Select TypeScript Version`.

<Image
  publicId="posts/typescript-vscode-error-fix-last-resort/select-typescript-version"
  alt="Select TypeScript Version in the command palette in VS Code"
/>

If the version of TypeScript that is selected is not the one you expect, select the correct version from the list. Generally speaking, you'll want to select the version of TypeScript that is specified in your project's `package.json` file, by selecting `Use Workspace Version` option.

### Restart the TS server process

If that doesn't fix the problem, or VS Code was already running my workspace's version of TypeScript, the next thing I'll do is restart the TS server process. This is the background process being run by VS Code to actually analyze and compile your TypeScript code into JavaScript. Sometimes this process malfunctions, and restarting it can fix the problem.

To restart the TS server process, open the Command Palette (Ctrl+Shift+P on Windows, or &#8984; on a Mac) and type `TypeScript: Restart TS Server`.

<Image
  publicId="posts/typescript-vscode-error-fix-last-resort/select-typescript-version"
  alt="Select TypeScript Version in the command palette in VS Code"
/>

### Restart the ESLint server process

On occasion I'll also need to restart the ESLint server process. Just like it sounds, this is the process that analyzes your code for linting errors, according to the rules specified in your project's `.eslintrc` file and the version of ESLint that is specified in your project's `package.json` file.

<Image
  publicId="posts/typescript-vscode-error-fix-last-resort/restart-eslint-server"
  alt="Restart ESLint Server in the command palette in VS Code"
/>

## If that doesn't work, I'm out of ideas

..and by that, I mean I'm still learning. There's loads to learn about TypeScript, and I've found quite a few great resources online from devs like me who have shared their experiences and knowledge. I hope this article helps you - and if you're looking for more, check these out:

- Kent C. Dodds has a great article called [Using fetch with TypeScript](https://kentcdodds.com/blog/using-fetch-with-type-script) which I nearly have memorized at this point. This is the problem I was trying work through when I discovered that I needed to restart the TS server process in VS Code.
- [James Q. Quick](https://www.youtube.com/@JamesQQuick) has a great YouTube channel where he shares tips and tutorials for building web apps with a wide variety of frameworks and technologies.
- I've got some more articles on working with TypeScript in VS Code, including [Refactoring TypeScript React components in VS Code](https://mikebifulco.com/posts/refactoring-typescript-react-components-vscode#resources-for-learning-typescript)
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Refactoring TypeScript React components in VS Code]]></title>
            <link>https://mikebifulco.com/posts/refactoring-typescript-react-components-vscode</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/refactoring-typescript-react-components-vscode</guid>
            <pubDate>Fri, 03 Feb 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Extracting types from a JavaScript object is a common task in TypeScript. This post shows how to do it with VS Code.]]></description>
            <content:encoded><![CDATA[
## Extracting types from a JavaScript object

I am brand new to TypeScript, and far from an expert. So far, I really enjoy using it to build React apps with Next.js. As I'm growing the skills I'll need to be a better TypeScript developer, I'm finding that a fairly typical chore for me is to refactor my code to extract types from a JavaScript object. For example, I often find myself writing code in react components that looks a lot like this:

```tsx
import Footer from '@components/Footer';
import Header from '@components/Header';

const PageLayout = ({ children }) => {
  return (
    <>
      <section className="min-h-[100vh] pb-8 sm:pb-12 lg:pb-12">
        <Header />
        <div className="lg:relative">{children}</div>
      </section>
      <Footer />
    </>
  );
};

export default PageLayout;
```

There is no type-checking going on in this code as it is written. I've been writing react with good ol' plain JavaScript for so long that creating components like this is reflexive for me. I'm not even thinking about it.

Eventually during implementation I get to the point where adding some complexity to the component requires me to add some type-checking. At that point, I usually refactor the component to lambda syntax, and add a type annotation to the component:

```tsx
import Footer from '@components/Footer';
import Header from '@components/Header';

const PageLayout = ({ children }) => {
  return (
    <>
      <section className="min-h-[100vh] pb-8 sm:pb-12 lg:pb-12">
        <Header />
        <div className="lg:relative">{children}</div>
      </section>
      <Footer />
    </>
  );
};

export default PageLayout;
```

Next, I'll add a type annotation to the `children` prop:

```tsx
import Footer from '@components/Footer';
import Header from '@components/Header';

const PageLayout = ({ children }: { children: React.ReactNode }) => {
  return (
    <>
      <section className="min-h-[100vh] pb-8 sm:pb-12 lg:pb-12">
        <Header />
        <div className="lg:relative">{children}</div>
      </section>
      <Footer />
    </>
  );
};
```

Taking it a step further, I'll give the function a return type signature, using `React.FC` and generics to define the props:

```tsx
import Footer from '@components/Footer';
import Header from '@components/Header';

const PageLayout: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  return (
    <>
      <section className="min-h-[100vh] pb-8 sm:pb-12 lg:pb-12">
        <Header />
        <div className="lg:relative">{children}</div>
      </section>
      <Footer />
    </>
  );
};
```

Up to this point, I don't really mind the way this component was written in any of the previous refactors. It's clearly getting more complex, but I can still understand what's going on. But what if I wanted to add a `variant` prop to the component? I'd have to add another type annotation to the function signature:

```tsx
import Footer from '@components/Footer';
import Header from '@components/Header';

const PageLayout: React.FC<{
  children: React.ReactNode;
  variant: 'dark' | 'light' | 'black' | 'tan';
}> = ({ children, variant }) => {
  return (
    <>
      <section className="min-h-[100vh] pb-8 sm:pb-12 lg:pb-12">
        <Header variant={variant} />
        <div className="lg:relative">{children}</div>
      </section>
      <Footer />
    </>
  );
};
```

Even with a little prettier formatting, this is getting a little hard to read. This is where I usually extract the props into a type, and then use that type in the function signature:

```tsx
import Footer from '@components/Footer';
import Header from '@components/Header';

type PageLayoutProps = {
  children: React.ReactNode;
  variant: 'dark' | 'light' | 'black' | 'tan';
};

type PageLayout = React.FC<PageLayoutProps>;

const PageLayout: PageLayout = ({ children, variant }) => {
  return (
    <>
      <section className="min-h-[100vh] pb-8 sm:pb-12 lg:pb-12">
        <Header variant={variant} />
        <div className="lg:relative">{children}</div>
      </section>
      <Footer />
    </>
  );
};
```

Now _this_ I like! The props for this page are defined in a single place, and the function signature is much easier to read.

## Using VS Code's refactor menu to extract types

As it works out, VS Code has loads of functionality to make this sort of work quicker. The refactor menu can be accessed by highlighting some code, right clicking on it, and selecting `Refactor...`. There are a number of TypeScript-specific functions provided which can help you refactor your code.

In this case, we can extract types from our component's signature in a few steps:

<Image
  publicId="posts/refactoring-typescript-react-components-vscode/refactor-1"
  alt="VS Code Screenshot: Select the entire `React.FC<` return type and right clicking on it"
  caption='Select the entire `React.FC<` return type and right click on it, and Choose "Refactor..." from the context menu.'
/>

<Image
  publicId="posts/refactoring-typescript-react-components-vscode/refactor-2"
  alt="VS Code Screenshot: Choose 'extract type to type alias' from the refactor menu"
  caption='Select "Extract type to type alias" to extract the type into a type alias'
/>

<Image
  publicId="posts/refactoring-typescript-react-components-vscode/refactor-3"
  alt="VS Code Screenshot: Give the extracted type a name, and hit enter."
  caption="Give the extracted type a name, and hit enter."
/>

## Bonus: Add JSDoc comments to your types for better intellisense

If you want to take it further, you can add a JSDoc comment to the type definition to add some documentation. This is a good way to document your code, and it's also a good way to get better intellisense for your code if it's supported in your editor:

```tsx
import Footer from "@components/Footer";
import Header from "@components/Header";

type PageLayoutProps = {
  children: React.ReactNode;
  variant: "dark" | "light" | "black" | "tan";
};

/**
 * The PageLayout component is used to wrap all pages in the application.
 * It provides a consistent header and footer, and a consistent layout for
 * the page content.
 * @param {object} props
 *   @param {React.ReactNode} props.children - The page content
 *   @param {"dark" | "light" | "black" | "tan"} props.variant - The color variant for the page
 * @returns {JSX.Element}
 **/
const PageLayout: PageLayout = ({ children, title }) => {

  /* etc */
```

## Don't learn TypeScript, just use it

...and by that I mean that TypeScript is a _great_ enhancement to building things with JavaScript, but you do not need to be an expert on TypeScript to use it by any means. I've been starting to use TypeScript more and more in my projects, and I've found that I can get a lot of mileage out of it without having to learn every single detail about it.

Theo from [t3.gg](https://t3.gg) has a great video that sums up my learning strategy for TypeScript pretty well, called Don't Learn TypeScript. I highly recommend watching it, or putting it in your queue for your next coffee break:

<YouTube youTubeId="kRiD6ZpAN_o" />

## Resources for learning TypeScript

As I mentioned, I'm fairly new to TypeScript - I only just started using it in the past few months. If you're learning TypeScript and are looking for some great places to learn, check these out:

- [Matt Pocock's YouTube channel](https://www.youtube.com/@mattpocockuk) is a library of really interesting videos about TypeScript. He shares tutorials as well as experience-driven, nuanced opinions about TypeScript (_when should I use an interface instead of a type?_ etc). IMO he's the defacto expert on TypeScript in real life.
- [TypeScript Course](https://www.typescriptcourse.com/) is a fantastic _free_ email course from [Joe Previte](https://jsjoe.io) [(@jsjoeio)](https://twitter.com/jsjoeio). It's a to learn TypeScript a little bit at a time.
- [TypeScript Deep Dive](https://basarat.gitbook.io/typescript/) is just what it sounds like - a thorough deep dive into TypeScript. It's a free book, with an available paid course on Udemy for those who want more .
- [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/intro.html) is the official TypeScript documentation. For better or worse, I don't think it's a great place to start, but it contains every detail you might possibly need. I've found myself coming back to it from time to time to look up specific features and to help debug this-and-that.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Sync your About page and your GitHub bio on your Next.js site]]></title>
            <link>https://mikebifulco.com/posts/next-js-github-bio-about-page</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/next-js-github-bio-about-page</guid>
            <pubDate>Fri, 09 Dec 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[Learn how to sync your About page and your personal GitHub README bio on your Next.js site, as a step towards owning your content on social media.]]></description>
            <content:encoded><![CDATA[
## Your about page tells the world who you are, and what matters to you

For many developers, the about page is one of the most important pages on your website. It tends to be one of the most highly-visited pages on many devs' sites. It serves as the page that will tell the world who you are, and what matters to you. It's also the page that will help you stand out from the crowd, and help you connect with your audience.

Similarly, your [GitHub profile README](https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-profile/customizing-your-profile/managing-your-profile-readme) is the first thing that people will see when they visit your profile on GitHub. I've seen many creative uses for personal GitHub profile pages, but they are most commonly used as a place to share a bio, and to connect with your audience.

They Sounds awfully similar, no?

This week, I decided that for me at least, they _should_ be one in the same. [My personal about page](https://mikebifulco.com/about) and my [GitHub Profile](https://github.com/mbifulco) contained a lot of overlapping information, but weren't _quite_ the same. My site is built with Next.js, and I use an extension of Markdown called MDX to write my content. My GitHub profile README is written in Markdown. Because of this, keeping them in sync turned out to be pretty easy.

## Setup and background

Making this setup work requires some modifications to your Next.js site, and it's important to understand how things work before you dive in. Here's a quick overview of how this setup works:

### Content flows from GitHub -> your Next.js site

In this setup, the source of truth for content on the about page will be GitHub Profile README. From the next.js site, we fetch the README and render it on the About page using a library called [`next-mdx-remote`](https://github.com/hashicorp/next-mdx-remote).

So, to update our bio in _both places_, we'll edit the README file on GitHub. This will update the content on our About page, as well as our GitHub profile README.

### About next-mdx-remote

[`next-mdx-remote`](https://github.com/hashicorp/next-mdx-remote) is an npm library that provides an API for loading remote MDX files into Next.js. It allows developers to write their pages in [MDX](https://mdxjs.com/docs/), an extension of [Markdown](https://daringfireball.net/projects/markdown/) that supports embedded React components. It also provides an API for loading the MDX files from a remote URL, allowing developers to use an external CMS or content storage system to manage their page content. This is exactly what we need to sync our About page and our GitHub profile README, which is written in Markdown.

## How to sync your Next.js site About page to your GitHub README

Here's how you can set this up:

1. First, create an About page on your Next.js site. Typically, this means creating a file in the `/pages/` directory of your source code called `about.jsx` (or `about.tsx` if you're using TypeScript).

```jsx
// For sake of example, we'll use a Layout component to represent the visual layout of the page
import Layout from '../components/Layout';

export default function About({ source }) {
  return <Layout>{/* content from GitHub will go here */}</Layout>;
}
```

2. Next, create a GitHub profile README. If you haven't done this before, Monica Powell ([@indigitalcolor](https://twitter.com/indigitalcolor)) has a great tutorial - [How to create a GitHub profile README](https://aboutmonica.com/blog/how-to-create-a-github-profile-readme). This is where you'll write your bio - and this is the file that will be synced to your About page.

3. Now you'll need to set up next-mdx-remote on your Next.js site. Once your readme is fetched from GitHub, we will use this library to serialize it as MDX -- in other words, to transform it from Markdown to renderable react components for Next.js.

If you don't already have it installed, you can install it with npm, yarn, or pnpm.

```bash {1,3-5}
npm install next-mdx-remote
# or
yarn add next-mdx-remote
# or
pnpm add next-mdx-remote
```

4. Next, we need to grab the raw Markdown from our GitHub README, and feed it into next-mdx-remote. I chose to do this in getStaticProps, which means it will be fetched and rendered once when my site is built, and then cached. This is fine for my use case, but if you're updating your about page frequently, you may want to use getStaticProps instead, to fetch your README on every page render.

So, back in `pages/about.jsx`:

```jsx {1,3-5}
import { serialize } from 'next-mdx-remote/serialize';

// For sake of example, we'll use a Layout component to represent the visual layout of the page
import Layout from '../components/Layout';

// fetch personal README from github and return it as mdx in getserversideprops
export async function getStaticProps() {
  const res = await fetch(
    // replace this with your own README's raw URL (see below)
    'https://raw.githubusercontent.com/mbifulco/mbifulco/main/README.md'
  );
  const content = await res.text();

  // include mdxOptions as needed on your site
  const mdxSource = await serialize(content /*, mdxOptions */);

  return {
    props: {
      mdxSource,
    },
  };
}

export default function About({ source }) {
  return <Layout>{/* content from GitHub will go here */}</Layout>;
}
```

To get the raw URL for your README, go to your GitHub profile, and click on the README file. Then, click the "Raw" button in the top right corner of the file. Copy the URL from the address bar, and replace the URL in the code above with your own.

5. Finally, you can render your README in your About page using MDX Remote.

```jsx
// If you want to have MDX render custom components, you can import them here
import { components } from '~/utils/mdx-components';
import { MDXRemote } from 'next-mdx-remote';
import { serialize } from 'next-mdx-remote/serialize';

// For sake of example, we'll use a Layout component to represent the visual layout of the page
import Layout from '../components/Layout';

export async function getStaticProps() {
  // fetch personal README from github
  const res = await fetch(
    // replace this with your own README's raw URL
    'https://raw.githubusercontent.com/[YOUR_USERNAME]/[YOUR_USERNAME]/[YOUR_DEFAULT_BRANCH]/README.md'
  );
  const content = await res.text();

  // include mdxOptions as needed on your site
  const mdxSource = await serialize(content /*, mdxOptions */);

  // pass the mdxSource to the page component in props
  return {
    props: {
      mdxSource,
    },
  };
}

export default function About({ mdxSource }) {
  return (
    <Layout>
      {/* note: passing in components is optional */}
      <MDXRemote {...mdxSource} components={components} />
    </Layout>
  );
}
```

Bingo bango, we're there! Now, whenever you update your README, your About page will reflect those changes the next time your site is built. If you'd like to see how [the about page for my site](https://mikebifulco.com/about) is implemented, you can check out the [source code on GitHub](https://github.com/mbifulco/blog/blob/main/src/pages/about/index.js), since it's all Open Source!

## More Next.js goodness

If you enjoyed this post, you might want to check out some of my other [articles on next.js](https://mikebifulco.com/tags/nextjs) :

- [Publish newsletters to your Next.js site with ConvertKit API](https://mikebifulco.com/posts/publish-your-newsletter-with-convertkit-api-next-js)
- [What it's like to migrate a high-traffic website from Gatsby to Next.js](https://mikebifulco.com/posts/migrate-gatsby-to-nextjs-apisyouwonthate-com)
- [https://mikebifulco.com/posts/mdx-auto-link-headings-with-rehype-slug](https://mikebifulco.com/posts/mdx-auto-link-headings-with-rehype-slug)
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Twitter and the Perils of Obedience]]></title>
            <link>https://mikebifulco.com/posts/twitter-and-the-perils-of-obedience</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/twitter-and-the-perils-of-obedience</guid>
            <pubDate>Mon, 28 Nov 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[Reflections on the current state of Twitter, and its similarity to the shocking results of a 1961 experiment by Yale Researcher Stanley Milgram.]]></description>
            <content:encoded><![CDATA[
<Aside type="warning">

## The bottom line: It's time to leave Twitter

As Twitter changes, ask yourself: Are you willing to follow any authority, even at the expense of your values? Before your next tweet, consider what staying truly costs-and explore new spaces that reflect your integrity.

</Aside>

## The Milgram Experiment

In 1961, a Yale University researcher named Stanley Milgram conducted a series of experiments as a part of his research on behavioral psychology. The goal of the experiment was to test participants' tendency to obey authority figures when under pressure.

The experiment was conducted on 40 volunteers -- all men between the ages of 20 and 50, from a variety of educational and economic backgrounds.

Milgram later summarized findings from the experiment in an essay titled _The Perils of Obedience_.

The results were breathtaking.

### The Experiment: Setup

Each study was guided by an _Experimenter_ dressed in a lab coat, who explained to participants that they'd be doing a "scientific study on memory and learning." When they arrived, participants were paired with an actor who they were _told_ was another participant in the study.

The actor was secretly working with the researcher, and during the experiment was instructed to play the role of a _Learner_.

The volunteer participant was given the role of _Teacher_. The Experimenter then explained that the study would involve the Teacher asking the Learner a series of questions. For each incorrect answer, the Teacher would be asked to hit a button which would administer an electric shock to the Learner. Subsequent incorrect answers would result in a shock of increasing intensity, from 15V to 450V.

The Learner was strapped into a device that looked like an electric chair, and then separated from the Teacher so that they could not see one-another.

<Image
  publicId="posts/twitter-and-the-perils-of-obedience/experiment-setup"
  alt="Diagram of the setup used for the Milgram Experiment, with the Experimenter and Teacher on one side of a wall, and the Learner on the other."
  caption="Credit: diagram of the Milgram experiment from Wikipedia"
/>

In reality, there were no shocks being administered, but this was unknown to the study participant playing the role of the Teacher. The actor playing the role of the Learner was instructed to pretend to be in pain, and recordings of increasingly alarming cries of pain were played when shocks were administered.

When the highest shock level was reached, the Learner fell completely silent.

During the experiment, if the Teacher showed hesitation to continue, the Experimenter gave them a series of specific instructions:

1. Please go on.
1. The experiment requires that you continue.
1. It is _absolutely essential_ that you continue.
1. You have no other choice; you _must_ go on.

These "prods" were given in order, and the second was only given if the Teacher refused to continue after the first (and so on).

The experiment was halted when the Teacher refused to continue despite all four prods, or when the Teacher reached the highest shock level three times in a row.

<Image
  publicId="posts/twitter-and-the-perils-of-obedience/experiment-photos"
  alt="Photos from the original Milgram experiment, credit Stanley Milgram."
  caption="Photos from the original Milgram experiment, credit Stanley Milgram"
/>

### What would you do?

Let's take a minute to pause here - put yourself in the shoes of the Teacher. You're in a lab, and you're told that you're taking part in a study on learning and memory. Everything you're seeing and hearing seems to be controlled, official, and legitimate.

Do you think you would continue to administer shocks to the Learner, even when they were clearly in pain?

What do you think the average person would do?

<span className="mb-8 flex items-center justify-center text-2xl">
  <Colophon />
</span>

### The Experiment: Results

As you might expect, every participant in the study indicated a desire to stop the experiment at least once. Many were visibly upset by the experience, and despite this, carried on following the Experimenter's instructions.

Before conducting the experiment, researchers surveyed a cohort of students and fellow researchers, to get a sense of what they thought the average person would do. In aggregate, they estimated that 1.2% of people would continue the experiment through the full 450V shock.

<Image
  publicId="posts/twitter-and-the-perils-of-obedience/predicted-results"
  alt="Predicted Results: 1.8% complete the full series of shocks, 98.2% refuse to continue at some point"
  caption="Surveys predicted that very few participants would carry out the full series of shocks"
/>

However, the actual results of the experiment revealed a disturbing truth about human behavior:

<Image
  publicId="posts/twitter-and-the-perils-of-obedience/actual-results"
  alt="Actual Results: 59.1% completed the full series of shocks, 40.9% refused to continue at some point"
  caption="The experimental results were much more grim."
/>

Very nearly 60% of participants carried out the full series of shocks, carrying the study to its conclusion -- even when the Learner sounded like they were clearly in pain, and until they fell silent.

Recreations of this experiment have produced similar results, [as recently as 2009](https://www.apa.org/news/press/releases/2008/12/replicating-milgram).

Milgram's experiment revealed the ease with which people obey authority figures - even when it conflicts with their morals. Twitter, under Musk, can feel like a modern replication of this phenomenon. With reduced moderation and authority shifting dramatically, users face their own “shock button”: Do they accept increasingly extreme content and directives, or walk away?

Like Milgram's participants, twitter users are nudged to compromise their ethics - creating a tension that asks: _how far will you go?_

## Obedience and the Perils of Twitter

I can't help but draw a connection between the Milgram experiment and the current state of Twitter since its acquisition by Elon Musk. Twitter has turned into a public experiment, testing our willingness to obey rules set by an authority figure, despite many less damaging alternatives.

Since Elon purchased the company, we've seen the voltage knob get turned up steadily and swiftly.

Under Musk's leadership, Twitter's employee base has been slashed from 7,500 to approximately 2,000, in an attempt to make the company profitable. It appears that Musk may be trying to avoid paying severance to these now-former employees. There are already [several lawsuits pending](https://www.reuters.com/technology/twitter-says-lawsuit-over-layoffs-lacks-merit-has-delayed-severance-pay-2022-11-22/) against the company.

A recent tweet from Musk included a poll which resulted in the reinstatement of former (and twice-impeached) president Trump's account.

For me, this was the final straw.

<Tweet align="center" tweetLink="irreverentmike/status/1594455660040572928" />

Since then, another poll from Musk has resulted in an abhorrent policy change: virtually all accounts that were previously suspended for violating Twitter's rules will be reinstated.

<Tweet align="center" tweetLink="elonmusk/status/1595473875847942146" />

Pandora's box is open, and the monsters are flooding in. Twitter has already seen a spike in hate speech, harassment, and abuse. Without significant and drastic changes in moderation, it will become a breeding ground for countless nightmares and real-world dangers. This will worsen the echo chamber effect for far-right conspiracy theorists, like those who participated in the January 6th, 2021 insurrection at the US Capitol.

This is a very real, very observable truth: racists, abusers, and other dangerous people are being given "amnesty" to come back the platform.

Legions of [advertisers have pulled their ad spend](https://www.npr.org/2022/11/25/1139180002/twitter-loses-50-top-advertisers-elon-musk) from Twitter as a result of Musk's takeover. I've seen many individuals abandon their Twitter accounts in the wake of these changes, moving to Mastodon or LinkedIn.

## We must build bridges

Why are so many people still active on Twitter, despite the steady stream of bad news? I can think of at least a few things:

### Career

Some have built a career around their Twitter presence and following. Heck, my personal Twitter account was a big part of my job [until recently](https://mikebifulco.com/newsletter/leaving-stripe-going-viral) - it's certainly much easier for me to abandon ship now that my job no longer relies on Twitter for outreach.

I can understand a deep hesitancy to abandon a platform that has been so central to your life, especially without a clear "winner" as an alternative. Embracing a new platform like Mastodon, Threads, or Bluesky requires starting from zero. It can be exhausting to build a new following, and it's hard to know if you'll ever reach the same level of engagement.

### Community Support

There are incredible communites on Twitter like `#BlackTechTwitter`, which has grown to be a critical resource for many people of color in tech. The logistics of getting hundreds-of-thousands of people to move to a new platform is staggering. The LA times recently published [an interview](https://www.latimes.com/business/story/2022-11-07/black-twitter-influencers-others-debate-leaving-twitter) with Pariss Chandler, the founder of [Black Tech Pipeline](https://blacktechpipeline.com/) and creator of the `#BlackTechTwitter` hashtag, discussing the challenges associated with leaving the platform.

It is encumbent on all of us to provide space and time for communities like these to find a new home. Moreover, it's critical that the new homes we create are _at least as valuable_ as Twitter was at its peak. There is a complex cost-benefit analysis for every community member to consider, and we must be mindful of that.

### News and Information

Some use Twitter as a way to keep up with relevant news in their industry. This feels like a solvable problem to me, but it faces a challenge of momentum. Until enough industry experts are sharing news elsewhere, these people will remain on twitter out of habit and convenience.

So -- if you find yourself using twitter and another platform for news, consider sharing useful information on the other platform. It's a small step, but it can make a big difference.

### Lack of social pressure

When it came down to it, even I was hesitating to leave twitter without _seeing someone else do it_ first.

In my first job after undergrad, I had a boss who frequently used the phrase "You are far more influential than you think". Those have proven to be very wise words.

Social pressure will be a necessary component of the transition away from a Twitter run by Elon Musk. I'm hopeful that we'll see more people leave the platform, and that the momentum will build. If and when you decide to consider greener pastures, use your influence and make it known to your community.

## Learning from the Milgram Experiment

Years after the experiment was complete, in his book _Obedience to Authority,_ Stanley Milgram ruminated the results of his now-infamous experiment:

> Ordinary people, simply doing their jobs, and without any particular hostility on their part, can become agents in a terrible destructive process. Moreover, even when the destructive effects of their work become patently clear, and they are asked to carry out actions incompatible with fundamental standards of morality, relatively **few people have the resources needed to resist authority.**

This is not the time to be complacent. We must build a bridge to a better future, and we must do it together.

## If not now, when?

Friends, it's time to start leaving Twitter. Move your news and discussions elsewhere, and bring your people with you. When you're ready, shutter your accounts, delete the app, and move on. I know it's hard, but it's time. Every moment we spend on Twitter is feeding legitimacy to a platform that is enabling abusers, endangering global politics, and destroying the fabric of our society.

Do not allow the voltage to rise by relying on Twitter as your primary social platform.

Perhaps most importantly, make it clear to your friends and neighbors from marginalized groups that their voices are valuable, and welcomed on the platforms you move to.

Bring your voice and your conversations elsewhere, and send the message that with its current leadership, Twitter is no longer a place for you.

<Image
  publicId="posts/twitter-and-the-perils-of-obedience/experiment-1"
  alt=""
/>
<Image
  publicId="posts/twitter-and-the-perils-of-obedience/experiment-2"
  alt=""
/>
<Image
  publicId="posts/twitter-and-the-perils-of-obedience/experiment-3"
  alt=""
/>

## Footnote: on the ethics of the Milgram Experiment

It's important to note that in the years since Milgram Experiment was conducted, it has been criticized for its methodology. [Research Ethics](https://en.wikipedia.org/wiki/Research#Research_ethics) is a complex and nuanced topic, and I don't believe that the experiment would be approved by modern ethics boards in its original form. However, I believe that the results of the experiment are still relevant, and that the experiment itself is still a valuable tool for understanding human behavior.

The experiment _has_ been recreated in a more ethical manner, with the same results. [This article](https://www.apa.org/news/press/releases/2008/12/replicating-milgram) from the American Psychological Association summarizes the results of a 2008 replication of the experiment, which was conducted by a team of researchers at Yale University. In this version of the study, participants were screened to ensure that they were not at risk of being harmed by the experiment, and were given the option to withdraw from the study at any time. The maximum simulated voltage level for the Learner was decreased to 150V, and a test shock was given to participants at 15V, as compared to 45V in Milgram's original study.

The results of the 2009 study were the similar to the original experiment.

## References

Information about the Milgram experiment can be found from the following resources:

- [APA Psych Net - Behavioral Study of obedience.](https://psycnet.apa.org/record/1964-03472-001)
- [Obedience to Authority](https://hardcover.app/books/obedience-to-authority) by Stanley Milgram
- [Internet archive - Obedience to authority: an experimental view](https://archive.org/details/obedien_mil_1974_00_3145)
- [Wikipedia entry for the Milgram experiment](https://en.wikipedia.org/wiki/Milgram_experiment)
- [APA - Replicating Milgram: Researcher Finds Most Will Administer Shocks to Others When Prodded by ‘Authority Figure’](https://www.apa.org/news/press/releases/2008/12/replicating-milgram)
- [APA - Replicating Milgram (pdf)](https://www.apa.org/pubs/journals/releases/amp-64-1-1.pdf)

### More perspective on leaving twitter

In my research for this post, I came across a few other articles about leaving Twitter, and I wanted to share them here:

- [Black Twitter influencers, other thought leaders debate leaving Twitter. But for what?](https://www.latimes.com/business/story/2022-11-07/black-twitter-influencers-others-debate-leaving-twitter) Alexandra Olson and Maryclaire Dale, LA Times via AP
- [“A double-edged sword”: 4 women of color on Elon’s Twitter takeover](https://www.mic.com/impact/elon-musk-twitter-women-leaving)
- [Why I Quit Elon Musk's Twitter](https://www.newyorker.com/news/daily-comment/why-i-quit-elon-musks-twitter) by Jelani Cobb, New Yorker

<small>

_Note: The photo used for the cover of this article is from [john elfes](https://unsplash.com/@johnelfes?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)_

</small>
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Devs: It's okay to use no-code tools]]></title>
            <link>https://mikebifulco.com/posts/devs-its-okay-to-use-no-code-tools</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/devs-its-okay-to-use-no-code-tools</guid>
            <pubDate>Tue, 27 Sep 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[Embrace no-code tools to save time, boost efficiency, and complement your coding skills. No-code is the future - don't be left behind!]]></description>
            <content:encoded><![CDATA[
Recently, I've been asking developers what they think of no-code tools. Friends, I'm here to tell you - some of the responses I've gotten are extremely frustrating.

They range from discouraging to straight up disparaging, especially for newbies who are excited about the prospect of building something for the first time.

"no-code tools?" I had one developer tell me. "What are those? Another bubble that's going to burst?"

"I wouldn't trust any tool that makes it easy for people with no coding experience to make a website," said another. "It's only a matter of time before something goes wrong and we'll have to rebuild it the right way."

"no-code is just a fad," said a third. "Real developers code. That's what separates the wheat from the chaff."

Ouch. I get it. I really do.

Maybe these developers have put in their 10,000 hours (or more) and they've honed their skills to become masters of their craft. They've seen "no-code" come into the spotlight, and they're rightfully skeptical.

But here's the thing: I'm not asking for your permission. I'm not asking for your blessing. I'm not even asking for your approval. I am imploring you to give these tools a serious look. They can save you time, and they're going to go a long way to build the next generation of software developers - whether you're ready or not, no-code tools will be a big part of the future.

## Devs are often insecure about using no-code tools

For some, mentioning the use of no-code tools can induce fear around job security, the validity of use cases for no-code tools, and some future need to “rebuild it later the right way”. This is understandable, but also wrong. Devs are not insecure about no-code because it is no-code. We are insecure about it because of what it represents. no-code is a new way of building things that is not as intuitive for them (yet). It represents a shift in the way things are done that may even threaten their jobs. But the thing is, this shift is inevitable.

The world is moving towards more no-code and less handwritten code. This is a trend that is only going to accelerate.
So, instead of being insecure about it, devs should embrace it. We should learn how to use no-code tools in harmony with hand-coded software, and strive to become no-code experts. This way, there is an opportunity to stay relevant in a no-code world and become the experts that companies will need to build the next generation of no-code products.

## I use no-code tools all the time

Any time I can take advantage of no-code tools, I do. It saves me time, lowers complexity, and results in that many fewer things needing my attention to be maintained in the long run. Some quick examples for you:

- I use an automated “sign up for my newsletter!” embed on [my personal website](https://mikebifulco.com) to interrupt readers at just the right time and ask for their email address. I configured [Polite Pop](https://politepop.com/) entirely on their website, and embedded it in my next.js site with a simple copy/paste
- For [APIs You Won't Hate](https://apisyouwonthate.com), we have several Zapier automations set up to populate an Airtable when someone submits a contact form. The process is different for sponsors vs. general contact - and I can change it any time without redeploying the site.
- I have uptime monitors on all of my web properties - I get a handy text from [Fathom](https://usefathom.com) any time a site goes down for more than 60 seconds
- I use [Google Home](https://home.google.com/welcome/) (shout out to my former team @ Google!) to automate my morning routine - the lights in my bedroom come up like an artificial sunrise, and by the time I get down to my kitchen, there's soft music playing, and my espresso machine is warm and ready to pull a shot.
- I use [Shortcuts for iOS](https://support.apple.com/guide/shortcuts/welcome/ios) on my iPhone for all sorts of things - turning off lights and making sure the doors are locked in my home at night, sending an automated text with my location to tell someone I'm headed their way, you name it.
- I use a [Stream Deck](https://www.elgato.com/en/stream-deck) to swap between camera views during livestreams, to toggle lights and set the temperature in my home office, and to hang up zoom calls or toggle my microphone without having to switch apps on my computer.

To be perfectly honest, I'm probably using many more that I've already forgotten about. I'm willing to bet that this short list probably spurred some recognition for you, too - you're probably already using no-code!

## You're probably already using no-code

Even in your dev work, you're probably already using a variety of no-code tools, whether you realize it or not. I certainly am! Vercel, Netlify, Cloudflare Pages, and GitHub Pages are great hosting options that require little-to-no-code to set up. Configuring web servers used to be a full-time job for every large project. Airtable is a great no-code alternative for gathering and storing data in a database. Chat widget tools like Intercom, Drift, and Front can be dropped onto any website by including one script and provide a massive superpower for messaging users and responding to customer support issues. Even everyday analytics tools like Google Analytics, Fathom, and Plausible are essentially no-code integrations that replace what used to be heaps of code for building telemetry into an app.

Stripe is investing in no-code tools to help business owners get things done more quickly. From Payment Links to Customer Portal to Pricing Tables, we're helping business owners and platform builders, because at the end of the day, your time is best spent doing things that add value to your products and services - and our no-code integrations give you more time to do just that.

If you've read this far and you find yourself thinking "these aren't no-code tools" because they can't be used to build an entire web app, I'd encourage you to rethink what "no-code" means. no-code tools are simply tools that allow you to get things done without writing code. They don't have to be a replacement for all of your code; think of them as an incredibly powerful complement to it.

## No-code doesn't mean low quality

No-code tools are often more reliable because they're built by teams of developers who are focused on a specific problem. They also tend to be more secure because they're not as complex as an entire web app, so there are fewer opportunities for bad actors to exploit vulnerabilities.

## No-code doesn't mean no extensibility

No-code tools also don't mean you have to compromise on features or customization. Many no-code tools offer APIs or other ways to extend their functionality. If you do find yourself needing more, you can always use a no-code tool as a starting point and then add custom code on top. They are a powerful way to get things done quickly and without having to write a lot of code.

There exists a dev subculture that hypes up building software in the most steampunky way (see: vim, mechanical keyboards, etc). It glorifies "make it look like I'm doing something super difficult and specialized" in a way that makes it hard to get started. This culture gets promoted for a variety of reasons - many of which are innocuous. For example, many developers are introverts, and so they express their personality through the things they use and build. We also tend to be tuned into the latest news on bleeding-edge tech, and because of that, many of us like to collect and show off our gear.

With that said, I don't think this kind of enthusiasm is entirely a bad thing.

I think it's great that there are people out there who love their keyboards, and their vim customizations, and who are willing to share that with the world. I also think it's great that there are people who are passionate about using those tools to build amazing things.

Things become problematic when they're used as a form of gatekeeping.

It's important to consider that this may deter new developers who are just getting started. Just remember that at the end of the day, it's all just a bunch of tools - and you can use whatever tools you want to build whatever you want.

## How to turn yourself into a no-code cheerleader

If you're a traditional developer, you may have already decided that no-code is not for you. You may think that it is “taking the easy way out”, and that it can't possibly work for anything more than the most basic apps. I'm here to tell you that you're wrong. no-code tools are powerful. They're flexible. They're easy to use. And they're getting better all the time. If you're a traditional developer, I challenge you to give no-code a try. Spend a few hours with one of the many no-code platforms out there and see what you can build. I think you'll be surprised.

## Go ahead, give no-code a try

Ready to dive in? There's plenty of great resources online for taking advantage of no-code tools.

- [Apps Without Code](https://www.appswithoutcode.com/)
- [Automate All the Things](https://www.aatt.io/)
- [r/nocode](https://redditcom/r/nocode)

If you're not using no-code already, give some of these tools a try. And if you are using them, showcase your efforts whenever possible - especially to your dev friends who may be skeptical.

- [If This, then That (IFTTT)](https://ifttt.com)
- [N8n](https://n8n.io/)
- [Zapier](https://zapier.com/)

As I mentioned earlier, [Stripe has a growing portfolio of no-code tools](https://stripe.com/docs/payments/no-code). These are a few that I'd recommend to anyone looking to dip their toes into the cool, refreshing waters of having to write less code:

### Payment Links

[Payment Links](https://stripe.com/docs/payments/no-code#send-a-payment-link) are a quick and easy way to share a URL for a specific product with your customers. You can create as many payment links as you need, and they can be used anywhere you might share a link. [Check out the docs](https://stripe.com/docs/payments/no-code#send-a-payment-link) for more information on getting started with payment links. You may also want to check out my other post, [No-code payments: How to use Stripe with customized NFC tags](https://dev.to/stripe/no-code-payments-how-to-use-stripe-with-customized-nfc-tags-3c1o).

### Pricing Table

You can use the Stripe Dashboard to configure a [Pricing Table](https://stripe.com/docs/payments/checkout/pricing-table) UI component, and embed it on your website. This will allow your customers to see pricing information and be taken to checkout without any custom code. The pricing table is designed to be flexible and fully responsive, and uses recommended practices for selling subscription-based products online.

### Customer Portal

The [Stripe Customer Portal](https://stripe.com/docs/customer-management/activate-no-code-customer-portal) is a Stripe-hosted solution for customer self-serve management of subscriptions. This allows your customers to change and cancel their subscriptions as needed, and includes a complete checkout workflow for collecting and updating their payment information.

## Wrapping up

So, what do you think? Have I made a compelling case for using no-code tools? I'd love to hear about the no-code and low code integrations you're using - drop me a comment below to show off your stuff, or track me down on twitter [@irreverentmike](https://twitter.com/irreverentmike).

If you've made it this far, thanks for reading. I think there's a better world out there for all of us if we embrace no-code, and extend an olive branch to our less technical friends who are interested in building apps with no-code tools.

<Aside type="note">

Author's note: This post was originally written as part of my work as a
Developer Advocate at [Stripe](https://stripe.com). As of November 2022, I no
longer work at Stripe, but I'm still a big fan of their products and the work
they do.

</Aside>

<small>

_Stripe fam: If you want to re-host this article on a stripe-owned URL, [get in touch!](mailto:hello@mikebifulco.com)_

</small>
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Growth hack: Publish newsletters to your Next.js site with ConvertKit API]]></title>
            <link>https://mikebifulco.com/posts/publish-your-newsletter-with-convertkit-api-next-js</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/publish-your-newsletter-with-convertkit-api-next-js</guid>
            <pubDate>Fri, 23 Sep 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[Use previous issues of your newsletter to attract new subscribers, using the ConvertKit API with your Next.js site.]]></description>
            <content:encoded><![CDATA[
## I publish a newsletter called Tiny Improvements

[My little newsletter](https://mikebifulco.com/newsletter) is all about making small, incremental improvements to your work and home life, especially if you're building a product or company. I've been publishing it for a while now, and I've been using ConvertKit to manage my subscribers and send out the newsletter.

<Aside>

Note: This is a follow-up to my [previous post on using ConvertKit with Remix](https://mikebifulco.com/posts/publish-your-newsletter-with-convertkit-api-remix). If your site is built using [**Remix.run**](https://remix.run), you'll probably want to head over there.

</Aside>

In this post, we'll go over how I use the ConvertKit API to publish a newsletter page for a site built with [Next.js](https://nextjs.org).

## Publish past issues to grow your newsletter

I recently started publishing back-issues of my [newsletter](https://mikebifulco.com/newsletter) to my site, so that I can share them as evidence of the type of writing I do. In addition to being SEO-indexable, it allows me to share the newsletter with people who aren't subscribed to it, with a link to subscribe at the bottom of each issue.

I wanted to explore a way to make _my_ process incrementally better, by using the [ConvertKit API](https://developers.convertkit.com/) to automate the publishing process with the same workflow that I use to send newsletters to subscribers.

## Using the ConvertKit API to publish newsletters to a Next.js site

Setting up an automated newsletter page is fairly simple, at least in theory:

1. Write newsletters and send them, using ConvertKit's broadcast features (for the sake of this post, we'll use the term "newsletter" and "broadcast" somewhat interchangeably).
2. Use the ConvertKit API's list-broadcasts endpoint to query for every published broadcast, to populate a newsletter index page
3. For each published broadcast, use the ConvertKit API to get the details of that broadcast, and then render the content of that broadcast on a page.
4. For SEO purposes, add each published newsletter page to `sitemap.xml`, with all the appropriate metadata.

To get newsletters from the ConvertKit API, I set up 2 helper functions in `/src/utils/convertKit.js`. First is `getNewsletter()`, which takes a broadcast ID and returns the details of that broadcast.

```js
export const getNewsletter = async (broadcastId) => {
  const res = await fetch(
    `https://api.convertkit.com/v3/broadcasts/${broadcastId}?api_secret=${CONVERTKIT_API_SECRET}`
  );

  // rename "broadcast" to "newsletter" for consistency
  const { broadcast: newsletter } = await res.json();

  return newsletter;
};
```

The second is `getAllNewsletters()`, which returns a list of all published broadcasts. In its simplest form, this function looks like this:

```js
export const getAllNewsletters = async () => {
  const response = await fetch(
    `https://api.convertkit.com/v3/broadcasts?api_secret=${CONVERTKIT_API_SECRET}`
  );
  const data = await response.json();

  // rename "broadcasts" to "newsletters" for consistency
  const { broadcasts: newsletters } = data;

  return newsletters;
};
```

<Aside type="warning">

We are using an environment variable to supply the variable `CONVERTKIT_API_SECRET` - it is **super important** to keep this value secret, and not share it on the client-side of your app.

</Aside>

### Keeping your ConvertKit API Secret key safe on Next.js sites

For this example, we're using `CONVERTKIT_API_SECRET` environment variable only on the server-rendered parts of our site, because we _do not want it to be exposed to the client_. To make this value accessible only server-side, add it to a file called `.env` or `.env.local`, according to [Next.js documentation](https://nextjs.org/docs/basic-features/environment-variables#loading-environment-variables). **Make sure you add `.env` and `.env.local` to your [`.gitignore` file](https://mikebifulco.com/posts/gitignore-io-is-great), so you don't accidentally commit it to your repository.**

Importantly, this environment variable should only be exposed server-side, because we _didn't_ name it with a `NEXT_PUBLIC_` prefix - to read more about using environment variables to web clients, check out [Next.js documentation](https://nextjs.org/docs/basic-features/environment-variables#exposing-environment-variables-to-the-browser).

### Rendering the newsletter index page

Now that we have a way to get a list of all published newsletters, we can use that to render a page with a preview of each past issue. I created a new file called `/src/pages/newsletter/index.js` to render the newsletter index page.

On this page, we use `getStaticProps` to fetch our list of newsletters on the server, and then pass them to render function, to display a list of links to each newsletter page.

<small>

_note: I stripped out the styling/presentation code from this example to keep
it focused on data loading logic._

</small>

```jsx
import { Link } from 'next/link';

import { getAllNewsletters } from '../../utils/convertKit';
import slugify from '../../utils/slugify';

export const getStaticProps = async () => {
  const newsletters = await getAllNewsletters();

  return {
    props: {
      newsletters,
    },
  };
};

const NewsletterIndexPage = ({ newsletters }) => {
  return (
    <>
      <h1>All Newsletters</h1>
      <ul>
        {newsletters?.map((newsletter) => (
          <li key={newsletter.id}>
            <Link href={`/newsletter/${slugify(newsletter.subject)}`}>
              {newsletter.subject} - {formatDate(newsletter.published_at)}
            </Link>
          </li>
        ))}
      </ul>
    </>
  );
};

export default NewsletterIndexPage;
```

You may have noticed that I'm also using a helper function called `slugify`, which uses the npm package `slugify`. This function takes a string and returns a skewer-case-version-of-it, which is useful for creating browser-friendly URLs from strings.

```js
import makeSlug from 'slugify';

export const slugify = (string) => {
  return makeSlug(string, {
    replacement: '-',
    remove: /[\[\],?*+~.()'"!:@]/g,
    strict: true,
    lower: true,
  });
};

export default slugify;
```

This is an optional step that caused me a fair bit of heartache - the easiest way to link to individual newsletter pages is to use the broadcast ID, but I wanted to use a more human-readable URL, so I used `slugify` to create a URL-friendly version of the newsletter subject.

The downsides of this approach are:

- each newsletter _must_ have a unique URL
- there's not a way to efficiently map a URL to a broadcast ID, so we have to iterate over all broadcasts to find the one that matches the URL (which you'll see in the next section)

For now, I can live with this approach, since this computation is done once during build time, and until I have hundreds of newsletters, it shouldn't be too big of a performance hit.

### Rendering a single newsletter page

Now that we have a page listing all published newsletters, we need to create a page template to render a single newsletter. I created a new file called `/src/pages/newsletter/[subject].js` to render the newsletter index page (note, once again, that presentation and styling code is removed here for simplicify):

```jsx
import { useEffect } from 'react';

import {
  broadcastTemplateParse,
  getAllNewsletters,
} from '../../utils/convertKit';
import slugify from '../../utils/slugify';

export const getStaticPaths = async () => {
  const newsletters = await getAllNewsletters();

  return {
    paths: newsletters.map((newsletter) => ({
      params: {
        subject: slugify(newsletter.subject),
      },
    })),
    fallback: false,
  };
};

export const getStaticProps = async (context) => {
  const newsletters = await getAllNewsletters();

  const { subject } = context.params;
  const slug = slugify(subject);

  const newsletter = newsletters.find(
    (newsletter) => slugify(newsletter.subject) == slug
  );

  return {
    props: {
      newsletter,
    },
  };
};

const SingleNewsletterPage = ({ newsletter }) => {
  const { subject } = newsletter;

  return (
    <>
      <h1>{subject}</h1>
      <div
        dangerouslySetInnerHTML={{
          __html: broadcastTemplateParse({ template: newsletter.content }),
        }}
      />
    </>
  );
};

export default SingleNewsletterPage;
```

The `getStaticPaths` function is used to generate a list of all possible URLs that should be pre-rendered. In this case, we're using the `getAllNewsletters` function to fetch a list of all published newsletters, and then using the `slugify` function to create a URL based on the newsletter's subject.

The `getStaticProps` function is used to fetch the data for a single newsletter, based on the URL. We use the `getAllNewsletters` function to fetch a list of all published newsletters, and then use `newsletters.find()` to look for the newsletter whose subject line matches the URL for the current page when run through `slugify`. This uses a JavaScript API called [Array.find()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find), which is used to find single item in an array that matches a condition.

#### Render the body using dangersoulySetInnerHTML

To render the contents of the newsletter, we are using a scary-looking React API pattern - `dangerouslySetInnerHTML`. This is a [React API](https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml) that allows you to render HTML that you have received from an API, and is generally considered a security risk. However, in this case, we are using it to render HTML that we have generated ourselves, and we are at least somewhat confident that it is safe to render. Generally speaking, this is a technique that shouldn't be used unless you are confident that the HTML you are rendering is safe.

#### Helper functions for displaying ConvertKit newsletter content

We're also using 2 helper functions, which are defined in `/src/utils/convertKit.js`:

```js
import { Liquid } from 'liquidjs';

const engine = new Liquid();

export const broadcastTemplateParse = ({ template, data }) => {
  const t = template.replaceAll('&quot;', '"');
  const res = engine.parseAndRenderSync(t, data);
  return res;
};

export const newsletterHasValidThumbnail = (newsletter) => {
  const { thumbnail_url: thumbnailUrl } = newsletter;
  if (!thumbnailUrl) return false;
  if (thumbnailUrl.startsWith('https://functions-js.convertkit.com/icons'))
    return false;
  return true;
};
```

The `newsletterHasValidThumbnail` function is a helper function that checks if the newsletter has a valid thumbnail image. ConvertKit provides a default thumbnail image for all newsletters, but you can also upload your own, by adding an image to your newsletter's body. This function checks if the thumbnail is the default image, and if so, returns `false` so we can skip rendering it.

The `broadcastTemplateParse` function is a helper function that takes a newsletter template and parses it with the [Liquid](https://shopify.github.io/liquid/) templating language. This is how ConvertKit allows you to customize the HTML of your newsletter, and use dynamic data like the subscriber's name, or the date the newsletter was sent.

**An important caveat:** There are _lots_ of little cases where this might not work perfectly, due to all of the amazing things you can do with Liquid in ConvertKit. At the moment, my newsletter uses fairly basic liquid customization - this may not do the trick for you if you're using more advanced features. Please test your implementation thoroughly!

### Adding more detail to the index page

At the time of writing this post, ConvertKit's v3 API is in "active development" - and as such, it's likely not feature complete. For example, the [current API for list-broadcasts](https://developers.convertkit.com/#list-broadcasts) provides a minimal amount of data about each broadcast:

```bash
curl https://api.convertkit.com/v3/broadcasts?api_secret=<your_secret_api_key>
```

```json
{
  "broadcasts": [
    {
      "id": 1,
      "created_at": "2014-02-13T21:45:16.000Z",
      "subject": "Welcome to my Newsletter!"
    },
    {
      "id": 2,
      "created_at": "2014-02-20T11:40:11.000Z",
      "subject": "Check out my latest blog posts!"
    },
    {
      "id": 3,
      "created_at": "2014-02-29T08:21:18.000Z",
      "subject": "How to get my free masterclass"
    }
  ]
```

Since we want to create an index page that shows a thumbnail for each newsletter, we need to query the API for more information about each newsletter. At the moment, the best way to do this is to query the API for each newsletter individually. It's not ideal, since we need to send an API call for each newsletter shown on the index page, but I'm hoping that with a bit of feedback, ConvertKit will add more data to the list-broadcasts API endpoint.

We already have a function to query the API for a single newsletter (remember `getNewsletter` from earlier?), so we can use that to query the API for each newsletter on the index page.

#### Filter out un-published newsletters

The list-broadcasts endpoint also doesn't currently return whether or not a given broadcast was _published_ yet - which means that if you draft a future broadcast on your ConvertKit dashboard, it will still be returned by the list API. I don't want to share these yet-to-be-sent newsletters on any of my sites, so we'll add some logic to `getAllNewsletters` to filter out any newsletters that haven't been published yet.

#### Don't render newsletters with duplicate subject lines

There are some cases where I send the same newsletter multiple times, with the same subject line, to different audiences - usually because I've forgotten to include some details in the original broadcast. This results in multiple broadcasts with essentially the same content. I don't want to show these on my site, so I added some logic to deduple any newsletters that have the same subject line, displaying only the most recent one (which should be the most correct, in theory).

This is the updated code for `getAllNewsletters` in `convertKit.js`:

```jsx
export const getAllNewsletters = async () => {
  const response = await fetch(
    `https://api.convertkit.com/v3/broadcasts?api_secret=${CONVERTKIT_API_SECRET}`
  );
  const data = await response.json();
  const { broadcasts } = data;

  // get details for each individual newsletter
  const newsletters = await Promise.all(
    broadcasts.map((broadcast) => getNewsletter(broadcast.id))
  );

  // hackish dedupe here - sometimes we publish a newsletter a _second_ time as a correction, or to a different audience.
  // In those cases, they should always have the same subject. We're using subject as a way to deduplicate newsletters in that case
  const dedupedBySubject = {};

  // return only newsletters that have been published, and sort by most recent to oldest
  newsletters
    .filter((newsletter) => !!newsletter.published_at)
    .sort((a, b) => new Date(b.published_at) - new Date(a.published_at))
    .forEach((newsletter) => {
      // the first one we encounter in this order will be the newest, so if there's one already we don't make any changes to the object map
      if (!dedupedBySubject[newsletter.subject])
        dedupedBySubject[newsletter.subject] = newsletter;
    });

  let nls = [];
  // iterate over the map we have of subject->newsletter, and push into a fresh array, which we'll return
  for (let subject in dedupedBySubject) {
    nls.push(dedupedBySubject[subject]);
  }

  return nls;
};
```

And with that, our basic implementation is complete - we've created a `/newsletter` page that shows a list of all of our newsletters, with a thumbnail image for each one. We've also added a `/newsletter/[subject]` page that shows the full content of a given newsletter.

## Next steps

There are a few things I'd like to add to this implementation in the future:

- I'm unhappy with the bottleneck I've created for myself using `slugify` on the subject line to create the URL slug. I'd like to find a more efficient way to do this. A reasonable fallback for now might be to use the `BroadcastId` as the slug instead of the subject line, but those aren't human-readable.
- This implementation presents some challenges for SEO - getting newsletter entries to show up in my site's `sitemap.xml` is currently done at build time, which means that new newsletters won't show up in the sitemap until I rebuild the site. In the future, I'll either need to generate the sitemap dynamically, or implement [Incremental Static Regeneration](https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration) so that new newsletters are added to the sitemap as soon as they're published.
- I'm pretty diligent about [embedding opengraph metadata](https://mikebifulco.com/posts/reset-your-open-graph-embeds-on-linkedin-twitter-facebook) on the pages on my site, including images and excerpts from the article to use as previews on sites like twitter and LinkedIn. This implementation makes that tricky, as determining _which_ image to use as the cover for a given newsletter is a bit of a challenge. Right now I'm using the first image within a newsletter. I'm not sure what the best solution is here, but I'm open to suggestions!

## Wrap-up

I hope this post has been helpful to you, and that you've learned something new about how to use ConvertKit's API to create a custom newsletter index page for your Next.js site. I'd also love it if you checked out Tiny Improvements, my little newsletter about making better products and a better life - [mikebifulco.com/newsletter](https://mikebifulco.com/newsletter).

If you have any questions, or if you've found a bug in my code, please feel free to reach out to me on Twitter [@irreverentmike](https://twitter.com/irreverentmike)!
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Publish your newsletter to your Remix site with the ConvertKit API]]></title>
            <link>https://mikebifulco.com/posts/publish-your-newsletter-with-convertkit-api-remix</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/publish-your-newsletter-with-convertkit-api-remix</guid>
            <pubDate>Mon, 19 Sep 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[Learn how to use the ConvertKit API to publish your newsletter to your Remix site.]]></description>
            <content:encoded><![CDATA[
## I publish a newsletter called Tiny Improvements

[My little newsletter](https://mikebifulco.com/newsletter) is all about making small, incremental improvements to your work and home life. I've been publishing it for over a year now and I've learned a lot about how to make it better.

It's a great way to share less-formal insights with the people who have given me access to their inbox - a privilege which I don't take lightly. It also helps me keep my writing skills sharp, and it's a great way to get direct feedback on my ideas.

Although the audience for my newsletter has been growing, and recently hit [some milestones](https://twitter.com/irreverentmike/status/1569796408043253760), I realized that I had quite a bit of great writing that went out once, via email, and was never seen again. I wanted to make it easier for people to find and read my past newsletter content without subscribing, as way to show the value it provides. I also wanted to take advantage of the [SEO benefits](https://mikebifulco.com/posts/seo-tools-for-new-web-projects) of having past issues of my newsletter content indexed by search engines.

In this post, we'll go over how I use the ConvertKit API to publish a newsletter page for a site built with [Remix](https://remix.run).

## Improve discoverability by publishing past issues

I have a second, important use case for publishing newsletters online. I also maintain my wife's website - [primaryfocus.tv](https://primaryfocus.tv) - which she uses to promote her business and YouTube channel (go [subscribe](https://youtube.com/c/primaryfocus)!).

Primary Focus has a newsletter, and I wanted to make it easy for her to publish her newsletter to her website as well. In fact, I wanted to give her a way to get her newsletter on her website with zero effort - and I was pleased to find that I could do that with the [ConvertKit API](https://developers.convertkit.com/).

Ideally, the workflow should look like this: newsletters are drafted and published in ConvertKit, and, once sent to her subscribers, automatically published to the website as well. This way, she can focus on writing and sending her newsletter, without adding an additional workflow to update her site.

Her site is built with Remix, so this post will go over the details of implementation for publishing past ConvertKit newsletters to a remix site, using their API.

## Using the ConvertKit API to publish newsletters to a Remix site

Setting up an automated newsletter page is fairly simple, at least in theory:

1. Write newsletters and send them, using ConvertKit's broadcast features (for the sake of this post, we'll use the term "newsletter" and "broadcast" somewhat interchangeably).
2. Use the ConvertKit API's list-broadcasts endpoint to query for every published broadcast, to populate a newsletter index page
3. For each published broadcast, use the ConvertKit API to get the details of that broadcast, and then render the content of that broadcast on a page.

To get newsletters from the ConvertKit API, I set up 2 helper functions. First is `getNewsletter()`, which takes a broadcast ID and returns the details of that broadcast.

```js
export const getNewsletter = async (broadcastId) => {
  const res = await fetch(
    `https://api.convertkit.com/v3/broadcasts/${broadcastId}?api_secret=${CONVERTKIT_API_SECRET}`
  );

  // rename "broadcast" to "newsletter" for consistency
  const { broadcast: newsletter } = await res.json();

  return newsletter;
};
```

The second is `getAllNewsletters()`, which returns a list of all published broadcasts. In its simplest form, this function looks like this:

```js
export const getAllNewsletters = async () => {
  const response = await fetch(
    `https://api.convertkit.com/v3/broadcasts?api_secret=${CONVERTKIT_API_SECRET}`
  );
  const data = await response.json();

  // rename "broadcasts" to "newsletters" for consistency
  const { broadcasts: newsletters } = data;

  return newsletters;
};
```

<Aside type="warning">

We are using an environment variable to supply the variable `CONVERTKIT_API_SECRET` - it is **super important** to keep this value secret, and not share it on the client-side of your app.

</Aside>

### Keeping your ConvertKit API Secret key safe on Remix sites

Remix provides a has a handy filename convention to ensure certain code _only_ runs serverside - any file that ends in `.server.ts` (for TypeScript) and `.server.js` (for JavaScript) will only be run on the server. This is perfect for keeping our ConvertKit API secret safe. I created a file called `/app/lib/util/convertkit.server.js` with the two functions above, to make sure to only ever access the secret key in there.

### Rendering the newsletter index page

Now that we have a way to get a list of all published newsletters, we can use that to render a page with a preview of each past issue. I created a new file called `/app/routes/newsletter/index.jsx` to render the newsletter index page.

<small>

_note: I stripped out the styling/presentation code from this example to keep
it focused on data loading logic._

</small>

```jsx
import { useLoaderData } from '@remix-run/react';
import { NewsletterCTA, NewsletterListItem } from '~/components';
import { getAllNewsletters } from '~/lib/util/convertKit.server';

export const loader = async ({ params, request }) => {
  return {
    newsletters: await getAllNewsletters(),
  };
};

const NewsletterListPage = () => {
  const { newsletters } = useLoaderData();

  return (
    <>
      <h1>Read past newsletters</h1>
      {newsletters.map((newsletter) => (
        <NewsletterListItem newsletter={newsletter} key={newsletter.id} />
      ))}

      {/* make sure to add a "hey please subscribe to the newsletter" widget to this page! */}
      <NewsletterCTA />
    </>
  );
};

export default NewsletterListPage;
```

This is a fairly standard implementation, if you're familiar with Remix. We use the loader pattern to fetch the list of newsletters, and pass them to the render function for the component with the `useLoaderData()` hook. We then render a list of `NewsletterListItem` components, which shows a header image and title for each newsletter, along with a link to the page for that specific newsletter.

### Rendering a single newsletter page

Now that we have a page listing all published newsletters, we need to create a page template to render a single newsletter. I created a new file called `/app/routes/newsletter/$id.jsx` to render the newsletter index page (note, once again, that presentation and styling code is removed here for simplicify):

```jsx
import { useLoaderData } from '@remix-run/react';
import NewsletterCTA from '~/components';
import config from '~/config';
import {
  broadcastTemplateParse,
  newsletterHasValidThumbnail,
} from '~/lib/util/convertKit';
import { getNewsletter } from '~/lib/util/convertKit.server';

// render meta tags on page for SEO
export const meta = ({ data }) => {
  const { newsletter, canonical } = data;
  const publishedAt = new Date(newsletter.published_at);

  const description = `Primary focus newsletter: ${
    newsletter.subject
  }, published on ${publishedAt.toLocaleDateString()}`;

  return {
    description,
    title: newsletter.subject
      ? `${newsletter.subject} - ${config.meta.title}`
      : config.meta.title,
    'og:image': newsletterHasValidThumbnail(newsletter)
      ? newsletter.thumbnail_url
      : null,
    'og:type': 'article',
    'og:title': newsletter.subject,
    'og:description': description,
    'og:url': canonical,
    'twitter:card': 'summary_large_image',
  };
};

export const loader = async ({ params, request }) => {
  const { id } = params;
  const newsletter = await getNewsletter(id);

  return { newsletter };
};

const NewsletterPage = () => {
  const { newsletter } = useLoaderData();

  const publishedAt = new Date(newsletter.published_at);
  return (
    <>
      <h1>{newsletter.subject}</h1>
      <p className="publish-date">{publishedAt.toLocaleDateString()}</p>
      <div
        dangerouslySetInnerHTML={{
          __html: broadcastTemplateParse({ template: newsletter.content }),
        }}
      />
      <NewsletterCTA />
    </>
  );
};

export default NewsletterPage;
```

Once again, we use the loader pattern to query the ConvertKit API for details about this specific newsletter, and pair that with `useLoaderData()` to provide that information to the page render function. We also use the `meta` function pattern to render meta tags for SEO purposes - you can read more about that in the [Remix docs](https://remix.run/docs/en/v1/api/conventions#meta).

#### Render the body using dangersoulySetInnerHTML

To render the contents of the newsletter, we are using a scary-looking React API pattern - `dangerouslySetInnerHTML`. This is a React API that allows you to render HTML that you have received from an API, and is generally considered a security risk. However, in this case, we are using it to render HTML that we have generated ourselves, and we are at least confident that it is somewhat safe to render. Generally speaking, this is a technique that shouldn't be used unless you are confident that the HTML you are rendering is safe.

#### Helper functions for displaying ConvertKit newsletter content

We're also using 2 helper functions, which are defined in `/app/lib/util/convertKit.js` (note that these are **not** in `convertkit.server.js`, since we need them on the client side):

```js
import { Liquid } from 'liquidjs';

const engine = new Liquid();

export const broadcastTemplateParse = ({ template, data }) => {
  const t = template.replaceAll('&quot;', '"');
  const res = engine.parseAndRenderSync(t, data);
  return res;
};

export const newsletterHasValidThumbnail = (newsletter) => {
  const { thumbnail_url: thumbnailUrl } = newsletter;
  if (!thumbnailUrl) return false;
  if (thumbnailUrl.startsWith('https://functions-js.convertkit.com/icons'))
    return false;
  return true;
};
```

The `newsletterHasValidThumbnail` function is a helper function that checks if the newsletter has a valid thumbnail image. ConvertKit provides a default thumbnail image for all newsletters, but you can also upload your own, by adding an image to your newsletter's body. This function checks if the thumbnail is the default image, and if so, returns `false` so we can skip rendering it.

The `broadcastTemplateParse` function is a helper function that takes a newsletter template and parses it with the [Liquid](https://shopify.github.io/liquid/) templating language. This is how ConvertKit allows you to customize the HTML of your newsletter, and use dynamic data like the subscriber's name, or the date the newsletter was sent.

**An important caveat:** There are _lots_ of little cases where this might not work perfectly, due to all of the amazing things you can do with Liquid in ConvertKit. At the moment, my newsletter uses fairly basic liquid customization - this may not do the trick for you if you're using more advanced features. Please test your implementation thoroughly!

### Adding more detail to the index page

At the time of writing this post, ConvertKit's v3 API is in "active development" - and as such, it's likely not feature complete. For example, the [current API for list-broadcasts](https://developers.convertkit.com/#list-broadcasts) provides a minimal amount of data about each broadcast:

```bash
curl https://api.convertkit.com/v3/broadcasts?api_secret=<your_secret_api_key>
```

```json
{
  "broadcasts": [
    {
      "id": 1,
      "created_at": "2014-02-13T21:45:16.000Z",
      "subject": "Welcome to my Newsletter!"
    },
    {
      "id": 2,
      "created_at": "2014-02-20T11:40:11.000Z",
      "subject": "Check out my latest blog posts!"
    },
    {
      "id": 3,
      "created_at": "2014-02-29T08:21:18.000Z",
      "subject": "How to get my free masterclass"
    }
  ]
```

Since we want to create an index page that shows a thumbnail for each newsletter, we need to query the API for more information about each newsletter. At the moment, the best way to do this is to query the API for each newsletter individually. It's not ideal, since we need to send an API call for each newsletter shown on the index page, but I'm hoping that with a bit of feedback, ConvertKit will add more data to the list-broadcasts API endpoint.

We already have a function to query the API for a single newsletter (remember `getNewsletter` from earlier?), so we can use that to query the API for each newsletter on the index page.

#### Filter out un-published newsletters

The list-broadcasts endpoint also doesn't currently return whether or not a given broadcast was _published_ yet - which means that if you draft a future broadcast on your ConvertKit dashboard, it will still be returned by the list API. I don't want to share these yet-to-be-sent newsletters on any of my sites, so we'll add some logic to `getAllNewsletters` to filter out any newsletters that haven't been published yet.

#### Don't render newsletters with duplicate subject lines

There are some cases where I send the same newsletter multiple times, with the same subject line, to different audiences - usually because I've forgotten to include some details in the original broadcast. This results in multiple broadcasts with essentially the same content. I don't want to show these on my site, so I added some logic to deduple any newsletters that have the same subject line, displaying only the most recent one (which should be the most correct, in theory).

This is the updated code for `getAllNewsletters` in `convertKit.server.js`:

```jsx
export const getAllNewsletters = async () => {
  const response = await fetch(
    `https://api.convertkit.com/v3/broadcasts?api_secret=${CONVERTKIT_API_SECRET}`
  );
  const data = await response.json();
  const { broadcasts } = data;

  // get details for each individual newsletter
  const newsletters = await Promise.all(
    broadcasts.map((broadcast) => getNewsletter(broadcast.id))
  );

  // hackish dedupe here - sometimes we publish a newsletter a _second_ time as a correction, or to a different audience.
  // In those cases, they should always have the same subject. We're using subject as a way to deduplicate newsletters in that case
  const dedupedBySubject = {};

  // return only newsletters that have been published, and sort by most recent to oldest
  newsletters
    .filter((newsletter) => !!newsletter.published_at)
    .sort((a, b) => new Date(b.published_at) - new Date(a.published_at))
    .forEach((newsletter) => {
      // the first one we encounter in this order will be the newest, so if there's one already we don't make any changes to the object map
      if (!dedupedBySubject[newsletter.subject])
        dedupedBySubject[newsletter.subject] = newsletter;
    });

  let nls = [];
  // iterate over the map we have of subject->newsletter, and push into a fresh array, which we'll return
  for (let subject in dedupedBySubject) {
    nls.push(dedupedBySubject[subject]);
  }

  return nls;
};
```

And with that, our journey is complete - we've created a `/newsletter` page that shows a list of all of our newsletters, with a thumbnail image for each one. We've also added a `/newsletter/$id` page that shows the full content of a given newsletter.

## Wrap-up

I hope this post has been helpful to you, and that you've learned something new about how to use ConvertKit's API to create a custom newsletter index page for your Remix site. To see what this looks like in practice, head over to [primaryfocus.tv/newsletter](https://primaryfocus.tv/newsletter).

In my next post, I'll share how I used a similar implementation in **Next.js** on my site - [mikebifulco.com](https://mikebifulco.com).

If you have any questions, or if you've found a bug in my code, please feel free to reach out to me on Twitter [@irreverentmike](https://twitter.com/irreverentmike)!
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[How Stripe Uses Friction Logs to Improve their Products]]></title>
            <link>https://mikebifulco.com/posts/how-stripe-uses-friction-logs</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/how-stripe-uses-friction-logs</guid>
            <pubDate>Fri, 16 Sep 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[A guide to friction logging, a practice that can be used by engineering teams building products to track and improve upon issues that users experience while using a product.]]></description>
            <content:encoded><![CDATA[
<Aside type="note">
  _This article was written during my time at Stripe as a Deveoper Advocate, and was co-authored by my inimitable teammate, [Charlie Gerard](https://charliegerard.dev/)._

I do not speak for Stripe, and this article is not official company policy, etc. and so on. It's just my experience with friction logs from my time at Stripe.

</Aside>

## What is a friction log?

Friction logging is a practice that can be used by engineering teams building products to track and improve upon issues that users experience while using a product. The goal of friction logging is to make a given product better for everyone involved. End users and developers get a product that delivers value more directly, the team building the product gets a more attached, happier user base, and salespeople have an easier time showing value to potential customers.

At [Stripe](https://stripe.com), we use Friction logs to share feedback with product teams about the products we build. This is at least part of the mission of our DevRel team. Our goal is to be the voice for devs who use Stripe's products to build their own. We often serve as the liaisons between these worlds: the devs using our products, and the engineering teams building them.

Stripe also encourages all employees to actively participate in giving feedback. During onboarding, every new Stripe is given training on how to give feedback on products, and the process for creating friction logs.

## Parts of a friction log

<Image
  publicId="posts/how-stripe-uses-friction-logs/parts-of-a-friction-log"
  alt="Parts of a friction log"
/>

### Context

The context describes the persona of the person reviewing the feature, as well as what they were trying to accomplish. For example, if you are reviewing a new API endpoint and this is your first time using the feature, it is important to mention this as part of your persona. You can try to write the context by answering the following questions:

- How experienced are you with the feature?
- What were you trying to build?
- Which parts of the feature is this friction log about?

Below is an example of context for a friction log about setting up a new printer:

<Image
  publicId="posts/how-stripe-uses-friction-logs/example-context"
  alt="Example context for a friction log about setting up a new printer"
/>

### Pros and cons

Once you've written the context, you can move on to summarizing the pros and cons you've experienced.

This part should be a list of bullet points clearly stating the parts of the feature or experience that you enjoyed or thought were useful, and the ones that you think could be better or did not match your expectation of how the feature should work.

<Image
  publicId="posts/how-stripe-uses-friction-logs/example-pros-and-cons"
  alt="Example pros and cons for a friction log about setting up a new printer"
/>

### Detailed stream of consciousness

Finally, the detailed stream of consciousness is the part where you should be giving feedback without necessarily following a specific structure. You should write it as you are going through your experience trying to use the feature. It can include anything you think could be useful to the team, no matter how small. Feel free to add screenshots, GIFs showing your interaction with the tool, links, etc.

We are all different in how we use tools, our level of knowledge and expertise, the applications we're trying to build, so any piece of feedback is valuable to help improve a product.

To give you an idea, here's an example of how this part of the friction log might look:

<Image
  publicId="posts/how-stripe-uses-friction-logs/example-stream-of-consciousness"
  alt="Stream of consciousness example for a friction log about setting up a new printer"
/>

## Framework for a great Friction log

### Share size (S/M/L) up front

**Small** - The friction log is small and manageable. It can be completed in a reasonable amount of time without feeling like a burden.

**Medium** - The friction log is of a moderate size. It may take some time to read, but it is not excessively long.

**Large** - The friction log is large and may take some time to consume. These likely capture larger user journeys, and show a holistic view of a process, as opposed to a small bit of confusion with a single feature.

### Make the journey clear

The friction log should make it clear what journey the user is taking, and what steps they are taking along the way, as well as context on their persona ("I'm brand new to collecting payments on the web", or "This is the 3rd major release of my product, but we need to add support for taking payments in Canada"). Additionally, The log should be easy to follow so that the intended audience can understand it -- whenever possible, use language that your product teams and stakeholders will understand without having to go do research of their own.

### Highlight both joy & frustration

While it is critical to share opportunities for improvement in a product, it is also extremely valuable to share what is going well. This helps to build trust with your engineering team, and can be a good reminder that you all share the same goal: making the product as good as it possibly can be.

### Be illustrative

Wherever it may be helpful, provide screenshots, videos, or other visuals to help explain the process you've undertaken, and the real experiences you've had. This may take the form of a link to a developer screencast for longer friction logs.

### Describe issues objectively

This is where emotional intelligence is critical. Avoid using emotionally loaded language, and instead describe the issues objectively. Something like "I got confused between steps 6 and 7, and went back to this docs page to look for what I missed" is far more helpful than "I wasted 2 hours on this, it's so bad!".

### Share your feedback broadly

At Stripe, when a friction log is completed, it is shared to an email list that includes the entire company, as well as with the specific team working on the feature or product being highlighted. This takes advantage of the network effect: when everyone can see your feedback, it's more likely that you'll start a conversation with a broad audience of affected parties.

You may find that there are people who actively disagree with your perspective - don't fret, this is usually a good thing! Exposing your friction log to people with a diversity of experience and background means that any suggested changes to your product will be more considerate of a larger userbase.

### Follow-up!

It's also good practice to follow up directly with people who may be tasked with coming up with fixes related to your friction log. Keeping an open dialog is important - it helps ensure that feedback is given and received in good faith, and that the outcome of your work is a meaningful solution (even if it isn't implemented right away).

**This is where the magic happens.** All your work in crafting a great friction log is worthless if you don't follow through and make sure that it has an impact on the product your company is building. Making sure that your log results in the creation of new feature requests and bugs is a good starting point - do your best to be a steward for these tickets after their creation, so that they are prioritized thoughtfully in your team's backlog.

The last bit of follow up comes after the implementation and release of updates to the product: tell the world! Update docs and release notes with the new changes, and follow up directly with affected users wherever possible. This is your opportunity to show them that your team is working hard to make things better for them. Let them know that you built something because of them, and that you're always open to more feedback. This creates attachment and loyalty, and is the virtuous cycle that great product teams strive for.

## On giving feedback

A friction log is essentially a detailed piece of feedback, so to ensure that it is helpful and received well, there are a few important points you need to keep in mind.

### Emotional intelligence is important

Emotional intelligence encompasses self-awareness, social awareness, empathy and relationship management. Writing a friction log focuses on your personal experience with a feature or product, however, you have to keep in mind that it will be read by people who have put a lot of time and effort into building what you are using.

Try to put yourself in their shoes and avoid using language that isn't very considerate. For example, instead of saying something like “This is by far the worst API I've ever used”, which is not only rude but also unhelpful, you could change it to “I've struggled using this API because X, Y, Z”. This way, your feedback changes from a general comment to one more focused on your personal experience, and it is more helpful to explain what you struggled with so the team can take action to make improvements. Additionally, try not to use the pronoun “you” to address your feedback. Instead of saying “the API endpoint you implemented isn't clear”, you could say “This API endpoint was a bit unclear to me”. This focuses your comments on the feature itself, instead of whoever implemented it.

### Trust is a critical ingredient

When giving any kind of feedback, trust is very important. In general, your teammates want you to do well and you should have a common goal of making the experience better for your users so, when receiving feedback, you should know it comes from a place of care. However, if your company doesn't have a great collaboration culture or if you only recently joined, it can be difficult to have this sense of trust. Before you try to implement friction logs as part of your process, make sure that you get to know your team members. If necessary, schedule calls to go through your friction logs with people so they can understand the state of mind you were in when you wrote your feedback.

### Giving feedback is hard; receiving it is even harder

A bit earlier in this post, I talked about emotional intelligence and how you should put yourself in other people's shoes when writing your friction log. This can be a difficult process when the feedback you need to give is not the most positive. However, remember that receiving feedback is even harder. If you're on the receiving side, try to detach yourself from what you are reading and remember that this is an opportunity to improve. If this is not something you are used to doing, it can be a bit difficult at first and might take a few tries to get comfortable with. Hopefully, the more you do it, the more you'll realize how beneficial it is, not only on a personal level but for all your users.

### Summary

If you're not already using friction logging as part of your product development process, you should definitely consider adopting it. Here's why:

- It can help you identify opportunities for improvement in your product, by highlighting bottlenecks and weaknesses.
  Showing that you listen to users and actively make changes to your product based on their feedback builds user trust and loyalty
- Friction Logging can help to build a culture of trust and feedback, and incentivize emotional intelligence in communication between your colleagues
- In the long run, friction logging can help you save time and money by ensuring that your product is constantly improving.
  Get our friction logging templates
- We've created a [friction logging toolkit](https://github.com/mikeb-stripe/friction-logging-toolkit) for you to use if you're interested in getting started with Friction Logging at your company
- You may also want to check out [frictionlog.com](https://frictionlog.com) - they provide lots of great articles, examples, and resources on Friction logging.

## About my co-author

<center>

![Charlie Gerard headshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qrn3697iitskc063b8y8.png)

</center>

Charlie Gerard is a Developer Advocate at Stripe, a [creative technologist](https://charliegerard.dev/) and [Google Developer Expert](https://developers.google.com/community/experts). She loves researching and [experimenting with technologies](https://charliegerard.dev/). When she's not coding, she enjoys spending time outdoors, trying new beers and reading.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[The Orton Effect - dreamy photo effect in CSS and React]]></title>
            <link>https://mikebifulco.com/posts/orton-effect-css-react</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/orton-effect-css-react</guid>
            <pubDate>Fri, 09 Sep 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[Implement the Orton Effect in CSS and React. The Orton Effect creates a surreal, dreamy image effect, named after photographer Michael Orton.]]></description>
            <content:encoded><![CDATA[
The [Orton Effect](https://www.capturelandscapes.com/orton-effect-explained/) is a photography technique that involves taking two pictures of the same scene, one with a long exposure and one with a shorter exposure, and then combining them. The result is an image that has both the sharpness of the long exposure and the detail of the shorter exposure. While it's not an exact replica, we can simulate a phoo filter for the Orton Effect using CSS and React.

## Emulating the Orton Effect in CSS

To emulate the Orton Effect in CSS, we need to layer 2 copies of the same image on top of one other. To accomplish that, we'll nest them under a single parent - in this case, the [`figure` element](https://developer.mozilla.org/en-US/docs/web/html/element/figure). Note that for the second image, we set [`aria-hidden=true`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden), and intentinally set `alt` to an empty string, so that Screen Readers and other visual assistive tools skip them. won't encounter the repeated image element. You can read more about that and other accessibility features of HTML on [MDN](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden).

```html
<figure class="orton-effect">
  <img
    src="https://source.unsplash.com/tRDGs9utMUo/1600x900"
    alt="A man in the crosswalk on a city street"
  />
  <img
    src="https://source.unsplash.com/tRDGs9utMUo/1600x900"
    aria-hidden="true"
    alt=""
  />
</figure>
```

Next, we'll use a CSS rule to apply some styles to the _first_ of the two images (in HTML-speak, that's the one on top).

```css
figure.orton-effect img:first-of-type {
  position: absolute;
  mix-blend-mode: lighten;
  filter: blur(50px);
  opacity: 50%;
}
```

We're setting `position: absolute;` to layer this image on top of its sibling within the `<figure>` element. The remaining 3 lines of CSS set the top image to use the `lighten` blend mode, apply a gaussian blur using `filter`, and make the top image partly translucent by way of the `opacity` CSS property.

This creates a hazy, glassy effect:

### Before:

<img
  src="https://res.cloudinary.com/mikebifulco-com/image/upload/v1662995195/posts/orton-effect-css-react/crosswalk.jpg"
  alt="A man in the crosswalk on a city street"
/>

### After:

<OrtonEffectImage
  src={
    'https://res.cloudinary.com/mikebifulco-com/image/upload/v1662995195/posts/orton-effect-css-react/crosswalk.jpg'
  }
  alt="A man in the crosswalk on a city street"
  blurRadius={50}
  opacity={50}
/>

It's subtle - but it is there, adding just a slight haze over the light parts of the photo, like a morning fog settling in over a dreamscape.

## The Orton Effect in React

To apply this to an adjustable React Component, we'll use CSS-in-JS to make blur and opacity dynamic. There's many ways to get this done, of course, so you may prefer a different approach. This is what a simple react component for this layout might look like:

```jsx
const OrtonEffectImage = ({ alt, blurRadius, opacity, src }) => {
  return (
    <figure>
      <img
        src={src}
        alt={alt}
        style={{
          mixBlendMode: 'lighten',
          filter: `blur(${blurRadius}px)`,
          opacity: `${opacity}%`,
          position: 'absolute',
        }}
      />
      <img src={src} ariaHidden alt="" />
    </figure>
  );
};
```

This gives us a reusable component that just needs a few parameters passed in - for example:

```jsx
<OrtonEffectImage
  src={
    'https://res.cloudinary.com/mikebifulco-com/image/upload/v1662995539/posts/orton-effect-css-react/snowy.jpg'
  }
  alt="A snowy landscape"
  blurRadius={30}
  opacity={70}
/>
```

Note that a few things have changed here - we're no longer using a named CSS class (`.orton-image`) to select and modify images via CSS. The CSS is now specified on the `img` tag itself, and because it is passed in via `style` prop, it is a JavaScript Object -- so keywords have gone from skewer-case to camelCase, and there's commas where we once had semicolons. Additionally, we're using ES6 String templates to interpolate style rules from the opacity and blur radiuses passed in.

There's some improvement to be done from here - you should do some error checking to make sure that opacity stays between 0 and 100%, and that the blur radius is a positive integer. It's also a good idea to provide some sensible fallback values for those options, in case they're not provided. I'll leave that up to you to implement.

## The Orton Effect in Action

Below you will see the Orton Effect applied to a handful of other images from Unsplash.

I've taken the above example a little further, and made blur and opacity adjustable, so that you can see how each parameter changes the image effect.

I've found that an opacity of somewhere between 25 and 50% and tends to create a nice, subtle effect. The "right" blur radius is a bit more dependent on the specific image.

<OrtonEffectImage
  src={
    'https://res.cloudinary.com/mikebifulco-com/image/upload/v1662995539/posts/orton-effect-css-react/snowy.jpg'
  }
  alt="A snowy landscape"
  blurRadius={30}
  opacity={70}
  showControls
/>

<OrtonEffectImage
  src={
    'https://res.cloudinary.com/mikebifulco-com/image/upload/v1662995644/posts/orton-effect-css-react/cafe.jpg'
  }
  alt="A scene at a local cafe"
  blurRadius={30}
  opacity={70}
  showControls
/>

<OrtonEffectImage
  src={
    'https://res.cloudinary.com/mikebifulco-com/image/upload/v1662995728/posts/orton-effect-css-react/pond.jpg'
  }
  alt="A pond with sunlight filtering through autumn leaves overhead"
  blurRadius={30}
  opacity={70}
  showControls
/>

## Summary

The Orton effect is a photography technique that involves taking two images - one in focus and one out of focus - and overlaying them to create a third image with a dreamy, ethereal quality.

It turns out that this effect can also be simulated using CSS and React! All you need is a bit of code to overlay two images and some CSS to blur one of the images.

If you're looking to add a touch of magic to your photos, then recreating the Orton effect with CSS and React is a great way to do it.

If you found this post useful, I'd love it if you'd consider subscribing to [my newsletter, Tiny Improvements](https://mikebifulco.com/newsletter) - I share articles and resources that catch my attention, as well as my perspective on tech news, designing products, and living a fulfilling life.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[The third place - the secret to a happy life for remote workers]]></title>
            <link>https://mikebifulco.com/posts/remote-work-and-the-third-place</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/remote-work-and-the-third-place</guid>
            <pubDate>Mon, 29 Aug 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[The Third Place is thought of as a space different from home (the first place) and work (the second place), where people can socialize and find community.]]></description>
            <content:encoded><![CDATA[
I live in a fast-growing city in the southeast US, where urban design and city planning are always a hot topic. As population density has increased, it's become apparent that Charlotte needs to make drastic and sweeping changes to accommodate the growing number of people living in the area.

Naturally, this means I'm also reading heaps about urban planning - which is where I first heard the term **third place** being used.

## What is the third place?

As defined by [Brookings](https://www.brookings.edu/blog/up-front/2016/09/14/third-places-as-community-builders):

> (...the) **Third place** is a term coined by sociologist Ray Oldenburg, referring to _places where people spend time between home ('first' place) and work ('second' place)._

Third places have traditionally been where people go to socialize, to relax, and to be a part of their community. You've probably seen them in urban areas, in the form of a town square, piazza, or public park. They might also be a subway station, a heavily trafficked intersection, or a kiosk on a street corner.

<Image
  publicId="posts/remote-work-and-the-third-place/lisboa"
  alt="A photo of a city street in Lisbon, with people walking together and talking"
  caption="Lisbon, Portugal is full of third spaces - public streetcorners, kiosks, and cafes buzzing with people chatting and relaxing."
/>

These spaces are important for people to feel like they belong, and have purpose beyond just home and work. It gives space for one to decompress and find entertainment, to find reprieve from the pressures of work and home life.

Simply put - the third space is a place where you're not expected to work or look after your household and family chores. It's an important part of life and finding balance. Each and every one of us will have our own personal third spaces. Spending time regularly in your third space can provide balance and tranquility, social interaction, and serendipity.

## Suburban living erases the third place

Notably, for people living in suburban places, the third place may be completely missing - folks commuting from the suburbs will skip third places as they drive straight to and from work. This phenomenon is particularly common amongst americans, where it is typical to drive to work, rather than walking, cycling, or taking public transit.

As you might imagine, this means that people living like this don't experience the benefits of a third place in the same way that an on-foot commuter might. This is particularly harmful for people who need a third place the most - those with demanding jobs, parents with young children, and so on.

<Image
  publicId="posts/remote-work-and-the-third-place/suburbia-overhead"
  alt="overhead photo of a suburban neighborhood"
  caption="Photo by Raphaël Biscaldi on Unsplash"
/>

## City living fosters the third place

For people living in cities, the third place is often more accessible. City dwellers are more likely to live in smaller apartments, which encourages them to get out more often. City dwellers are also more likely to use public transit or walk to work, which gives them time to relax or socialize on their way to and from work.

The third place is an important part of city life, and it's one of the things that makes cities such great places to live.

## The third place and remote work

People who work remotely may find themselves one degree further away from a third place - living and working in the same place can create a life with only one place - blurring the lines between home-space and work-space. This makes finding the benefits of a third place even more challenging.

The past several years of post-pandemic-living have been extremely challenging for all of us - and for many, adapting to remote work has had a steep learning curve. I have found that in order to work remotely and live well, I have needed to make a concerted effort to build a life that intentionally includes second and third places that fit into my routines.

## Finding your third place

If you're looking for a third place, there are a few things you can do to find one that's right for you.

The first step is to find a place that suits you. If you're an introvert, you might want a third place that's quiet and relaxing. If you're an extrovert, you might want a third place that's lively and social. There are third places for all kinds of people, so it's important to find one that's right for you.

One way to find a third place that suits you is to explore. Wander around your neighborhood and see what kinds of places there are. Visit a shop or a park you've never been to, or take a class at a new gym. If you see a place that looks interesting, go in and check it out. You might find a third place that you never would have thought of otherwise.

### The third place: community, socialization, and balance

For each of us, the third place will be a unique choice. It might be your favorite coffee shop, your back yard, a beach, a hiking trail, or something completely different. What's important here is that the third space is literally anything other than where you do home-things and office-things - if you work from home, this has to work for you. Find something that makes you feel good, energized, empowered, different. For me, this has taken many forms:

#### Coworking spaces

<Image
  publicId="posts/remote-work-and-the-third-place/atlas-local"
  alt="Photo of a coworking space, with people working at desks in an open office space"
  caption="Atlas Local coworking in Greenville, SC, USA"
/>

Coworking is obviously near and dear to my heart, since [I once built a coworking product](https://mikebifulco.com/tags/smpl). These are great because they supplant your typical work community with likeminded, colocated people who don't have the same problems as you. You can complain to them or unplug completely from work and just hang out. In my experience, people are far more likely to have a eureka moment at a coworking space than in the stuffy hallways of your typical cube farm or open office.

Serendipity is a happy byproduct of interacting with people who don't have the same colleagues as you. Their problems and joys are different, and they can share their perspective on your world, just as you can do the same for them.

#### Cafes

<Image
  publicId="posts/remote-work-and-the-third-place/coffee-shop"
  alt="A laptop sitting on a table at a coffee shop"
  caption="Coffee shops are great for relaxing, reading, and watching the world go by."
/>

My god, do I love a good cafe. I have great gear for making coffee at home, yet I still spend plenty of time at cafes. This is because, for me, there's a change in mindset at a cafe. I know I typically have 1-2 hours of comfortable time at any given cafe, and I can hammer through some really great work during this time. It also requires transit/transition time on either side of it, where I can clear my mind, give myself a break, see nature, go for a bike ride/drive/etc. This has a multiplicative effect on my productivity - small doses of repose are amazing.

### Touch grass, feel the sun

<Image
  publicId="posts/remote-work-and-the-third-place/touch-grass"
  alt="Photo of a bicycle leaning against a fence, with a green riverbed behind it"
  caption="There's no replacement for spending time outside."
/>

Many times, I'll use the great outdoors as my third space. Going for a long walk in the morning (1-2hrs) while listening to a podcast can set my energy for the day. When I know I've got calls/meetings/deadlines all day, this helps me to feel like I haven't burned an entire day behind my computer screen. This can also take the form of a run or a bike ride or (whatever you do to exercise) - turning your mind off of work really is a booster. Don't let hustle porn ruin your perception of your own throughput (but don't lie to yourself, either). At the end of the day, you still have to get things done, but doing so with a mindful eye on balance can keep you healthier and happier in the long run.

There are also times where I know I'll be on a super long call (30min+) where I just need to listen - going for a walk during these calls (even in super hot or super cold weather) is often a guarantee that I'll pay better attention to the content of the call than if I'm left to poke around in my browser, on twitter, reddit, etc. I have several regular 1:1s with teammates where this is the expectation and the norm. Even though we're not in the same place, we will pop our earbuds in and go for a walk at the same time, talking together like a normal old phonecall instead of performing business-normality in front of a web cam.

## Conclusion

Generally, I've been extremely happy as a remote worker for a long time by creating a series of third places for myself. If you're new to working remotely, and you're having a difficult time being productive, this may provide some relief. It's also a great way to meet new people, and to find a sense of community.

If you live in a city, there's a good chance you already have a third place. If you live in a suburb, you might have to work a little harder to find one. Either way, it's important to find a third place that suits you, and to make it a habit to spend time there.

<small>

_(Quick privilege note: I'm lucky to have an exceptionally charmed life. There are countless people who have been through an unimaginable hell during the pandemic. There's also plenty of people who can barely make ends meet, and don't have time to fret over finding the perfect way to bring balance to their life. I do not mean to trivilize or minimize these lived experiences in any way.)_

</small>

## Publications about Third Places:

- [The Wellbeing thesis](https://thewellbeingthesis.org.uk/foundations-for-success/importance-of-taking-breaks-and-having-other-interests/) says breaks can reduce or prevent stress, help to maintain performance throughout the day and reduce the need for a long recovery at the end of the day
- [How Do Work Breaks Help Your Brain?](https://www.psychologytoday.com/us/blog/changepower/201704/how-do-work-breaks-help-your-brain-5-surprising-answers) says _“Movement breaks” are essential for your physical and emotional health, and that breaks restore motivation, especially for long-term goals._
- [Atomic Habits](https://atomichabits.com) - habits are the compound interest of self-improvement, and finding a (series of) third place(s) is a _huge_ part of that - there's a great [primer video on Atomic Habits](https://youtu.be/U_nzqnXWvSo) from the book's author, James Clear.

## More from me

If you liked this, you may appreciate my articles from the early days of the pandemic:

- [Are you suddenly a remote worker? Let's figure it out together.](https://mikebifulco.com/posts/are-you-suddenly-a-remote-worker)
- [On normalcy](https://mikebifulco.com/posts/on-normalcy)
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[SEO tools I used to grow my sites to 20k+ visitors/month]]></title>
            <link>https://mikebifulco.com/posts/seo-tools-for-new-web-projects</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/seo-tools-for-new-web-projects</guid>
            <pubDate>Mon, 22 Aug 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[I use these tools on every project to help track source code, monitor traffic on my site, and optimize content for better Search Engine Optimization (SEO).]]></description>
            <content:encoded><![CDATA[
## SEO & analytics help grow site traffic

Whether you're working on your own blog, a news site, or building a product, you _absolutely must_ care about your site's SEO. If your site is not optimized for search engines, it is harder to find, leading to fewer visitors and potential customers. SEO tools can help you improve the usability of your site, making it easier for users to find the information they are looking for.

These are the tools that I use to monitor and enhance my sites' performance. The can help you build a site that is easier to find and use, too.

## ahrefs webmaster tools

You only need to spend a few moments researching SEO online before ahrefs pops up _somewhere_ in your results. In addition to their incredible [blog](https://ahrefs.com/blog/) and [studies](https://ahrefs.com/blog/category/data-studies/) on how search works on the web, they provide a fantastic suite of free tools for monitoring and improviing the SEO on your sites.

<Image
  publicId="posts/seo-tools-for-new-projects/ahrefs-audit"
  alt="Screenshot of a weekly audit email from ahrefs - showing a 100 SEO score for mikebifulco.com, with a few warnings."
  caption="There's always room to improve SEO, and ahrefs webmaster tools makes it easy to digest"
/>

I have found [ahrefs webmaster tools](https://ahrefs.com/webmaster-tools) to be absolutely invaluable in keeping an eye on my sites' content. Once you register a free account and verify that you have control of the sites you want to monitor, ahrefs will kick off a weekly audit of all the pages on your domain. It will check for common pitfalls, and give your site a health score from 0-100. If you're a dev, it may be helpful to think of it as a linter for SEO.

I've used it to find and fix countless problems with my sites, from broken links to missing Canonical URLs, removing unnecessary redirects and finding opportunities to link existing articles to one another.

You will get weekly audit reports in email, which let you know when things change - this can be helpful in situations where things out of your control end up affecting your site. Ever had someone take down an article that you link to? Ahrefs will find it.

## Google Search Console

My adoption of [Google Search Console](https://search.google.com/search-console/about) come from what I learned taking Monica Lent's [Blogging for Devs](https://bloggingfordevs.com) course.

Google Search Console gives you reports on how and when people see your site pop up in Google Search results. Note that it won't track people _on your site_ like Google Analytics and Fathom do - just your performance in search. This is a useful litmus for your site's organic growth and authority. If you're investing in sharing your expertise and building a searchable site, your performance on Google Search Console should grow over time. In other words, you can see whether you're gaining traction via SEO or not.

To get started, you'll need to register your site with the Google Search Console. Verifying your ownership takes a few quick steps, and doesn't require you to add Google Analytics (which is helpful if, like me, you've chosen [Fathom](https://mikebifulco.com/posts/why-fathom-analytics) for its privacy-first features).

Best of all, it's free! Just register and follow instructions to add a DNS record, or upload a file to a specific place to verify that you own the site you're interested in monitoring. You should make sure to have a sitemap on your site - they're easy to generate, and worth the time to get right. This is what Google's crawlers primarily use to index your articles for search results.

I use the Search Console to make decisions about things to write about next, and track the progress of my site over time. At the moment, Google will keeps 16 months of your site's traffic history around for you to analyze, but that history starts once you've registered you site with the Search Console. So, the sooner you get set up, the better!

## Fathom Analytics

[Fathom](https://usefathom.com) is privacy first analytics for the web. According to their site, _Fathom is a Google Analytics alternative that doesn’t compromise visitor privacy for data. We revolutionized website analytics by making them easy to use and respectful of privacy laws (like GDPR and more)._

If you've never paid attention analytics for your web properties, Fathom will be a revelation - it's super useful to have an understanding of which pages on your site are getting traffic, where that traffic is coming from, and what times of day are most busy.

If you've used Google Analytics in the past, you may be surprised just how freeing it is to use an analytics tool that prioritizes analytics. You _really_ don't need to know _who_ is on a given page - instead, focusing on the content on your site which is being visited, and the journey readers take to get there is a super useful tool to have when you're researching and writing new articles.

It's great, and puts your readers' privacy first. Google's advantage is quickly vanishing due to new regulations, and privacy tools that are being built into browsers and operating systems. Fathom does a great job of providing value without fishing for every minute detail about your readers.

Fathom is lightweight and ridiculously easy to use. The Fathom team provides docs for a variety of platforms and JAMstack site builders, including [Gatsby](https://usefathom.com/docs/integrations/gatsby), [ConvertKit](https://usefathom.com/docs/integrations/convertkit), [Next.js](https://usefathom.com/docs/integrations/next), [Vue](https://usefathom.com/docs/integrations/vue), [Webflow](https://usefathom.com/docs/integrations/webflow), [Wordpress](https://usefathom.com/docs/integrations/wordpress), and quite a few more.

I've written a bit about my experiences with Fathom before. You may want to check out my other articles, including: [Why I switched to Fathom for Analytics](https://mikebifulco.com/posts/why-fathom-analytics) and [How to add Fathom Analytics to your Remix.run app](https://mikebifulco.com/posts/add-fathom-analytics-to-remix)

### Self-host Fathom for free - Fathom Lite

If you're hesitant to pay for Fathom, they do also provide an open source version called [Fathom Lite](https://github.com/usefathom/fathom) - you'll need to configure and host it yourself, but it should give you an idea of what Fathom's premiums service is like.

If you're interested in trying out Fathom's paid service, use my [**referral link**](https://usefathom.com/ref/DPSSYB) for a discount to get you started.

## Cloudflare

I use [Cloudflare](https://cloudflare.com) to manage the DNS records for all of my sites. In addition to having a _really_ straightforward UI for DNS management, they offer a host of other features to keep your sites running well. This includes automated protection for DDoS attacks, maintenance mode, and performance enhancements such as origin server optimization and caching.

Cloudflare provides a [Free Tier](https://www.cloudflare.com/plans/) that will work for most personal sites. You'll need to set up an account, look for the instructions to add your domain to your Cloudflare account, and then update your DNS settings as needed.

Because I own domains from a variety of registrars, it's really nice to be able to manage DNS for all of them in one place. They also provide a ton of other great dev tools, like [Cloudflare Workers](https://workers.cloudflare.com/), which you can use to add interactivity to your site.

## F5Bot

<Image
  publicId="posts/seo-tools-for-new-projects/f5bot"
  alt="Screenshot of f5bot.com - get an email for when you're mentioned online!"
  caption="F5bot is free, and dead simple to set up. "
/>

The pitch for [f5bot](https://f5bot.com) is simple - as they say, it is a service that will help you to "Get an email when you're mentioned online!".

It's completely free, and takes just moments to set up - you just need to create an account, and set up keywords for the service to track. When your keywords are mentioned on [Reddit](https://reddit.com), [Hackernews](https://news.ycombinator.com), or [Lobste.rs](https://lobste.rs), you'll get a tidy little email in your inbox.

<Image
  publicId="posts/seo-tools-for-new-projects/f5bot-notification "
  alt="screenshot of a notification from f5bot in my gmail inbox. It's a simple plaintext email with a link to an article on mikebifulco.com that was mentioned on Reddit."
  caption="This is what typical notification from f5bot looks like."
/>

Notifications come _very_ quickly - in my experience, I see them within minutes of my sites being mentioned online. This is hugely helpful because it allows you to respond quickly, strike up a conversation, and make a connection with the people who are sharing your work. Those connections are the backbone of building a great personal brand online.

You can set up any search keyword you want, so if there's a competitor or topic that you're hoping to keep an eye on, it's great for that, too.

Overall, I highly recommend [f5bot](https://f5bot.com) - it's an incredibly useful tool, it's free, and it couldn't be easier to set up.

## Related reading

If you're going on the SEO-improvement journey for your sites, you might find these helpful:

- [Why I switched to Fathom for Analytics](https://mikebifulco.com/posts/why-fathom-analytics)
- [How to add Fathom Analytics to your Remix.run app](https://mikebifulco.com/posts/add-fathom-analytics-to-remix)
- [Don't center-align paragraph text](https://mikebifulco.com/posts/dont-center-paragraph-text) - this is utterly unrelated to SEO, but c'mon, do better.
- [SEO for Devs](https://seofordevs.com) - I absolutely cannot recommend this **free course** enough. Monica Lent has a masterful understanding of SEO, and I've learned a ton from her over the years.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[The correct semantic HTML for adding subtitles to h1 tags]]></title>
            <link>https://mikebifulco.com/posts/semantic-html-heading-subtitle</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/semantic-html-heading-subtitle</guid>
            <pubDate>Tue, 05 Jul 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[This is the right format to use if you want to add a subtitle below an h1 tag on your html pages. Semantic HTML makes your site more accessible and better for SEO, since it is easier for search engines to process.]]></description>
            <content:encoded><![CDATA[
## Semantic HTML makes your sites better

Semantic HTML is important because it helps improve the accessibility of a web page and makes the code more readable. Semantic elements are those that clearly describe their meaning in a way that is easy for both humans and machines to understand.

Search engines can more easily parse and understand semantic HTML, [which can help improve your website's SEO](https://developers.google.com/style/semantic-tagging). Semantic HTML uses tags to describe the meaning of content on a page, rather than just its presentation. This can help search engines better understand the content of a page and index it appropriately.

### Using h2 as a subtitle for an h1 is incorrect

According to the [html spec](https://html.spec.whatwg.org/multipage/dom.html#heading-content-2), `h1` through `h6` tags are meant to indicate the structure of a document. In other words, each page should have at most 1 `<h1>` tag, and `<h2>` elements should be _sub-sections_ of that `h1` - not additional descriptions for it.

This [warning from the HTML spec](https://html.spec.whatwg.org/multipage/dom.html#sectioning-content) does a great job of explaining it:

> For example, the following snippet, intended to represent the heading of a corporate site, is non-conforming because the second line is not intended to be a heading of a subsection, but merely a subheading or subtitle (a subordinate heading for the same section).
>
> ```html
> <body>
>   <h1>ACME Corporation</h1>
>   <h2>The leaders in arbitrary fast delivery since 1920</h2>
>   ...
> </body>
> ```

(07/05/2022) As of the time of this writing, whatwg goes on to recommend use of `hgroup` in its solution. [According to MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hgroup#usage_notes), hgroup should not be used, as it is not supported by assistive technologies needed for accesible reading of HTML sites.

## Use this code to add subtitles to headings

The correct semantic structure of HTML for a heading with a subtitle is straightforward - nest your `<h1>`, etc with in a `<header>` tag, and include a `<p>` tag with an appropriate class name as a sibling to that `h1`:

```html
<header>
  <h1>How to bootstrap a product as a solo founder</h1>
  <p class="tagline">
    Important lessongs learned from building 10 products on my own in 2 years
  </p>
</header>
```

For more details on this, check out [MDN docs on the header tag](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/header), and their [semantics section](https://developer.mozilla.org/en-US/docs/Glossary/Semantics).

### 🚨 UPDATE: I was wrong! 🚨

The first version of this article was wrong! I previously recommended using the `<hgroup>` tag as per the whatwg spec, but I was corrected by [@AnalyticsEqv](https://twitter.com/AnalyticsEqv) on twitter:

<blockquote class="twitter-tweet">
  <p lang="en" dir="ltr">
    MDN specifically recommends against &lt;hgroup&gt; because assistive
    technologies don&#39;t support it.
  </p>
  &mdash; EQV Analytics 🇺🇦 (@AnalyticsEqv){' '}
  <a href="https://twitter.com/AnalyticsEqv/status/1544328749272993792?ref_src=twsrc%5Etfw">
    July 5, 2022
  </a>
</blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8" />

Thanks for the correction! I definitely get things wrong sometimes, and I'm always happy to correct myself when appropriate.

## Did you find this helpful?

You might also like these other articles I've written:

- [How to run dependabot locally on your projects](https://mikebifulco.com/posts/run-dependabot-locally)
- [No Floating Promises: an eslint rule to prevent async code errors](https://mikebifulco.com/posts/eslint-no-floating-promises)
- [JavaScript tips: nullish coalescing](https://mikebifulco.com/posts/nullish-coalescing-javascript)

If you want to hear more from me, consider subscribing to my newsletter 👇🏼
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[How to add Fathom Analytics to your Remix.run app]]></title>
            <link>https://mikebifulco.com/posts/add-fathom-analytics-to-remix</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/add-fathom-analytics-to-remix</guid>
            <pubDate>Sun, 05 Jun 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[Building a website using the Remix.run webb app framework? This tutorial will teach you how to add privacy-first analytics to your Remix site with Fathom.]]></description>
            <content:encoded><![CDATA[
Building a website using the Remix.run web app framework? This tutorial will teach you how to add privacy-first analytics to your Remix site with Fathom.

## How to set up Fathom on your Remix site

1. Sign into your account with [Fathom](https://usefathom.com/login), and create a new site.
2. Open the settings for that site, and look for _Script settings_. Hit the clipboard icon to copy the Script tag for your site.

   <Image
     publicId="posts/add-fathom-analytics-to-remix/script-settings"
     alt="Script settings for one of my sites on Fathom's dashboard"
     caption="You site's embed code will be on the script settings page. Hit the clipboard button to copy the code"
   />

3. Open up your Remix site in your IDE of choice. open `root.tsx` (or `root.jsx` if you're using JavaScript instead of TypeScript), and paste your embed code right before the `<Script />` tag:

```jsx
return (
  <html lang="en">
    <head>
      <Meta />
      <Links />
    </head>
    <body>
      <Layout>
        <Outlet />
      </Layout>
      <ScrollRestoration />

      <script
        src="https://cdn.usefathom.com/script.js"
        data-site="TRSSCIOR"
        defer
      />
      <Scripts />
      <LiveReload />
    </body>
  </html>
);
```

<small>

_Note: ☝🏽 I've edited the `<script>` tag here to be self closing, rather than having `<script></script>`. It should work either way._

</small>

4. Start your site with `npm run dev` or `yarn dev` and visit any page (you may have to hit reload if you had the page open already). You should see this reflected in your fathom dashboard in real time!
   <Image
     publicId="posts/add-fathom-analytics-to-remix/tracking-results"
     alt="You'll know it's working when you see a live visitor on your fathom dashboard"
     caption="You'll know it's working when you see a live visitor on your fathom dashboard"
   />

## Try out Fathom - it's great!

I've been using Fathom for years, and am a happy paying customer. If you'd like to give it a shot, you can get $10 off of Fathom when you **use my referral link [https://usefathom.com/ref/DPSSYB](https://usefathom.com/ref/DPSSYB)** to get started.

## If you enjoyed this video

- I wrote a post when I initially adopted fathom, called [Why I switched to Fathom for analytics](https://mikebifulco.com/posts/why-fathom-analytics)
- Make sure to [subscribe to my YouTube channel](https://www.youtube.com/channel/mikebifulco)
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[I'm building a tiny product]]></title>
            <link>https://mikebifulco.com/posts/building-tiny-products</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/building-tiny-products</guid>
            <pubDate>Sun, 22 May 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[Let's call it an experiment. I'm building a tiny product to see if I can make something people will buy.]]></description>
            <content:encoded><![CDATA[
## Right then, that settles it.

I'm building a tiny little business. I've been itching to build something from start to finish that I can complete relatively quickly, and so that's what I'm doing. I'm sitting at my computer right now, browsing the web for inspiration for itty-bitty businesses; ideally, something I can put together in under a month (even better if I can keep it to a couple weeks).

So, it's time for me to build something. Hopefully someone will be happy with whatever I come up with, and fork over some money.

## Why am I qualified to do this?

Let's talk about that.

### I've built a SaaS company in the past

Although I was not alone, I built it with two amazing friends [@helloseann](https://twitter.com/helloseann) and [@garrettTichy](https://twitter.com/GarrettTichy). We built [smpl.io](https://smpl.io) (sold in 2020), a subscription-based SaaS which helped independent-scale coworking spaces run smoothly. It was a fairly complicated, SaaS company built on a complex subscription model with lots of options, and bells and whistles, and an endless list of exciting features to build. It was also a complicated marketplace to build for, which was an awesome experience, but really was all-consuming.

### I work as a Developer Advocate at Stripe

Building smpl is a big part of the reason that I'm working at Stripe today as a Developer Advocate - making that business tick meant that we were wading in the depths of some of the more intricate parts of building with Stripe: subscriptions, Connect, and international taxes. It gave me a massive appreciation for the monetization-side of building a business.

### I can work in the open

I'm going be live streaming as much of this process as I can on my [Twitch](https://twitch.tv/irreverentmike) and [YouTube Channel](https://www.youtube.com/c/MikeBifulco). I would love it if you subscribe so that you can catch some stream sessions - this is where I'll brainstorm and iterate on ideas, build the damn thing, and put it out into the world.

## What am I going to use to build this?

Well, I've got lots of things I want to try. I've been tapping into the power of lots of no-code tools lately, and writing about [**CRMs**](https://mikebifulco.com/posts/how-do-you-choose-the-right-crm-for-your-product), so it's likely we'll see some of those come into play. I've been enjoying web things with [**Remix**](https://remix.run) and [**Next.js**](https://next.js.org), and I'll use [**Stripe**](https://stripe.com) for taking payments when we're ready for that. There may be an interation of this thing that is completely no-code, too. I know that there are quite a few APIs available for making physical things appear in the world which I might take advantage of. There are **mailing APIs**, like [**Lob.com**](https://lob.com) (who are a sponsor of [APIs You Won't Hate](https://apisyouwonthate.com), by the way). There are also services which can be used for **printing physical goods** like stickers or posters or shirts or mugs which I may use, too.

## What do I want to get out of this?

I'm following a path that may be familiar if you spend time on [Indie Hackers](https://indiehackers.com), or if you've read about [David Vassallo's Portfolio of Small Bets](https://dvassallo.gumroad.com/l/small-bets), or the book [Company of One, by Paul Jarvis](https://www.amazon.com/Company-One-Staying-Small-Business/dp/1328972356).
I want to learn from the experience of starting a business today as a creator, pursuing my small ideas to see what gets traction and what doesn't.

I'm going to live stream as much of this process as possible, and take notes along the way - ultimately, I'd like for you, the reader, to be able to benefit from my experimentation as well. As I'm building, I'll do my best to take feedback and iterate quickly. I want to get a sense of how long it takes for one person to build something, and just what it takes to support a product in the wild.

So, let's do this thing! Head over to [my YouTube Channel](https://www.youtube.com/c/MikeBifulco) and [my Twitch](https://twitch.tv/irreverentmike), hit subscribe, and you'll get a notification when I'm streaming.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[How do you choose the right CRM for your product?]]></title>
            <link>https://mikebifulco.com/posts/how-do-you-choose-the-right-crm-for-your-product</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/how-do-you-choose-the-right-crm-for-your-product</guid>
            <pubDate>Tue, 10 May 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[You're building relationships with all of your customers, whether you know it or not. Setting up the right CRM for your product can help make those relationships stronger.]]></description>
            <content:encoded><![CDATA[
## You’re building relationships with all of your customers…

…whether you know it or not. Winning your prospects’ hard-earned money is hard. Founders spend hundreds and thousands of hours building products to solve a problem, pouring blood, sweat, tears, and money into product development. Building a product is only part of the equation: you have to earn the trust of your customers by creating a brand and voice that they trust. Landing sales, and keeping happy customers takes time and compassion. Thankfully, Customer Relationship Management (CRM) software exists to help you and your team do a great job of maintaining great relationships with your customers.

**CRM stands for “Customer Relationship Management”,** and CRM software helps you do just that: it provides tooling to track of your interactions and commitments to prospects, customers, and visitors to your app, service, or site. Often this comes in the form of integrations that automate part of the process - keeping track of contact information, logging important events and milestones in the customer journey, and reminding you to follow-up on leads before they go cold.

## What Types of CRMs are there?

Like most things, no CRM is a perfect solution for everyone. They vary in complexity, price, and usability - and perhaps most importantly, each CRM you encounter will have its own ethos, or underlying strategy. Ultimately, it’s up to you to decide which type of CRM fits your product best. As I see it, most CRMs fall into a few basic categories.

### Sales-based CRMs

**Examples: [Close.io](https://close.io), [Salesforce](https://salesforce.com), [Hubspot](https://hubspot.com)**

These are generally best for products whose success is based on a traditional sales process. If you have salespeople who contact prospective customers and manage relationships with them throughout the sales process, these CRMs may be a good fit. They tend to center around closing a sale, guiding you to craft messaging and contact strategies (via email, SMS, or phone call) that rely on high-touch salespeople doing their thing.

### Conversational Marketing CRMs

**Examples: [Intercom](https://intercom.com), [Drift](https://drift.com), [Front](https://front.com)**

You’ve probably bumped into some flavor of conversational Marketing CRM, as they have been wildly popular for the last several years. These usually look like a chat widget living in the bottom corner of a web page or mobile app. They’re highly configurable, and allow you to automate conversational messages to users as they browse your site or app. They can be used to highlight functionality, press visitors to sign up for trials, and complete sales. They rely on your team building conversational messaging that fits your brand, and guiding customers to make decisions. Many also offer real-time chat functionality, where members of your team can message and reply to website visitors through the embedded chat widget.

### Inbox based CRMs

**Examples: [Streak](https://www.streak.com/), [Copper](https://copper.com)**

If your customer support or sales process relies heavily on communication through email, these may be the CRM for you. They use the contents of your inbox to catalog customer relationships, allow your team to keep track of these relationships across inboxes. This typically means that email threads with customers get back-channeled notes and chat functionality. An important caveat with these tools is that they tend to be strongly-tied to the email service your team uses - your options for inbox CRMs will be limited based on whether you use G Suite or Microsoft 365

### Self-maintained CRMs

**Examples: [Monday](https://monday.com), [Airtable CRM templates](https://www.streak.com/), Notion CRM templates ([personal](https://www.notion.so/templates/personal-crm), [sales](https://www.notion.so/templates/sales-crm)), [Roam Research](https://roambrain.com/personal-crm/)**

These tools rely on you doing some of the work. They usually look like miniature table-based databases, and are used to leave notes on customer conversations, track potential and realized revenue, and other relevant metadata about your customer conversations. Some options offer simple automation out of the box, allowing you to plug in to tools like n8n and Zapier to add or update records.

### …something else?

No doubt there are other types of CRMs I’ve missed. **What’s your tool of choice for managing customer relationships? Do you have any tips or tricks to share with other founders and product teams? Did I miss something important, or get something wrong?** Share your thoughts with me on twitter [@irreverentmike](https://twitter.com/irreverentmike).

<small>

_Note: cover photo by [Andrew Neel](https://unsplash.com/@andrewtneel?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com)_

</small>
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[What it's like to migrate a high-traffic website from Gatsby to Next.js]]></title>
            <link>https://mikebifulco.com/posts/migrate-gatsby-to-nextjs-apisyouwonthate-com</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/migrate-gatsby-to-nextjs-apisyouwonthate-com</guid>
            <pubDate>Wed, 02 Mar 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[I migrated apisyouwonthate.com, a site with 20k+ monthly visits, from Gatsby to Next.js at the end of 2021. Let's talk about what I learned from that experience.]]></description>
            <content:encoded><![CDATA[
[APIs You Won't Hate](https://apisyouwonthate.com) is a resource for developers who want to learn how to build APIs that are secure, performant, and easy to use. I've been helping to run and maintain the site since roughly the beginning of 2018, when I rebuilt it from a [Jekyll](https://jekyllrb.com/) site to a static site with [Gatsby](https://www.gatsbyjs.com/). This was a huge leap forward for the site - as we were growing the community and adding resources for API developers regularly, it became apparent that we were going to need to support some features that I wasn't really interested in building on top of Jekyll - support for multiple authors, an image optimzation solution.

## Why we chose to move away from Gatsby

So, I built the site with Gatsby, as a visual clone of the Jekyll site. It worked fantastically for us, but as we added more and more articles and authors to the site, it became challenging to maintain, for a variety of reasons.

1.  **Building the site was slow**

    From a clean cache, it could take from 11-15 minutes to build, which meant that regular deployments to our hosting provider were starting to get expensive. It also meant that any debug tasks which required a production build were _intolerably_ slow, and very frustrating.

2.  **Dealing with images was challenging**

    Gatsby has an _amazingly_ clever [strategy for image optimization](https://www.gatsbyjs.com/plugins/gatsby-image/), which involves sending all images used on the site through a pre-build pipeline that makes them accessible via Gatsby's graphql API. This is a foundational part of how Gatsby sites are meant to run, and it gives plenty of options for image loading strategies and optimization approaches.

    What we never quite got right with our implementation was a strategy that would allow authors to upload images to the [apisyouwonthate.com repo](https://github.com/apisyouwonthate/apisyouwonthate.com) with a naming strategy that was sensible.

    Essentially, due to a quirk in our chosen implementation, each image _on the site_ had to have a unique name, and if two images with the same name were uploaded, it caused all kinds of problems. You can imagine that in the course of writing dozens of articles about APIs, there's more than one occasion to create an image called `devtools-network-tab.png`, or `cover.png`, etc.

3.  **Updating the site required too much understanding of Gatsby's underlying platform**

    This basically meant that of the three of us who maintain the site, I was the only one equipped to make significant changes, because I had spent a good deal of time in my day-to-day job building prototypes with Gatsby for [Gymnasium](https://thegymnasium.com). When either of my teammates wanted to make changes to the site, they had a choice: spend hours and hours trying to figure out how the site was configured, struggle to make changes, and submit a PR, _or_ create an issue on GitHub and assign it to me to fix. You can probably guess which happened more often - and looking back, it makes total sense.

4.  **Some lugnut\* had used boostrap to design the layout for the site.**

    <small>

    (\*It was me.)

    </small>

    I used bootstrap out of convenience, and hamfisted it into working with our React site using a couple of libraries and band-aids to get it all "working" properly. This resulted in a near-infinite supply of teeny tiny little layout bugs. These would be fantastic if I needed them for job security... but in practice they were relentless headaches.

## So, what did we gain from moving to Next.js?

Let me be the first to tell you that it's _highly_ likely that everything I accomplished in the site rebuild with Next.js is _possible_ with Gatsby (or your favorite framework). This rebuild sets the stage for a number of features to come, and should make it easier for us to collaborate with new authors, iterate on site designs, and add small features without having to suffer a 10+ minute CI process.

This rebuild gave me a chance to add features, and add some meaningful updates which had been on my plate for quite a long time. Here's a quick summary of some of my favorite features of the new site:

### SEO features

For the first time ever, **Open Graph Images** are embedded correctly across the site - the site uses a fairly simple strategy, grabbing a predetermined cover image of just-the-right-size and embedding that in the header of each page using [Open Graph metadata](https://mikebifulco.com/posts/reset-your-open-graph-embeds-on-linkedin-twitter-facebook).

<Image
  publicId="posts/migrate-gatsby-to-nextjs-apisyouwonthate-com/og-embeds-work"
  alt="An APIs You Won't Hate article shared on twitter now includes the cover image for the post"
  caption="Rich Open Graph embeds get much more traffic from twitter than the alternative."
/>

We've also got fairly fine-grained control of other SEO metadata, including author names, article titles, and descriptions. Our new implementation will allow us to set Canonical URLs for articles crossposted to APIs You Won't Hate from other sources as well, which makes for better SEO all around. This may also help down the line if we want to add sponsored posts to the site which point to another origin as the canonical home for the information we share.

Want to see how it works? Dive into the [SEO component in the site's source code](https://github.com/apisyouwonthate/apisyouwonthate.com/blob/main/src/components/SEO/SEO.js).

### Contact form & Newsletter signup

We had previously been using [Netlify Forms](https://www.netlify.com/products/forms/) for the site's contact form, but since the new site is hosted on Vercel, that is no longer possible. We're now using [Airtable's API](https://github.com/apisyouwonthate/apisyouwonthate.com/blob/main/src/pages/api/contact/index.js) for the form, which lets us collate all submissions into one place. New entries to this form trigger a routine which notifies site owners that we got a message. We then use Airtable to track responses, and make sure that nothing gets lost in the mail.

This is all made possible by Next.js API routes. These are serverless functions that are magically deployed to the cloud for any route at `/pages/api/[slug]`. We use a similar approach for our Newsletter signup form, which adds contacts to a list on mailjet. You can check out the [API code here](https://github.com/apisyouwonthate/apisyouwonthate.com/blob/main/src/pages/api/newsletter/index.js), and the [newsletter form code here](https://github.com/apisyouwonthate/apisyouwonthate.com/blob/main/src/components/NewsletterForm/NewsletterForm.js).

### Lighthouse scores

Our Lighthouse scores _shot up_ with this reimplementation - and while they're a moving target for a variety of reasons, performance on the site is generally really great. This is helped immensely by [Next.js's Image component](https://nextjs.org/docs/basic-features/image-optimization), which uses a variety of web standards and recommended practices to load the right-size image depending on readers' given device and browser.

<Image
  publicId="posts/migrate-gatsby-to-nextjs-apisyouwonthate-com/lighthouse-scores"
  alt="Lighthouse scores for APIs You Won't Hate: 95 Performance, 100 Accessibility, 100 Best Practies, 100 SEO"
  caption="Near-perfect lighthouse scores were far easier to land thanks to our use of Next.js Image Optimization"
/>

### Search Performance

One of the most important litmus tests available for our site's general performance comes from Google's Search Console. Thankfully, since the site was deployed, we've seen consistent traffic on across all of our pages, with a slight-but-steady increase week to week:

<Image
  publicId="posts/migrate-gatsby-to-nextjs-apisyouwonthate-com/search-results"
  alt="Search Console traffic for APIs You Won't Hate"
  caption="Search Console traffic for APIs You Won't Hate"
/>

Next also made it _far_ easier to generate a `sitemap.xml` for APIs You Won't Hate. In Gatsbyland, we needed to use [`gatsby-plugin-sitemap`](https://www.gatsbyjs.com/docs/how-to/adding-common-features/creating-a-sitemap/), which _is_ configurable, but is generated at _build time._ This meant that debugging sitemap changes took a full 10min+ for _each change_ - which was completely untenable for us.

By contrast, our [sitemap implementation with Next.js](https://github.com/apisyouwonthate/apisyouwonthate.com/blob/main/next-sitemap.js) uses a library called [next-sitemap](https://github.com/iamvishnusankar/next-sitemap). It is _also_ generated at build time, but in a local dev environment builds take only a few seconds, allowing me to nail our sitemap much more quickly.

<Image
  publicId="posts/migrate-gatsby-to-nextjs-apisyouwonthate-com/sitemap"
  alt="Google Search Contole's Sitemap ingestion for APIs You Won't Hate"
  caption="Once everything was right, we pointed Google Search Console to the new sitemap, and verified that everything was working correctly."
/>

### Visual redesign

Because this implementation work gave me an opportunity to rip out the old site's visual design, I was able to make some sorely changes to the site's overall look and feel. I removed Bootstrap and `react-bootstrap`, and used [Chakra UI](https://chakra-ui.com/) for layout building instead. There's a bit of a learning curve with Chakra (like any other UI library), but now that I'm familiar with it, I can build new responsive site pages efficiently and reliably.

Here's some side-by-side comparisons of the old and new site:

**Home Page**

<div className="grid gap-4 md:grid-cols-2">
  <Image
    publicId="posts/migrate-gatsby-to-nextjs-apisyouwonthate-com/home-before"
    alt="Old home page design for apisyouwonthate.com"
    caption="Home page: before"
  />
  <Image
    publicId="posts/migrate-gatsby-to-nextjs-apisyouwonthate-com/home-after"
    alt="New home page design for apisyouwonthate.com"
    caption="After"
  />
</div>

**Book feature page**

<div className="grid md:grid-cols-2 gap-4">
  <Image
    publicId="posts/migrate-gatsby-to-nextjs-apisyouwonthate-com/book-before"
    alt="Old Book feature page for apisyouwonthate.com"
    caption="Book feature page: before"
  />

  <Image
    publicId="posts/migrate-gatsby-to-nextjs-apisyouwonthate-com/book-after"
    alt="New book feature page for apisyouwonthate.com"
    caption="After"
  />
</div>

**Blog landing page**

<div className="grid md:grid-cols-2 gap-4">
<Image
  publicId="posts/migrate-gatsby-to-nextjs-apisyouwonthate-com/blog-before"
  caption="Old blog landing page for apisyouwonthate.com"
  alt="Blog landing page: before"
/>

<Image
  publicId="posts/migrate-gatsby-to-nextjs-apisyouwonthate-com/blog-after"
  caption="New blog landing page for apisyouwonthate.com"
  alt="After"
/>
</div>

## Summary

We've been up and running on Next for a few months now, and everything has been working smoothly. I'm really happy with how this implementation work went, and am really lucky to be able to have a wealth of choices in amazing developer communities that surround JAMstack and SSG tools. Having now built sites and companies with create-react-app, Gatsby, next.js, and Remix Run (keep an eye out for this one!) -- I can say with a high degree of confidence that they are _all_ super tools. You can get your work done in any one of these libraries - often the challenge we face as developers is sticking with our bets long enough to see them through.

Keeping [APIs You Won't Hate](https://apisyouwonthate.com) running and growing has been a forcing function to build a site that is performant and dependable, and affects a large-scale audience... for me, that's more than enough to motivate the work it takes to keep the site running. The community we've built and the knowledge we're sharing are truly fantastic, and it's my privilege to build real sites that people (hopefully) don't hate.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Next.js with MDX tips: Provide shortcuts to article headings]]></title>
            <link>https://mikebifulco.com/posts/mdx-auto-link-headings-with-rehype-slug</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/mdx-auto-link-headings-with-rehype-slug</guid>
            <pubDate>Sun, 02 Jan 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[This tutorial will teach you how to automatically add links to heading tags in your mdx posts on your Next.js site with a plugin called rehype-slug. This should work for most nextJS sites that use MDX for content, as well as many other JavaScript-based sites which use MDX.]]></description>
            <content:encoded><![CDATA[
## Why you should link to headings in your articles

You may have come across this pattern in articles and posts on sites you frequent - article headings (think `<h1>`, `<h2>`, `<h3>`, `<h4>`, `<h5>`, and `<h6>` in html) will be be wrapped in links that point to themselves. This allows readers to link to _specific_ headings in your articles, jumping to relevant bits of content without forcing someone to read through an entire article. Generally speaking, it will look something like this:

```html
<a href="#some-unique-id">
  <h1 id="some-unique-id">My first blog post</h1>
</a>
```

The `<a>` tag here has an `href` value of `#some-unique-id` - this is the id of the heading tag. This is based on an HTML [standard defined by the W3C](https://www.w3.org/TR/html401/struct/links.html#h-12.2.3). In short, you can link to any element on an HTML page which has a unique `id` attribute defined, by appending `#[id]` to the end of the URL, like `www.example.com#id-of-the-element`.

## This is tricky with Markdown and MDX

In most static site generators and JAMStack frameworks which allow you to use Markdown and MDX to generate content, the goal is simple: give authors a _very_ simple way to author content using Markdown syntax. The unfortunate side effect in this case is that there's not a way to specify IDs for the headings in Markdown posts (at least, not one that I'm aware of).

A sample markdown post might look like this:

```md
---
title: Hello, world
---

# A fish called wanda

In this essay, I will explain the difference between...
```

This results in the following output:

```html
<h1>A fish called wanda</h1>
<p>In this essay, I will explain the difference between...</p>
```

Fantastic! That's a nice, easy way to write, but there's not a way to add an id to the heading tag. At least, not out of the box. This is where MDX's plugins come in handy.

## Automatically linking to headings in your mdx posts with rehype plugins

> _Note: This tutorial assumes you're using MDX with NextJS, althought it may be applicable to other systems. Feel free to [send me](https://twitter.com/irreverentmike) any hurdles you encounter with other frameworks, and I'll try to document them here._

### Step 1: Generate IDs for all headings automatically with rehype-slug

[`rehype-slug`](https://github.com/rehypejs/rehype-slug) is a plugin that works with MDX, and will automatically generate IDs for your headings by generating a slug based on the text they contain.

1. Install `rehype-slug` in your project by running `npm install --save rehype-slug` or `yarn add rehype-slug`

2. Add `rehype-slug` to the list of rehype plugins MDX uses. In the case of next.js sites, it is likely wherever you call `serialize()` from `next-mdx-remote`.

```jsx
import rehypeSlug from 'rehype-slug';

// ...

const options = {
  mdxOptions: {
    rehypePlugins: [
      rehypeSlug, // add IDs to any h1-h6 tag that doesn't have one, using a slug made from its text
    ],
  },
};

const mdxSource = await serialize(post.content, options);

// ...
```

**Note:** My site uses `serialize()` in several places, so I extracted `options` to its own file. This avoids repeated code, and allows me to manage my plugins for MDX from one place.

At this point, if you fire up your dev environment, and use your browser devtools to inspect any of the headings generated from markdown for your site, they should all have an `id` property added. For the example above, you'd see:

```html
<h1 id="a-fish-called-wanda">A fish called wanda</h1>
```

We're halfway there - you can now link to `www.example.com#a-fish-called-wanda`, and the browser will automatically scroll to the heading.

### Step 2: use MDXProvider to customize the way heading tags render

[MDXProvider](https://mdxjs.com/docs/using-mdx/#mdx-provider) is a wrapper component which allows you to customize the way your MDX renders by providing a list of `components`.

This step will depend heavily on the UI frameworks you've chosen for your site - I use [Chakra UI](https://chakra-ui.com/) for my nextjs site, but you can use whatever you like - [tailwindcss](https://tailwindcss.com/), [Material UI](https://mui.com/), etc will all have similar parallels.

Here's a simplified version of the code, which I'll show just for `<h1>` - you'd want to extend this for all title tags, i.e. `<h1>` through `<h6>`:

```jsx
import Link from 'next/link';

const CustomH1 = ({ id, ...rest }) => {
  if (id) {
    return (
      <Link href={`#${id}`}>
        <h1 {...rest} />
      </Link>
    );
  }
  return <h1 {...rest} />;
};

const components = {
  h1: CustomH1,
};

// this would also work in pages/_app.js
const Layout = ({ children }) => {
  return <MDXProvider components={components}>{children}</MDXProvider>;
};
```

### Doing it with Chakra UI

Like I mentioned above, my site uses Chakra UI to compose page layouts. I've added a bit of customization to links on my site - including a hover behavior which adds a nice `#` character before headings when they're hovered over. If you're curious about [my implementation](https://github.com/mbifulco/blog/pull/577) with Chakra UI, it looks a bit like this:

```jsx
import NextLink from 'next/link';
import { Heading, Link } from '@chakra-ui/react';

const CustomHeading = ({ as, id, ...props }) => {
  if (id) {
    return (
      <Link href={`#${id}`}>
        <NextLink href={`#${id}`}>
          <Heading
            as={as}
            display="inline"
            id={id}
            lineHeight={'1em'}
            {...props}
            _hover={{
              _before: {
                content: '"#"',
                position: 'relative',
                marginLeft: '-1.2ch',
                paddingRight: '0.2ch',
              },
            }}
          />
        </NextLink>
      </Link>
    );
  }
  return <Heading as={as} {...props} />;
};

const H1 = (props) => <CustomHeading as="h1" {...props} />;
const H2 = (props) => <CustomHeading as="h2" {...props} />;
const H3 = (props) => <CustomHeading as="h3" {...props} />;
const H4 = (props) => <CustomHeading as="h4" {...props} />;
const H5 = (props) => <CustomHeading as="h5" {...props} />;
const H6 = (props) => <CustomHeading as="h6" {...props} />;

const components = {
  h1: H1,
  h2: H2,
  h3: H3,
  h4: H4,
  h5: H5,
  h6: H6,
};

// ...etc - components is passed to MDXProvider in my Layout component
```

## The Result

The result is what you see on [this page](/posts/mdx-auto-link-headings-with-rehype-slug#automatically-linking-to-headings-in-your-mdx-posts), and any of the other posts on my site! Every heading on my markdown pages contains an ID, and is wrapped in a link to itself. This makes it easy for readers to tap on the link to send it to their URL bar, or to right-click/long-press and copy a link to the part of the article they want to link to.

The final markup looks a bit like this:

```html
<a href="#a-fish-called-wanda">
  <h1 id="a-fish-called-wanda">A fish called wanda</h1>
</a>
```

I hope you found this helpful! If you run into any trouble, feel free to [drop me a line on twitter](https://twitter.com/irreverentmike). Beyond that, I'd love it if you shared this post with someone who you think could benefit from it.

## Auto-linking headings with other frameworks

- Generic **HTML and JavaScript** - if you're looking for a platform-agnostic solution, you may want to check out this CSS Tricks Article, [On Adding IDs to Headings](https://css-tricks.com/on-adding-ids-to-headers/)
- **Jekyll** - a reader was kind enough to send me a tutorial for the same functionality in [Jekyll](https://jekyllrb.com/). Check it out on [David Darnes](https://twitter.com/DavidDarnes)' site here: [Adding heading links to your Jekyll blog](https://darn.es/adding-heading-links-to-your-jekyll-blog/)
- **11ty** - There doesn't seem to be a standard practice for this pattern with [11ty](https://11ty.dev/), but there was a great discussion on ways this might be implemented with plugins and shortcodes in this GitHub Issue: [Support generating IDs for headings, for section direct links ](https://github.com/11ty/eleventy/issues/1593)
- **Gatsby** - [Gatsby](https://www.gatsbyjs.org/) has a plugin which supports this behavior, called [gatsby-remark-autolink-headers](https://www.gatsbyjs.com/plugins/gatsby-remark-autolink-headers/)

## More reading

If you found this helpful, you may also be interested in:

- [JavaScript Tips: Nullish Coalescing (??)](https://mikebifulco.com/posts/nullish-coalescing-javascript)
- [JavaScript Tips: Using Array.filter(Boolean)](https://mikebifulco.com/posts/javascript-filter-boolean)
- [MDX: I should have done this sooner](https://mikebifulco.com/posts/moving-to-mdx)
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[No Floating Promises: an eslint rule to prevent async code errors]]></title>
            <link>https://mikebifulco.com/posts/eslint-no-floating-promises</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/eslint-no-floating-promises</guid>
            <pubDate>Sat, 11 Dec 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[The article discusses the ESLint rule no-floating-promises which disallows promises without await. The rule is designed to prevent developers from accidentally forgetting to await promises, which can lead to unexpected behavior.]]></description>
            <content:encoded><![CDATA[
On my past few weekend Twitch streams ([twitch.tv/irreverentmike](https://www.twitch.tv/irreverentmike) by the way) I've been working on a browser-based guitar tuner, to make usre of silly domain name I bought a year or so ago, [guithub.org](https://guithub.org).

Working with Web APIs for Audio is super interesting, and has given me an opportunity to research and learn about lots of great stuff that's built into modern web browsers that I hadn't used much before, like the [Canvas API](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API) and the [Web Audio API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API).

It also requires me to use _lots_ of asynchronous code. Both Web Audio and Canvas require `async` to function, and as a result I've been using a lot of promises in my code. As I write and refactor the code for my pet project, I've found myself running into lots of errors relating to the setup and use of `async` _stuff._

## The basics of async / await in JavaScript

Executing code with `async` / `await` in JavaScript code requires a small amount of setup. At its most basic, it looks like this:

```js
// Functions which use await to execute code must be declared with the "async" keyword
async function foo() {
  return await bar();
}

// written another way
const foo = async () => {
  await bar();
};
```

The `async` keyword is used to adorn the parent function, to let JavaScript know that somewhere inside the function you're going to be `await`ing something from another function call.

The `await` keyword is used to tell JavaScript that the function you're calling on that line is _asynchronous_, and that it will be waiting for something to happen before it can continue.

## What happens when you forget to use `async`

_Both_ of these ingredients are required for `async` / `await` to work, but drastically different things happen if you forget one or the other. If you forget to add `async` - it's very likely that your code won't run at all. Somewhere along the line, the JavaScript interpreter will crash, and tell you that you're trying to use `await` in a function that isn't marked as `async`.

## What is a floating promise?

**A floating promise is an async function that is called without use of the `await` keyword.**

In many cases, if you forget to include `await`, your IDE/linter/interpreter won't fail at all, because you technically haven't done anything wrong. You _can_ call an async function and not wait for it... this essentially creates a `Promise` but doesn't wait for it to resolve or reject. You'll effectively never hear back from it, and it may not even continue to execute.

I'll take an example of what this looks like from the docs page for `eslint-plugin-no-floating-promise`, which you can find on [npm](https://www.npmjs.com/package/eslint-plugin-no-floating-promise) and [GitHub](https://github.com/SebastienGllmt/eslint-plugin-no-floating-promise#readme):

```js
async function writeToDb() {
  // asynchronously write to DB
}
writeToDb(); // <- note we have no await here but probably the user intended to await on this!
```

When `writeToDb()` is called, it's not waiting for anything to happen, and it's not returning a `Promise` to the caller. Instead, the app will continue on its merry way without necessarily throwing any exceptions... and very likely without writing to the database at all.

It gets worse if you're relying on the return value from an async function:

```js
async function createNewRecordInDb(input) {
  // asynchronously create new record in DB;
  let newRecord = await blah(input.name, input.email);

  return newRecord;
}

const entry = createNewRecordInDb({
  name: 'John Doe',
  email: 'foo@bar.com'
);

console.log('welcome to earth a brand new entry', entry)
```

This is a problem, as the code operates assuming you've gotten back a value from a function that's actually still executing. This is called a _floating promise_, and it's a somewhat common mistake to make. It's a promise that is not being used by the rest of the code, so it's not being resolved.

### If you use JavaScript: eslint-plugin-no-floating-promise Saves the day

As mentioned above, the eslint-plugin-no-floating-promise rule is a great way to make sure you don't accidentally forget to use `await` in your async functions. If you're working in JavaScript and your project already uses eslint, adding `eslint-plugin-no-floating-promise` is as easy as adding the plugin to your `.eslintrc` config file:

```json
{
  "plugins": ["no-floating-promise"]
}
```

and then adding the rule to your `rules` object:

```json
{
  "rules": {
    "no-floating-promise/no-floating-promise": 2
  }
}
```

You can see more details in the [docs for eslint-plugin-no-floating-promise](https://www.npmjs.com/package/eslint-plugin-no-floating-promise).

### If you use TypeScript: `@typescript-eslint/no-floating-promises` already exists!

If you're working in TypeScript, there's already a handy solution baked into `@typescript-eslint` - just activate the rule `@typescript-eslint/no-floating-promises` and you're good to go!

```json
{
  /* ... */
  "rules": {
    "@typescript-eslint/no-floating-promises": "error"
  }
}
```

## Conclusion

This is a really great way to protect yourself from an asynchronous programming issue in JavaScript and Typescript that can be extremely frustrating to debug if you're not actively looking for it. While suffering through finding floating promises in your code may be one way to learn about async / await in JavaScript, it's probably not a great use of your time, and setting up a quick lint rule can save you time, frustration, and maybe a broken keyboard or two.

## More Reading

- Interested in learning more about promises? You may enjoy my series on `Promise.allSettled()`:
  - Part 1: [Solve\* all your problems with Promise.allSettled()](https://mikebifulco.com/posts/solve-all-your-problems-with-promise-allsettled)
  - Part 2: [Promise.allSettled() Pt.2 - it's partly settled!](https://mikebifulco.com/posts/promise-all-settled-pt-2-its-partly-settled)

<small>

_Note: The cover image for this post is based on a photo by <a href="https://unsplash.com/@praveentcom?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Praveen Thirumurugan</a> on <a href="https://unsplash.com/s/photos/pool-sign?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>_

</small>
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[How to run dependabot locally on your projects]]></title>
            <link>https://mikebifulco.com/posts/run-dependabot-locally</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/run-dependabot-locally</guid>
            <pubDate>Fri, 10 Dec 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[Since its release, teams around the world have been using dependabot to automate the process of keeping your project's dependencies up to date. In this article, I'll show you how you can run dependabot on the command line using dependabot-core.]]></description>
            <content:encoded><![CDATA[
Dependabot is a fantastically useful tool provided by GitHub to monitor security vulnerabilities in your project's dependencies.

It can be used to automatically create Issues and Pull requests on your projects for security fixes and library updates, which is a great way to keep your project's dependencies up to date.

<Aside type="info">

Note: this is a follow on to my post about [why GitHub's Dependabot is so amazing](https://mikebifulco.com/posts/i-have-to-tell-you-about-dependabot). If you're not yet using Dependabot in your projects, you may want to start there!

</Aside>

Since I published my initial article, one questions I get asked fairly regularly by readers and folks on twitter is: what do I have to do to run Dependabot locally? To be honest, this is not something I had ever considered - and for a while I didn't think it was something you could do. It turns out I was wrong! Running dependabot locally will let you create a custom security management system to automate Pull Requests and Issues for your project's dependencies.

## How to run dependabot locally on your projects

**If you're working on a software development project that has needs which aren't met by Dependabot's built-in automation, you'll be happy to hear that you can customize your dependency automation with [Dependabot Core](https://github.com/dependabot/dependabot-core) and [Dependabot Script](https://github.com/dependabot/dependabot-script). They're designed to be used together to allow you to set up your own Dependabot automations, with options for interactive and non-interactive workflows.**

- [Dependabot Core](https://github.com/dependabot/dependabot-core) contains the main logic that is used to create PRs and Issues with Dependabot. This is where the bulk of the brains for Dependabot's automation is contained, and it's what you'll be using to create your own automation. You will also find Dependabot's public issue tracker within this repo, so if you find yourself running into challenges, you can open an issue there, or search through existing threads to see if anyone else has already run into the same problem as you.
- [Dependabot Script](https://github.com/dependabot/dependabot-script) is a library which contains _sample_ scripts that use Dependabot core. It's a helpful illustration of how to use Dependabot's core to create dependency update automations which suit your needs.

## Setup

1. To get started, clone the [dependabot-script](https://github.com/dependabot/dependabot-script) repo, with `git clone https://github.com/dependabot/dependabot-script.git`
1. Install the repo's dependencies with `rbenv install` (which sets up the correct version of Ruby), followed by `bundle install` (which installs the rest of the dependencies)

## Configure Dependabot Helpers

From here, steps will vary depending on the particulars of your project. There are _helpers_ provided for dependabot-core for Terraform, Python, Go Dep, Go Modules, Elixir, PHP, and JavaScript. The install steps for each of these vary slightly - you should check the [Readme for dependabot-script](https://github.com/dependabot/dependabot-script#native-helpers) for details.

## Familiarize yourself with the default script

Once you're set up, you'll want to look at [update-script.rb](https://github.com/dependabot/dependabot-script/blob/main/update-script.rb) - this contains a fairly generic setup to test for dependencies with dependabot-core. You will need to modify this file to suit your needs.

Look for the [following lines](https://github.com/dependabot/dependabot-script/blob/main/update-script.rb#L17-L23) to customize and set up your credentials:

```rb
# GitHub credentials with write permission to the repo you want to update
# (so that you can create a new branch, commit and pull request).
# If using a private registry it's also possible to add details of that here.
credentials =
  [{
    "type" => "git_source",
    "host" => "github.com",
    "username" => "x-access-token",
    "password" => "a-github-access-token"
  }]
```

Next, specify the name of your repo, the language you want Dependabot to check for updated libraries and security vulnerabilities, and the package manager you use:

```rb
# Name of the dependency you'd like to update. (Alternatively, you could easily
# modify this script to loop through all the dependencies returned by
# `parser.parse`.)
dependency_name = "rails"

# Name of the package manager you'd like to do the update for. Options are:
# - bundler
# - pip (includes pipenv)
# - npm_and_yarn
# - maven
# - gradle
# - cargo
# - hex
# - composer
# - nuget
# - dep
# - go_modules
# - elm
# - submodules
# - docker
# - terraform
package_manager = "npm_and_yarn"

```

## Run the script

You've done all the work needed to run the script, and generate a round of automated updates via PR. Run dependabot-core with your newly customized script with:

```bash
bundle exec irb
```

Follow any prompts on the CLI, and you've done it! Note that there are a couple other ways you might run Dependabot locally, but this is the easiest way to get started. You can check out the other options in the [README.md](https://github.com/dependabot/dependabot-script#running-dependabot) for more details.

## Now customize it!

Once you've got the base script running, check out the [docs for dependabot-core](https://github.com/dependabot/dependabot-core#dependabot-package-manager) to see how to customize it further. For example, you may want to use `FileParser` to list all dependencies for your projects, to keep an eye on changes to OSS Licenses. You might use `MetadataFinder` to look up which of your dependencies are looking for sponsors, so that you can help fund the tools that keep your software running.

## What will you use Dependabot for?

From here, the sky's the limit! If you're someone who is customizing dependabot for a specific need, I'd love to hear what you're doing. Feel free to drop me a line on [twitter @irreverentmike](https://twitter.com/irreverentmike) - I'd love to hear about your project!

## More reading

- GitHub provides a ton of other features and functionality to manage security in your software. You can read more at [github.com/features/security](https://github.com/features/security)
- As mentioned above, this is a follow-up to [my initial article, a primer on Dependabot](https://mikebifulco.com/posts/i-have-to-tell-you-about-dependabot). Feel free to give that a look!
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Hey, influencers: be careful with ChatGPT]]></title>
            <link>https://mikebifulco.com/posts/product-marketing-defy-expectations</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/product-marketing-defy-expectations</guid>
            <pubDate>Mon, 29 Nov 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[Powerful AI tools like ChatGPT make it super easy to generate inaccurate and dangerous and inaccurate content. Relying heavily on AI to write can be messy.]]></description>
            <content:encoded><![CDATA[
One of the most famous ad campaigns in history is Yellow Tail wine's "Crazy Rooster" campaign. **It's so famous because it broke two cardinal rules of advertising:**

1. You don't want to be memorable for the wrong reasons.
2. You don't want to offend your customer base.

What made this campaign so effective was that it didn't just break these rules, but completely shattered them by doing the exact opposite of what conventional wisdom would tell you.

They built their entire brand around being offensive. They were known for making crazy claims like, "Yellow Tail tastes like s\*\*t." They put up billboards in airports saying, "If it wasn't for stupid people, we wouldn't have any customers." And they even used slogans like, "The only thing yellow about Yellow Tail is the color of our piss."  These things wouldn't actually make anybody want to buy Yellow Tail wine… Right?

What they found was that people loved it. And when people love something, they tell other people about it. The end result? A $500 million brand in Australia with no marketing spend. Why? Because they focused on the right things.

**Von Restorff Effect: Bonkers Marketing Campaigns Spawn Successful Brands**

<Colophon />

Ok... so _now..._ this is an important place to take a pause.

<Aside type="warning">

Up to this point, every word you read was written by AI. It's also **completely untrue**.

</Aside>

<Colophon />

I've been playing around with the idea of using AI to generate blog posts for my site, mostly out of curiosity. I wanted to see if AI could produce quality writing content, with the hope of comparing analytics for a few AI-generated articles to some that were written entirely on my own.

There are tools available online which let you feed a couple bullet points into a generator and select the type of writing you're looking for (article, email copy, bulleted lists, etc). You pick a few options and hit go, and in moments you've got some fresh new prose to use for whatever you please.

## Validating the "Crazy Rooster" campaign

After reading the generated article stub above, I wanted to find some images of the marketing campaign mentioned in the text, so off to the search engines I went. This, for me, was a truly jaw-dropping moment: There wasn't a single image I could find which mentions or references the "Crazy Rooster" campaign.

I dug deeper. I soon found that not only were there no images from the campaign, but I couldn't find any references to that ad campaign anywhere. Yellow Tail's site, marketing blogs, search engines, all returned _nothing._ I even searched for smaller fragments of text from the article above, and came back with nothing meaningful.

<Image
  publicId="posts/product-marketing-defy-expectations/crazy-rooster"
  alt="Search results for 'yellow tail crazy rooster' on DuckDuckGo showing nothing relevant"
  caption="A web search for the Crazy Rooster campaign"
/>

As far as I can tell, it never happened. It doesn't exist.

**In other words, AI had written a really compelling article which was _completely and utterly fabricated!_**

What I suspect really happened is this: the information I fed to the algorithm that this particular AI used weaved together partial anecdotes from a large number of publicly available external sources, creating a believable, compelling, yet non-existent story about a real brand's marketing strategy.

That is _fucking_ impressive... and kind of terrifying!

Friends, I'm here to tell you: the AI tools that are available right now can author content which is _shockingly_ good -- but **there is a massively important caveat** that we all need to understand about AI-powered writing:

<Aside type="info">

**Remember:** AI is just _guessing_ at the "Intelligence" part of its job (at least for now).

</Aside>

Can you imagine if I had accepted this as truth, and published it without surrounding context? The only reason I discovered this wasn't true was because I took the time to look up corroborating information - but it would be _super_ easy to skip that step, especially if you don't understand some of the fundamentals of AI.

## What is the Von Restorff Effect?

In principle, the Von Restorff Effect is simple: **given a group of similar choices, people tend to remember experiences or products which defy expectations** - the thing which stands out the most tends to be stickiest, and the more _memorable_ the unexpected experience is, the stickier something will be.

For an extremely simple example, let's say I gave you 10 seconds to memorize as many animals from this list as possible:

<div className="grid grid-cols-3 gap-2 sm:grid-cols-4 md:grid-cols-6">
  <Button className="inline-block">Wolf</Button>
  <Button className="inline-block">Beaver</Button>
  <Button className="inline-block">Camel</Button>
  <Button className="inline-block">Snail</Button>
  <Button className="inline-block">Llama</Button>
  <Button className="inline-block">Pig</Button>
  <Button className="inline-block">Mink</Button>
  <Button className="inline-block">Squirrel</Button>
  <Button className="inline-block bg-orange-500">
    <span>Owl</span>
  </Button>
  <Button className="inline-block">Giraffe</Button>
  <Button className="inline-block">Penguin</Button>
  <Button className="inline-block">Eagle</Button>
  <Button className="inline-block">Moth</Button>
  <Button className="inline-block">Sheep</Button>
  <Button className="inline-block">Camel</Button>
  <Button className="inline-block">Panda</Button>
  <Button className="inline-block">Koala</Button>
  <Button className="inline-block">Chameleon</Button>
</div>

I'd put money any arbitrary person remembering _Owl_ over some of the others mentioned in there.

This phenomenon can also be used to make _products_ more sticky by building _experiences_ which defy expectations - in any marketplace with significant competiton, creating a stand-out experience can give your product a massive advantage.

## How this post came to be

For articles on this site, I keep a list of topics that I think I want to write about in a big list. I slowly add to individual topics over time, and once I feel like there's enough information on a given topic to produce a meaningful article, I spend some time organizing thoughts from the note into prose, and then publish.

To generate this article, I grabbed one of the ideas from that list, which was this _Von Restorff effect,_ which is a [very real psychological phenomenon](https://en.wikipedia.org/wiki/Von_Restorff_effect) that caught my attention some time back.

I fed the topic and a few cliff notes into an AI tool to see what it could generate - really it was just, a few bullet points and the thesis statement for the article. I wanted to talk about how the Von Restorff Effect can be used in product marketing, to create something sticky; something that will be memorable.

And so I fed the tool and I clicked `go`. The article above is what came out of it. What I was really really impressed with initially was the _quality_ of the writing. No grammatical changes were needed, there was a beginning, a middle, and an end, and it put together a super compelling story that served the points I was hoping to make.

In short, I was really impressed... and then absolutely stunned when I realized what happened.

## Learning from this experience

So I came away with this experience with two important learnings:

<Aside type="note">

1. Ironically, **this experience was an amazing example of the Von Restorff Effect** for me. I froze in bewilderment the moment I realized what was going on, thoughts racing through my mind like I had reached the end of _Fight Club_ for the first time. It's a moment I won't soon forget.
2. This is a really important lesson in working with AI, and how powerful it is. If you're not aware of the capabilities _and limits_ of the tools you're using, you are entering dangerous territory.

</Aside>

## The Von Restorff Effect and product marketing

The nugget here for people building products is simple: **if you can create an experience that completely defies expectations, your product will be far stickier with your potential customers.**

## A caveat on AI tools

It's worth noting that I have intentionally omitted the names of the AI tool that led me to this experience. For me, this is because I'm struggling with whether or not it's responsible to point my readers to tools which can easily lead you into a false sense of certainty. _With great power,_ as they say...

Given that most of my audience are developers, I think it should suffice to say that I used a product based on [Open AI's GPT-3](https://openai.com/) - an extremely robust AI tool for generating language.

This is a story that I've struggled to tell because of how important I feel like this is.

I can tell you this much: I certainly won't be writing blog posts with AI any time soon, but I will be periodically checking in on this stuff to see how much better it's getting. I think there's an ethical responsibility to understand the limits and capabilities of AI content creation tools.

## AI and Code Generation with GitHub Copilot

If you're a software developer, you may have come across [GitHub Copilot](https://copilot.github.com/) - billed as "Your AI Pair Programmer", it's a freely available tool which will **generate code for you** with little prompting. You can do as little as writing a few comments, and copilot will generate everything from classes to algorithms to complex patterns login flows and cryptography.

<Image
  publicId="posts/product-marketing-defy-expectations/github-copilot"
  alt="Screenshot from a demo on GitHub Copilot's home page"
  caption="Copilot will write code with you.. for you... and alongside you."
/>

You _should_ really spend some time using Copilot if you haven't already. It's pretty amazing to write a few lines of pseudocode in comments and see what it can generate for you. It feels like magic.

### AI-generated code is still risky

But, just like when using AI to generate writing, be warned: GitHub Copilot isn't perfect - it's pulling from a massive amount of public code, and making guesses based on what you tell it to do. It won't necessarily write the world's most performant code, and in some cases it will generate code with serious flaws. Since its early release as a technical preview, there have been all kinds of problems reported with copilot, including one report which gained attention since it appeared that Copilot was generating code that included (other people's) valid API keys:

<Tweet align="center" tweetLink="pkell7/status/1411058236321681414" />

## A cautionary conclusion

As we introduce AI into more parts of our work and our lives, we need to be aware of the _risks_ of using it. As technologists, there's an ethical responsibility to communicate these risks to our non-techncial neighbors in ways that they can understand. It's my hope that this anecdote about trying to generate a blogpost with AI is something that can serve as a warning which you can explain to your aunt Judy, your boss, or the influencers in your feed who may not seem to understand the risks of using AI.

I'd love it if you shared this post with a friend - and if you've got thoughts on other experiments you'd like to see, let me know! Find me at [@irreverentmike](https://twitter.com/irreverentmike) on twitter, or [@mbifulco](https://github.com/mbifulco) on GitHub.

## More reading

- 📖 If you're interested in learning about AI fundamentals, I recommend reading <a href="https://www.amazon.com/gp/product/0465094279/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0465094279&linkCode=as2&tag=irreverentm02-20&linkId=3b9fba7a06bd067249ef768ce946c146" target="_blank" rel="noopener noreferrer">The Master Algorithm, by Pedro Domingos</a> (Amazon affiliate link). It's a great primer on various types of AI.
- 🎨 If you're into design and usability, check out my thoughts on why [you should never center paragraph text](https://mikebifulco.com/posts/dont-center-paragraph-text)
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Massively speed up VS Code loading time on Apple Silicon Macs in one step]]></title>
            <link>https://mikebifulco.com/posts/make-vs-code-load-faster-mac-apple-silicon</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/make-vs-code-load-faster-mac-apple-silicon</guid>
            <pubDate>Wed, 24 Nov 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[If you're running an Apple Silicon Mac (with an M1, M1 Pro, or M1 Max chip), you may be able to speed up VS Code massively with a quick update.]]></description>
            <content:encoded><![CDATA[
<Aside type="note">

**Note:** This is an update to my recent post, [How to make VS Code load faster with a little bit of housekeeping](https://mikebifulco.com/posts/make-vs-code-load-faster-by-removing-extensions).
I was pretty happy with the startup speed I gained by removing a few
extensions, but VS Code still took a while to load.

</Aside>

Yesterday I stumbled on something that let me **load VS Code 775% faster** than before on my Mac laptop. Seriously. On a cold boot of VS Code, my load time went from 15 seconds to just about 2 seconds. So, how did I do it? Let's cut to the chase:

## The Solution

**If you are running Visual Studio Code on a Mac with an Apple Silicon processor (also known as an M1, M1 Pro, or M1 Max), you will get a _massive_ performance boost by installing an Apple Silicon optimized build of VS Code.**

This is because previous builds weren't natively compatible with Apple Silicon, and ran Intel code through a virtualization process that apple calls Rosetta.

The fix: **Download the [latest version of VS Code](https://code.visualstudio.com/download) for Mac, install it.** If you were previously running an Intel build, this is _all_ you need to do. That's it!

## What's going on here

In 2019, Apple released their first round of computers that run on their own processors, which they call Apple Silicon. These chips are fundamentally different from the Intel processors that Apple was using on all of their computers until recently. Apple found massive performance benefits from their migration to a new chipset, but running software on the new processor architecture requires app developers to recompile their software for the new chips.

Thankfully, engineers at Apple were smart enough to know that asking every Mac app developer in the world to recompile their apps for Apple Silicon will take a very long time. To hedge against this, they built a recompilation layer into MacOS called _Rosetta,_ which allows Intel apps to run on the new chips. Because there's essentially a thin VM layer running these apps, they are slower and less energy efficient than apps compiled specifically for Apple Silicon.

That's exactly the gain we're finding here by updating VS Code. There wasn't an Apple Silicon build available until [September of 2020](https://github.com/microsoft/vscode/issues/101662), due to VS Code's dependency on Electron to run.

If this quick fix helps you and you're like me, you likely installed Code long before September of 2020. Your install of Code would get regular updates, but you were getting Intel builds of the app. Switching to a more recently downloaded version of the app will automatically install an Apple Silicon build, and just like that, you're sorted! 🧙‍♂️

## Check to see if you're running an Intel version of VS Code

In the process of figuring all of this out, I discovered that you can actually see which apps on your machine are running Intel builds vs Apple Silicon Builds.

To check any given app, follow these steps:

1. Open **Activity Monitor** (hit command + Space, and type in "Activity monitor")
2. Right click on one of the _headings_ at the top of the table of running processes, to see a list of possible columns for the table.
3. Make sure the option called **Kind** is checked
4. You'll now see a column labeled "Kind", which will say "Apple" or "Intel"

<Image
  publicId="posts/make-vs-code-load-faster-mac-apple-silicon/kind-column"
  caption="The 'Kind' column in Activity Monitor tells you which processor architecture every app is built to run against"
  alt="Screenshot of Activity Monitor, with the 'Kind' column added"
/>

If you're running an Intel version of VS Code, you'll see something like this:

<Image
  publicId="posts/make-vs-code-load-faster-mac-apple-silicon/intel-build"
  caption="The 'Kind' column will say Intel - and I bet your load times for VS Code could be much better."
  alt="Screenshot of Activity Monitor, with the Visual Studio Code row highlighted, and the 'Kind' column showing 'Intel'"
/>

If that's the case, I have great news! You're probably going to see a massive speed boost. This is a good time to close VS Code and time how long it takes to start fresh. On my M1 Macbook Air with 16GB of ram, it took about 15s.

Now, go **Download the [latest version of VS Code](https://code.visualstudio.com/download) for Mac** and install it on your computer (Choose to "Replace" the old install if prompted).

When that's done, you should see this the next time you load VS Code:

<Image
  publicId="posts/make-vs-code-load-faster-mac-apple-silicon/apple-build"
  caption="The 'Kind' column will say Apple"
  alt="Screenshot of Activity Monitor, with the Visual Studio Code row highlighted, and the 'Kind' column showing 'Intel'"
/>

How was that load time now? For me, it was down to _about 2 seconds!_ It's not every day you get those kind of gains.

## If you found this helpful, you may want to check out:

- **[How to make VS Code load faster with a little bit of housekeeping](https://mikebifulco.com/posts/make-vs-code-load-faster-by-removing-extensions)**, my previous post on speeding up VS Code
- **[I reclaimed 10GB of disk space from `node_modules`](https://mikebifulco.com/posts/reclaimed-10gb-of-disk-space-from-node-modules)** if you also happen to use Node to write JavaScript apps.
- **[gitignore.io is great](https://mikebifulco.com/posts/gitignore-io-is-great)** for a tip on a super helpful tool for setting up `.gitignore` files on new projects.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Learn to build web3 apps on the blockchain with Buildspace]]></title>
            <link>https://mikebifulco.com/posts/learn-web3-blockchain-with-buildspace</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/learn-web3-blockchain-with-buildspace</guid>
            <pubDate>Mon, 22 Nov 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[Buildspace offers free, online, cohort-based courses on building web3 blockchain apps. If you're interested in dipping your toe into the world of Ethereum apps, the blockchain, or NFTs - it's a great starting point.]]></description>
            <content:encoded><![CDATA[
As I write this post, I'm working through taking my second course on [Buildspace](https://buildspace.so/). It's been a unique learning experience that's helped me get my hands dirty with technologies that I was only _vaguely_ familiar with before, and I really think you should consider giving it a shot.

**Buildspace offers free, online, cohort-based courses on building web3 blockchain apps. Each course starts with a live-streamed kickoff, with an instructor and cohort of learners taking the course with you. From there, you're welcome to take things at your own pace. If you complete a course within a week, you're issued a certificate in the form of an NFT which is yours forever.**

After you create an account and enroll in a course Buildspace, you'll need to do two things before the live kickoff for your particular course: connect an ethereum wallet (which is used to verify that you're completing coursework, and to issue your course certificate NFT), and link your Discord account. You'll use Discord to chat with fellow students during the course, and to ask instructors for help.

<Aside type="note">

After completing a course successfully, you'll be given _alumni_ permissions, which grants you access to a host of other channels, including channels where companies post job opportunities for web3 developers. How's that for a benefit of a free online course? 🎉

</Aside>

## Buildspace is **free**

That brings me to my next point - buildspace is _FREE_. Free, free. They even plaster it on their homepage:

<Image
  publicId="posts/learn-web3-blockchain-with-buildspace/it-is-free"
  alt="screenshot of Buildspace's price: free!"
  caption="Don't take my word for it... it's free!"
/>

## Cohort-based learning is exciting

All of Buildspace's courses are run with a learning cohort: this is a group of people who all start a given course at the _same_ time. For me, this had an incredibly energizing effect: jumping into a course livestream with dozens-to-hundreds of other people who are all excited to learn _this thing, right now_ is really magical. It got me hyped to participate, and excited about learning with other people.

You'll find yourself chatting with classmates in Discord to help them along, or debug problems that you're having in real time. This is truly something special, particularly for courses like this which are really more-than-a-little-technical. I feel at least somewhat qualified to weigh in on this experience, too - I spent 7 years working as technical director for [Gymnasium](https://thegymnasium.com/), another free, online code school which offers fully self-paced courses for creatives who want to learn to build for the web.

There are also regular _coworking_ sessions, which work a whole lot like the live kickoff - at a scheduled time, you'll hop onto Discord and join a room with a group of people who are progressing through the course you're working on. You can chat with each other in there, or use the time as quiet, dedicated studying time - whatever works best for you.

<Image
  publicId="posts/learn-web3-blockchain-with-buildspace/just-a-few-steps"
  alt="Screenshot of buildspace's coworking directions"
  caption="The landing page for Buildspace's courseware."
/>

## What have I built?

Like I mentioned above, I'm currently working through my second course.

The first course I took was called **Build a Web3 App with Solidity + Ethereum Smart Contracts.** In this course, I learned about developing apps for the Ethereum blockchain using a library called Solidity. From start to finish, the course took me about 5 hours of dedicated effort (your results will definitely vary based on your experience with related tools and technology). I learned how to bootstrap a blockchain app, and the general loop of the blockchain development experience, including deploying my app to a test network. The course encourages you to explore and get creative along the way, so I ended up adding some functionality to my blockchain app here and there to get a little more experience with Solidity.

For completing this course within a week, I earned a certificate. My certificate lives on the blockchain, of course, by way of an NFT... this is honestly the first _compelling_ use of NFTs I've seen anywhere. What does it look like? Here you go:

<Image
  publicId="posts/learn-web3-blockchain-with-buildspace/course-cert-nft"
  alt="Screencap of my course certificate NFT on Opensea.io"
  caption="The certificate lives on the blockchain, where information about me copleting the course will securely remain. This is what it looks like on Opensea's viewer."
/>

I'm currently working through a course called **Mint your own NFT collection and ship a Web3 app to show them off** - just like it says on the tin, the idea here is to learn about building apps that produce NFTs. I'm about 25% of the way through this course, and expect to finish it this week.

## Is this for everyone?

Well, no, not really - but that's okay! These are fairly involved techncial courses, and they do require a bit of previous experience building software. You'll be most comfortable if you've built things for the web before using JavaScript, Node, React, etc. If those aren't your jam, I'd imagine even PHP, Python, and Ruby devs will have a reasonably easy time with this stuff &mdash; and maybe even mobile developers, too. If you're _brand new_ to building software, you might find some of the tools and topics extremely challenging. There's a risk that you might be discouraged given an experience like that. For that reason, I'd suggest taking some basic intro courses to building with HTML,CSS, and JavaScript, and maybe dipping a toe into the world of making apps with React first.

You may also have some real hesitations about the climate impact of blockchain technologies. I absolutely do - my guidance here is to do what you feel is right. I'm a strong proponent of learning new tech, even with climate worries. It's clear to methat this stuff is here to stay in some form or another, and the more climate-aware devs we have thinking about the blockchain, the better chance we have of creating innovations in crypto that aren't going to cook the planet.

## Why should you do it?

While I'll admit that I'm still _fully_ unconvinced of the value of creating and selling shiny jpegs on the blockchain, I _do_ think there's serious value in understanding how the blockchain works, and getting to know what the heck is going on in the world of cryptocurrency. There's massive amounts of the world economy moving through currencies on various blockchains right now, and any amount of literacy you can build for this world _will_ benefit you.

I also think it's a critically important skill to be able to learn new things regularly. It keeps your mind sharp, and can help you find new career opportunities in some very in-demand jobs. I'm also on a career path where part of my job is teaching people how to build things for a living. Everyone has a slightly different learning style, and I've found that cohort-based courses are a really great way for me to get some intense, quick learning done. I enjoy the camaraderie that is built into the live-kickoff and cohort-based course experience, and I really love helping other people pick up new skills.

<Aside type="note">

**If you're on the fence, here's the thing: go try it. Take a course!**

</Aside>

Courses on [Buildspace](https://buildspace.so/) are literally free - there's no cost to you to give it a shot, and you may learn a thing or two along the way. The team behind Buildspace are energetic, positive, and uplifting, and I've genuinely enjoyed learning from them, and watching them build their school out in the open.

I'm excited to finish this course, and will certainly be keeping an eye out for more in the future.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Some things I learned from live coding on Twitch]]></title>
            <link>https://mikebifulco.com/posts/twitch-streaming-software-development-lessons</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/twitch-streaming-software-development-lessons</guid>
            <pubDate>Thu, 18 Nov 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[For years I did a weekly coding livestream of my React and Python work on Twitch every week, and I'm getting back into it again. This is what sticks out to me as the most valuable learnings from those experiences.]]></description>
            <content:encoded><![CDATA[
Recently, I've been getting back into live coding on the weekend. I didn't realize how much I missed it.

I worked as Technical Director for an online code school (aka'd as a MOOC, for Massively Online Open Course) called thegymnasium.com from 2014-2020, and during that time, I did a weekly livestream of my work on twitch [twitch.tv/irreverentmike](https://www.twitch.tv/irreverentmike) just about every week for 2-4 hours. It's something I was able to do because everything Gymnasium does is Open Source - you can peruse the source code that powers [Gymnasium on Github](https://github.com/gymnasium).

<Image
  publicId="posts/twitch-streaming-software-development-lessons/livestreaming"
  alt="Screenshot of a livestream - VS Code window open with an overlay of me on camera in the upper right"
  caption="Writing up a GitHub Issue on a recent livestream"
/>

My intention with the livestream was to share my Open Source work on Gymnasium with the world - the easy parts, the hard parts, and everything in between. Depending on the week, I'd be working in VS Code, updating the Python code that Gymnasium ran on, or building front-end components in [React](https://mikebifulco.com/tags/react), or working in Sketch on designs with our extremely talented designer.

It was a fantastic experience, and a great way to connect with Gymnasium's growing audience of thousands of learners around the world. Importantly, it was also a growth opportunity for me - streaming to a live audience gave me an opportunity to connect with and help people from all over. I got to explain complex development topics to learners in simple terms, and let them see what it's _really_ like for a professional developer to break things in real time.

## Lessons learned from live coding

Over the years, I started to notice some of the benefits that my stream provided that aren't obvious at first blush:

1. **Sharing bumps and bruises is a superpower** - Traditional online tutorials often only show the happy path for developers using a tool or implementing a new feature. This leaves students at a significant disadvantage if they have to figure out how to debug something. In live coding, I was _breaking things_ left-and-right, while forcing myself to talk through my debug process, with all my bumps and bruises shown to the world. Time and time again I got feedback from my audience that this was the most valuable part of watching me - seeing how to research/recover/resolve when things go wrong. It's a hard skill to learn on your own, and it's honestly easy to forget that I have years and years of experience un-breaking my own code in various capacities.
2. **Explaining yourself has reflective benefits** - Slowing down and explaining what I was doing and why will really changed the way I work. For me, it caused me to think more deliberately through solutions, and often helped me land the foresight to deploy a better solution more quickly. It's a bit like the benefits of Paired Programming - explaining what you're doing to _someone_ else means that you have to speak your intentions aloud. More often than not, that ends up being a great way to hear yourself explaining flawed ideas. You should give it a shot sometime.
3. **You'll call out your own faults** - This process of slowing down also helped me document my work more thoroughly - when I found myself spending lots of time explaining a complicated solution, workarounds, or strange tricks I'd used, it was a good indicator that the _thing_ I was working on should either (a) have numerous comments in my code to explain the madness within, or (b) that it should be marked as something to later revisit, with occam's razor.

<br />

## So yeah, I'm back at it again...

I recently started streaming again on the weekends - this time it's not the work I'm doing in my day-to-day at Google, but instead my personal projects which are all OSS. It's a great way to get back into coding for enjoyment, and to force myself to deliver results... I can crank out 2-3 hours of really good work when I'm on stream without getting (too) distracted. If you want to catch some of that, you can find me on twitch at https://www.twitch.tv/irreverentmike
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[JavaScript Tips: Nullish Coalescing (??)]]></title>
            <link>https://mikebifulco.com/posts/nullish-coalescing-javascript</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/nullish-coalescing-javascript</guid>
            <pubDate>Mon, 15 Nov 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[Let's take a look at the Nullish Coalescing operator (??) in JavaScript, which returns the right operand if the left is null or undefined.]]></description>
            <content:encoded><![CDATA[
## What does the Nullish Coalescing (`??`) operator do in JavaScript?

JavaScript's Nullish Coalescing operator is two question mark characters next to one another (`??`). It takes a left-hand and right-hand operand, returning the right value _if_ the left is `null` or `undefined`. Otherwise, it returns the left value.

```js
let x;

x = 1 ?? 100; // 1
x = null ?? 100; // 100
x = undefined ?? 100; // 100

x = 'Peas' ?? 'Carrots'; // Peas
x = null ?? 'Carrots'; // Carrots
x = undefined ?? 'Carrots'; // Carrots
```

Note that unlike [using Boolean on array.filter()](https://mikebifulco.com/posts/javascript-filter-boolean), there _aren't_ special cases to consider here for _truthy_ or _falsy_ values in Javascript. Nullish Coalescing _only_ returns the right value for `Null` and `undefined`, and not for `false` and some other cases, like:

```js
let y;

y = -1 ?? 2; // -1
y = false ?? 2; // false

y = true ?? 2; // true
y = NaN ?? 2; // NaN
y = Infinity ?? 2; // Infinity
y = -Infinity ?? 2; // -Infinity

y = new Date() ?? 'soon'; // [the date object created by new Date()]
```

## Use Nullish Coalescing in React Components

This can be used to simplify what has become a fairly common pattern in React components - checking whether a value is present before rendering it, and providing a fallback if not:

```jsx
// use a ternary operator
const LetterIntro = ({ name }) => {
  return <div>Hi {name ? name : 'there'},</div>;
};

const BetterLetterIntro = ({ name }) => {
  return <div>Hi {name ?? 'there'}</div>;
};
```

Both of these are _valid_ syntax, but you might argue that the latter is easier to read, so long as you understand what the `??` operator is doing.

## Make sure to check compatibility on your project

Nullish coalescing is quickly becoming available for use in browsers and JavaScript / Node / Deno, but you should make sure that the project you're working on is using a compatible version of the language before you start to add `??` to all your code.

## Compatibility with Node and Deno

To ensure compatibility with Node, your project must be using **Node version 14.0.0** or later.

To ensure compatibility with Deno, you rproject must be using **Deno version 1.0.0** or later.

## Compatibility with modern browsers

Another thing to condier - as of the writing of this article, Nullish Coalescing isn't available in every web browser quite yet - Internet Explorer and Opera for Android are the two remaining holdouts. I'll leave it to you to decide whether or not that's a showstopper for you - and I don't know if I'd expect to see support in IE _ever_ given its [end-of-life](https://docs.microsoft.com/en-us/lifecycle/announcements/internet-explorer-11-end-of-support) announcement in mid 2021.

<picture>
  <source
    type="image/webp"
    srcSet="https://caniuse.bitsofco.de/static/v1/mdn-javascript__operators__nullish_coalescing-1636908973156.webp"
  />
  <source
    type="image/png"
    srcSet="https://caniuse.bitsofco.de/static/v1/mdn-javascript__operators__nullish_coalescing-1636908973156.png"
  />
  <img
    src="https://caniuse.bitsofco.de/static/v1/mdn-javascript__operators__nullish_coalescing-1636908973156.jpg"
    alt="Data on support for the mdn-javascript__operators__nullish_coalescing feature across the major browsers from caniuse.com"
  />
</picture>

## More on Nullish Coalescing

My pal Alexander Karan put together a similar tutorial about [The Nullish Coalescing Operator](https://blog.alexanderkaran.com/nullish-coalescing-operator) on his site. It's worth a read - he's a one heck of a smart developer.

## Additional Reading

If you found this useful, you might also want to check out these other articles:

- [Using array.filter(Boolean)](https://mikebifulco.com/posts/javascript-filter-boolean)
- A primer on [deconstructructing objects in JavaScript](https://mikebifulco.com/posts/deconfusing-javascript-destructuring-syntax)
- [Understanding import syntax in Node](https://mikebifulco.com/posts/picking-apart-javascript-import)
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[JavaScript Tips: Using Array.filter(Boolean)]]></title>
            <link>https://mikebifulco.com/posts/javascript-filter-boolean</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/javascript-filter-boolean</guid>
            <pubDate>Fri, 12 Nov 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[If you come across array.filter(Boolean) in JavaScript code, never fear! It's a handy bit of functional programming that cleans up arrays with null and undefined values in them.]]></description>
            <content:encoded><![CDATA[
## What does .filter(Boolean) do on Arrays?

This is a pattern I've been coming across quite a bit lately in JavaScript code, and can be extremely helpful once you understand what's going on. In short, it's a bit of [functional programming](https://mikebifulco.com/tags/functional-programming) which is used to remove `null` and `undefined` values from an array.

```js
const values = [1, 2, 3, 4, null, 5, 6, 7, undefined];

console.log(values.length);
// Output: 9

console.log(values.filter(Boolean).length);
// Output: 7

// note that this does not mutate the value original array
console.log(values.length);
// Output: 9
```

## How does the Boolean part of .filter(Boolean) work?

We're using a function built into arrays in JavaScript, called [Array.prototype.filter](https://developer.mozilla.org/en-US/docs/web/javascript/reference/global_objects/array/filter), which _creates a new array_ containing all elements that pass the check within the function it takes as an argument. In this case, we're using the JavaScript `Boolean` object wrapper's constructor as that testing function.

`Boolean` is a helper class in JavaScript which can be used to test whether a given value or expression evaluates to `true` or `false`. There's a subtle, but **really important point** here - `Boolean()` follows the JavaScript rules of _truthiness_. That means that the output `Boolean()` might not always be what you imagine.

In this context, passing `Boolean` to `.filter` is effectively shorthand for doing this:

```js
array.filter((item) => {
  return Boolean(item);
});
```

which is also approximately the same as

```js
array.filter((item) => {
  return !!item; // evaluate whether item is truthy
});
```

or, simplified

```js
array.filter((item) => !!item);
```

I suspect that you may have seen at least one of these variations before. In the end, `array.filter(Boolean)` is just shorthand for any of the other options above. It's the kind of thing that can cause even seasoned programmers to recoil in horror the first time they see it. Near as I can tell, though, it's a perfectly fine replacement.

### Examples of Boolean evaluating for _truthiness_

```js
// straightforward boolean
Boolean(true); // true
Boolean(false); // false

// null/undefined
Boolean(null); // false
Boolean(undefined); // false

// hmm...
Boolean(NaN); // false
Boolean(0); // false
Boolean(-0); // false
Boolean(-1); // true

// empty strings vs blank strings
Boolean(''); // false
Boolean(' '); // true

// empty objects
Boolean([]); // true
Boolean({}); // true

// Date is just an object
Boolean(new Date()); // true

// oh god
Boolean('false'); // true
Boolean('Or any string, really'); // true
Boolean('The blog of Mike Bifulco'); // true
```

## Warning: Be careful with the truth(y)

So - `someArray.filter(Boolean)` is really helpful for removing `null` and `undefined` values, but it's important to bear in mind that there are quite a few confusing cases above... this trick will remove items with a value of `0` from your array! That can be a significant difference for interfaces where displaying a `0` is perfectly fine.

**EDIT: ** Hi, Mike from The Future™️ here - I've edited the next paragraph to reflect the _actual_ truth... I had confused `-1` with `false` from my days as a BASIC programmer, where we'd sometimes create infinite loops with `while (-1)`... but even that means "while `true`"!

I also want to call some attention to cases that evaluate to `-1`. <s>for _many_ programmers, `-1` is synonymous with `false`, because that is _absolutely_ the case in many langauges... but not here.</s> The `-1` case can also be unintuitive if you're not expecting it, but true to form, in JavaScript, `-1` is a truthy value!

## Array.filter(Boolean) For React Developers

I tend to come across this pattern being used fairly often for iterating over collections in React, to clean up an input array which may have had results removed from it upstream for some reason. This protects you from scary errors like `Can't read property foo of undefined` or `Can't read property bar of null`:

```jsx

const people = [
  {
    name: 'Mike Bifulco',
    email: 'hello@mikebifulco.com',
  },
  null,
  null,
  null,
  {
    name: "Jimi Hendrix",
    email: 'jimi@heyjimihimi@guitarsolo',
  }
]

// display a list of people
const PeopleList = ({people}) => {
  return (
    <ul>
      {people.map(person) => {
        // this will crash if there's a null/undefined in the list!
        return (
          <li>{person.name}: {person.email}</li>
        );
      }}
    </ul>
  );
}

// a safer implementation
const SaferPeopleList = ({people}) => {
  return (
    <ul>
      {people
        .filter(Boolean) // this _one weird trick!_
        .map(person) => {
          return (
            <li>{person.name}: {person.email}</li>
          );
        }
      }
    </ul>
  );
}
```

## Functional Programming reminder

Like I mentioned above, this is a handy bit of functional programming -- as is the case with nearly all clever bits of functional programming, it's important to remember that we're not _mutating_ any arrays here - we are creating new ones. Let's show what that means in a quick example:

```js
const myPets = [
  'Leo',
  'Hamilton',
  null,
  'Jet',
  'Pepper',
  'Otis',
  undefined,
  'Iona',
];

console.log(myPets.length); // 8

myPets
  .filter(Boolean) // filter null and undefined
  .forEach((pet) => {
    console.log(pet); // prints all pet names once, no null or undefined present
  });

console.log(myPets.length); // still 8! filter _does not mutate the original array_
```

## Wrapping up

Hopefully this has helped to demystify this little code pattern a bit. What do you think? Is this something you'll use in your projects? Are there dangers/tricks/cases I didn't consider here?

Tell me all about it on twitter <a href="https://twitter.com/irreverentmike">@irreverentmike</a>. Thanks for reading!

_note: Cover photo for this article is from <a href="https://unsplash.com/@pawel_czerwinski?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Pawel Czerwinski</a> on <a href="https://unsplash.com/s/photos/array?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>_
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[How to make VS Code load faster with a little bit of housekeeping]]></title>
            <link>https://mikebifulco.com/posts/make-vs-code-load-faster-by-removing-extensions</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/make-vs-code-load-faster-by-removing-extensions</guid>
            <pubDate>Sun, 07 Nov 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[Have you noticed that your favorite IDE has been slow to load lately? Try removing these before losing hope.]]></description>
            <content:encoded><![CDATA[
<Aside type="info">

**🚨Update: 11-24-2021🚨**

If you're looking to speed up VS Code and you're _also_ using a Mac with an Apple Silicon Chip (an M1, M1 Pro, or M1 Max), you should read this article first: **[Massively speed up VS Code loading time on Apple Silicon Macs in one step](https://mikebifulco.com/posts/make-vs-code-load-faster-mac-apple-silicon).**

The tips in this article are still perfectly valid, but you'll see much, much better gains from the new tip. Come back here after you've done that.

</Aside>

If you're a user of Visual Studio Code, you may find that over time it feels like new IDE windows are slow to load. In my experience, loading an environment from a cold start (firing up VS Code when it isn't running at all), or opening a window for a new project (`File >> New Window`) when Code is already running tend to take about the same amount of time.

This is notably different from opening a new tab within the IDE - again, in my experience, once Code is up and running, new tabs take almost no time to fire up.

## Why is it slow?

In its most basic form VS Code is fairly performant - a fresh install of the IDE opens very quickly. Over time, if you're anything like me, you've probably installed any number of community-built [extensions from the VS Code Marketplace](https://marketplace.visualstudio.com/VSCode)

## The Solution

Well, the good news is that this one is exactly as easy as it sounds - you can gain quite a bit of startup performance by **removing unused and unnecessary extensions from VS Code**, by opening your Extensions pane (`Shift + command + X` on a mac, likely `control + shift + X` on Windows/Linux), and typing `@installed` into the search bar at the top of the list to see which extensions are currently installed. In my case, it looks like this:

<Image
  publicId="posts/make-vs-code-load-faster-by-removing-extensions/vscode-extensions-pane"
  alt="VS Code Extensions pane highlighted in red"
  caption="My installed extensions pane, highlighted in red"
/>

Extensions with particularly long load times will have their "Activation Time" highlighted in this list. It's currently shown in the upper-right corner of the extension list item with a load time in milliseconds listed next to it:

<Image
  publicId="posts/make-vs-code-load-faster-by-removing-extensions/extension-load-time"
  alt="VS Code Extensions pane highlighted in red"
  caption="My installed extensions pane, highlighted in red"
/>

## How to remove extensions with long activation times from Visual Studio Code

1. Scan through your list of installed extensions, and remove any you don't use
2. If there are remaining extensions which have high activation times listed, consider whether there's better options available (and install those!)
3. If there aren't better options available, you'll either need to live with the load time for a given extension, or choose to bid it farewell. Worth noting here: these extensions are (generally) open-source, so you may want to visit the repo for that extension and [search for "activation time"](https://github.com/prettier/prettier-vscode/issues?q=activation+time) to see if anyone else is running into the same problem. If not, you might want to open an issue and let the maintainers of that extension know you're having trouble, or open a PR if you have a solution to offer up.

...and that should do ya! If you're still running into performance issues after this, it could be any number of things. Are you running out of disk space on your computer? Maybe you're running out of available RAM? Are you running other applications that slow your machine down?

Additionally, if you're a JavaScript or Node app developer, you may want to check out my article on [Reclaiming Disk Space from `node_modules`](https://mikebifulco.com/posts/reclaimed-10gb-of-disk-space-from-node-modules).

I hope this helps! Feel free to share it with a friend if you found it useful.

This post was inspired by a tweet I let fly recently after playing with load times in [Visual Studio Code](https://code.visualstudio.com/):

<Tweet
  tweetLink="https://twitter.com/irreverentmike/status/1454054616027574283"
  align="center"
/>

_note: Cover photo for this article is from by <a href="https://unsplash.com/@loic?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Djim Loic</a> on <a href="https://unsplash.com/s/photos/time?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>._
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Don't center align paragraph text]]></title>
            <link>https://mikebifulco.com/posts/dont-center-paragraph-text</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/dont-center-paragraph-text</guid>
            <pubDate>Sat, 10 Apr 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[Stop using centered text. It's bad for usability, accessibility, and eye scanning -- and nobody anywhere wants to read like that.]]></description>
            <content:encoded><![CDATA[
import CenteredTextDemo from '../../components/demos/CenteredTextDemo';

<Aside type="note">

This is an experimental post, meant to demonstrate to you the topic we're discussing. I'd love to hear what you think about it. [Drop me a line](https://twitter.com/irreverentmike) if you find this compelling - I'm hoping to create more like it!

</Aside>

<CenteredTextDemo>

This is -- without exception -- my biggest design-related pet peeve. You've probably come across it yourself from time to time, and if you're lucky, it's not something you noticed. Centering text on a web site, email, or flyer is an easy way to make it appear like a designer's spin has been put on a document. It's an easy change to make in most editors, and in many cases it's probably done without a second thought.

I'll cut to the chase: _center-aligning text is really bad_ in most cases. From a young age, we're trained to read text by starting at the beginning of the line and moving our eyes across the page to the end of the line. From there, it's a relatively low-effort thing to move your eyes back to the beginning of the next line. That all changes when text is centered, since the start of each line is aligned inconsistently. It takes more effort to find the beginning of the next line, to make sure you've only moved down _one_ line, and to continue reading.

## Three great reasons you shouldn't center-align text:

1. A ragged leading-edge makes it harder to move your eyes to the next line of text
2. People with dyslexia may find centered text challenging to read.
3. Lists (like this one) become disorienting to read, and harder to scan

The British Dyslexia Association provides a <a href="https://www.bdadyslexia.org.uk/advice/employers/creating-a-dyslexia-friendly-workplace/dyslexia-friendly-style-guide" target="_blank">dyslexia-friendly style guide</a>, which calls out a simple rule for text:

<Aside type="note">Left align text, without justification.</Aside>

As a designer, this is _such_ an easy win. As a developer, it's often as easy as:

```css
/* change this */
.some-style-rule {
  text-align: center;
}

/* ...to this! */
.some-style-rule {
  text-align: initial;
}
```

## When you _can_ use centered-text

Generally speaking, if you're certain that your text will fit on _one line,_ it may be okay to center it. This generally applies to page titles, captions on pictures, and things of that nature. Even then, generally speaking my guidance is to avoid it. Like many other things in design, if there's not a good reason _to_ do it... you're better without.

## Summary

If you're working on a design that relies on centered text, consider other options. If you come across a big blob of centered text in your workplace, or out in the world somewhere, please feel free to use this post as a demo.

</CenteredTextDemo>
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Book notes: Working In Public]]></title>
            <link>https://mikebifulco.com/posts/working-in-public</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/working-in-public</guid>
            <pubDate>Mon, 30 Nov 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[My review of Working in Public: The Making and Maintenance of Open Source Software by Nadia Eghbal]]></description>
            <content:encoded><![CDATA[
I recently finished reading _Working in Public: The Making and Maintenance of Open Source Software_ by [Nadia Eghbal](https://nadiaeghbal.com/), thanks to a book club organized by [Chris Traganos](https://twitter.com/chris_trag) at [Stripe](https://press.stripe.com/). While I can't say this is a book I would have found my way to own my own, I found myself tearing through it far more quickly than I would have guessed. I'd fully recommend giving it a read - you can pick it up on [Amazon](https://smile.amazon.com/Working-Public-Making-Maintenance-Software/dp/0578675862).

Below is a pretty raw copy/paste of my notes on _Working in Public_, which I take in Roam Research as I read. If you'd like to discuss any of this with me, drop me a line on [twitter @irreverentmike](https://twitter.com/irreverentmike).

**Notes on _Working in Public_**

# Part 1

## Chapter 2: The Structure of an Open Source Project

- &#8203;
  <Highlight>
    Developers don't contribute to open source for lack of technical ability,
    but rather due to fear of committing a faux pas
  </Highlight>
  - There's a huge hurdle to get over here, particularly for new contributors.
  Even sending a very small PR or opening an issue has a mental tax associated
  with it that can prevent progress, community from being built
- &#8203;

  <Highlight>
    The process of getting a change approved depends, among other things, on the
    **complexity** of the change (and the complexity of the project), as well as
    one's **reputation** among those with the ability to approve the change.
  </Highlight>
  - Reputation is a tricky currency, particularly when some folks build clout by
  being funny / sarcastic to gain viral notoriety. This doesn't necessarily
  equate to value to the community or trustworthiness, but often can be parlayed
  into exactly that.

- &#8203;

  <Highlight>
    If a project's contributor base is growing rapidly, and there is enough work
    to hand off, maintainers may start to distribute work more widely. In a
    **distributed** state, maintainers actively recruit more contributors to
    pitch in, with the goal of retaining them in the project.
  </Highlight>
  - At some point, the success of a project causes a requirement for a shift in
  operations - from building the thing to **supporting** it, and recruiting
  community members to help get things done on either end of that. Teams'
  ability to make that pivot is critical to success.

- &#8203;

  <Highlight>Healthy open source (re: node.js contribution policy)</Highlight>-
  Design a contribution policy and code of conduct which entices contributors
  **and** retains them. Based on my experience, this is the magic in getting
  something over the hump from being fledgling to more broadly successful.

## Chapter 3: Roles, incentives, and relationships

- Open source developers were frequently characterized as "hobby" devlopers
  - Hm! TIL.
- A theory of the commons
  - In the last half of the 1900s, economist Elinor Ostrom came up with an 8-part theory to what makes up a successful "Commons", or resource that is owned, used, and managed by a community. These rules outline the basic tenets of what makes a successful commons, and apply directly to successful OSS in many ways.
  - Making sure members are biased toward **working together** is a key to success. This may mean distributing knowledge and capability so that everyone has value and meaning, and no one person can hold up the process. Obviously encouraging collaboration is a valuable outcome here, too - so empowering folks to use each other as a resource is extremely helpful.
- <Highlight>
    Intrinsic motivation makes it easier for people to self-organize to achieve
    the same outcome.
  </Highlight>

- The newcomer effect
  - <Highlight>
      "Because newcomers have not yet developed commitment to the group and have
      not yet learned how the group operates, it is rational for established
      group members to distrust them"
    </Highlight>
  - This happens all the time in OSS - many projects have core maintainers who
    do all the work, and a significant amount of gatekeeping by way of bluntly shutting
    down PRs or issues when they're disinterested in them. It's fair to say that
    for the contributors getting shut down, a steady and consistent participation
    in the project will help them get notice, but it can feel like an unfair hurdle,
    too. What might be a more equitable solution to this? Not empowering code owners
    as much? Adding an objective, third party moderator to make some decisions?
- All Contributors
  - https://allcontributors.org/
  - Recognize All Contributors Including those that don't push code
- On Contributors...
  - Again, I'm reminded of the madness of Hacktoberfest 2020 - lots of garbage contributions from people just trying to get a free t-shirt does not make for good OSS, good community, or good contributions.
  - &#8203;<Highlight>Bus Factor</Highlight> is the number of contributors in a project
    who would need to be hit by a bus for it to be in jeopardy. lol

# Part 2: How People Maintain

## Chapter 4: The Work Required by Software

- Software, once written is never really finished. Chasing the feeling of a "finished" app/program/site is something that took me FOREVER to get over. I never felt like I had done anything, because nothing ever got to the finish line. It turns out that the finish line doesn't exist, and a decade+ of building "incomplete" things was the catalyst that I needed to figure that out. As such, <Highlight>greenfield</Highlight> projects are "coveted" because they're a blank canvas, enabling us to chase that feeling of a fresh _starting line_ to point us to a goal that is always just past the horizon. It's a feeling of hope - and thankfully a beneficial one, as rebuilding software from scratch is often inherently beneficial. Neat.
- <Highlight>Free as in speech, not as in beer</Highlight> vs
  <Highlight>free as in puppy</Highlight> is a brilliant analogy
- <Highlight>
    By focusing too much on iterating upon their incumbent product, companies
    risk missing major opportunities for so-called "disruptive innovation,"
    which eventually replaces existing products. - Clayton Christensen in Book:
    The Innovator's Dilemma
  </Highlight>

- The anecdote about Sophie Alpert being offered $600 to **open a PR on someone's project** because it would draw positive attention is mind-blowing.
  - "Is this what it feels like to be an influencer?" - Sophie
- <Highlight>
    We can think of a creator's reputation as a "battery," or store of value,
    for attention. More followers mean more attention in the bank, but when
    people follow a creator they do so because they expect to receive more
    content. If creators don't produce anything new, their followers will
    eventually get bored and leave. Reputation, like software, requires
    maintenance over time.
  </Highlight>

## Chapter 5: Managing the Costs of Production

- Absolutely mind-blowing that at one point, cryptographic code was treated the same as munitions by the US government. Early developers of OpenSSL <Highlight>had to become licensed arms dealers to be able to write and "export" (i.e., distribute) their code.</Highlight>
  - This is an implicit declaration that certain types of technical solutions can be weaponized, and perhaps just as importantly that sometime in the past, some of our legislators had a reasonable understanding of this. In the US, at least, it's apparent that this is no longer the case. Don't believe me? Pull up a congressional hearing with Tim Cook, Zuckerberg, etc
  - Relatedly, it is asymptotically difficult for lawmakers to keep up with the changing pace of technology. There's a decent argument to be made for a citizen-run, or commons-run governing body for technical regulation, rather that trusting some crusty old white men from flyover states whose pre-government professional lives weren't the least bit technical.
- <Highlight>
    When software is in static state, **what if there is no free-rider
    problem?** When code is non-rivalrous, it only has first-copy costs, which
    the creator is intrinsically motivated to provide -- so the problem doesn't
    seem to lie in how many people **consume** it. For this reason, I'm
    skeptical of attempts to charge for access to information, whether it's
    newspaper articles or open source software.
  </Highlight>

- This hints at one of the most fascinating things about content creators online. Virtually all of the really, truly successful creators are driven by an enjoyment of creating and sharing -- and might not typically start creating as a business. Often times it takes hundreds of youtube videos, or dozens of podcast episodes, blog posts, etc to get any kind of sizeable following. It's those with the fortitude and perseverance to continue without an audience that find success. Perhaps the audience is their reward, or perhaps the audience is a natural byproduct of the law of large numbers: create enough of something, and put it out into the world, and **some size** of audience will find you.
- <Highlight>
    At a high level, it's also possible that throwing away projects and starting
    fresh is the most cos-effective approach: rebuilding the whole system, piece
    by piece.
  </Highlight>

- There are many companies that operate like this - occasionally dropping an existing product for a **completely new** rewrite. This has been done with projects as small as weather apps and as large as Windows and MacOS, and is often a good decision. It strikes me that this is often only possible due to a luxury of funding, time, and resources. Imagine telling a scrappy startup that their best bet is to ditch their entire source library, and start anew. It wouldn't work! Many fledgling companies fall apart because of early and inflexible assumptions made, or technical debt built up to save time. The luckiest of them find success despite this debt, and carry on to be successful. I'd imagine this success often brings about an effort to rebuild the plane while it's flying, in a modern Ship of Theseus paradox.
- Automation! This section rang true with me to the core. When building [smpl](https://www.crunchbase.com/organization/smpl-llc), our biggest superpower was automation. It made our engineering team of 2 feel much larger than it was, and helped us to execute successfully and dependably. To this day I think that process automation is the closest thing I have to a superpower.
- It's interesting that a book about OSS has me thinking about work, content, and contributions outside of software so often. So much of what's discussed here has interesting implications politically, socially, and in content creation of any sort for public consumption (art, blogs, youtube, instagram, etc)
- I didn't know about [dear-github](https://github.com/dear-github/dear-github) or its relatives [dear-github2](https://github.com/drop-ice/dear-github-2.0) and [isaacs/github](https://github.com/isaacs/github). It'll be interesting to give these a read. As of this writing, `dear-github2` has had activity as recently as 2 weeks ago

### The role of Money in OSS

- Companies pay for access, attention, and feature proposals. This can often have adverse effects: companies are essentially skipping the line to pay for attention, and as a result aren't vetted by the same processes as other OSS Contributors (particularly those who request fixes and features). This can be a governance nightmare, and can cause mistrust in a project if done incorrectly.
- Advertising in OSS projects has real untapped potential, but often gets shot down. There was a product called Code Fund by Eric Berry which aimed to put ads into the readmes of OSS repos on github. It rose to $24k/mo revenue in 4 months before GitHub shut it down as a violation of their ToS.
- Trivago appears as a sponsor on Webpack, and this has helped them to recruit JavaScript developers, who see them as a good company to work for as a result of their support.
- An interesting difference in funding projects comes by way of GitHub's sponsors feature (and other services like Pateron), whose goals are more oriented towards having individuals back a **contributor** (rather than a project) on a monthly basis. The subscription is seen as a vote of confidence in the person, rather than slippery backing for a single project.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[How to reset your Open Graph embed on LinkedIn, Twitter, and Facebook]]></title>
            <link>https://mikebifulco.com/posts/reset-your-open-graph-embeds-on-linkedin-twitter-facebook</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/reset-your-open-graph-embeds-on-linkedin-twitter-facebook</guid>
            <pubDate>Thu, 17 Sep 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[If you're dealing with Open Graph metadata for your site, and you can't figure out how to get your OG content to update after you make changes, this is your guide.]]></description>
            <content:encoded><![CDATA[
## Earlier today, we had a problem at [Gymnasium](https://thegymnasium.com).

We released a [new 5 minute tutorial on Making Headings and Lists more Accessible](https://thegymnasium.com/courses/take5/making-headings-and-lists-more-accessible) - which is great news! If you build things for the web, and you've got 5 minutes to spare in your day (you do), you should give it a look.

After the course was made public, our marketing wizard did her magic and started posting to our various social media pages: [Facebook](https://www.facebook.com/aquentgymnasium), [Twitter](https://twitter.com/AquentGymnasium), and [LinkedIn](https://www.linkedin.com/school/gymnasium/).

It was immediately apparent that something was off. During our course release process, we missed the fact that Open Graph metadata for that course page wasn't correctly included. Unfortunately, that meant that _none_ of our posts on social media had the beautiful image previews that we'd expect to see (and by extension would likely see far less engagement).

<Aside>
  <em>Open Graph</em> metadata tells other services what kind of information is
  shown when a URL loads, so that they can create a preview of the URL that
  makes sense. Read more at{' '}
  <a href="https://ogp.me" target="_blank" rel="noopener noreferrer">
    ogp.me
  </a>
  .
</Aside>

Fast forward a short while, and we updated our CMS with the necessary metadata for Open Graph Shares to work correctly. Newly shared links in our team Slack now looked great!

<Image
  publicId="posts/open-graph-cache-reset/slack-after"
  alt="screenshot of a post in slack"
  caption="Screenshot from slack after the fix - our new course was shared with the correct image"
/>
.

## Social networks cache link previews

Rather than redownload the preview image and metadata for a given link every time it's shared, your entire open graph preview is often cached. Depending on the site, that cache may be cleared regularly throughout the day.

Because we had _already_ posted links to our courses, every site we had shared to had cached our shared links with the bare defaults. The result was relatively plain, and not relevant to the content on the page - something like:

`Free online courses on design and web development | Gymnasium`

With Gymnasium's logo beside it. Just defaults! Not a great look.

Because we were working on a concerted marketing push to announce our new courses, these extremely plain previews were bad news. We've seen from experience that having an attractive (and differentiated) share image helps gain traction during the initial publicity of new content.

## _You_ can trigger a cache reset on each of these sites!

After some brief research, we found that there are tools to reset the cache on each of the major social networking sites. They're each extremely easy to use - paste your URL in a box, click a button, and reset the cache if necessary. Here's the ones we found to be useful:

### Use these links

- **Facebook Sharing Debugger**: [https://developers.facebook.com/tools/debug/](https://developers.facebook.com/tools/debug/)
- **LinkedIn Post Inspector**: [https://www.linkedin.com/post-inspector/](https://www.linkedin.com/post-inspector/)
- **Twitter Card Validator**: [https://cards-dev.twitter.com/validator](https://cards-dev.twitter.com/validator)

That's all there is to it! Hit reset, re-share your link, and you should see your latest Open Graph preview shared. Phew! 😅
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[gitignore.io is great]]></title>
            <link>https://mikebifulco.com/posts/gitignore-io-is-great</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/gitignore-io-is-great</guid>
            <pubDate>Wed, 05 Aug 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Put simply, gitignore.io is a tool that is so profoundly helpful that I've forgotten what life was like without it.]]></description>
            <content:encoded><![CDATA[
Put simply, [gitignore.io](https://gitignore.io) is a tool that is so profoundly helpful that I've _forgotten what life was like without it._

Its purpose is simple: for any project you're working on, it'll generate a valid [`.gitignore`](https://docs.github.com/en/rest/reference/gitignore) file for you. All you need to do is use the autocomplete box provided to describe the type of project you're working on:

<Image
  publicId="gitignore-fill-in-the-blanks"
  alt="Screenshot of the web interface for gitignore"
  border="2px solid #888"
  borderRadius="1rem"
/>

<Aside type="note">
  A <em>.gitignore</em> file is used to tell git to <em>exclude</em> files from
  being added to a given repo. Each line of the file represents a filename,
  directory, or pattern. When git looks for changes in your working directory,
  it will automatically ignore any file that matches an entry in your .gitignore
  file.
</Aside>

From there, you'll hit the `Create` button, which will bring you to a page that displays nothing but the raw text which you'll need to add to your project's `.gitignore`. If you selected just `react`, for example this is what you'd see on the next page:

```
  # Created by https://www.toptal.com/developers/gitignore/api/react
  # Edit at https://www.toptal.com/developers/gitignore?templates=react

  ### react ###
  .DS_*
  *.log
  logs
  **/*.backup.*
  **/*.back.*

  node_modules
  bower_components

  *.sublime*

  psd
  thumb
  sketch

  # End of https://www.toptal.com/developers/gitignore/api/react
```

That's all there is to it, too! I use it on the vast majority of projects I work on, new and old, and as far as I can tell, it hasn't let me down in any meaningful way.

## It's Open Source!

One of the reasons I like this tool so much is that it gets better the more people use it. Is it missing support for a project type that you work with? Go ahead and submit a [Pull Request](https://github.com/toptal/gitignore.io), and it may be integrated into the product one day. Or, if you're not quite comfortable with a full-on PR, you can start the discussion in an issue on the repo. Maybe something isn't working like you'd expect -- and it's worth pitching in your two cents in the discussion on an open issue. _All of that_ is contributing to Open Source -- don't forget!

As I understand it, it was created by [@joeblau](https://twitter.com/joeblau), and quickly gained momentum with developers. As I write this post, there are [**135** contributors](https://github.com/toptal/gitignore.io/graphs/contributors) on the project.

[Gitignore.io](https://gitignore.io) is a great example of a successful Open Source tool born out of the desire for an improved developer workflow. It currently appears to be operated by [TopTal](https://www.toptal.com/), a company that helps freelancers find work.

<Aside type="info">
  <small>
    (note for transparency: I have no connection to TopTal, and this is not a
    sponsored post. I <strike>do</strike> <em>(update: 11/2020) used to</em>{' '}
    work for{' '}
    <a
      href="https://aquent.com?utm_campaign=mikebifulco&utm_source=mikebifulco.com&utm_content=gitignore-io-is-great"
      target="_blank"
      rel="noopener noreferrer"
    >
      Aquent
    </a>
    , which is a creative staffing agency. If you're looking for work, give{' '}
    <strike>us</strike> them a look!).
  </small>
</Aside>

## There's a CLI

If you prefer it, there's a [CLI](https://docs.gitignore.io/install/command-line) which will help you generate gitignore files, powered by this same project. I can't say I've used it, but I know some of you will want to give it a go, so it's worth mentioning

## There's other options, too

If you don't find gitignore.io particularly appealing, there's always other ways to cretae your `.gitignore` file. You can write it by hand, or grab one from another project you work on. [GitHub also maintains a repo](https://github.com/github/gitignore) of popular gitignore files, which seems to be updated quite frequently as well.

### Was this helpful?

If you found this useful, I'd love it if you subscribed to my mailing list. Details are below!
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[MDX - I should have done this sooner]]></title>
            <link>https://mikebifulco.com/posts/moving-to-mdx</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/moving-to-mdx</guid>
            <pubDate>Wed, 22 Jul 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[I added support for mdx to my site, and it's made life much bettter.]]></description>
            <content:encoded><![CDATA[
As of _this very post,_ I've added support for [MDX](https://www.gatsbyjs.org/docs/mdx/plugins/) to my site. It should make writing new content _much_ easier for me. By removing lots of process that has proven unnecessary, I'll be able to get back to writing more here, an I'm very excited about that.

And it works great! Here's an example of a custom shortcode I wrote, called `<Aside />`:

<Aside>These can be used to highlight important things.</Aside>

And the relevant code for Aside:

```jsx {1,3}
const Aside = (props) => {
  const theme = useTheme();
  return (
    <Box
      borderLeft="8px solid"
      padding="1rem 0 1rem 2rem"
      borderColor={theme.colors.pink[400]}
      backgroundColor={theme.colors.pink[50]}
      margin="2rem 0 2rem 0rem"
      {...props}
    />
  );
};
```

Its use is fairly simple, too -

```jsx
<Aside>These can be used to highlight important things.</Aside>
```

# h/t

This is on the heels of last night's (now defunct) Reactadelphia Meetup, where a very talented developer named [Prince](https://prince.dev/) gave a fantastic talk on MDX. I found it particularly inspiring -- it was that rare talk which had substance _and_ motivation. I already had a pretty good grasp of what one might use MDX for in practice, but Prince made some great points about why MDX is such a game changer.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Why I switched to Fathom for web analytics]]></title>
            <link>https://mikebifulco.com/posts/why-fathom-analytics</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/why-fathom-analytics</guid>
            <pubDate>Sun, 03 May 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[I fully switched my personal site from Google Analytics to Fathom - something that I had been considering for a while, and finally decided to go all in on.]]></description>
            <content:encoded><![CDATA[
This morning, I fully switched my personal site from Google Analytics to [Fathom](https://usefathom.com/) - something that I had been considering for a while, and finally decided to go all in on. Thanks to my colleagues [@andrewpmiller](https://twitter.com/andrewpmiller) and [@jeremias](https://twitter.com/jeremias) for planting this seed months ago - I'm glad I finally made the switch.

## What is Fathom?

In their words, Fathom is "simple analytics for website owners & businesses". Near as I can tell, that's a perfect distillation of what they've built. Fathom provides an easily digestible single page analytics view of your site's traffic.

It's a service that rids you of some of the heft of having Google watch you and your users' every move. They're open and transparent about being [Privacy First](https://usefathom.com/privacy) - something which has long since melted away from Google's ethos.

In addition to giving you information about the traffic coming and going from your web property, fathom also lets you set goals for your site traffic - so that you can keep an eye on performance of what matters to you. Maybe you want to see how many people are visiting your "about me" page, or track newsletter subscriptions -- with Fathom, it's a straightforward javascript call to make that happen.

## Why Fathom?

For me, the functionality it provides is perfect - [my personal site](https://mikebifulco.com) is slowly growing in traffic, which is great! I had been using Google Analytics to keep an eye on my site's traffic, but honestly - I spent a disproportionate amount of time getting lost in all of the bells and whistles of GA. That time wasn't giving me more usable insight... I was just getting lost in the tool.

I also love the idea of Privacy First tooling, which Fathom hits out of the park. When you visit my site, I'm not keeping any of your PII, or doing anything creepy with your browsing behavior. I just want to know how various articles perform, so that I can make better decisions about what to write in the future.

Another benefit was the install process - getting Fathom set up was a breeze. You may know that my site is built on [Gatsby](https://gatsbyjs.org/) - it turns out there's a reasonably well-featured [plugin for gatsby](https://github.com/lgraubner/gatsby-plugin-fathom) created by a member of the community. In addition to that, they're reportedly shipping their own plugin in the next few weeks.

<Tweet tweetLink="usefathom/status/1256954976238055424" align="center" />

<Aside>
  Note: it looks like in the coming weeks, Fathom will be providing their own
  Gatsby plugin!
</Aside>

## Looking for a free option?

**Fathom also has a self-hosted product** called "[fathom lite](https://github.com/usefathom/fathom)" which you can run yourself if you want to use their service for free. It isn't as full-featured as full blown fathom, but it will give you a good idea of what you're in for. I set it up on Heroku (using [these instructions](https://gist.github.com/gmolveau/78f88af3f5951ba6e093f93a07caa302)) for a few weeks before deciding to take the plunge and pay for Fathom's SaaS service.

## Try it yourself!

Thinking about giving it a whirl? One of the perks of being a Fathom customer is their affiliate program - you can use my link to [sign up for Fathom](https://usefathom.com/ref/DPSSYB) for a $10 discount on your first invoice. Sweet!
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[On normalcy, daily routines, and the pandemic]]></title>
            <link>https://mikebifulco.com/posts/on-normalcy</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/on-normalcy</guid>
            <pubDate>Tue, 21 Apr 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[On my walk this morning, I found myself wondering what it's going to be like when things go back to normal.]]></description>
            <content:encoded><![CDATA[
On my walk this morning, I found myself wondering what it's going to be like when things go back to normal.

If you've ever read the book Hatchet, there is a boy in the book named Brian who is stranded alone in the wilderness with only a hatchet for survival. I read it when I was in middle school - the main plot line in the book illustrates is how difficult solo survival can be. At the very end of the book is about Brian's experience going the grocery store for the first time after he's rescued, and what it feels like when he's thrust back into a world where the food at his fingertips is endlessly plentiful.

He suddenly sees the grocery store as a fruitful oasis of fresh produce, and snacks, and meat, and all the things he could ever want - thing that he just straight up didn't have while he was stranded alone.

What it's going to be like when the world comes back together? What are going to be the things that I have back in my life that I'll have missed?

I'm looking forward to finding out what my grocery store is. I'm looking forward to having something-like-normal back, and I'm looking forward to being able to appreciate those things.

Lately I’ve been trying to center myself on that.

I’d like to encourage you to center yourself on some of those things, as well as the things that you have right now that are going well (no matter how small they might be!). Hopefully, some things in your life are working out still.

For me, at least those things are the things that keep me going right now.

## There’s still great work being done

These are a few things I’ve found useful this week from far and wide

- 📉 [HealthData.org](https://covid19.healthdata.org/projections) has a frequently updated view of how each of the 50 states + DC are flattening the curve, as compared to hospital capacity. A remarkably well-done data visualization, but a sobering reminder of where we’re at.
- 🎨 [Dracula](https://draculatheme.com/visual-studio-code/) is a color theme made for VS Code (and many other editors) which is based on great color theory, and is frequently and lovingly updated.
- 🌲 [Ecologi](https://ecologi.com/irreverentmike?r=5d386c6667bad5001010ffae) is a wonderful service which will let you donate a couple bucks a month to offsetting your carbon footprint by funding the planting of new trees and other Gold Standard approved projects.

I hope you have a great day.

Talk soon!
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Help your users when your web app crashes]]></title>
            <link>https://mikebifulco.com/posts/plan-for-things-to-go-wrong-in-your-web-app</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/plan-for-things-to-go-wrong-in-your-web-app</guid>
            <pubDate>Tue, 21 Apr 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[This post came from my work on Surviving Other People's APIs.  I've been working on a chapter on Async - the content below came from that writing, but doesn't quite make sense in the context of the book.  I didn't want to scrap it entirely, so it's found its way into a blog post.  I'd love to know what you think!]]></description>
            <content:encoded><![CDATA[
**Note:** This post came from my work on [Surviving Other People's APIs](https://leanpub.com/surviving-other-peoples-web-apis). I've been working on a chapter on **Async** - the content below came from that writing, but doesn't quite make sense in the context of the book. I didn't want to scrap it entirely, so it's found its way into a blog post. I'd love to know what you think!

## Plan for things to go wrong

Setting up an interface to pull data from an API asynchronously is a clear upgrade over the alternative; we're now able to update the content on a given page without reloading all of the markup and assets (images, css, etc) on the page. For better or worse, your asynchronous upgrades will also introduce some potential for things to go wrong for the people using your app. Once again, this is an opportunity to anticipate the things which might go wrong, and build fallbacks for when they do.

### Dealing with dropped connectivity

Even if you've used a hyper-modern, robust websocket-enabled API-calling technology, at some point or another, the folks using your app will lose their internet connectivity. This isn't just the canonical example of someone on a train going through a tunnel, either. Often times connectivity will go down briefly for mobile users when they switch from a cellular connection to wifi, or when they go between wifi networks, or when they lose wifi and go back to cellular.

You should test your software to make sure it will continue to work in these cases. It turns out this can be pretty easy to simulate, too - if you're on a phone, turn airplane mode on, wait a moment, and then switch it off again. On a laptop or desktop developer environment, you can switch wifi off, or disable your LAN connection. Even better, if you're using Chrome devtools, you can use their responsive tools to shut off connectivity on a single tab:

<Image
  publicId="posts/plan-for-things-to-go-wrong-in-your-web-app/chrome-devtools"
  alt="Screenshot of the throttling interface in Chrome Devtools' responsive mode"
  caption="Chrome DevTools has a simple switch to shut off connectivity"
/>

Once you're able to simulate this kind of trouble, you can build out fallbacks for when things go wrong. A typical approach to this is to keep track of the result of your API call locally. If a drop in connectivity is detected, you should let the user know that it looks like they're offline. From there, you can give them the opportunity to retry the API call, and automatically retry your call when you can tell things are working correctly again.

<Image
  publicId="posts/plan-for-things-to-go-wrong-in-your-web-app/recover-from-offline"
  alt="Mockup of a mobile app showing a modal popup notification for when internet connectivity goes down, which takes over the entire screen."
  caption="Recovering from a dropped connection during an async save operation"
/>

Certain technologies will do the bulk of this work for you. For example, if a connectivity drop is detected, Firebase will save any API operations to a queue in the client browser's local storage, and will execute offline changes as soon as connectivity comes back. Even still, as when creating interfaces which take advantage of features like this, you should let your users know when they're offline. It's best to fully communicate what will happen when the connection comes back, too - in clear, human-friendly language.

<Image
  publicId="posts/plan-for-things-to-go-wrong-in-your-web-app/working-offline"
  alt="Mockup of a mobile app which informs the user they're working offline, and that changes will be sync'd when the connection comes back."
  caption="Explain clearly what will happen when the connection comes back"
/>

Note that in this case, we have the opportunity to create an interface which is a whole lot less shouty than in the last example. There's no need for the offline notice to be put in a modal window which takes up the whole screen. Colors are dialed back a bit, too - yellow is used in the example, which is much less anxiety-inducing than the-sky-is-falling-red.

As a follow-up to this, when the connection comes back, it's good practice to fire off a notification when the offline requests are completed successfully.

### Dealing with changing APIs

At some point, the APIs you're calling will change. In an ideal world, these sorts of changes are well-documented, and deprecation notices are made available months in advance of permanent changes which will break your application. It is part of your team's job to keep an eye on any services you use for breaking changes coming your way. This can be as simple as assigning a task every sprint to check for API and dependency updates.

This is a perfectly functional approach to watching out for version changes -- until it isn't. For larger applications, you may find that as you build more features which depend on a growing number of external services and dependencies, this task becomes an untenable time sink. Luckily, in many cases, there are ways to automate the process. One such tool is called [Dependabot](https://mikebifulco.com/posts/i-have-to-tell-you-about-dependabot), which is owned by the folks at GitHub.

<Image
  publicId="posts/plan-for-things-to-go-wrong-in-your-web-app/dependabot"
  alt="Screenshot from dependabot's marketing page"
  caption="Dependabot can be found at https://dependabot.com"
/>

Dependabot (and services like it) will keep an eye on dependency lists in your project (like `package.json` in Node projects, and `Gemfile` in Ruby projects). Once initialized, it will regularly check your dependency lists against the published versions of each library. When new versions are published, it'll open a simple pull request for each updated library, which you can review, test, and merge when ready.

<Image
  publicId="posts/plan-for-things-to-go-wrong-in-your-web-app/github-dependabot"
  alt="Screenshot from github.com showing a repo with automated Pull Requests, created by dependabot"
  caption="Lots of small pull requests - one for each library which has been updated!"
/>

Generally speaking, this makes the task of keeping dependencies up to date much simpler. The majority of the work can now be done by your test suites via CI - and changes can be verified by reading changelogs for each updated package.

As this becomes more common, maintainers of various libraries are getting better at posting easy-to-understand changelogs, which reduces the chances that you'll merge a catastrophic change into your project. These kinds of proactive measures should help you sleep more soundly at night.

Even still, sometimes things go wrong for one reason or another.

Maybe you merged and released a dependency update which has a breaking change to a mission critical API. Maybe one of your web page uses an API with a version set to `@latest` (!), and you wake up one day to find hundreds of help tickets from people who used to love your application. If you had been keeping an eye on server logs for your application, you may have noticed that overnight you received a spike in 4xx or 5xx errors from API calls. Be honest with yourself - how often do you proactively check server logs for errors? Don't fault yourself if the answer is less than often - most of us never check.

Once again, this is a place where automation can save the day. There is no shortage of tooling available to help you detect problems reactively just as they start, and with a nimble enough release strategy, you can minimize application downtime.

### Use error reporting to turn reactive situations into proactive messaging

Imagine this: you're in charge of an application which uses an external service to check the weather for [whatever purpose]. You've got thousands of happy users who regularly use your app to check the weather before going about their day. One day, without warning, the weather API begins sending back data in a completely different format than you'd expect - a change big enough to render your app useless.

In the old world, you wouldn't find out about this problem until help tickets and angry tweets started rolling in. At that point, it's past too-late - your beloved customers are upset, and you're the fireman who showed up after the roof collapses on your house.

We can do better than that.

There are a plethora of services available which will detect and report application crashes to you the instant they happen, so your support team can spring into action at a moment's notice. Some of these services include [Raygun](https://raygun.com/platform/crash-reporting), [Sentry](https://sentry.io/), [LogRocket](https://logrocket.com/), [Rollbar](https://rollbar.com/), and [Data Dog](https://www.datadoghq.com/). With a few lines of code, these will plug into your app, and keep an eye on network requests. When a page crashes, they'll fire off all manner of notifications - SMS, email, webhooks, Slack messages, you name it.

If you can't afford to use one of these services, or otherwise prefer not to, you can scrap together a simple one yourself. This generally looks like a wrapper function which you can use to call APIs. It should contain the logic to detect failures, and fire off whatever calls are necessary to alert your team to the problem. For teams with a small budget, the easiest approach may be using Slack's incoming webhooks feature to send a message to a channel dedicated to an application crash:

```javascript
const callApi = async ({ url, options }) => {
  try {
    // send off the API call
    const response = fetch(url, options);
    return response;
  } catch (e) {
    //something went wrong, let's notify the team!

    /* helper function to gather as much information as possible about this session, possibly including:
      - user name and contact information
      - URL or page they were visiting
      - which action caused this error
      - browser metadata ("IE7" or "Firefox 58", etc)
      - anything else that might help your support team send a thoughtful, personal response!
    */
    const metadata = getUserMetadata();

    // just what it sounds like - send a message to your team's slack channel via incoming webhook
    sendSlackWebhook({
      error: e,
      metadata: metadata,
    });

    // send the response back to the interface so you can let the user know something went wrong
    return e;
  }
};
```

These can greatly decrease your effective response time. If you're able to detect these problems and set your dev team off on a solution before users start complaining, the people using your app will feel loved. Think about how rare it is to use software and feel like the people who are making it care about you directly! If you're a small, scrappy start-up, this can really help you hang on to early customers. If you're a larger company, it means lower attrition rates, and better support ratings.

Error reporting can also help you detect crashes with user-by-user granularity. You may see crash reports coming in from a single user over and over. Reaching out to that individual to see how you can help them before they message you can honestly feel like magic. I've even had users thank me for dropping them a line and telling them I see that they're having trouble, and that I'm on the case. It's a great feeling - particularly when the alternative is a red-hot support email or a scathing tweet.

### Build a global status indicator... before you need it!

In all of the projects I work on, it's become common practice to include a global status indicator into the fundamental roots of the application. In its simplest form, this amounts to a content container that lives somewhere near the very top of every page off the application. The vast majority of the time, it sits invisible and dormant. On page load, and once every few minutes it checks our CMS for content - if something goes wrong, we use that field in our CMS to alert users to the issue, and update it regularly with easily understandable messages about resolution of the issue.

If you don't use a CMS, never fear - you can use something like GitHub Pages to host a json file which you can use for these kinds of warnings. Have your interface check the public URL of your GitHub Pages site, and if there's anything more than a blank file or object, that content can be parsed and displayed in your status indicator.

### And then?

For now, that's it! Like I mentioned, this was just an excerpt from a chapter that didn't quite fit with what I'm writing. What do you think? Is there anything you do to harden your site against failures that are out of your control?

## More reading

If you found this article useful, here's some related work I've published:

- [I have to tell you about Dependabot](https://mikebifulco.com/posts/i-have-to-tell-you-about-dependabot)
- [Run Dependabot locally](https://mikebifulco.com/posts/run-dependabot-locally)
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Are you suddenly a remote worker? Let's figure it out together.]]></title>
            <link>https://mikebifulco.com/posts/are-you-suddenly-a-remote-worker</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/are-you-suddenly-a-remote-worker</guid>
            <pubDate>Sat, 04 Apr 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[My guess is that if you’re reading this, you’re a newly remote worker, due to the rapid and terrifying expansion of the COVID19 Pandemic. I’m not here share medical advice; if that’s what you’re after, there’s far better places to look.]]></description>
            <content:encoded><![CDATA[
Hey there - I’m [Mike Bifulco](https://twitter.com/irreverentmike). I’m a programmer, designer, entrepreneur, author, and podcaster… and I’ve been working remotely as the Technical Director for [Gymnasium](https://thegymnasium.com) (an online code school) since 2015, contributor to [Workfrom](https://workfrom.co) since 2016, and cofounder of [smpl](https://www.crunchbase.com/organization/smpl-llc) (software for independent coworking companies) since 2017.

My guess is that if you’re reading this, you’re a newly remote worker, due to the rapid and terrifying expansion of the COVID19 Pandemic. I’m not here share medical advice; if that’s what you’re after, there’s far better places to look.

This publication is meant to help all of us who are suddenly tasked with doing our job from somewhere uncomfortable. Let’s talk about working from home.

I’ll be sending out periodic updates with some stream-of-consciousness thoughts on working remotely, or living in the world in 2020, or being human… whatever feels like it makes sense.

Primarily, I’ll share a few things which might be helpful to you right now.

Stuffing work-life into your home-life
As I see it, making remote work work isn’t easy. It took me quite a while to get used to. Save yourself some trouble, and do these things first:

- 🖥 Separate work from home. When you’re working, you should feel like you’re working. Don’t set up in front of the TV with Netflix on. Give yourself a nice, clean place to work from, and situate yourself there only when you’re working. If you live in a small space, this may mean transforming your coffee table or dining table to work-mode during your working hours.
- ⏲ Give yourself a schedule. Do you normally work from 9-5? Make it so, at least to start! Remote working can mean an extremely flexible lifestyle, for sure, but it will probably also cause a massive dive in your productivity, at least at first. Do yourself a favor and stick to your normal work hours for a few days, until you get into the swing of things.
- 🗣 Communicate with your people. If you share your living space with other people, it’s best to be extremely forthcoming about what you need to get work done. Don’t do well with distractions? Explain that to them. Do you need to be sure your kids won’t barge in on video calls? Tell them! Communicating is fun and nice, and you’re going to need to do a whole lot of it.

That’s all for now. If there’s anything I can do to help you or the people that matter to you figure this all out, please don’t hesitate to drop me a line [@irreverentmike](https://twitter.com/irreverentmike).

(If this was helpful, I’d love it if you’d share it with someone who might also like it!)

This post is a sample from one of my weekly newsletters. If you liked it, you can also subscribe to my newsletter Tiny Improvements here 👇🏼
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Introducing Pistola - Building a passion project with radical transparency]]></title>
            <link>https://mikebifulco.com/posts/crosspost-introducing-pistola</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/crosspost-introducing-pistola</guid>
            <pubDate>Fri, 21 Feb 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[If you follow me across the various other social networks I use, you'll likely stumble across my passion for cycling. For the past 8 or so years, road cycling has been my primary form of exercise. I love cycling; it keeps me sane, and helps me live a healthier life, while seeing the world. If you haven't been on a bike recently, you should give it a shot - I can't recommend it enough.]]></description>
            <content:encoded><![CDATA[
## An (extremely brief) history

If you follow me across the various other social networks I use, you'll likely stumble across my passion for cycling. For the past 8 or so years, road cycling has been my primary form of exercise. I love cycling; it keeps me sane, and helps me live a healthier life, while seeing the world. If you haven't been on a bike recently, you should give it a shot - I can't recommend it enough.

It should come as no surprise, then, that I recently started a passion project that involves cycling. Details are (intentionally) a little unclear at this point, but I'm putting together **something** which will help cyclists, runners, hikers (and athletes of many other sorts) understand data that they record using IoT sensors during workouts. Think this-and-that to do with GPS tracking, Heart Rate, speed, power, etc.

I'm guessing that many of the folks reading this right now may be thinking this sounds familiar. Products like Strava, Endomondo, MapMyFitness, Garmin Connect, Apple Fitness, and Google health all fit into a Venn Diagram that helps folks who track their workouts. It's true! I'm hoping I can carve out a small-but-mighty and impassioned audience from within those larger umbrella services. The trick, though, is that I have to figure out what that means - what's missing for the people who use those services that I can provide?

## How the heck do I think I can succeed?

I can see how you might think takes some granite _cojones_ to think that this kind of hairbrained idea could go well. I'll try to make the case for my plan:

[Strava just added its 50 _Millionth_ user](https://dailyspin.co/articles/strava-now-has-50-million-users/). Hot damn! That's a ton of people. The way I see it, if I can manage to attract a few thousand paying customers, at a couple bucks a month, I can offset costs for a 1-man operation, and maybe have a chance at building something really exciting.

I just finished devouring [Paul Jarvis'](https://twitter.com/pjrvs) fantastic book [Company of One](https://ofone.co/), and I'm hoping to adopt some of the strategies outlined in Jarvis' book, which describes how radical transparency can serve a small operation well:

- I believe that the right kind of customer for me is someone who appreciates the human side of what I'm doing. This isn't a venture-backed project with zillions of dollars pushing it along. I'm not working out of a SoMa loft, down the block from Facebook, Google, and Apple. This is an espresso-powered love letter to my passion, built from my basement office during the wee hours of the morning, and late at night.
- I intend to be very public with what I'm building. Since I'm sourcing my feature list from the needs of real people (by way of surveys), I feel it's only fair to have a [public roadmap](https://github.com/orgs/gopistola/projects/1) of what I'm building. This will facilitate further feedback and discussion from the people using Pistola. I love that idea.
- I'm going to make the formulas I use to calculate calories burned **Open Source**. As far as I can tell, there isn't a single product on the market that explains _exactly_ how they calculate calories burned. It's patently crazy to me that this is something that the industry treats as a trade secret. Can you believe that? To boot, nobody really makes mention that the calorie numbers they show you are _estimates_ -- which they are. It's an inexact science, but you're never made aware of that anywhere. We can do better.
- I'm going to make my costs and earnings publicly viewable (at least to start). I'll admit, this one makes me a bit anxious. Precisely because I'm building this thing out of pocket, I'm going to ask users to pay for Pistola from the get-go. By leaning on the candor I'm using to build Pistola, I'm hoping that the people who will want to use the product will be empathetic to the cause, and -- for the price of a cup of coffee each month -- chip in a few bucks for access to Pistola. Their money will power the product, and they'll know what kind of margins I'm operating on.

## Where does that leave me now?

At the moment, I'm a few steps away from having a very small MVP put together. This will allow you to create an account, upload workouts to pistola, and analyze your workout on a relatively simple timeline. To begin with, all workouts will be private, so you'll only be able to see your information. Shareable content will come later.

I'm going to use the blog at https://pistola.io/blog as a way to document my process.

I've also published the first episode of a podcast called [Building Pistola](https://pistola.io/podcast). These audio-only vignettes will be published from time-to-time, documenting my process, struggles, and concerns. Can't get more out-in-the-open than that!

Last week I put out a [user research survey](https://gopistola.typeform.com/to/osVw3W), asking folks about their experience with Strava. I'm going to analyze those results and summarize them in a blog post. That information will be used to power the first version of Pistola's product roadmap.

## Next steps

- If you're with me still, I'd love it if you subscribed to the podcast ([Building Pistola](https://pistola.io/podcast), and signed up for the [pistola newsletter](https://pistola.io/).
- If you've got feature ideas, or you're a GitHub user and you want to keep an eye on things, check out the [Product Roadmap](https://github.com/orgs/gopistola/projects/1).
- It's time for me to get my nose back to the grindstone, and continue building the product!

Most of, all thank you for reading, and for your support. I'm hoping this crazy idea can grow some legs, and I won't get anywhere without support and encouragement from the design, developer, cycling, and running communities. I'd love to hear your feedback, criticism, and encouragement. I'm here for it, and I deeply appreciate it. My inbox is always open: [mike@pistola.io](mailto:mike@pistola.io)

Thank you!
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Do you have your own Gatsby site? Let's brainstorm a dev.to cross-poster]]></title>
            <link>https://mikebifulco.com/posts/gatsby-dev-to-cross-poster-brainstorm</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/gatsby-dev-to-cross-poster-brainstorm</guid>
            <pubDate>Sun, 23 Jun 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[So, like all good things, the idea for this post comes from a tweet...]]></description>
            <content:encoded><![CDATA[
<small>

_Note: I updated some names and links in this post. Dev.to's product became
**Forem** when it went open source_

</small>

So, like all good things, the idea for this post comes from a tweet:

<Tweet tweetLink="irreverentmike/status/1141169316273897536" align="center" />

This is something I've been ruminating on for a bit. I've even tried to build it - a few times! I keep starting in on the work and getting lost in the millions of directions I could take it.

Here's what I'd like: When I publish a new post to [my gatsby site](https://mikebifulco.com) (you're on it now!), I'd like for that post to appear on [dev.to](https://dev.to) automatically.

## It should:

- recreate my post verbatim, from its original markdown source
- use the `canonical_url` frontmatter field to make sure I retain SEO goodness on my post
- happen without my intervention
- be agnostic of where my posts are coming from. At the time of writing this article, I use [takeshape.io](https://www.takeshape.io) as a headless CMS for my site, so my individual posts aren't in source control
- only take posts from my `master` branch, since I use feature branches for draft posts from time to time
- use the [dev.to API](https://developers.forem.com/api) (update: now called the _Forem API_), of course

## Nice to have:

- maybe posts should be set to `published: false` at first, so I can preview/review/update them as needed for dev.to?

## Possible approaches for this:

1. Tap into GitHub's webhooks somehow, and fire off a post here
1. Come from a job kicked off after CI, maybe? I use CircleCI, but would like this feature to be fairly implementation agnostic.
1. Use a [GitHub App](https://developer.github.com/v3/apps/)?
1. ...or a [GitHub Action](https://github.com/mbifulco/thepraticaldev-crosspost-action)?
1. Perhaps just a lamba function deployed to AWS or [Netlify Functions](https://functions.netlify.com/).

So - here's where I ask for your help. Surely there's a simple approach here I haven't thought of, or maybe it's a matter of collecting a few scenarios and building something based on 80/20.

What else am I missing here? I'd love your help. What use cases would you have for a cross-poster from your gatsby site? How would you implement it? How can we help each other?
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[I have to tell you about Dependabot 🤖]]></title>
            <link>https://mikebifulco.com/posts/i-have-to-tell-you-about-dependabot</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/i-have-to-tell-you-about-dependabot</guid>
            <pubDate>Fri, 31 May 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[Dependabot is an automation service that will automatically create PRs to keep your projects' dependencies up to date, and it is really powerful.]]></description>
            <content:encoded><![CDATA[
**Update (2021, pt.2): Do you want to know how to run Dependabot locally?**

I wrote a follow-up to this article based on a question I've been getting fairly regularly: How do you run dependabot locally? You asked, I answered - check it out here: How to [run dependabot locally](https://mikebifulco.com/posts/run-dependabot-locally) on your projects

**Update (2021)** Dependabot has been Acquired by GitHub, and many of the links from this post stopped working once they took down the original site (dependabot dot com). I've updated URLs here to point to more relevant links within GitHub's docs.

[Dependabot](https://github.com/dependabot) is an automation service that will automatically create PRs to keep your projects' dependencies up to date, and it is really powerful.

<Image
  publicId="posts/i-have-to-tell-you-about-dependabot/dependabot-settings"
  alt="Screenshot of the settings interface for a project on the former Dependabot.com"
  caption="Setup for Dependabot is flexible, quick, and straightforward."
/>

In just a few, sweet, wonderful minutes, you can install and configure it to automatically keep an eye on your project dependencies, and set a daily or weekly schedule to submit updates and changes. Automation at its finest - dependabot is like having a super mindful teammate who keeps an eye on npm (or pip or rubygems or one of [many other languages](https://docs.github.com/en/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/about-dependabot-version-updates#supported-repositories-and-ecosystems)) - you'll automatically get great, well-formed PRs for each dependency version bump, which you can test locally, or have sent up to your CI toolchain of choice.

After you run through the setup process, dependabot will monitor your repo and submit PRs to update individual dependencies on a daily or weekly rhythm (your choice!). If the PR contains an important security update, it will be assigned a label of Security, too.

<Image
  publicId="posts/i-have-to-tell-you-about-dependabot/dependabot-pr"
  alt="An example PR from dependabot"
  caption="Automatically created PRs are simple and to the point."
/>

Honestly, for me, it's like adding a member to my team. I love automation, and I love making my life simpler. Until now, for all of my projects, myself or another teammate would regularly run through all the dependencies in a given repo, and manually update them one at a time, testing and pushing them to GitHub to be run through CI and then eventually merged by the team. The honest truth is that this process can take quite a while, and can be forgotten, and isn't mindful of important security updates at all. That's all over now.

<Image
  publicId="posts/i-have-to-tell-you-about-dependabot/merge"
  alt="An example PR from dependabot"
  caption="Dependabot will merge this PR once CI is done, thanks to the @dependabot merge command"
/>

## What else?

There are a _ton_ of other features available to you the moment you install dependabot. It responds to a wide variety of commands by way of GitHub comment. In the screenshot above, I've approved a PR and asked dependabot to merge it as soon as CI has passed. Now I don't have to babysit the repo in order to merge updates! Sweet!

If your repo contains multiple languages, Dependabot can handle that. If you've got a complex monorepo with multiple files representing your dependencies (for example, a node project set up with Lerna), dependabot can monitor each dependency file individually, with different rules for each.

<Image
  publicId="posts/i-have-to-tell-you-about-dependabot/github"
  alt="Dependabot's announcement that they were acquired by GitHub"
  caption="Dependabot was acquired by GitHub"
/>

This was the final kicker for me. Dependabot was [just acquired by GitHub](https://github.blog/2019-07-25-one-million-dependabot-pull-requests-merged/), and is now available completely free for use. That's incredible! There's no reason for you not to give it a shot. Go check it out now, post haste!

Go install [Dependabot](https://docs.github.com/en/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/about-dependabot-version-updates)!

## For more reading

- Check out my follow-up post: How to [run dependabot locally](https://mikebifulco.com/posts/run-dependabot-locally)

_Note: the cover photo for this article comes from one of my favorite photographers, [Alex Knight](https://twitter.com/agkdesign), and was made available un [Unsplash](https://unsplash.com/search/photos/robot?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText). Thank you Alex for your work!_
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[CSS talk: you should really know about the ch unit]]></title>
            <link>https://mikebifulco.com/posts/all-about-ch</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/all-about-ch</guid>
            <pubDate>Fri, 17 May 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[This is an article about CSS and usability. The ch unit in CSS was a revelation for me, and I promise that if you don't know about it already, you're gonna love it. ]]></description>
            <content:encoded><![CDATA[
I often joke that to learn about design is to doom yourself to be lightly annoyed by everything. After some repetition, you'll start to internalize some of the basic rules of industrial design, or print design, or fashion design, or mechanical design, or whatever it is that gets you excited. You'll start to find design quirks in the world which were once hidden to you. After all, every single thing in the built environment has been put there by someone who took their time to bring it to life. The downside, of course, is that you'll also start to see designs that downright suck. I find that it's helpful to think of it as finding opportunity for improvement.

Today's opportunity for improvement is brought to you by [Wikipedia](https://en.wikipedia.org/wiki/Ralph_Waldo_Emerson), which had me going cross-eyed as I read through an article in the early hours of this morning.

<Image
  publicId="posts/all-about-ch/wikipedia-4k"
  alt="Screenshot of a wikipedia article on a wide monitor. Text spans fully from left to right, taking up the full width of available space."
  caption="A fullscreen desktop view of wikipedia on my 4k monitor."
/>

## What is a ch, and why you should c(h)are

It's simple, actually - ch is a CSS unit which represents the width of a character! If you're using a proportional font (where not all characters are the same width), 1ch is the width of the 0 character in the typeface you're using. This is particularly helpful for usability as it relates to reading long passages of text.

## Line length and reading usability - err, readability

Limiting the line width for text in long passages is a great tool for making things more readable. [Studies have shown](https://baymard.com/blog/line-length-readability) that for optimal reading, text should be limited to somewhere around 60 characters per line. Think about it - this is why paperback books are generally smaller than an A4 page. This is why people love reading on their kindle. This is why Barnes and Noble sells Nooks like hotca - well, it's why the Nook is shaped like it is, at least.

In practice, what does this look like? Let's take that same wikipedia article and limit its paragraphs to 60 characters:

```css
p {
  max-width: 60ch;
}
```

Here's what it looks like:

<Image
  publicId="posts/all-about-ch/wikipedia-ch-applied"
  alt="The same wikipedia article with a limit set on p max-width for ch yields a page that is much easier to consume visually, and is more readable."
  caption="Column width adjusted using the CSS ch unit."
/>

Okay, so that's not a fully-baked design update, but with a few tweaks we can make it a little nicer by bumping up the font size, and adjusting the layout of the right-hand column (side note: wikipedia uses float: right on that column, surprisingly!)

<Image
  publicId="posts/all-about-ch/wikipedia-ch-adjusted"
  alt="With a few additional layout tweaks, the page can be reflowed around the ch-limited paragraphs, making the entire article more coherent and easier to read."
  caption="Font size bumped up, and right-hand column adjusted to snap in place next to it.  Much easier to read!"
/>

That's not bad at all! One of the nice things about using a character **count** for setting the width of that section is that it scales nicely for folks who use the browser's zoom functionality. You can also put your text passages inside of pixel-size-limited divs to make them work in responsive layouts at smaller sizes:

```html
<style>
  @media screen and (min-width: 800px) {
    .blogpost {
      max-width: 400px;
    }
  }
  .blogpost p {
    max-width: 60ch;
  }
</style>

<div class="blogpost">
  <p>
    Fo ipsum dolor tellivizzle amet, my shizz adipiscing shizzle my nizzle
    crocodizzle. Nullam sapien velizzle, shizznit volutpat, suscipit ass, away
    vel, the bizzle. Dizzle fo shizzle tortizzle. Sizzle erizzle. Fusce izzle
    dolizzle dapibus fizzle tempus dope. Maurizzle pellentesque hizzle et
    turpis. Shiznit check out this fo shizzle. Pellentesque eleifend rhoncizzle
    shiznit. In hac habitasse platea dictumst. Donec dapibizzle. Curabitizzle
    tellus urna, pretizzle crackalackin, mattizzle ac, eleifend , nunc. Nizzle
    suscipizzle. Integizzle rizzle you son of a bizzle sizzle mofo.
  </p>
  <p>
    Dizzle ut dolizzle. Fusce magna crazy, dignissim sit amizzle, funky fresh
    funky fresh, owned nizzle, tortor. Maecenas a nisi. Tellivizzle ghetto neque
    izzle get down get down. Shut the shizzle up stuff. Cras aliquet tristique
    turpizzle. Suspendisse gizzle ultricizzle dope. Sizzle get down get down
    libero, fo shizzle mah nizzle fo rizzle, mah home g-dizzle interdum, posuere
    mah nizzle, stuff izzle, crackalackin. Da bomb mofo tellizzle. Boom
    shackalack aliquizzle gangster sizzle amet dolor. For sure dapibizzle sheezy
    id mah nizzle. Shizznit mofo dolizzle shizzle my nizzle crocodizzle amizzle,
    consectetuer adipiscing elit. Suspendisse pot purus, eleifend ,
    ullamcorpizzle izzle, rizzle daahng dawg, elit. Nizzle porta rutrum nunc.
  </p>
</div>
```

I dropped this stuff in a [codepen](https://codepen.io/mbifulco/pen/rgxryB) if you'd like to play around with it. You'll see a green background when the media query activates.

_Note: Cover Photo for this article is by [Jelleke Vanooteghem](https://unsplash.com/photos/2OCh8tuNsBo?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/). Thank you for your work!_
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Promise.allSettled() Pt.2 - it's partly settled!]]></title>
            <link>https://mikebifulco.com/posts/promise-all-settled-pt-2-its-partly-settled</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/promise-all-settled-pt-2-its-partly-settled</guid>
            <pubDate>Fri, 26 Apr 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[This is a follow-up to my first post on the upcoming Promise.allSettled() function, coming soon to a node application near you. ]]></description>
            <content:encoded><![CDATA[
This is a follow-up to my [first post](https://mikebifulco.com/posts/solve-all-your-problems-with-promise-allsettled) on the upcoming `Promise.allSettled()` function, coming soon to a node application near you.

Earlier today I was greeted by a [Pull Request](https://github.com/mbifulco/blog/pull/14) on my first post from GitHub user `@j-f1`.

<Image
  publicId="posts/promise-all-settled-pt-2-its-partly-settled/pr"
  alt="Screenshot of a github pull request on my last blog post"
  caption="PR on my last post, showing how to use Promise.allSettled() now!"
/>

It turns out there _is_ a handy way to add `Promise.allSettled()` to your apps _right now!_ 🎉.  It's fiendishly simple to use, too.

## **The core-js npm package**

That's right - [core-js](https://github.com/zloirock/core-js).  From their `README.md`, it is exactly what it sounds like:

<Aside>

It is a polyfill of the JavaScript standard library, which supports:

- The latest ECMAScript standard.
- ECMAScript standard library proposals.
- Some WHATWG / W3C standards (cross-platform or closely related ECMAScript).

It is maximally modular: you can easily choose to load only the features you will be using.
It can be used without polluting the global namespace.
It is [tightly integrated with `babel`: this allows many optimizations of `core-js` import.](https://github.com/zloirock/core-js/blob/master/docs/2019-03-19-core-js-3-babel-and-a-look-into-the-future.md#Babel)

</Aside>

[Looking further down in the readme](https://github.com/zloirock/core-js/blob/master/docs/2019-03-19-core-js-3-babel-and-a-look-into-the-future.md#Babel), there's a list of supported features in the polyfill:

<Aside>

[Promise.allSettled](https://github.com/tc39/proposal-promise-allSettled) stage 2 proposal

</Aside>

Well hot damn! That'll do it!

## **How to use core-js**

As `@j-f1` indicated, in any project that uses `babel` as a transpiler, all you need to do is add core-js to your project, and include it at your app's entry point:

First, add the dependency to your project

```bash
    > yarn add core-js
```

Then, at your app's entry point (usually something like `index.js`, or `app.js` in the root of your project):

```js
import 'core-js';
```

or, if you want to include _just_ the `Promise.allSettled()` polyfill, and nothing else, use:

```js
import 'core-js/proposals/promise-all-settled';
```

That's it! 🍻
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Picking apart JavaScript import syntax]]></title>
            <link>https://mikebifulco.com/posts/picking-apart-javascript-import</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/picking-apart-javascript-import</guid>
            <pubDate>Wed, 17 Apr 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[Part 2 in a series of posts on destructuring syntax for JavaScript and Node.]]></description>
            <content:encoded><![CDATA[
Note: this is a follow-up to my [first post](https://mikebifulco.com/posts/deconfusing-javascript-destructuring-syntax) on destructuring.  Import syntax uses destructuring pretty liberally, and it can be really confusing for folks who are new to using it. Give my other article a read first if this all seems confusing!

Let's talk about importing dependencies into your node projects.  As your work gets more complex, you will inevitably come across syntax like this:

```js
  import React, { useState, useEffect } from 'react';
  import { Link } from 'gatsby';
  import Button from '@material-ui/core/Button';
  import moment from 'moment';
  ​
  import { Layout } from '../components';
```

At first glance, it's pretty straightforward.  We're importing a handful of bits to use in a React component.  As you might imagine, though, I've selected these four lines of code because each one is unique.  In fact, during my journey as a blossoming Node/React developer, I've found ways to mess up _every single one_ of these.

You're gonna mess this stuff up, too, and that's perfectly fine! For now, I'm here to help.

We're going to look through each one of these, in order of complexity, and I'll do my best to explain what the hell is going on, and the way I think about imports as I work.

## **Straightforward import syntax - the easiest case**

```js
import moment from 'moment';
```

If you've worked in .Net languages, or Python, or Ruby, or one of many other languages under the sun, this should be second nature to you.  I'm calling it out here specifically because some of us may never have seen it before.

### **What's going on here?**

Well, it turns out it's pretty easy.  [moment](https://www.npmjs.com/package/moment) is a JavaScript library, which has been included in our node project's `package.json` file's `dependencies` or `devDependencies`.  If you're new to node and are unfamilar with `package.json`, read more about it [here](https://nodesource.com/blog/the-basics-of-package-json-in-node-js-and-npm/).

This line of code creates a reference to everything made available in the `moment` library, and puts it into what is effectively a variable that we can use to access it.  the `'moment'` bit (in quotes) is what tells the compiler which library to get.  The other one, `moment` (_not_ in quotes) is the variable.  So from here in, we can access moment just like any other variable in this file:

```js
import moment from 'moment';

console.log(moment().get('year'));
// 2019
```

### **The un-obvious bit**

Behind the scenes, this is just taking everything that is made available by the `moment` library through `export default` [in its main file](https://github.com/moment/moment/blob/develop/src/moment.js#L95) , and stuffing it into a variable - and that variable can have _any valid name_ we want!

It may be confusing, but you absolutely could do this, if the this name made more sense to you:

```js
import ThatReallyUsefulDateLibrary from 'moment';

console.log(ThatReallyUsefulDateLibrary().get('year'));
// 2019
```

## **Importing a component from somewhere within a library**

Next up - this slightly more complex beast:

```js
import Button from '@material-ui/core/Button';
```

Here we're grabbing the `<Button />` component from the [@material-ui library](https://material-ui.com). Again, this is fairly straightforward - but it may be helpful to think of this in terms of the structure of the material-ui project.  Material-ui exports _loads_ of great stuff, and it's all organized into logical groupings.  Think of it a bit like this:

```js
// material-ui exports
const muiExports = {
  core: {
    Button: () => {}, // some component
    TextField: () => {}, // another useful component
    // and loads more
  },
};
```

With the import syntax for `Button` above, we're telling the compiler to give us a reference to the exported thing called `Button`, which is found in the `@material-ui` library under `/core/Button`.  The compiler essentially treats this like the JSON object in the snippet above.

Here's the thing - that _also_ means we can destructure it! 😁. This syntax would also work to import `Button`:

```js
import { Button } from '@material-ui/core';
```

That also means we can import _multiple things_ from `/core` in a single line!

```js
import { Button, TextField } from '@material-ui/core';
```

Cool, huh? I know this can be confusing, but try to stick with it.  It'll all start to make sense to you before long.  This brings us to our next example:

### **Importing a subset of a library by way of destructuring**

```js
import { Link } from 'gatsby';
```

Boom! This should be easy by now.  One of the things that `Gatsby` makes available is their [`link`](https://www.gatsbyjs.org/docs/gatsby-link/) component.  We're importing _just that component_ to use here.

### **Renaming an import**

But what if we already have a component called `Link` in our project? Or, what if we're making a Legend of Zelda fan-site, and `Link` is already defined in a component or variable that we can't rename?  Well, it turns out renaming something in an import is as easy as renaming something in a destructured statement.   We can rename the same component from `gatsby` like this:

```js
import { Link as GatsbyWebLink } from 'gatsby';
```

We can also rename _one or many destructured imports_ in a single statement:

```js
import {
  Link as GatsbyWebLink,
  graphql as graphqlQuery,
  useStaticQuery,
} from 'gatsby';
```

Piece of cake! 🍰

## **Relative imports**

One more quick thing - the compiler knows to look for something _you_ exported if you use a _relative path_ in your import location string:

```js
import { Layout } from '../components';
```

Just like anywhere else, you can combine and rename things to your heart's content here:

```js
import { Layout, Button as SuperButton } from '../components';
```

## **Putting it all together**

The best isn't alway last, but this is certainly the last example I've got to share today:

```js
import React, { useEffect, useState } from 'react';
```

If you've been playing along at home, this should all be familiar now - we're grabbing the default export from `react`, which we've put into the variable `react`.  We also destructured `useState` and `useEffect` from _the same library_.  If you're asking yourself "Well couldn't we also access `useState` as a child of `React`"? The answer is - well, actually, yeah!

This is perfectly valid

```js
const [loading, setLoading] = React.useState(false);
```

… but it's not as nice to type or to read as

```js
const [loading, setLoading] = useState(false);
```

They're both equally functional from an execution standpoint, but the latter is used by convention.

## **I think that's it.**

I think.  It turns out this was a really tricky post to write - there's a billion ways to import a file, and there's probably loads of cases I've missed here.  There are _definitely_ also performance and bundle size implications for some of the varieties of import syntaxes shown here.  While they're absolutely real constraints, and have real implications on your app's performance, I left that discussion for another day - purely for the sake of simplicity.

There's also the not-so-small matter that using [import](https://caniuse.com/#feat=imports) requires a transpiler like Babel or Webpack right now.  That's another super-complex universe that I'm not sure i'm equipped to explain in a single blog post.  This also means I've skipped showing how any of the above syntax works with `require()`.  There's frankly an exhausting amount to explain here - future improvements to EcmaScript and node will make it all better.

## **Say hi!**

As always, if I've gotten anything wrong here, I'd love to know about it! Drop me a line [@irreverentmike](https://twitter.com/irreverentmike).  I'd love to hear from you. 👋
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Solve* all your problems with Promise.allSettled()]]></title>
            <link>https://mikebifulco.com/posts/solve-all-your-problems-with-promise-allsettled</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/solve-all-your-problems-with-promise-allsettled</guid>
            <pubDate>Fri, 12 Apr 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[Promise.allSettled() is a new API coming to the JavaScript / ES6 standard which can help you more efficiently build node applications that make simultaneous asynchronous API calls]]></description>
            <content:encoded><![CDATA[
(Note: This post was inspired by a talk from [Wes Bos](https://twitter.com/wesbos) at JAMstack_conf_nyc. Thanks for the tip, Wes!)

Of late, I've found myself building JavaScript web applications with increasing complexity. If you're familiar with modern JavaScript, you've undoubtedly come across [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) - a construct which helps you execute code asynchronously. A `Promise`  is just what it sounds like: you use them to execute code which will (promise to) return a value at some point in the future:

Check out this somewhat-contrived example, wherein we asynchronously load comments on a blog post:

```js
const loadComments = new Promise((resolve, reject) => {
  // run an asynchronous API call
  BlogEngine.loadCommentsForPost({ id: '12345' })
    .then((comments) => {
      // Everything worked! Return this promise with the comments we got back.
      resolve(comments);
    })
    .error((err) => {
      // something went wrong - send the error back
      reject(new Error(err));
    });
});
```

There's also an alternative syntax pattern, `async` / `await`, which lets you write promises in a more legible, pseudo-serial form:

```js
const loadComments = async () => {
  try {
    const comments = await BlogEngine.loadCommentsForPost({ id: '12345' });
    return comments;
  } catch (err) {
    return new Error(err);
  }
};
```

## Dealing with multiple promises

Inevitably, you'll find yourself in situations where you need to execute multiple promises. Let's start off simply:

```js
  const postIds = ['1', '2', '3', '4', '5'];
  postIds.each((id) => {
    // load the comments for this post
    const comments = await loadComments(id);

    // then do something with them, like spit them out to the console, for example
    console.log(`Returned ${comments.length} comments, bru`);
  })
```

Easy! A quick loop gets us comments for every post we're interested in. There's a catch here, though - the `await`  keyword will stop execution of the loop until `loadComments`  returns for each post. This means we're loading comments for each post _sequentially_, and not taking advantage of the browser's ability to send off multiple API requests at a time.

The easiest way to send off multiple requests at once is wit `Promise.all()`. It's a function which takes an _array of_ `_Promise_`_s_, and returns an array with the responses from each promise:

```js
  const postIds = ['1', '2', '3', '4', '5'];
  const promises = postIds.map(async (id) => {
    return await loadComments(id);
  };

  const postComments = Promise.all(promises);

  // postComments will be an Array of results fromj the promises we created:
  console.log(JSON.postComments);
  /*
  [
    { post1Comments },
    { post2Comments },
    etc...
  ]
```

There is **one important catch (lol)** with `Promise.all()`. If _any_ of the promises sent to `Promise.all()` fails or `reject`s,  *everything*  fails. From the \[MDN Web Docs\](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global\_Objects/Promise/all) (emphasis mine):

> The `Promise.all()`  method returns a single `Promise`  that resolves when all of the promises passed as an iterable have resolved or when the iterable contains no promises. **\*\*It rejects with the reason of the first promise that rejects.\*\***

Well damn, it turns out that `Promise.all()`  is fairly conservative in its execution strategy. If you're unaware of this, it can be pretty dangerous. In the example above, it's not great if loading comments for _one post_ causes the comments for _every post_ not to load, right? Damn.

## **Enter** `**Promise.allSettled()**` 

Until fairly recently, there wasn't a spectacular answer for scenarios like this. \_\_However\_\_, we will soon have widespread access to [`Promise.allSettled()`](https://github.com/tc39/proposal-promise-allSettled), which is currently a Stage 3 proposal in front of the ECMAscript Technical Committee 39, the body in charge of approving and ratifying changes to ECMAscript (aka "JavaScript", for the un-initiated).

You see, `Promise.allSettled()`  does exactly what we'd like in the example above loading blog comments. Rather than failing if _any_ of the proments handed to it fail, it waits until they all finish executing (until they all "settle", in other words), and returns an array from each:

(this code sample is cribbed from the github proposal - go give it a look for more detail)

```js
const promises = [fetch('index.html'), fetch('https://does-not-exist/')];
const results = await Promise.allSettled(promises);
const successfulPromises = results.filter((p) => p.status === 'fulfilled');
```

## **Using** `**Promise.All()**` ** now (updated!)**

**4/26/19 Update:**

Install the [`core-js`](https://github.com/zloirock/core-js) package and include this somewhere in your codebase:

```js
import 'core-js/proposals/promise-all-settled';
```

**Original post:**

Ok, here's the thing - that's the tricky part. I wrote this post thinking it'd be as easy as telling you to use a `stage-3` preset in the `.babelrc` config on your project. As it turns out, as of v7, Babel has [stopped publishing stage presets](https://babeljs.io/blog/2018/07/27/removing-babels-stage-presets)! If that means anything to you, you ought to read their post.

The answer right now is that it's _not_ yet a great idea to use `Promise.allSettled()`, because it isn't widely supported. To boot, as far as I can tell, there's not a babel config extension which will add support to your projects. At the moment, the best you'll get is a polyfill or an alternative library which implements `allSettled()`.

I know that can be disappointing - be sure that I've got a dozen problems that would be well-served with this new bit of syntax. What I want you to focus on, though, is how amazing it is that JavaScript is continuing to grow. It's exciting and really freaking cool to see that these additions to the language are also being worked on in [public](https://github.com/tc39/proposal-promise-allSettled). Open Source is such a beautiful thing!

If you're really motivated to use `Promise.All()`  in your code, you'd do well to contribute to the process in some way. This may be something as small as writing your own polyfill, or giving feedback to the folks involved with tc39, or one of the alternative libraries to use.

## Footnote

I'll do my best to keep this post up to date. When `allSettled` is released, I'll let y'all know. 👍
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[I reclaimed 10GB of disk space from node_modules]]></title>
            <link>https://mikebifulco.com/posts/reclaimed-10gb-of-disk-space-from-node-modules</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/reclaimed-10gb-of-disk-space-from-node-modules</guid>
            <pubDate>Tue, 02 Apr 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[If you're not careful, your node projects can start to fill all the spare disk space on your computer. This one weird trick (lol) can help avoid that.]]></description>
            <content:encoded><![CDATA[
## I really don't like my laptop.

I've been using a 2017 Macbook Pro for the past couple years.  As I'm sure you've heard, it is a fiercely disappointing device largely due to its courageous lack of ports, flawed keyboard design, and astonishing sticker price.  My personal machine is a 13" version, with 16GB of memory, _no_ touchbar, and a 256GB SSD. When I bought it, upgrading to 16GB of memory seemed far more important splurging on processor speed or disk space.  That's probably still true - but I've found myself endlessly frustrated by the tiny capacity of the SSD in my day to day work.

Roughly once every 6 weeks, my machine grinds to a halt as I run out of disk space, so I have to suffer through all the usual suspects for clearing up some room:

- empty the trash
- delete unused applications
- make sure all my photos are moved to my NAS, cloud storage, and offsite archives
- remove old virtualbox VM images

## A new kind of purge

Last week, however, I came across a surprising new way to free up some disk space: clearing out `node_modules` directories.

Curiosity hit me, and I searched my mac for folders named `node_modules`. This is what I found:

- My machine has `7,731` _total_  `node_modules` folders.  Wow!
- Under `~/src/**`, where I keep all of my dev projects, I had a grand total of 7,719 `node_modules`
- These folders contain _hundreds of thousands of files_ (which should be no surprise), and took up nearly **10GB** of disk space!

## Turtles all the way down 🐢🐢🐢

That last number was a bit of a revelation to me at first.  If you're unfamiliar, `node_modules` contains a copy of each of the [npm packages](https://www.npmjs.com) which you add to your project (with `npm install` or `yarn add`, etc) on projects which use node.  Each of them are pinned to a specific version, which is typically specified in `package.json`.

Somewhat logically, each of the dependencies in your project's `node_modules` directory may also have a `node_modules` directory, containing their dependencies, each pinned to a specific version (again, defined in the `package.json` file of that dependency).

This is where file and disk space bloat happen - the libraries you add to your project may each contain dozens of dependencies, each of which have dozens more, etc etc, all the way down to super basic node and C libraries which make up the fundamental building blocks of node.

(Mind you - This is oversimplifying things a bit - depending on how you set up `npm` or `yarn` , there is _some_ optimization done here. If one version of a given npm module is required more than once by your dependency tree, it may only appear once.)

## The fix

Actually, this was pretty easy to fix.  I did a search for all of the `node_modules` folders under `~/src/**`, and deleted all of them, right from finder (sorry, terminal apologists).  I then emptied the trash on my mac, and I was 10GB richer.

<Image
  publicId="posts/reclaimed-10gb-of-disk-space-from-node-modules/disk-space"
  alt="Screenshot of MacOS folder info for a node_modules search"
  caption="10 GB of space, just for node_modules!"
/>

## What did it break?

It's been a week since I've done this. So far the only inkling of a downside is that when I revisit projects I'm actively working on, I need to run `yarn install` to recreate the `node_modules` directory there. I switch between a good handful of projects, and I'm back to a fair few directories, but at least these are just the ones I'm currently using. I'm good with that.

<Image
  publicId="posts/reclaimed-10gb-of-disk-space-from-node-modules/terminal"
  alt="Terminal search for directories called node_modules"
  caption="A week later, I'm back up to 1209 node\_modules directories"
/>

## Can we do better?

There is an alternative to `npm` and `yarn` called [`pnpm`](https://pnpm.io/), which claims to be a "Fast, disk space efficient package manager".  Its primary feature looks promising:

<Image
  publicId="posts/reclaimed-10gb-of-disk-space-from-node-modules/pnpm"
  alt="pnpm's value prop - one version of each package saved to disk"
  caption="One version of each module sounds great"
/>

I haven't tried it yet, but will certainly be giving it a shot.

## Epilogue 

I think it's fair to say that this is a problem that the folks at npm and Facebook (who maintain yarn) are also looking closely at. My guess is that some healthy competition will improve this disk space nightmare... hopefully before I'm forced to buy a laptop with 1TB of storage. 🥳

---

### More reading

I'm certainly not the first one to write about this.  Some more great reading for you to check out, if you're interested:

- [The node_modules problem](https://dev.to/leoat12/the-nodemodules-problem-29dc)
- [What Happened When I Peeked Into My Node_Modules Directory](https://medium.com/s/silicon-satire/i-peeked-into-my-node-modules-directory-and-you-wont-believe-what-happened-next-b89f63d21558) (this is the infamous tongue-in-cheek Guy Fieri article)
- [What’s really wrong with node_modules and why this is your fault](https://hackernoon.com/whats-really-wrong-with-node-modules-and-why-this-is-your-fault-8ac9fa893823?gi=1ff87c0f83ba)
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Egg sticker update: We raised $176 NZD!]]></title>
            <link>https://mikebifulco.com/posts/sticker-update-we-raised-176-nzd</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/sticker-update-we-raised-176-nzd</guid>
            <pubDate>Thu, 28 Mar 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[Last week I posted about some stickers I designed and had put up for sale to benefit victims of the shooting in Christchurch, NZ.  They sold out far, far more quickly than I ever would have guessed.]]></description>
            <content:encoded><![CDATA[
## We did it!

You all are amazing.  Last week I posted about [some stickers I designed](https://mikebifulco.com/posts/egg-them-all) and had put up for sale to benefit victims of the shooting in Christchurch, NZ.  They sold out far, _far_ more quickly than I ever would have guessed.  Having never done this before, I ordered a modest print run.  The next time I do something like this (and there _will_ be a next time), I'll double the order, at the very least.

This morning I made a donation to the [LaunchGood campaign](https://www.launchgood.com/campaign/support_for_the_families__victims_of_the_new_zealand_mosque_shootings), thanks to all of you:

<Image
  publicId="posts/sticker-update-we-raised-176-nzd/donation-confirmation"
  alt="Confirmation of our community donation to LaunchGood"
  caption="A powerful reminder that community is amazing. Thank you all!"
/>
.

It's a drop in a (thankfully) much larger bucket, but having some positive impact in what was starting to feel like a hopeless, dark time really means a lot to me.

Thank you all - keep making the world a better place. ❤️
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Understanding JavaScript Destructuring Syntax]]></title>
            <link>https://mikebifulco.com/posts/deconfusing-javascript-destructuring-syntax</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/deconfusing-javascript-destructuring-syntax</guid>
            <pubDate>Tue, 26 Mar 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[Destructuring syntax in es6 (or es2015, etc) JavaScript is a wonderfully useful bit of the language.  It allows you to extract values from an Object and assign them to a new variable in one statement -- but it can be confusing to read.]]></description>
            <content:encoded><![CDATA[
(note: the header photo from this article is from [Dakota Roos](https://unsplash.com/photos/dSRhwPe6v9c?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/structure?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText).  Thank you for your work!)

[Destructuring](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) syntax in es6 (or es2015, etc) JavaScript is a wonderfully useful bit of the language.  It allows you to extract values from an `Object` and assign them to a new variable in one statement.  If you've not come across destructuring before, a fairly basic case looks like this:

```jsx
const person = {
  name: 'Mike Bifulco',
  height: 556,
  fears: ['heights', 'fire'],
};
const { name } = person;
console.log(name); // this will print 'Mike Bifulco'
```

So - what's happening here is pretty simple.  We are creating a `const` called `name`, and filling it with the value found in `person.name` . This is accomplished using the bracket structure to the left of the `=`.

(If you haven't seen or used this before, it can definitely be confusing.  Don't fault yourself for that - it'll become second-nature before long.)

There's are many other useful things you can do by way of destructuring.  For me, the most common among them are:

## Renaming

If you want to pluck a value from within an object, but also need to rename it (for purposes of code readability, perhaps), you can do so in one line:

```jsx
const person = {
  name: 'Mike Bifulco',
  height: 556,
  fears: ['heights', 'fire'],
};

const { height: currentHeight } = person;

console.log(currentHeight); // 556
console.log(height); // undefined!
```

Just like that, we've assigned `person.height` to `currentHeight` in one line.  Sweet!

## Extracting

You can extract one value from an object, and create another variable with everything else, you can do that, too:

```jsx
const person = {
  name: 'Mike Bifulco',
  height: 556,
  fears: ['heights', 'fire'],
};

const { fears, ...fearlessPerson } = person;

console.log(fearlessPerson.fears); // undefined!
console.log(fears[0]); // heights
```

This is a combination of destructuring syntax and the spread operator (`...` ). Very handy!

## Hard mode: complex destructuring

So both extracting and renaming things with destructuring are fairly straightforward.  I've been using both of those tricks comfortably for a while now.  In the past few months, I've been poking around with [GatsbyJS](https://gatsbyjs.org) for a few different projects (including my own website).  When I was starting to customize and implement my own Gatsby theme, I started to see some _really_ complex looking destructuring syntax, used to pull nested values from GraphQL queries throughout the site.

I was really thrown - at first glance, it's not obvious what's going on.  Let's take a look at an example, pulled from a React component used to render a single page in a Gatsby theme:

```jsx
const singlePage = ({
  data,
  location,
  pageContext: { nextPagePath, previousPagePath },
}) => {
  return <p>...react component markup</p>;
};
```

There's a combination of things happening in the definition of the `singlePage` React component.  Let's look at just that destructure, and simplify it a bit:

```jsx
const {
  data,
  location,
  pageContext: { nextPagePath, previousPagePath },
} = props;
```

It took some staring, and some playing around to figure out what was being accomplished here, so let's run through it step by step:

1.  The right side of this `const` is `= props` which tells us that all of these values are being destructured from an object called `props` .
2.  The first two values, `data` and `location` make good sense - they look just like the examples above.  This line will create a `const` from each of those two paths in the `props` object.
3.  `pageContext` is where things get interesting -  this is _another_ destructuring.  Somewhat confusingly, the values that are being pulled from `props` here are `nextPagePath` and `previousPagePath` . There is no variable being created for `pageContext` .

If that description didn't help - I don't blame you.  It really took some practice for me to understand what's going on.  I'm not even sure I would recommend using this syntax - it's not particularly easy to read, especially when tools like `prettier` squish it onto fewer lines.

With that said, it seems to be the way-to-go when pulling data from GraphQL queries on Gatsby (and likely elsewhere). If you're going to be working in that world, it's a good idea to familiarize yourself with what's going on here.

## Homework

I think the best way to get used to this syntax is just play around with it yourself.  I've created a JSBin which you can use to experiment a bit.  I'd love to hear how you do with it! [Check it out here](https://jsbin.com/kifizij/2/edit?js,console).

Some challenges for you:

- Rename the variable `displayName` to `currentUserName`
- Extract `editedBy` into its own variable
- Create an object called `meta` which contains everything in `directions` except for the `contactNumber`

## Wrapping up

I'd love to hear how you fare with this - I found myself writing this post as a matter of self-help.  Often times these things won't be made concrete until I practice in isolation for a while.  What creative uses do you have for destructuring? Did I get anything wrong here? Let's talk about it.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Quick tip: Here's how to uninstall Postgres from your Mac]]></title>
            <link>https://mikebifulco.com/posts/quick-tip-uninstall-postgres-from-your-mac</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/quick-tip-uninstall-postgres-from-your-mac</guid>
            <pubDate>Tue, 19 Mar 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[Uninstalling Postgres database software from a computer running MacOS isn't super straightforward - this is what I found helpful.]]></description>
            <content:encoded><![CDATA[
# The Problem

Earlier tonight, my Macbook Pro decided it was done having disk space, and in the middle of a Time Machine backup, it started gnawing through every last bit of free space I had left.  Great.

In a frenzy of panic-and-uninstall, I came across an install of [Postgres](https://www.postgresql.org/) 9.x which I haven't used in quite a long time.   I wanted to carefully uninstall it, in part because I knew that the Postgres install process does loads of not-easy-to-clean things to your mac, including adding a user account to your device, and an app, and a bunch of settings.

My goodness, what a ride.

# The Solution

There's not a simple uninstaller for _everything_, so far as I can tell.

Eventually, the gods of web search brought me to [this beautiful gist](https://gist.github.com/Atlas7/b1a40a2ffd85728b33e7) on GitHub, which listed everything I needed to do to complete the uninstall safely. (I've also [forked](https://gist.github.com/mbifulco/1e44a2e9b7e3bd784f01ef5a138da829) the gist, in case the original ever disappears 😅).

I don't want to take any credit for the work - it seems to have originally come from [this blog post](https://hzchirs-blog.logdown.com/posts/142678-how-completely-uninstall-postgresql-9x-on-mac-osx) from 2013, which was not returned by my Bing-fu (yeah, you read that right).  

I'm posting it here in the hopes that will help some other soul in the future who is going through this experience.  Good luck out there!
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Egg them all: a fundraiser for New Zealand]]></title>
            <link>https://mikebifulco.com/posts/egg-them-all</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/egg-them-all</guid>
            <pubDate>Mon, 18 Mar 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[Get yourself some of these eggtastic stickers - gun violence is intolerable, and we need sensible gun reform. 100% of proceeds go to charity!]]></description>
            <content:encoded><![CDATA[
I wish I could do as much as I can to spare you the pain of hearing about the horrible shooting that happened in New Zealand last week.

But, as it works out, I'm really (really) mad about it.  So I made these angry little eggy guys, in honor of a particularly [woke-ass seventeen year old](https://www.youtube.com/watch?v=aht5XZFflzQ) who has made the news for publicly rebuking an Australian Senator who had some pretty disgusting views on the matter.

So, I've had a small run of these stickers made.  I'm going to sell them from my site, with 100% of proceeds going to the LaunchGood charity for the [United for Christchurch Mosque Shootings](https://www.launchgood.com/campaign/support_for_the_families__victims_of_the_new_zealand_mosque_shootings).

# So, want some stickers?

I'm not sure the best way to make this happen, but I'm thinking $5 for the pair of them.  They'll come die-cut, on a small sticker sheet which is about 2"x4" in size (so the stickers will be just smaller than half that size)  Want a set? Jump over to the [shop page](https://mikebifulco.com/shop#angry-little-egg), and we'll make it happen. Thanks in advance for putting some good energy into the world.

# Update: Sold out!

Thanks for all of your support - I had a small run of stickers made up, and they were all gone within 48 hours! Next time I do something like this, I'll double the order.  Thank you all for your help.  It means the world ❤️

<Image
  publicId="posts/egg-them-all/sold-out"
  alt="Screenshot of a donation to the Cristchurch Mosque charity for $173.33 USD"
  caption="We donated $173.33 to charity, thanks to you."
/>
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[5 Chrome extensions I use for productivity]]></title>
            <link>https://mikebifulco.com/posts/chrome-extensions-i-use</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/chrome-extensions-i-use</guid>
            <pubDate>Wed, 13 Mar 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[An efficient workday is helped tremendously by having a handful of productivity boosters in your quiver. I use these extensions for Chrome to make my day a little nicer.]]></description>
            <content:encoded><![CDATA[
# Dashlane

<Image
  publicId="posts/chrome-extensions-i-use/dashlane"
  caption="Dashlane password manager Chrome Extension"
/>

First thing's first - get yourself a good password manager. I chose [Dashlane](https://www.dashlane.com/en/cs/mvKFbmiWCXxQ) (referral link) a few years back because of its security dashboard, which alerts you to your accounts which have been found in data breaches, any passwords you've used more than once, or passwords which are insecure.  Other great options are [1Password](https://1password.com/) and [LastPass](https://www.lastpass.com/).

# Elevate for Strava

<Image
  publicId="posts/chrome-extensions-i-use/elevate-for-strava"
  caption="Elevate helps me see how far I've ridden this year compared to years past."
/>

If nothing else, I am two things: a data nerd, and a [cyclist](https://www.instagram.com/p/Bqkko6CBtTu/).  I love cycling - it is my go to for exercise, meditation, and transport whenever possible.  Strava is the best service for aggregating GPS and biometric data recorded during cycling activities.  [Eleva](https://thomaschampagne.github.io/elevate/#/landing)[te](https://chrome.google.com/webstore/detail/elevate-for-strava/dhiaggccakkgdfcadnklkbljcgicpckn) is sugar on top of Strava - it adds a horde of wonderful data visualizations and progress measurements to the experience.  I frequently turn to the fitness trend tab to motivate myself to ride more regularly.  Did I mention that Elevate is [Open Source](https://github.com/thomaschampagne/elevate)? Heck yeah.

# FIO / Figure it Out

<Image
  publicId="posts/chrome-extensions-i-use/fio"
  caption="Screenshot of Figure It Out / FIO"
/>

One of the great luxuries of working in technology is being able to connect with people from wherever in the world you are.  In the past few years, I've been able to work from all over North America, Asia, and Europe, with folks spanning dozens of time zones.  I use FIO to see what time it is for my colleagues around the world.  With FIO installed, your new tabs in Chrome will show information about a collection of time zones (of your choosing), as well as a rough visualization of the state of daylight (or night light) where they are.  Brilliant!

# μBlock Origin

<Image
  publicId="posts/chrome-extensions-i-use/ublock"
  caption="uBlock Origin's README on GitHub"
/>

An ad-blocker that works reliably and quickly, and is [open source](https://github.com/gorhill/uBlock).  Be still my heart! uBlock stops annoying mid-roll ads on YouTube, and removes in-page ads from all over the internet.  Big quality of life improvement, and it's completely free.

# Toggl Button

<Image
  publicId="posts/chrome-extensions-i-use/toggl"
  caption="Toggl's use is simple: I use it as a timer for everything"
/>

I go through occasional phases where I track _all_ of my activities in a time tracker.  For me, the app of choice is Toggl, which is simple and intuitive, and lets me keep track of how long things are taking me via an app on my phone, their website, and this lovely browser extension.  It's clean and simple, and offers loads of integrations and customizations that might fit your productivity workflow, too.  The [Toggl Button for Chrome](https://chrome.google.com/webstore/detail/toggl-button-productivity/oejgccbfbmkkpaidnkphaiaecficdnfn) lives right next to the address bar, and stays out of the way when you don't need it.  I've gotten away with their Free plan for the most part - if you're using time tracking to bill customers, it's definitely worth looking at their paid features.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Stop speaking into the top of your Blue Yeti Microphone]]></title>
            <link>https://mikebifulco.com/posts/my-favorite-design-problem</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/my-favorite-design-problem</guid>
            <pubDate>Thu, 28 Feb 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[No, really, it doesn't work that way.  It will sound loads better if you stop talking into the top of your Blue Yeti mic. It's an easy mistake to make.]]></description>
            <content:encoded><![CDATA[
It's one of those things. Once you see it, you absolutely cannot _un-see_ it. You probably ended up here because someone saw you using your Blue Yeti on camera, and linked you to this article. This is an easy change, and it's for your own good.

## Enter the yeti

If you're a hobbyist podcaster, you've almost certainly come across recommendations for the [blue yeti](https://www.bluemic.com/en-us/products/yeti/) microphone. For about a hundred bucks, you get a decent quality condenser microphone that will plug into your computer via USB. Frankly, for the _vast_ majority of people getting into podcasting, it'll be more than you ever need, particularly if you use it correctly.

Funny enough, there is one other yelly-screamy ~~article~~ podcast about [if you're going to use a blue yeti, please use it right](https://podcasts.apple.com/us/podcast/if-youre-going-to-use-a-blue-yeti-please-use-it-right/id1175250113?i=1000569052086), but even that diatribe doesn't cover what I'm so peeved about. The Yeti has a problem - its audience is casual enough not to be expert on high end microphones, and they're not incentivized to learn about their new device.

Check this out:

<Image
  publicId="posts/my-favorite-design-problem/getting-started"
  alt="Excerpt from the user manual on Blue's website"
  caption={
    <>
      Excerpt from the user manual on Blue's{' '}
      <a href="https://www.bluemic.com/pdf/manuals/yeti/Blue_Yeti_QuickStartGuide-EN.pdf">
        website
      </a>
    </>
  }
/>

Most peoples' exposures to microphones are limited to weddings and bar mitzvahs, and the occasional rock concert or other public event. They're used to seeing folks using a handheld mic, and speaking into the top of it -

<Image
  publicId="posts/my-favorite-design-problem/performer-with-mic"
  alt="A performer singing into a handheld microphone"
  caption={
    <>
      A performer singing into a handheld microphone.
      <br />
      <span className="credit">Ana Paes on Unsplash</span>
    </>
  }
/>

If you take apart a Yeti, underneath that chic metal-grate dome, you'll actually find 3 microphone capsules - none of them pointed upwards. There is no combination of settings on the Yeti that will yield great audio if you're speaking into the top of the device.

If you ask me (and you do), this isn't user error. The physical design of these types of microphones is ambiguous enough that their proper use isn't apparent. Folks who buy a Yeti are generally only exposed to microphones with a drastically different form factor - how are they supposed to know better?

## What to do about it

At some level, as long as they're selling like gangbusters, there's nothing that should motivate Blue to ever change the sleek design of their Yeti. In fact, they've expanded their Yeti lineup since its inception. You'll notice this design challenge is now present across a good few of [Blue's microphones](https://www.bluemic.com/en-us/).

<Image
  publicId="posts/my-favorite-design-problem/blue-lineup"
  alt="A few of Blue's microphones from their website - all of which have the same design challenge"
/>

If, hypothetically, Blue wanted to improve on this design to ensure that users of their mic had the best possible recording results, what could they do? Since they already include a whole-page sized warning in the bundled instruction manual for the product, I think the next best step is to physically change the product. Something as simple as a graphic silkscreened onto the mesh dome might do the trick:

<Image
  publicId="posts/my-favorite-design-problem/target"
  alt="Why not just put a target on the thing?"
/>

## Footnote

I should add that I don't mean to target Blue specifically. This isn't just about their microphone. This happens with any number of other mics from other companies with similar design. The Yeti just happens to be the most popular. In fact, I have one, and I use one - and it's great! Maybe that's why this burns me up so much.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Embracing Prettier]]></title>
            <link>https://mikebifulco.com/posts/embracing-prettier</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/embracing-prettier</guid>
            <pubDate>Mon, 25 Feb 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[Prettier.js is a fantastic way to systemize and automate your project's code style.]]></description>
            <content:encoded><![CDATA[
[Prettier](https://prettier.io/) is "an opinionated code formatter", built to fit into your developer workflow. It's been out in the world for quite a while now, but until today, I had never successfully used it in any project I worked on. In truth, there's a few reasons for this:

1. I was really used to (and really happy with) using [`eslint-config-airbnb`](https://www.npmjs.com/package/eslint-config-airbnb) for all of my projects. Across the board, I'd configured every node/react/js-based project to use the same airbnb config, and had a functional workflow for ensuring code quality at some level through those lint checks.
1. I was too busy to switch. This is a bit of a bullshit answer, since one of prettier's biggest advertised features is its lightweight setup. That's not to mention the amount of time that prettier _should_ save me once in use. A bad excuse.
1. **I could never get it to work(!)** So - despite being adept at reading through docs, every single time I started down the path of setting up prettier on a project, I couldn't get it to work. Despite my peers shouting from the rooftops about how deliciously sublime prettier makes the development workflow, it seemed like a permanent impasse.

## So what was the problem, then?

Well, it all came down to a formatting issue. The header image for this article tells the story: every time I installed prettier, when I triggered formatting with Visual Studio Code's `formatOnSave` setting, my React/jsx components would get scrambled. After some squinting, it appears that something was telling my IDE to treat these jsx files as pure Javascript, where `<` means "less than", and shouldn't ever be treated as the start of a component `<tag>`.

## The Fix

In my case, it came down to a conflicting extension for Visual Studio Code. It turns out that the [beautify](https://marketplace.visualstudio.com/items?itemName=HookyQR.beautify) plugin takes precedence over Prettier in its default configuration. After some plucking around, I determined that if I _disable_ Beautify in the workspace where I'm using prettier, everything just suddenly... works. 😍

<Image
  publicId="posts/embracing-prettier/disable-beautify"
  alt="VS Code's extension interface showing the Beautify plugin, with an arrow pointing to the option that says 'Disable (workspace)'"
  caption="Disable beautify in your project workspace, and everything gets better"
/>

In my case, that was it! Prettier is now working as advertised.

The jury's still out on whether prettier is life-changing for me, but it's working, at the very least. My next step was to jump into `.prettierrc`, and override _just a few_ settings:

```js
    {
      "trailingComma": "es5",
      "semi": false,
      "singleQuote": true,
      "jsxSingleQuote": false,
      "tabWidth": 2
    }
```

_(note: this is my first time writing JavaScript without semicolons. I'm really breaking the rules now!)_
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[It was time - starting a writing habit to share my expertise]]></title>
            <link>https://mikebifulco.com/posts/it-was-time</link>
            <guid isPermaLink="false">https://mikebifulco.com/posts/it-was-time</guid>
            <pubDate>Sun, 24 Feb 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[I've got some strong opinions on things - I hope that's okay. Thankfully, this is not just another 'hello world' post]]></description>
            <content:encoded><![CDATA[
### This is happening.

Hey - here's hoping I can use this as a place to help others, and get my thoughts onto paper.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[You are not your user. Except when you are.]]></title>
            <link>https://mikebifulco.com/newsletter/you-are-not-your-user</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/you-are-not-your-user</guid>
            <pubDate>Wed, 03 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA["You are not your user" is fundamentally good advice. It's also occasionally wrong, but in a very useful way.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

"You are not your user" is fundamentally good advice. It's also occasionally wrong, but in a very useful way.

## You Are Not Your User

One of the first things you learn in UX is that **you are not your user**.

This is usually true, and is worth repeating because (all) people are very good at forgetting it. The more time you spend with a product, the harder it gets to see it clearly. You know where everything is. You know why the confusing part is confusing. You know the history behind that _one_ weird button label, and the customer complaint that led to that one edge case, and the Slack thread where everyone finally agreed to ship the thing as-is because it was Friday and everyone was tired.

That kind of knowledge is useful for building the product, but it's terrible for seeing the product.

It creates snow blindness. The product becomes so familiar that you stop noticing the parts that are strange, brittle, or needlessly complicated. You stop seeing the first five minutes because you've already lived the next five years.

<SponsoredSection
  imagePublicId="sponsors/tripo-ai/project-eden"
  sponsorName="Tripo AI"
  CTAtext="Start Creating with Tripo AI"
  href="https://www.tripo3d.ai/?utm_source=newsletter&utm_medium=sponsorship&utm_campaign=launchtinyimp"
>

**Explore AI-native 3D workflows for your product.**<br />
Turn your ideas into high-quality 3D assets faster, including product visualization, interior and home design, gaming, film, VR/AR, digital twins, robotics simulation, and interactive experiences.

</SponsoredSection>

This is one reason I try not to say "users" when I can avoid it. The problem isn't with the word itself - but rather that it adds a layer of euphemism between designers and the _people_ they are trying to build for. It's a small abstraction that cuts both ways; at times designers say "users" to sound smart, and in other moments "users" is a way to forget the reality that there are people on the other side of these screens.

The _person_ on the other side of the black mirror is probably busy. They may be distracted. They may be skeptical. They may be trying to get something done while their kid asks for a snack, their dog barks at the mailman, and their coffee gets cold.

If you want to build good products, you have to keep remembering to [imagine others complexly](https://en.wikipedia.org/wiki/Wikipedia:Imagine_others_complexly).

## Except When You Are

Every once in a while, though, you really are building for yourself.

That's how my project [Guithub](https://guithub.org) started.

Guithub is an online guitar tuner I recently built and published for myself ("recently" is doing a lot of work here. I've owned the domain since 2020, which means this tiny side project managed to take me roughly six years to finish!).

I play guitar and sing, and for years I played a couple times a month at bars around town. Like most guitar players, I own tuners. They're fine - "does what it says on the tin", as they say, but for the most part they're designed to be _generically_ useful for a wide range of musicians in a wide range of contexts.

Tuners have always bothered me in a few specific ways:

Tuners are built around standard guitar tuning (EADGBE). Most assume you are tuning open strings. If you put a capo on after tuning, it starts to sound a little weird the further you move up the neck. And if, hypothetically, you play a lot of songs in alternate tunings because you spent too much time listening to _Bon Iver_ or _The Tallest Man on Earth_, you end up doing more mental translation than you want to do while standing in front of people.

I also usually play with a laptop or tablet in front of me, with chord charts and lyrics - because I just don't have it all memorized.

All this to say: a tuner _built for me_ isn't complicated -- but it _is_ fairly different from the one you'll pull out of the box from your local guitar shop.

I wanted a tuner that worked the way I actually play. I wanted to open a browser, pick an instrument, pick a tuning, set a capo position, and get back to playing.

That was the whole idea.

Not a universal tuner for every musician in every context: a tuner for me.

## The Six-Year Side Project

The annoying thing about Guithub is that I understood the basic problem pretty well.

I studied computer science and mechanical engineering, so the math and physics behind a tuner are not especially mysterious. You listen to a sound, find the fundamental frequency, map that frequency to a note, and tell the musician whether they are sharp or flat.

That sounds straightforward until you try to make it work in a browser, on real devices, in real rooms, with real instruments.

Sound is messy. Instruments produce harmonics. Microphones vary wildly. Rooms are noisy. Browsers have their own constraints. And there is a big difference between understanding a Fourier transform and building a pitch detector that feels fast and reliable enough to trust.

The first version I built could identify notes reasonably well, but not well enough that I would have wanted to use it on stage. So the project sat there for years, in the extremely crowded drawer where I keep ideas that are "basically working" and therefore nowhere near done.

Then, eventually, I had the embarrassingly obvious thought that there might already be an npm package for this.

Of course there was.

With a library handling the core pitch detection, and an LLM helping me wire things together and test the important paths, I finally got past the part that had kept me stuck. That freed me up to work on the actual product.

The product was never "can I implement signal processing from scratch?"

The product was "can I tune quickly and get back to the song?"

That distinction matters. A lot of side projects get stuck because the interesting technical problem disguises itself as the product. Sometimes it is. Often it's just the thing standing between you and the product.

## The Homepage Is the Product

Because Guithub is built for the exact situation I kept running into, the homepage is the product.

There is no ceremony: go to [guithub.org](https://guithub.org), modify default settings if you need to, and get to tuning. It supports guitar, bass, banjo, and ukulele. It supports different tunings. It supports capo positions. It is meant to be useful on the device I probably already have in front of me when I am playing.

I have tried not to turn it into a fluffy product homepage, even though search engines and LLM indexers would prefer that. It's a funny tension: SEO wants explanation, but a great product experience is (in this case) just the thing itself.

For this project, I'm trying to let the tool win.

The best version of Guithub is not impressive. It's forgettable in the right way. It opens quickly, helps you tune, and lets you move on with your life.

That is what I wanted as a musician - and if that's what other guitarists want, I'll be super happy to see it.

## Build the Thing That Keeps Bothering You

This is the part where "you are not your user" gets complicated.

You should not assume everyone is like you. That's a path to misguided products, confusing defaults, and founders confidently explaining that customers are wrong for not understanding the brilliant thing they built.

But... _sometimes_ your own frustration is a useful starting point. Not because it makes you representative of the whole audience, but because it gives you access to details and compassion that are hard to fake.

You have _felt_ existing options fail you. You know which parts are merely annoying and which parts actually matter. You know the little moment where you mutter under your breath and think, "why does this work this way?"

That moment is worth paying attention to.

[Craftwork](https://craftwork.com) came from a version of this too. Finding a reliable, professional, high-quality painting company for your home should not feel like a gamble, but it often does. That frustration was specific enough to give us a place to start.

Specific frustration is not the same thing as product-market fit. It's not proof that other people care. It's not a business model. It's not distribution.

But: it _is_ a signal.

Sometimes the thing that keeps bothering you is just a thing that keeps bothering you.

Sometimes it's the first draft of something useful.

---

## Guitarists, try my sweet tuner

If you play music ([_like me!_](https://guithub.org/about)), I would love for you to try [Guithub](https://guithub.org). And if it breaks, annoys you, or gets in your way, please tell me. You can reply here or email me at [hello@mikebifulco.com](mailto:hello@mikebifulco.com).
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Dunning-Kruger for Vibe Coders]]></title>
            <link>https://mikebifulco.com/newsletter/dunning-kruger-for-vibe-coders</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/dunning-kruger-for-vibe-coders</guid>
            <pubDate>Tue, 28 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[The first thing AI teaches you about coding is confidence. The second is why that's a problem. Let's talk about the Dunning-Kruger effect.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

AI makes it easier than ever to build something that feels like it works. It does not make it easier to understand what you've built, how it works, or how it might break.

---

## Learning Feels Like Progress, Until It Doesn't

One of the most enjoyable parts of learning something new is how quickly it can feel like you're getting good at it.

You start from nothing, make a bit of progress, and then suddenly things begin to click. A few early wins stack up, and you get that dopamine boost from the feeling that you have a handle on what you're doing. If you've ever watched someone pick up a new skill for the first time, you've probably seen this happen. Beginner's luck and a handful of successful attempts can create a surprising amount of confidence.

The problem is that this confidence is often built on a very small slice of reality.

When you've been doing something for a long time, you develop an intuition for how much there is to know. Beginners do not have that perspective yet, which makes it easy to overestimate how far along they are. Eventually, if they stick with it, they run into the limits of their understanding. That moment, when things stop working as expected and the gaps become obvious, tends to be uncomfortable, but it is also where real learning begins.

This pattern is well understood as the [**Dunning-Kruger Effect**](https://en.wikipedia.org/wiki/Dunning%E2%80%93Kruger_effect). More formally, it describes the tendency of people with a small amount of experience to be overconfident in their abilities. It also captures the inverse tendency, where highly skilled people underestimate their relative competence. The effect was first identified by psychologists [David Dunning](https://en.wikipedia.org/wiki/David_Dunning) and [Justin Kruger](https://en.wikipedia.org/wiki/Justin_Kruger) in 1999.

The Dunning-Kruger Effect is a natural, typical pattern of human learning. It is **not** a sign of low intelligence. It's a lack of experience.

The issue is not confidence itself. It is confidence that has not yet been tested.

---

## AI Changes the Pace, Not the Fundamentals

When everyone has superpowered LLMs at our fingertips, the game changes. What's different now is how quickly someone can get an early sense of competence.

Rather than learn about weather patterns or signal processing or buying ads on Google (or whatever problem you're working on), you can slap a few sentences together and send it off to your LLM of choice, and in moments you can have a working prototype.

That's really cool - but it should give you at least a _little_ anxiety.

Modern AI tools make it possible to build things that would have taken weeks or months in a matter of hours. Someone who has never written code before can assemble a working application, connect it to real data, and deploy it to the internet without fully understanding how any of it works. The results are often impressive enough to reinforce the feeling that they are on the right track.

It is hard to overstate how big of a shift this is. The first program I ever wrote added three numbers together and printed the result to a terminal. It was simple, but it forced me to understand every step along the way. That constraint is largely gone now.

What has not changed is how computers behave. They still do exactly what you tell them to do, even when what you told them to do is incomplete, inconsistent, or quietly destructive. AI can help you write those instructions faster, but it does not guarantee that they're correct.

---

## Experience Is Mostly About Anticipating Failure

If you spend enough time around production systems, you start to realize that a large part of the job is not building new features, but anticipating and avoiding failure modes.

That is why experienced teams invest so much energy in things that can feel tedious at first glance. They plan before they build. They test changes in environments that are isolated from real users. They introduce safeguards like feature flags and rate limits, and they maintain the ability to roll back changes when something goes wrong. These practices exist because systems are fragile in ways that are not always obvious, especially early on.

If you are new to building software, and especially if you are learning through AI-assisted tools, there is a good chance you have not yet had the experience that makes these practices feel necessary. That is a normal part of the process. The risk comes from assuming that you can skip that part entirely, or worse, _not knowing_ that you should be doing it.

Dunning-Kruger comes for us all.

---

## The Real Risk Is Misplaced Confidence

The tools themselves are not the problem. The combination of speed and confidence is.

When you can build something quickly and it seems like it works right away, it's natural to trust it more than you should. That trust can extend further than it ought to, especially when the system begins to handle real data or real users.

Here's my April 2026 Prediction: Sometime soon, someone is going to push something into a context where the stakes are higher than their understanding of the system, and it is not going to behave the way they expect. Overconfidence will meet under-experience, and something will come crashing down. This will cause real, profound problems for a business that has been otherwise successful, and the dominos will start to fall. Will it be a fortune 500 company, a moonshot startup, a government agency, or a small business? I don't know the answer to that, but I feel confident that something will happen, and we'll all learn hard lessons from it.

It is not hard to imagine how it plays out. Ask your engineer friends about their biggest fears for failures in production: A script runs twice when it should have run once. A production database gets deleted with one little line of code. A set of permissions is broader than intended. A piece of logic that seemed harmless at small scale behaves very differently under load.

None of these scenarios are new, but the barrier to encountering them is now much lower.

---

## What This Means in Practice

If you have been doing this for a while, your role is not to discourage people from using these tools. It is to help them use them safely.

That usually means putting guardrails in place where they matter most. Limiting access to production systems, being deliberate about how credentials are managed, and creating environments where experimentation does not carry real risk all go a long way. Just as important is being open to the fact that people will be exploring vibe coding tools. That curiosity is a good thing! When exploration happens in the open, it is much easier to guide it.

If you are newer to this world, **the most useful thing you can do is adopt a deliberate skepticism** toward the tools you use and anything you build.

Assume that your system has edge cases you have not considered. Look for the places where it might break, especially under conditions that are slightly different from what you tested. Make sure you have a way to recover when something goes wrong, whether that means backups, staging environments, or simply the ability to turn something off quickly.

It is also worth writing down how your system works, at least at a high level. The decisions you make early on tend to fade from memory faster than you expect, and when something breaks, that context becomes incredibly valuable.

Perhaps most importantly, resist the urge to treat speed as the primary goal. Building quickly is useful, but building something you understand is what allows you to keep it running.

---

## Understanding the Tool Matters More Than Using It

None of this is an argument to avoid AI. These tools are genuinely useful, and they are only getting better.

But it is important to understand what they are doing. Large language models are not reasoning about your system in the way a human collaborator might. They are generating likely sequences of text based on patterns in their training data and the context you provide. That can produce very convincing output, but it does not come with guarantees.

The people who benefit most from these tools are the ones who can engage with them critically. They can ask better questions, recognize when something looks off, and take the time to verify the results before relying on them.

In practice, that means [spending more time reading and writing](https://mikebifulco.com/newsletter/next-great-engineering-skill-is-context-not-code) than you might expect. It means thinking through your systems in plain language, not just code, and being able to explain what they are doing and why.

---

## The Curve Is Still There

The underlying learning curve has not changed.

It is still easy to feel confident early on, and it is still necessary to move past that initial confidence to build something durable. AI has made the early stages faster and more rewarding, but it has not removed the need for deeper understanding.

If anything, it has made that understanding more important.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Lessons I Learned the Hard Way]]></title>
            <link>https://mikebifulco.com/newsletter/lessons-i-learned-the-hard-way</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/lessons-i-learned-the-hard-way</guid>
            <pubDate>Tue, 17 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Your brain rewires itself based on what you practice. If you stop practicing hard things, you slowly lose the ability to do them.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

Your brain rewires itself based on what you practice. If you stop practicing hard things, you slowly lose the ability to do them.

---

Early in my career I remember sitting at a bar with two close friends, laughing about something we called **"information addiction."**

It would only take a few minutes of observation to see it: if we didn't know something, we googled it -- immediately.

Movie trivia? Google it.
Strange symptom after a long flight? Google it.
When was Sean Connery born? Google it.

At the time this felt revolutionary. As millennials, we grew in the first generation where knowledge was always within reach. Expertise wasn't something locked inside universities or trade guilds anymore. It was a few searches away.

That experience shaped a lot of how I think about my generation. The defining skill millennials developed wasn't memorization. It was learning how to learn. If you could research, synthesize, and experiment, there was almost no problem you couldn't teach yourself to solve.

But something has changed in the last few years.

The internet used to give you **information**. Now it increasingly gives you **answers** (whether or not they're correct is another story).

- Why read _Hamlet_ when an LLM can summarize it perfectly?
- Why grind through calculus when a model can solve every step instantly?
- Why learn Cantonese if a phone can translate the conversation for you?

The temptation is obvious... effort is optional now.

And human beings are very good at choosing the easier path.

I'm not immune to this either. I use LLMs all the time; they're incredible tools. They help me write code faster, summarize documents, and explore ideas in ways that would have taken much longer even a few years ago.

I've come to realize there's an important difference between **getting an answer** and **learning something**.

The difference is happening inside your brain.

## Neuroplasticity

There's a concept in neuroscience called **neuroplasticity**, which describes the brain's ability to reorganize itself based on how it's used.

In simple terms: the more you do something, the stronger the neural pathways supporting that activity become. Practice literally changes the structure of your brain. And if you stop practicing something long enough, those pathways weaken.

In other words: **use it or lose it** is a real thing.

That's why musicians practice. It's why I was fluent in Spanish after high school, but was barely conversational 15 years later. It's why someone who writes code every day develops instincts that no tutorial can fully explain.

Learning is not just absorbing information. It's building physical circuitry.

And circuitry only forms through effort.

## Some Lessons Are Best Learned the Hard Way

I can generate code with Claude or Codex. But I won't write great software unless I keep practicing and scrutinizing my code.

I can translate a paragraph of Spanish instantly with Google Translate. But I can't actually understand a conversation unless I spend years training my ear and vocabulary.

The same thing is true with music. The more often I pick up my guitar, the better my playing becomes. There's no shortcut to becoming a better musician.

Some knowledge only exists on the other side of repetition.

Which is why I've started to believe something that sounds slightly old-fashioned:

**Some lessons are best learned the hard way.**

Not because technology is bad. Not because efficiency is wrong. But because your brain still runs on the same rules it always has.

If we stop practicing difficult things, we eventually lose the ability to do them.

## A Small Suggestion

So here's my suggestion: Pick at least _one thing_ in your life that you're willing to learn the hard way.

Something where progress comes slowly. Something where you have to practice even when it's frustrating. Something where the only real path forward is repetition.

For me, it's been keeping up with music and language learning.

Neither of them can be optimized away. Both of them reward patience. And both of them sharpen a part of my brain that shortcuts can't reach. They challenge and strengthen parts of my brain that I wouldn't otherwise use, and help me have real, meaningful connections with other people in my life. They create opportunity, empathy, and human connection.

If you want to keep your wit sharp in an age of instant answers, make sure there's at least one thing you're still willing to practice the slow way.

---

## More from me this week

<Image
  publicId="newsletters/lessons-i-learned-the-hard-way/guithub"
  alt="Screenshot of the Guithub app for tuning your instrument"
  caption="I built the guitar tuner I always wanted"
/>

- Speaking of practicing music, I recently shipped the guitar tuner I always wanted - [Guithub](https://guithub.org) is a tiny little PWA for tuning your instrument on the fly. It has all the features I ever wanted: support for multiple tunings, capo positioning, as well as bass guitar, ukulele, banjo, and more. I also got to play with an aesthetic I like. If you're a musician, give it a look! Proper launch announcement coming soon.

- My interview with [Alex from Supergood](https://apisyouwonthate.com/podcast/supergood-is-building-unofficial-apis-for-everything/) for the APIs You Won't Hate podcast. Alex is a supremely thoughtful guy, and his company is building a super interesting product. Supergood is building unofficial APIs for everything - really.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Learn to Love the Rebuild]]></title>
            <link>https://mikebifulco.com/newsletter/learn-to-love-the-rebuild</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/learn-to-love-the-rebuild</guid>
            <pubDate>Tue, 17 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Refactoring isn't a necessary evil -- it is the job. Why the best product teams rebuild constantly, at every scale.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

Becoming a great product builder means falling in love with the process of building and rebuilding.

---

I have always felt like I'm somewhere between the before photo and the after photo.

As in -- I've never felt like I'm "finished" with anything, really. The next version is just around the corner. It's just mid-process.

For a long time, I assumed that feeling meant I was behind. That at some point I would arrive at a stable, finished version of myself, or my work, and finally feel settled. But the longer I build things for a living, the more I realize that the in-between feeling is a sign that I'm on the right track.

## The Engineer's Reality

If you write software, you live in the messy middle whether you like it or not. You ship something that works well enough. Then you watch how it behaves in the wild. You discover the edge case you didn't anticipate, or the assumption that quietly shaped the entire architecture, or the part of the interface that makes perfect sense to you and none at all to anyone else.

And then you rebuild.

Here's the secret: for great products, that rebuild keeps happening, all the time, at every scale. You rewrite a sentence in a `README` because it doesn't quite communicate what you meant. You refactor a function that felt clever last week and now just feels brittle. You restructure a module. You revisit a feature that solved the wrong problem. Sometimes you rethink the product entirely. If you are unlucky or ambitious enough, you end up rethinking the company.

The rebuild is fractal. It repeats at every level. The same humility is required whether you are fixing a single line or reimagining the direction of the business.

## Failing to learn from the past is a recipe for disaster

Teams that forget this are usually the ones that get surprised. Usually this is because it's taboo to question past decisions, despite the richness of learnings you get from seeing people use a product or feature after launch. Instead, boxes are checked and the product is deemed “good enough,” and instead of learning from the product's shortcomings and revisiting first principles, the team shifts into protection mode. Architecture calcifies. The roadmap becomes incremental.

Rebuilding starts to feel risky instead of necessary.

And that is exactly when the ground shifts beneath you. The cost of building something new keeps dropping. LLMs have dramatically reduced the time between idea and implementation. Patterns that once required deep specialization can now be scaffolded quickly. A small team with good taste and the willingness to rethink fundamentals can move faster than an entrenched organization that is busy defending yesterday's decisions.

Ever open up a beloved product and have the sinking feeling that it hasn't changed in years? In the past, that meant stable product-market fit. For utilitarian tools today, it might be a warning sign that someone is about to build something better.

## Looking at your past work

We _all_ cringe when we look back at what we produced years ago. _I can't believe I wrote that!_ is a sign that you've grown. If you look at a project from two years ago and wouldn't change a thing, that is when you should worry.

The cringe is useful. It is a divining rod. It points directly at the thing that is ready to be rebuilt. Your past work is a treasure trove of opportunities for self-disruption. Take your work, make it better, and help your teammates do the same.

## If you don't rebuild, someone else will

If you aren't willing to revisit your foundations, someone else will. Not because they are smarter, but often because they are less attached to the work, or to the "we've always done it this way" mentality that quietly takes hold in teams of all sizes.

Learning to love the rebuild isn't perfectionism, it's humility and honesty. Look at your own work and admit that the current version is not sacred, and you'll be able to build better things.

So look at the thing you shipped last quarter. Find the part that makes you wince. That is where you start.

---

## More Reading

- 📖 [The Messy Middle](https://hardcover.app/books/the-messy-middle) by Scott Belsky is a great reference point for falling in love with the sisyphean product building process.
- 🎥 [Ira Glass on Good Taste](https://www.youtube.com/watch?v=E7rCOlqGVQU) - Glass has a famous quote about how _everyone_ has bad taste at first, especially when doing creative work. The nut at the core of the message is that you will do best if you _just start making stuff now_. Product building is creative work - don't sell yourself short by thinking otherwise.
- 💎 [Today is Your Day to Start](https://mikebifulco.com/newsletter/today-is-your-day-to-start) - My treatise on a similar theme. The only better time to start than now was 10 years ago.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Just Enough Is an Ongoing Practice]]></title>
            <link>https://mikebifulco.com/newsletter/just-enough-is-an-ongoing-practice</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/just-enough-is-an-ongoing-practice</guid>
            <pubDate>Tue, 10 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Stable products still need maintenance. Defaults and shiny features quietly tax systems over time, and efficiency is a sign of craftsmanship, not penny-pinching.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

Stable products still need maintenance. Defaults and shiny features quietly tax systems over time, and efficiency is a sign of craftsmanship, not penny-pinching.

## “Just Enough” Is an Ongoing Practice

At some point, my next.js website crossed a line I did not notice right away. It was stable, not changing much apart from new posts and newsletters. Traffic was healthy. And yet, I was steadily consuming more of the resources measured by **Vercel's free tier**. Nothing had broken. Nothing felt slow. But the line on the graph kept moving in the wrong direction.

That surprised me.

We often tend to think of stability as the end of something. Engineer ship something, it works, and we move on. Modern web frameworks ship with helpful defaults, and those defaults are optimized for convenience, not restraint. Prefetching everything on the page. Recomputing pages that could have been built once. Redirecting politely when a bot is clearly probing your pagination. Individually, each decision makes sense. Over time, they quietly add up.

Taking time to chase this down pulled me away from real work, the kind with deadlines and people waiting on me. I am not short on things that demand attention.

The results of a few hours of my time were exactly the doctor ordered:

<Image
  publicId="newsletters/just-enough-is-an-ongoing-practice/isr-reads"
  alt="A screenshot of the Vercel dashboard showing ISR reads before and after the changes"
  caption="ISR Reads before and after the changes"
/>

<Image
  publicId="newsletters/just-enough-is-an-ongoing-practice/fast-origin-transfer"
  alt="A screenshot of the Vercel dashboard showing Fast Origin Transfer before and after the changes"
  caption="Fast Origin Transfer before and after the changes"
/>

ISR Reads and Fast Origin Transfer both dropped dramatically, and flattened out. The site went back to living comfortably within a modest tier, even with steady traffic. What struck me was not how clever the fixes were, but how ordinary they felt in hindsight. These were not optimizations born from genius. They were the result of paying attention.

<Aside type="note">

👉 <b>Interested in the details of these changes?</b> Check out my post on [reducing Next.js bandwidth with link prefetch](https://mikebifulco.com/posts/reduce-nextjs-bandwidth-with-link-prefetch).

</Aside>

## Keeping the lights on

The larger takeaway isn't at all about ISR or Fast Origin Transfer or prefetching. I think there's a lesson in what it means for a product to be "finished".

Launches of new products and features are exciting. It is _always_ a thrill to be working on the new hotness, drawing attention from your peers and customers.

But - there is a version of craftsmanship that only shows up after spotlight moves on. Funny enough, during my time at Google and Stripe, this was called KTLO: Keeping The Lights On.

## The unsung hero of the product lifecycle

This is the craft and attention to detail that shapes the integrity of the system. Efficiency, performance, and even environmental impact rarely make it into launch announcements. They still shape the integrity of the system. It's the work that is often thankless, and invisible to end users.

Growing the skill for this kind of work is not a one-time event. It is a skill that must be cultivated over time. It is a skill that must be practiced regularly. It is a skill that must be honed over time.

This is the same idea I wrote about before as **[just enough, nothing more](https://mikebifulco.com/newsletter/reflecting-on-one-year-as-startup-cto#just-enough-and-nothing-more)**. You don't cross the finish line once. You return to it. You notice drift. You develop a sense for new signals to listen to from the systems you've built and used. You remove things that no longer serve the system. You question defaults that once seemed harmless.

A stable product is not a finished product. It is simply a product that now requires a different kind of care.

“Just enough” is not a milestone. It is an ongoing practice.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[My 2026 Developer Tech Stack]]></title>
            <link>https://mikebifulco.com/newsletter/developer-product-engineer-tech-stack-2026</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/developer-product-engineer-tech-stack-2026</guid>
            <pubDate>Tue, 27 Jan 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[The tools I use as CTO and product engineer at a Y Combinator-backed startup in 2026.]]></description>
            <content:encoded><![CDATA[
## The Big idea

This year, my work shifted from "write code" to "orchestrate systems." That means communicating well, taking great notes, and using AI tools to enhance my thinking rather than replace it.

## The Hardware

I work on a 14" M2 MacBook Pro. I'm a big fan of the M-series chips - my M2 hasn't slowed down yet. I prefer portability over screen size since I do a lot of work from kitchen counters and coffee shops.

At my desk, I run dual 27" 4K monitors with the Mac in clamshell mode, plus a Logitech MX Keys keyboard and MX Master 3 mouse - a setup that hasn't changed in years.

I'm also getting more done on my phone than ever - currently a Pixel 10 Pro. I've been eyeing Nothing phones lately; their quirky-meets-minimal design ethos is appealing.

E-paper devices have been in and out of my bag this year. A friend gifted me a Daylight Computer, which I use for reading and notes. I also briefly had a Boox Palma 2 - a _sublime_ phone-sized e-reader I loved until its fragile screen broke. Glad I paid for the extended warranty.

## My Software Stack

The biggest change from last year? My software stack changes regularly now. I've flipped between IDEs, switched note-taking apps, and dabbled with AI tools across the spectrum - from ChatGPT and Gemini, to Copilot and Cursor and Claude Code, to fully-local models via Ollama.

The takeaway: flexibility beats loyalty. Tools are changing fast, and it's worth trying new ones to see what fits.

Here's what I'm _currently_ using:

### Claude Code

[Claude Code](https://claude.com/product/claude-code) lets me stay in the role I'm best at: planner, architect, reviewer, unblocker. I spend less time executing and more time shaping the work. Critically, it doesn't replace my judgment - it multiplies it. [I've been reviewing code for years](https://mikebifulco.com/newsletter/ai-is-your-intern-not-your-boss), and Claude keeps me reading code and providing active feedback. I'm not writing zero code, but I am writing a lot less.

### MCPs (Model Context Protocol)

MCPs are the quiet unlock. They connect Claude Code to real systems instead of isolated prompts - repos, tickets, docs, logs, all linked. This is what turns AI from a clever assistant into something that can reason alongside you.

### Obsidian

I take [**loads of notes**](https://mikebifulco.com/newsletter/unlock-productivity-with-networked-note-taking) - meetings, calls, books, friends, articles, you name it. I switched from Logseq to [Obsidian](https://obsidian.md/) this year due to an ongoing macOS bug that made Logseq painfully slow. Obsidian is fine, but it suffers from Notion's curse: it's too easy to get distracted perfecting your setup instead of using the tool.

### Raycast

[Raycast](https://www.raycast.com) replaces Spotlight on macOS. It's more than a launcher - I use it for translations (English ↔ Spanish), looking up Tailwind classes, finding Lucide icons, and dozens of other small utilities throughout my day.

### WisprFlow

[WisprFlow](https://ref.wisprflow.ai/mike-bifulco) is a voice-to-text tool that runs locally on your Mac. Talk to your computer and it turns into text. I'm a fan of multimodal input; I spent years on the Google Assistant team waiting for seamless switching between typing and talking. WisprFlow delivers that, and it understands code-speak surprisingly well. Say "users slash mike" and it outputs `users/mike`. I use it constantly now for thoughts while walking, rough designs, notes to myself, and messages to teammates.

### Linear

[Linear](https://linear.app) is still the backbone of planning for my team. It's where our shared understanding of the work plan lives. It's also where we share context with LLMs via MCPs, meaning Claude Code can read and update Linear tickets as work gets done. This helps documentation happen automatically instead of as an afterthought.

### The product stack

The way we build software at [Craftwork](https://craftwork.com) is changing too. We use TypeScript for most of our code now, steadily moving away from Ruby on Rails. The app lives in a monorepo: Next.js, React, TypeScript, OpenAPI, tRPC, and Postgres. We also rely on a handful of third-party tools: PostHog for analytics, Render for hosting, Sentry for errors, Stripe for payments, and Twilio for voice/SMS.

## The secret sauce

This is the year I started viewing my 20+ years of writing code as a replaceable commodity. Thanks to LLMs, the difference between an engineer and a 10x engineer is [no longer code](https://mikebifulco.com/newsletter/next-great-engineering-skill-is-context-not-code). It's context, collaboration, and communication, with humans and machines alike.

Many devs struggle with this. I share my tools and workflow because I find it helpful when others do the same, but ultimately the tools are worthless without the people. Bring humanity, creativity, and humility to your work. Invest in yourself.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[The Zeroth Loop: They Don't Quit, They Forget]]></title>
            <link>https://mikebifulco.com/newsletter/zeroth-loop-they-dont-quit-they-forget</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/zeroth-loop-they-dont-quit-they-forget</guid>
            <pubDate>Tue, 06 Jan 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Most habits don't fall apart because people quit. They fall apart because they aren't sticky.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

Most habits don't fall apart because people quit. They fall apart because they aren't sticky.

Cognitive science tells us that habits form when a simple loop closes: a cue triggers an action, the action produces a reward, and the brain decides the sequence is worth repeating.

As builders, we often focus on the loop inside our apps. But the most successful products understand that the loop starts long before a user ever signs up. This is The Zeroth Loop.

<SponsoredSection
  imagePublicId="sponsors/crowdstake/landing-page-builder"
  sponsorName="Crowdstake"
  CTAtext="Start Pre-Launch"
  brandColor="#0B5D9E"
  href="https://www.vpdae.com/redirect/rsv3r61v9hvqbdgc7czgbhwjhh6"
>

### Quickly turn ideas into beautiful landing pages

Launch AI-powered waitlist landing pages in minutes. Test demand, pricing, and features. Know exactly what your audience wants before building - no tech skills required.

</SponsoredSection>

<img
  src="https://www.vpdae.com/open/cf6ab0e8.gif?opens=1"
  width="1"
  height="1"
/>

## The Zeroth Loop: Before the First Use

The first encounter with a product usually happens in the wild: a landing page, a demo video, or a screenshot shared on social media.

The strongest marketing moments already contain a full behavior loop. When you watch a great 15-second demo, your brain performs a dry run. You see the cue, you recognize the action, and you anticipate the reward.

A good demo doesn't just explain features; it allows the user to experience the payoff ahead of time. By the time they click "Sign Up," the habit loop already exists in outline form. The **Zeroth Loop** has already closed.

## Where Your Products Lose Momentum

Product people tend to spend loads of time planning and building the nuts-and-bolts of how our apps work. We spend hours designing the perfect onboarding flow, the perfect settings page, the perfect error message.

Marketing people tend to think about the moments _before_ features matter - how do people find and engage with your product in the first place?

These two perspectives are hugely important, and they need to work together. Neither is optional for your product to be successful.

Builders who don't have marketing chops tend to overestimate intent. We see a signup as commitment, but often it's just curiosity. If a person's first interaction with your product doesn't produce a clear, immediate reward, the behavior never stabilizes.

When this happens, nothing _really_ breaks. The app just fades into the background. It stays installed, the tab stays open, and the user simply forgets it exists.

The habit never formed, and all your work goes to waste.

## Systems Over Memory

This is why thoughtful nudges are so important. Reminders often get a bad reputation because they're implemented poorly, but their cognitive role is simple: they reintroduce the cue before a new routine vanishes from memory.

<Image
  publicId="newsletters/zeroth-loop-they-dont-quit-they-forget/reward-cycle"
  alt="The cue-response-reward cycle"
/>

Durable habits don't rely on willpower or perfect recall; they rely on systems that bring the cue back before the natural erosion of forgetful humans takes over.

## A Tiny Improvement: Design for Three Loops

Zoom out and reframe your product journey around the first three loops:

<Image
  publicId="newsletters/zeroth-loop-they-dont-quit-they-forget/three-loops"
  alt="A three-loop diagram"
  caption="A three-loop diagram"
/>

### The Zeroth Loop (Marketing)

Does your demo or screenshot allow the user to visualize the reward? Can they "feel" the problem being solved before they even have an account?

### The First Loop (Onboarding)

Is onboarding and time-to-value fast enough to keep the user engaged? Getting people to _do something useful_ for the first time is the critical path here.

### The Second Loop (Utility)

Once they take the action, how quickly do they get evidence of success? In other words, has your tool or app actually delivered on its promise?

## The Takeaway

The reward is rarely the interface. If your app helps people optimize code, the reward isn't a "Success" toast message- it's the faster build time or the green checkmark in GitHub.

The outcome has to show up in the user's own context. That external payoff is what creates the memory: "Last time I did this, something good happened." When that happens early, repetition follows naturally. When it doesn't, no amount of UI polish can save it.

---

## More reading on habit loops

- [The Power of Habit](https://hardcover.app/books/the-power-of-habit-why-we-do-what-we-do-in-life-and-business): A clear and approachable explanation of the cue-routine-reward loop, with enough real-world examples to make it useful beyond theory.

- [Fogg Behavior Model](https://thedecisionlab.com/reference-guide/psychology/fogg-behavior-model): A practical framework for understanding why behaviors happen, and why they often don't. Especially helpful for diagnosing stalled adoption.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Science-Backed Secrets of Long, Happy Lives]]></title>
            <link>https://mikebifulco.com/newsletter/habits-of-high-longevity-people</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/habits-of-high-longevity-people</guid>
            <pubDate>Tue, 09 Dec 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[A guide to the habits of high longevity people.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

What if sleeping a little better, moving a little more, and finding a sense of purpose could measurably change your life?

Not as a vibe. As a fact, supported by decades of research.

## How to live a long, happy life

When researchers study people who live the longest, most fulfilling lives, they don't find hacks or extreme discipline. They find the same small behaviors repeated quietly over time.

Thankfully, there's no magic to it. The behaviors that have emerged are simple and accessible, and -- apparently -- they work. If you're looking for a "one weird trick" panacea, you won't find it here. The fact of the matter is that when you repeat a few seemingly small behaviors over and over again, they start to add up.

## Why tiny beats dramatic

Big changes fail because they ask too much, too fast. Small habits succeed because they're easy to repeat. I love that this is backed by actual, real Behavioral science, too - the data shows that consistency is better than intensity.

A tiny habit rarely feels life-changing in the moment. But repeated often enough, it changes what a normal day looks like. Enough normal days, and the long arc follows.

## The same habits, over and over again

Across longevity research, the same few habits appear again and again:

- **Adequate rest:** Roughly seven to eight hours of quality sleep, consistently.

- **Eating lots of plants:** Meals centered on vegetables, fruits, legumes, and whole grains, with moderate portions.

- **Daily, natural movement:** Low-impact movement woven into everyday life.

- **Strong social connection:** Regular time with friends, family, or community. It's a stronger predictor of happiness than wealth.

- **A sense of purpose and optimism:** Feeling useful, connected, and oriented toward something that matters.

Over the course of a lifetime, these tiny shifts in mindset and behavior can have a massive impact on you. And to me, at least, no single one of these sounds particularly difficult to maintain.

## Little changes that snuck up on me.

For years, I have been adopting little, bitty morsels of self-improvement. They help me to grow personally, stay balanced, and manage stress.

When I started managing a team at Google during the pandemic, I adopted a [simple morning ritual](https://mikebifulco.com/newsletter/continuous-self-improvement). I do five minutes of journaling, and five minutes of meditation. Nothing elaborate. That small routine helped me manage stress and show up more consistently for my team.

I've also been doing daily language learning for years. Just a few minutes a day stretches a different part of my brain, and has satisfied my personal desire to learn something new. Even better, I'm at least _conversational_ in Spanish, and I can read a surprising amount of Japanese by now!

## The Long View

Longevity and happiness are on my mind a lot lately - I've been thinking about shaping the long arc of my life's story. I want to be as happy as possible for the small amount of time I have on earth. It's as easy as that!

I find it very encouraging that there is research behind these ideas... If small habits can reliably improve a day, it's not much of a leap to believe they can shape decades too.

As the new year approaches, maybe it's worth a complete shift in perspective: You don't need a hard reset. Instead, maybe adopt a habit that's easy enough to keep, even on bad days.

Then, maybe: another one.

## My Question for You

**When you try to build new habits, what actually works for you? How do you keep yourself honest once the motivation fades?**

Hit reply and tell me. I read every response, and I'm genuinely curious.

---

## More reading

Ready to go all-in on longevity, habits, and happiness? Here are some of the resources I found myself reading that really grabbed my attention.

- [A Harvard Study of Adult Development](https://news.harvard.edu/gazette/story/2017/04/over-nearly-80-years-harvard-study-has-been-showing-how-to-live-a-healthy-and-happy-life) shows that close relationships and social connection are stronger predictors of long, healthy lives than wealth, fame, or status.
- [Blue Zones and the Power 9 Principles](https://pmc.ncbi.nlm.nih.gov/articles/PMC6125071/) is a study on communities where people live past 100 most often. It identifies common lifestyle traits tied to longevity, like natural movement, purpose, and plant-forward diets.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[The Science of Spotting Hidden Product Ideas]]></title>
            <link>https://mikebifulco.com/newsletter/mirror-effect-cognition-behavioral-science</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/mirror-effect-cognition-behavioral-science</guid>
            <pubDate>Tue, 02 Dec 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[The best product ideas hide in plain sight, in your habits and everyone else's. Watch what people actually do, not what they say they want. Build for that.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

The best product ideas hide in plain sight, in your habits and everyone else's. Watch what people actually do, not what they say they want. Build for that.

Most teams start their search for ideas with a brainstorm. The trouble is that people are unreliable narrators of their own needs. We guess. We speculate. We tell ourselves a story about what might help, instead of looking at how we actually behave.

Lucky for you, a little applied science can give you a clearer way to see.

Below are three ideas rooted in behavioral psychology which can help you find opportunities through observation of your own habits and those of others.

### Revealed preference

**Revealed preference** is the idea that actions speak more clearly than opinions.

In the software world, these actions are everywhere. When developers repeat the same chores by hand, maintain a giant list of test data in a scratch file, or juggle three tools to get one thing done, they are revealing what they actually need.

[Bruno](https://www.usebruno.com/?ref=mikebifulco.com) is a clean example. It's an API tool that has gained favor as Postman added account login requirements that their users weren't asking for, while the real preference was simple: keep everything local, work fast, commit changes, share them with a team.

<Image
  publicId="newsletters/mirror-effect-cognition-behavioral-science/bruno"
  alt="A screenshot of the Bruno homepage"
  caption="Bruno's success isn't a coincidence. It's the result of paying attention to the way devs use their tools."
/>

Bruno didn't invent a new workflow. It paid attention to the one people were already trying to use.

### Habit loops

When behaviorists talk about the **Habit Loop**, they describe it as cue, routine, reward. If the routine becomes messy, people still follow it, because the reward matters.

But the mess reveals an opportunity.

Testing an API is a perfect illustration. The cue is obvious. The reward is seeing the result. What changed over time was the routine. Postman added friction. Bruno's approach added value. All Bruno did was design a routine that matched the way developers already think.

When you look closely at routines that people repeat every day, the problems usually introduce themselves.

### Jobs to Be Done

**Jobs to Be Done** reframes product building around one question: what job is someone trying to get done, and how well are their tools helping them do it?

People "hire" their tools and workflows when they get things done. Sometimes it means a stack of half solutions held together with muscle memory. When you see the duct tape, you are seeing the job that isn't being served very well.

In Bruno's case, the job was straightforward. Teams wanted an easy, dependable way to explore and share their API workflows with their teams. The job didn't change. The tools did.

## Gaze into your own mirror

This process of finding opportunities works best when you turn the lens on yourself.

Ever tried to describe your workflow to someone who has never done it before? I bet you'll find _something_ that sounds at least a little absurd that you've been doing for ages.

Look at the workflows you repeat without thinking. Look at where you slow down, or compensate, or adapt to a tool that isn't quite right. These moments are often small, but they are rarely isolated. If something bothers you, it probably bothers someone else. Enough shared friction becomes a market.

Most people think they need inspiration. What they really need is observation.

## The takeaway

You don't have to invent a brand new idea. You just have to watch behavior more closely than everyone else.

_Revealed preferences_ show you what people truly value.

_Habit loops_ show you where routines break down.

_Jobs to Be Done_ shows you why the work matters in the first place.

Everything else is just paying attention.

---

# Keep on learning, my dudes

- Everyone's favorite self-help author James Clear has a great article on the [Habit loop](https://jamesclear.com/habit-triggers) that's worth a read.
- [Jobs to be done](https://hardcover.app/books/jobs-to-be-done-theory-to-practice) is the OG tome by Clayton Christensen that broke ground on the idea of breaking down customer needs into specific "jobs" that your product can satisfy.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[The Psychology Hack Hiding in Great Products]]></title>
            <link>https://mikebifulco.com/newsletter/nudge-theory-for-guiding-user-behavior</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/nudge-theory-for-guiding-user-behavior</guid>
            <pubDate>Tue, 25 Nov 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Every message is a moment of influence. Make the nudge helpful and you'll create power users and build loyalty.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

Every message is a moment of influence. Make the nudge helpful and you'll create power users and build loyalty.

## What is Nudge Theory?

Nudge Theory is a framework for guiding user behavior through subtle, persuasive techniques. It is based on the idea that people are more likely to change their behavior if they are given a choice that is easy to make.

In other words, a little proactive messaging goes a long way.

### Why Nudge Theory Matters

There's a little bit of behavioral science at play when a product uses thoughtful nudges in its onboarding. Research in behavioral economics shows that small, well-timed cues can help people adopt new habits and tools more easily. In other words, a gentle nudge at the right moment can make all the difference.

## A concrete example: Blacksmith

That's exactly what we found with [Blacksmith](https://blacksmith.sh?utm_source=tinyimprovements&utm_medium=email&utm_campaign=nudge-theory-for-guiding-user-behavior). It promised to speed up our CI workflows for less cost, something my team at [Craftwork](https://craftwork.com) would benefit from immensely.

<Image
  publicId="newsletters/nudge-theory-for-guiding-user-behavior/blacksmith-value-prop"
  alt="A screenshot of the Blacksmith's home page value prop"
/>

Our initial onboarding was smooth - the software generated a PR to swap our CI workflows onto their infrastructure. The speed boost was immediate, and life-changing for my team.

### Thoughtful Nudges in Action

What really impressed me was what happened a day later - each day, I would receive an email with a new tip, rooted in behavioral insights, to guide us step-by-step on how to get the most value from Blacksmith.

From the first message, Blacksmith gently introduced us to one feature at a time. Each day, a new tip arrived - ensuring that the game-changing features the Blacksmith team built didn't get lost in my haste to try the product out on Day 1.

<Image
  publicId="newsletters/nudge-theory-for-guiding-user-behavior/blacksmith-drip-campaign"
  alt="A screenshot of the Blacksmith's onboarding process"
  caption="Zero code-changes required? Sign me up."
/>

They could have spent a lot of time developing a slick, highly-interactive onboarding wizard -- which I almost certainly would have skipped. Instead, a slick little drip campaign offered even more value for my team.

You better believe I tried each one.

---

## Use these powers for good

- The Wikipedia entry for [Nudge Theory](https://en.wikipedia.org/wiki/Nudge_theory) is a great primer - it may sound wishy-washy, but this is real behavioral science.
- Nudge Theory is, of course, a two-sided coin - there's a great paper on [ethical concerns with nudging](https://journals.sagepub.com/doi/10.1177/10434631231155005) that is worth a read.

So, how will you turn this knowledge into action? Whether you're building a product or trying to influence people to be better neighbors, there is a whole lot of power in the way you reach people with your messaging.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Contributing to Open Source without being a Jerk]]></title>
            <link>https://mikebifulco.com/newsletter/open-source-is-community</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/open-source-is-community</guid>
            <pubDate>Tue, 11 Nov 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Open source doesn't work without good faith - and sometimes you need to patch a dependency to do your part.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

Open source works best when we treat each other like humans - not vending machines for bug fixes.

## How We Patched a Broken Package - and What It Taught Us

Recently at [Craftwork](https://craftwork.com), we hit a snag using the [@payloadcms/storage-uploadthing](https://github.com/payloadcms/payload/tree/main/packages/storage-uploadthing) plugin for image uploads in [Payload CMS](https://payloadcms.com).

One of our engineers dug in, found the issue, and fixed it. We opened a [pull request](https://github.com/payloadcms/payload/pull/14250), hoping to help others in the same situation.

But here's the thing: We couldn't afford to wait for the PR to get merged before moving forward. Publishing a forked npm package is a common fallback - but it can be hard to maintain long-term.

In addition to creating a fork to submit a fix, we used [`pnpm patch`](https://mikebifulco.com/posts/patching-npm-dependencies-with-pnpm-patch) to apply the fix to our repo. It's clean, version-controlled, and works until the upstream package is updated.

## Maintainers Aren't the Problem

It's easy to forget that open source projects are often maintained by small teams under heavy load. At the time of writing, Payload has over 375 open pull requests. Expecting our fix to jump the line would be absurd.

This isn't about neglect or indifference. It's about capacity.

In other repos, we've seen PRs sit untouched for months, with long threads of angsty, impatient comments. I get it - but that doesn't help anyone. Especially not the maintainers.

### A Better Way to Contribute

Here's what we did instead:

- 🛠 Fixed the issue locally using `pnpm patch` (need a tutorial? I [gotchu](https://mikebifulco.com/posts/patching-npm-dependencies-with-pnpm-patch))
- 💬 Shared the patch tutorial in the GitHub PR to unblock others
- 🔁 Opened a new, cleaner PR
- 🤝 Let the maintainers off the hook - no pressure, just help

This approach makes open source better for _everyone_. It gives control back to contributors, and it gives maintainers room to breathe.

It is easy to forget that contributing to open source isn't just Pull Requests - discussion, community building, managing expectations, and creative solutions help us all build a better internet together.

I'm confident you'll get more results if you treat people with humanity - and you will [build a reputation for yourself](https://mikebifulco.com/newsletter/serendipity-isnt-an-accident) that makes people eager to help you when they can.

---

## Want to Do Open Source Better?

Read [_Working in Public_](https://hardcover.app/books/working-in-public) by Nadia Eghbal. It's the best book I've read on the culture of open source: what's broken, what's beautiful, and what's worth fixing.

Also, if you like learning by watching smart people build in public, check out:

- [cmgriffing](https://www.twitch.tv/cmgriffing) streams dev work and product experiments on both Twitch and YouTub
- [Rizel Scarlett](https://www.twitch.tv/blackgirlbytes1) does open source work, conference prep, and interviews on her channel

---

## Give without the expectation of receiving

Open source is a special kind of economy. Show up with something useful. Share what you've learned. Make it easier for the next person.

Let's be better guests in each other's repos.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[The next great engineering skill is not coding]]></title>
            <link>https://mikebifulco.com/newsletter/next-great-engineering-skill-is-context-not-code</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/next-great-engineering-skill-is-context-not-code</guid>
            <pubDate>Thu, 23 Oct 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[You have likely ignored it your entire career. That stops now - it's time to hone your writing skills.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

When providing accurate context is make-or-break for your workflow, everyone needs to become a better writer.

We convinced ourselves that moving fast was the same as being smart. Shipping first. Reacting faster than anyone else. What we did not notice is that this trained an entire generation of builders to think only in the moment, never on the record.

That mindset worked when everything stayed in your own head. It breaks completely when your collaborators are machines. And it is the same thing your teammates have quietly been begging you to fix for years.

### Why this suddenly matters

- With LLMs and agents, context is not just helpful, it is _everything_.
- Developers are historically allergic to context. We want to skip the ticket and jump to the code.
- That habit is now actively expensive.
- Clear writing is fast implementation. Fuzzy writing creates hallucinations, bugs, and rework, and wastes time.
- If you get good at writing for agents, you automatically get better at writing for humans. Your teammates have been asking for this for years anyway - they're gonna love you for it.

## A simple framework for writing to agents (and humans, and future-you)

1. State the problem or goal. What is happening? What outcome matters?
2. Provide history. What have you already tried, seen, or ruled out?
3. List constraints. What absolutely must not break?
4. Point to the code. If you were starting, where would you look first? Any past examples or similar patterns?

Go back and re-read your instructions, and imagine this is the first time you're hearing about the bug or feature you're describing. Is there enough information for you to get the job done?

Iterate as needed. That's really all there is to it.

## A real example

I was getting spam signups to the Tiny Improvements mailing list. Dozens a day. Instead of stewing on it internally like I used to, I wrote up this description from my phone while on a plane:

```
I have been getting spam signups on my newsletter form for the past couple weeks - can you read through `SubscriptionForm.tsx` and help me come up with a plan to deter spam signups?

Here are some sample subscriptions from the past few weeks that are all spam:
(list of ~50 spam signups, including the addresses, first and last names used)

Based on what I'm seeing here, I think we can probably do a few things to deter spam signups:
1. make sure the honeypot field on the form is working as expected
2. Automatically reject signups where the first name is mixed case has >3 capital letters: i.e. XavcASkiox
3. Automatically reject signups where the first name has >4 consecutive consonants: i.e. mtpDQVeZaqb

For signups that _fail_ any of our spam checks, we should make it look like the subscription was a success, but don't actually subscribe the email address, and instead log the spam signup attempt to Posthog analytics for further analysis.
```

That 90 seconds of writing turned into a working fix with minimal edits, and thankfully, spam fell off a cliff.

And bonus: writing it down cleared background mental noise I did not realize I was carrying.

## Conclusion

If context is now make-or-break, writing is no longer optional - it's the difference between wasting your time and speeding up your workflow.

Write down what you're thinking about. It frees your brain, helps your team, and makes agents actually useful.

_And if you're the one sending automated spam signups to my newsletter: c'mon, dude._

---

### For more Context on Context

- [Matt Pocock's video on LLM Context](https://youtu.be/-uW5-TaVXu4) is a superb explainer on the topic, with a really helpful series of diagrams to help you visualize the concept.
- Michael Reeves shows what happens when you [corrupt the back-context](https://www.youtube.com/shorts/WP5_XJY_P0Q) of an LLM conversation. It's chaotic - and convincing.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[AI and the New Language of Human-Centered Design]]></title>
            <link>https://mikebifulco.com/newsletter/ai-and-human-centered-design</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/ai-and-human-centered-design</guid>
            <pubDate>Thu, 02 Oct 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Software has always required people to think like a computer. AI flips it on its head: people expect computers to work the way they think.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

Software has always required people to think like a computer. AI flips it on its head: people expect computers to work the way they think.

That shift sounds subtle, but it’s massive. It changes what “human-centered design” really means.

## From Rules to Recall

Traditional software is deterministic: repeatable, predictable, safe.
AI is different. It’s non-deterministic - send the same input to your favorite LLM twice, and you'll get different results.

Responses vary: sometimes it feels human, sometimes it feels flat wrong.

That unpredictability makes trust fragile. But it also makes experiences feel alive -- and perhaps counterintuitively, more trustworthy.

## Memory changes everything

Think about how different this is from your experience with traditional software: LLM-powered apps let you have a custom, differentiated experience every time you use them. Your chat session today is _shaped by_ your previous conversations.

Made an update to your profile? AI can suggest how to automate or change your work next based on your new information.

Suddenly, Gmail and Google Docs _know about each other_, and can suggest helpful actions based on your work across both.

Screens don’t sit still anymore. They grow, adapt, and remember.

## Hybrid Intelligence

People who use software to get complex work done have traditionally needed to build mastery of their tools through repetition. There are _countless_ tutorials on how to use Photoshop to do hyper-specific tasks, because Photoshop is an app that has an incredibly broad set of features, a steep learning curve, and requires deliberate practice to master.

The curve was steep, but the payoff was control and precision.

In a world where AI is the interface, that mastery is _far_ less important.

Now, new users can pull up photoshop with literally no idea of how to accomplish their goal, other than to describe the outcome. That's enough for an agent to take a swing at the task, and often get it right. When it doesn't, the user can course-correct with more natural language.

That's pretty wild - and about as far from the goals of "traditional" UX as you can get.

For novices, it's liberating, but it means AI holds more knowledge of your past than you do.

## UX’s New Job

Design used to be about helping people find the right button. UX Practitioners labor endlessly over trying to make _your next step_ obvious.

I think that's going to fundamentally change.

For AI-powered work, design work needs to focus primarily on::

- Getting work done confidently
- Validating results users may not fully understand
- Making like the system feel like a partner, not a puzzle

Human-centered design has to evolve.

## What’s next?

Autocomplete is already table stakes. Some apps already _feel_ old without it. However, thoughtlessly slapping an AI layer onto a tired interface is worse - it feels cheap.

Here's where I think we're headed:

Conversational interfaces that actually work will be the norm for most workflows. Multimodal (voice + typing + camera) input will become far more common.

Work will regularly involve conversation and collaboration with multiple agents, fine tuned to perform specific tasks in concert with one-another.

User Interfaces will evolve beyond chat-with-an-llm-flavored UX: agents building compact, atomic, and situational UIs on the fly. For example: Want to update your bio? Here's a tiny form with _just_ what you need - nothing superfluous or distracting.

When that happens, we’ll need something like a UX-lint for AI-built experiences. Guardrails for design itself, so that AI-generated UIs look consistent, feel familiar, and don't break the fundamental rules of usability.

## What it means for Product Builders

👉 I’m not certain where this ends up, But I do know this: the products that win will be the ones that anticipate this new language of human-centered design, where AI, memory, and trust define the experience.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Dieter Rams 10 Principles of Design]]></title>
            <link>https://mikebifulco.com/newsletter/dieter-rams-10-principles-of-design</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/dieter-rams-10-principles-of-design</guid>
            <pubDate>Tue, 23 Sep 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Good design is good design, no matter what you're building.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

Good design is universal - no matter what you're building.

## Back to Basics

Dieter Rams is the legendary German industrial designer behind Braun’s iconic products from 1955 to 1997(!). His career was built around designing physical objects, from furniture to shelving to hifi systems.

Rams' designs are iconic for a reason: he had a deliberate, principled approach to building products that worked and felt good, which he eventually codified into the [Principles of Good Design](https://en.wikipedia.org/wiki/Dieter_Rams#Ten_Principles_of_Good_design).

1. Good design is innovative
2. Good design makes a product useful
3. Good design is aesthetic
4. Good design makes a product understandable
5. Good design is unobtrusive
6. Good design is honest
7. Good design is long-lasting
8. Good design is thorough down to the last detail
9. Good design is environmentally friendly
10. Good design is as little design as possible

The principles _themselves_ are written with a focus on simplicity and clarity: winnowed down to _exactly_ the essential elements of good design.

These weren’t written with Figma or React in mind. But when you’re building software, especially products people spend hours in every day, it turns out physical object rules apply just fine.

There is a reason we talk about these principles, even 60 years later. They are mantras for building products that work well, feel good, and stick around.

### Balancing the Principles

Apple has historically been the poster child for Rams-style design. Some of their most successul products have had hallmark features of Rams' principles. The original iPod takes much of its physical design from the Braun T3, a transistor radio made in 1958.

<Image
  publicId="newsletters/dieter-rams-10-principles-of-design/comparison"
  alt="Braun's T3 from 1958 looks a whole lot like the original iPod, or is it the other way around?"
/>

It's fair to say that Apple has earned their reputation for great design.

But the new direction in iOS 26 feels... different.

The new _Liquid Glass_ aesthetic looks fresh, futuristic, and bold. But it also cranks the aesthetic dial to 11 and turns everything else down. It's pretty, but at the expense of clarity.

At the IOS26 launch, apple execs praised the new design for putting _content_ at the center of the IOS. In practice, the interface draws attention to itself. Shiny, translucent buttons and frosted glass backgrounds make everything a little more difficult to focus on, and a little more distracting.

<Image
  publicId="newsletters/dieter-rams-10-principles-of-design/liquid-glass"
  alt="Screenshot of iOS 26"
/>

<span className="text-sm italic">
  From{' '}
  <a
    href="https://www.apple.com/newsroom/2025/06/apple-introduces-a-delightful-and-elegant-new-software-design/"
    target="_blank"
    rel="noopener noreferrer"
  >
    Apple's Press Release
  </a>{' '}
  on their new design system
</span>

It was so distracting that during the beta period after the announcment of the new design language, Apple [pulled back dramatically](https://9to5mac.com/2025/07/07/liquid-glass-in-ios-26-beta-3-is-much-less-dramatic-as-apple-optimizes-redesign-for-usability/) on the amount of glassy translucent elements in the interface (a great decision, in my opinion).

Even still, it’s a design that feels like it was made to impress other designers. Not to help people get things done. The new design is bold, but it’s not particularly useful. It’s aesthetic, but not unobtrusive.

And that’s the real test:
When the design is working, people don’t notice it.
When it’s not, they notice everything.

### Balance is a continuous practice

It's unlikely that Apple set out to make a less usable product. More likely, they got caught up in the excitement of a new design language and pushed it too far. In recent years, their executive suite has shifted away from product-focused, design-minded leaders -- which can be felt in moments like this.

Design work is a continuous practice of balancing the principles. It’s easy to get caught up in one aspect of design (aesthetics, innovation, etc) and lose sight of the whole.

When I reflect on products that get out of the way and let me do my work, I can see Rams' principles at play. Products like:

- [Superhuman](https://superhuman.com/ti): a beautifully designed email client that focuses on speed and clarity. _(transparency note: Superhuman is a past sponsor of Tiny Improvements)_
- [LogSeq](https://logseq.com/): a note-taking app where taking notes is the focus, rather than _organizing_ notes.
- [VS Code](https://code.visualstudio.com/): An IDE that strikes a balance between speed, usability, and extensiveness, that grows with developers as they become more sophisticated.

## In Summary

The Principles of Design still hold up, even in a world of hover states, folding screens, and haptic feedback. The tools change, but the job doesn’t: design should serve the person using it. Not impress the person who made it.

So the next time you're building something new, ask yourself:
Am I adding more design?
Or am I adding more clarity?

Rams designed with clarity. Restraint. Respect for the person using the product.

So should we.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Beyond Click Counts: Finding the Right Signals for Good Design]]></title>
            <link>https://mikebifulco.com/newsletter/beyond-click-counts-good-signals-for-design-success</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/beyond-click-counts-good-signals-for-design-success</guid>
            <pubDate>Wed, 03 Sep 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Click counts are noise. Real design success is measured in signals that show whether people actually achieved what they came to do.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

Design success is measured in signals that show whether people actually achieved what they came to do.

## Clicks Aren't the Problem

When it comes to design success, clicks aren't the problem - they're just a symptom you'll hear about when people are frustrated.

Last time I argued that [“too many clicks” isn't useful feedback](https://mikebifulco.com/newsletter/stop-counting-clicks).

When something works, people finish tasks, move forward, and feel confident doing their work.

When things aren't working and people are really frustrated, you'll _hear_ about it through the feedback mechanisms you make available to your end users.

There is also a meaningful gap between these two camps: when workflows are merely good enough, people won’t complain, but they also won’t thrive. This silent middle ground is where design stagnates, and where you lose the opportunity to turn reluctant users into superfans.

The opportunity for design teams is to improve user experience by collecting data, feedback, and listening to signals that can help you make your designs better.

So, what is a the right signal that your designs are working?

Here's the catch: **there's no universal checklist.**

What you measure should depend on the purpose of the feature you're building. Clearly defining success metrics and goals will help you decide what signals to measure.

## All Design Leaves Evidence

Good, bad, or otherwise, the output of your design creates signals that you can observe, quantitatively measure, and qualitatively assess in order to improved your feature on its next iteration.

A signup form, a payroll system, and a paint-color selector each have different definitions of success. You can't copy-paste metrics across projects. What matters is asking, up front: what does success look like here?

If your goal is to get high-intent leads to convert to sales, you'll likely want to measure dropoff at each step of your funnel. Make changes to your design to improve the conversion rate at each step, **and** iterate based on what you measure.

Maybe you're designing for a scenario where accuracy is paramount - like in many mechanical engineering or medical design scenarios. In this case, success might be measured by how many incorrect entries are submitted into your system.

Maybe it's speed. Maybe it's accuracy. Maybe it's trust. Whatever it is, define it clearly. Once you do, your metrics stop being vanity numbers and start being a compass. They help you see if you're heading the right way, or if it's time to adjust course.

Iteration without evidence is just guesswork. Iteration with the right signals is how you build something people actually love to use.

## The Takeaway

Don't count clicks. Decide what success means for _this_ design, then measure and observe the signals that point you toward it, and iterate from there.

---

## More on measuring design success

- While not _directly_ about design, Scott Belsky's [The Messy Middle](https://hardcover.app/books/the-messy-middle) reflects on the challenges of getting through the most ambiguous parts of any project.
- Dan Mall has a great video on [Measuring Quality in Design Systems](https://www.youtube.com/watch?v=FJ2ppNwT6Ts)
- I'm a big fan of (previous Tiny Improvement Sponsor) PostHog because they offer tools to make your product better with a massively generous free tier. Check out their [Complete Guide to Event Tracking](https://posthog.com/tutorials/event-tracking-guide) to see how you can track events and metrics in your product in a snap.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Stop Counting Clicks]]></title>
            <link>https://mikebifulco.com/newsletter/stop-counting-clicks</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/stop-counting-clicks</guid>
            <pubDate>Tue, 26 Aug 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Too many clicks isn't the problem. It's a signal that your design isn't successful.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

**"Too many clicks" isn’t the problem.** It's a _signal_ that your design isn't getting the job done. Clarity, confidence, and cognitive load are the real culprits.

Your users won't notice steps they're taking if each one is obvious and friction-free. They **do** notice when they’re lost, frustrated, or overwhelmed.

## Listen to what they mean, not what they say

**“This takes too many clicks.”**

If you build software long enough, you’ll hear this from someone.

At face value, it sounds like helpful feedback. It often comes from people who aren't software designers. They may not be able to recognize and express their real frustrations with what you've built.

Thankfully, you're here to help! It's _your job_ to respond with curiosity and empathy, and figure out what they're really trying to tell you.

"Too many clicks" is a signal that your users are feeling frustrated. It typically means something like **I can't figure out how to do what I need to do.**

When you hear "too many clicks" from one of your users or constituents, don't stop there - take the time to figure out what they're really trying to tell you.

### Why Click-Counting Fails

You may have heard of the "3-Click Rule" - this is the idea that users should be able to find what they need to do in 3 clicks.

It's a notion that has stuck around for ages. It's simple, easy to remember, and easy to test.

But here's the thing: counting clicks **sucks** as a usability metric.

I'm not making this up. UX research groups far and wide have debunked this idea over and over again, including the legendary [Nielsen Norman Group](https://www.nngroup.com/articles/3-click-rule/) and [Centre Centre](https://articles.centercentre.com/three_click_rule/).

**Clicks are scapegoats.** People only notice them when they’re frustrated.

### The Real Culprit: Cognitive Load

The people using your app pay a small mental tax for everything they do while using your software.

However, not all all actions are created equally:

- Clicking is a _motor load_ - the physical effort required to move a finger or cursor to a place and click is tiny.
- Scanning and reading what's the page is a **visual load** - reading isn't free, after all
- Deciding, remembering, or scanning a page to figure out what to do _is_ a big tax. That’s _cognitive load_ - and it's much more expensive to your users.

<Image
  publicId="newsletters/stop-counting-clicks/cognitive-load"
  alt="There are different costs to the work your users are doing."
/>

If you shave clicks but make people think harder, you’ve made things worse. Just as well, if you need to collet 20 fields from your users, one great big form may feel more daunting than a stepper with a handful of steps and clear indications of progress.

### Better than counting clicks

Instead of obsessing over steps, measure what matters:

- **Task success:** Do people finish the job they set out to do?
- **Time on task:** Do they move through in a reasonable amount of time?
- **Error/backtracks:** Are they doing a lot of scrolling around or navigating to find what they need?
- **Satisfaction:** When all is said and done, do they feel like their work was easy?

These are meaningful measures of usability, and they get to the heart of what people are _feeling_ while they use your apps.

### What you should look for instead

When someone says “too many clicks,” dig a little deeper, and interrogate what’s really going on.

Here are some common reasons people feel like they’re clicking too much:

- The flow doesn’t match their mental model
- Labels are unclear
- Nav hierarchy is confusing
- They’re not confident in what the right next step is

Your job isn’t to delete clicks. It’s to **fix the underlying friction**.

So - stop counting clicks to fix your design, and instead, **focus on the overall experience.**

If a flow is clear, users won’t care how many taps it took. If your design is really successful, people won't notice that you did anything for them at all.

<Image
  publicId="newsletters/stop-counting-clicks/anything-at-all"
  alt="If your design is really successful, people won't notice that you did anything for them at all."
/>

---

## Don't take my word for it

There are plenty of reputable sources documenting why click counting should never be your goal. If you're looking for some more reading on the topic, check these out:

- [Nielsen Norman Group: The 3-Click Rule is False](https://www.nngroup.com/articles/three-click-rule-myth/)
- [Centre Centre: The Myth of the 3-Click Rule](https://articles.centercentre.com/three_click_rule/)
- [Indeed Design: Breaking the Myth of Big Click Energy](https://blog.indeed.com/design/breaking-the-myth-of-big-click-energy)
- [Stephanie Fox UX: The Myth of Too Many Clicks](https://stephaniefox.ca/ux-blog/too-many-clicks)
- [Web Accessibility Initiative: Tips for designing Multi-Page Forms](https://www.w3.org/WAI/tutorials/forms/multi-page/#:~:text=Where%20possible%2C%20divide%20long%20forms,who%20have%20various%20cognitive%20disabilities)
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Founder Math: When to Stop Searching and Start Choosing with the 37% Rule]]></title>
            <link>https://mikebifulco.com/newsletter/optimal-stopping-problem-for-founders</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/optimal-stopping-problem-for-founders</guid>
            <pubDate>Tue, 19 Aug 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[How do you know when to stop searching and just choose? A classic bit of math offers a simple rule.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

By using a bit of math called the **optimal stopping problem**, you’ll learn exactly when to stop second-guessing yourself, and start making confident decisions, whether you’re choosing features, hiring teammates, or testing new ideas.

## Two simple rules for decision making

The **optimal stopping problem** comes from probability and decision theory. It describes how find the balance between time and quality when searching for the best option in a given set. The math behind optimal stopping is fairly complex, but the rules are simple.

For our purposes, we can use two simple rules to guide decision making:

- **Rule 1**: If you **know how many options you have**, use the first 37% of them to get a sense of the quality of your options, then choose the next item that is better than all of the previous items.
- **Rule 2**: If you **don't know how many options you have**, use the square root of the number of options you have seen so far to guide your decision.

These two rules give you a surprisingly effective way to stop overthinking and start **acting**.

## Applied science: hiring engineers

Hiring software engineers is always tricky: posting a job opening online results in a flood of applications, and you're left with the difficult task of sifting through them to find the best fit.

In practice, everyone you interview will _also_ be interviewing with other companies. This means you can't keep applicants waiting around while you interview everyone who applies. Sit on a good candidate for too long, and they'll be snapped up by another company.

It's a problem that is perfect for the 37% rule.

If you post a job and get 20 applicants in the first day, you can plan ahead. That’s where the 37% rule works best: interview the first 7 candidates just to set the bar, then hire the next person who’s better than everyone you’ve seen so far.

If you're hiring on a rolling basis, you don't know how many candidates will apply, the √N rule helps. Say you’ve looked at 16 resumes so far, that’s √16 = 4. Once you’ve seen four solid benchmarks, you’re ready to grab the next standout.

## Applied science: Influencer and Partner Outreach

Marketing often comes down to people. You might have a long list of influencers, [newsletter authors](https://mikebifulco.com/sponsor), or potential partners you want to reach out to for an ad partnership - but when do you stop searching for more and commit to building a relationship?

If you know the list size in advance (say 30 people), use the **37% rule**: spend time with the first 11 to understand what quality looks like, then commit to the next standout who outshines the rest.

If your outreach is open-ended and you don’t know how many conversations you’ll have, use the **√N rule** instead. After you’ve talked to 16, that’s √16 = 4. Once you’ve met those first four, you’re in a strong position to recognize and act on the next really promising relationship.

"Perfect" partners for influencer marketing don’t exist. Better to stop searching, commit, and grow the relationship once you've found a good fit.

## Conclusion

This is definitely a _don't take my word for it_ kind of thing - variations of the optimal stopping problem are used all over the place: from options trading, to finding your next high-paying job, this exact kind of logic has been used to make smarter decisions without the analysis paralysis.

So if they can do it, you can too.

## Further reading

If this idea hooked you, there is _loads_ more to learn. I'd recommend starting with these:

- The wikipedia article on [Optimal Stopping Problem](https://en.wikipedia.org/wiki/Optimal_stopping) has a handful of great examples of optimal stopping in action, and links to deeper mathematics from a variety of fields, including computer science, economics, and finance. Definitely worth a dive.

- As you might expect, the Numberphile YouTube channel has a great video on this topic: The [Mathematical Way to Choose a Toilet](https://www.youtube.com/watch?v=ZWib5olGbQ0).
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[You Built It. They Didn’t Come.]]></title>
            <link>https://mikebifulco.com/newsletter/product-is-a-signal</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/product-is-a-signal</guid>
            <pubDate>Tue, 05 Aug 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[My first launch failed. Years later, we sold the product - but it didn’t have to be that hard. Here’s what I’d do differently today.]]></description>
            <content:encoded><![CDATA[
My first product launch was a disaster. I had spent the better part of a year building smpl with my two cofounders; our MVP worked great, we were using it to manage our own business, and on launch day... crickets.

Thousands of lines of code, months of effort, and a beautiful marketing site. We had decided to keep smpl a secret _until it [was] ✌🏾ready✌🏾.

**Our critical launch mistake: nobody knew the damn product existed!**

In the end, smpl was a success story, but it was a success story that could have had a dramatically different trajectory.

## Trust is the hardest thing to build

When you're starting a new product or company, drumming up interest with an audience of potential customers is a critical ingredient to success. When it works, it starts with authenticity; by showing up in the places where your customers are, and becoming a trusted voice in the community.

Bar none, the single most common reason for a fumbled launch is a failure to earn the trust of the people who are supposed to use your product.

There are no shortcuts to earning trust. As a founder and a builder, this comes down to **signal** - how are you substantively showing the world that you care about the product space, that you've built a product worth using, and even more importantly -- one that's worth paying for?

### Listen first, then build

The first part of building your signal is simple: immerse yourself in the world of the people you want to serve. Listen to them, _empathize_ with their problems, and become an enthusiastic part of their community.

Go where your audience is: if they're on reddit, join the subreddit. Subscribe to relevant creators on YouTube and TikTok, and watch as many of their videos as you can. Get the newsletters, read the books, go to meetups. Do whatever you can to **be a part of the community**.

In the earliest stages of product development, you should be listening more than anything. Ask questions, and listen to the answers, and decide on a product direction based on what you're observing, not on what you thought you knew all along.

Perhaps most importantly: becoming a regular in the places where you're building your market is how you become trusted by the community. It is _really_ difficult to just show up and start selling; you have to be a part of the community first.

### Ship early, ship ugly

Once you're building, ship often, and share updates with your target audience. Don't get hung up on perfection here -- share what's new and what's working well _as well as_ the things that aren't working.

It's okay to be wrong - and probably a good thing at this stage. Features that hit the cutting room floor are ones that you can learn from, and your customers will appreciate your honesty.

Because you did your homework in the first step, you should already know where your audience goes to talk about your niche. That's great news! Share your work there, with vulnerability and honesty.

You'd be surprised how much value you can get from sharing your work in this way. Something along the lines of "Hey, I just built this tool because I was frustrated with XYZ. Does anyone else find this useful?" can be a great way to get the ball rolling. This is a great time to offer free access to your product, and get feedback from die-hards in your target audience.

### The big reveal is the path to failure

Let's all say it together: [Nobody wants The Big Reveal™️](https://mikebifulco.com/newsletter/nobody-wants-a-big-reveal). Keeping your work secret is a surefire way to launch a product that nobody wants to an empty room.

### Authenticity and the trust economy

You'll do best when the work you share comes from your heart - and not from a hastily written ChatGPT prompt. That's not to say that you should _never_ use LLMs to help you communicate, but people will be able to tell when they're being **generated-at** rather than **spoken-to**.

These signals are getting more difficult to spot; trust is harder to earn in a world where people can fake the signs of passion and success. You've probably seen headlines recently about [Soham Parekh](https://techcrunch.com/2025/07/03/who-is-soham-parekh-the-serial-moonlighter-silicon-valley-startups-cant-stop-hiring/), a talented engineer who has been working for multiple startups at the same time.

It takes less effort than ever for someone to _appear_ productive, successful, and visionary. Everything is getting wrapped in a glossy layer of AI-powered "productivity"; work is being churned out of LLMs at a pace that's hard to keep up with.

What you can't fake is results, authenticity, and the ability to deliver. Show up and _be human,_ and you'll find the right people to build for.

### Prove that your work can be trusted

The most fundamentally helpful thing you can do is build a product that has real value. All of the steps you've taken to this point should help here: you've embedded yourself with your audience, built a product that you've gone _super deep on_, and shown the world that you can deliver.

Now you've got to keep the momentum going. Product development is a marathon, and when done right, it's also a [virtuous cycle](https://mikebifulco.com/newsletter/eraser-or-wrecking-ball).

<Image
  publicId="newsletters/eraser-or-wrecking-ball/product-cycle"
  alt="The virtuous   product cycle"
  caption="The virtuous product cycle"
/>

Each iteration of your work should make the product a little more refined, and more valuable to your target audience.

---

## My favorite book for audience building

Not sponsored, I'm just a bit of an Arvid Kahl stan: His book [The Embedded Entrepreneur](https://www.theembeddedentrepreneur.com/?utm_source=mikebifulco.com&utm_medium=newsletter&utm_campaign=product-is-a-signal) is a must-read for anyone who's trying to build a product.

It _fundamentally_ changed the way I think about building products. Don't miss it.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Beyond ✨Shiny✨ Degrees: World-changing innovations from unexpected places]]></title>
            <link>https://mikebifulco.com/newsletter/public-education-and-the-value-of-collaboration</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/public-education-and-the-value-of-collaboration</guid>
            <pubDate>Tue, 15 Jul 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Public investments in education and research are a no-brainer, and these examples of game-changing innovations that came from "low value" fields of study tell you why.]]></description>
            <content:encoded><![CDATA[
## The Big idea

Your Computer Science Degree, MBA, or Law Degree is a great thing, but don't get it twisted: history-making innovations come from all areas of study.

## Public Education: Are we really debating this?

Right now, quite a bit of energy is being spent on dismantling the United States public education system. In a word, this is absolutely _baffling_ to me.

There is a ixation on cost-cutting, privatization, and the profitability of any field of study. In 2019 (the most recent dates for which I was able to find reliable data), the average income for someone with a bachelor's degree in a STEM field was $78k USD, vs $53k for someone with a bachelor's degree in a non-STEM field. (source: [National Science Board](https://ncses.nsf.gov/pubs/nsb20212/stem-labor-market-conditions-and-the-economy)).

<Image
  publicId="newsletters/public-education-and-the-value-of-collaboration/chart"
  alt="Median Salaries by workforce and education level: 2019"
  caption="Source: National Science Board"
/>

No doubt that gap has widened by 2025 - if you're motivated by earnings, studying STEM is a smart bet.

The wage gap between STEM and non-STEM fields drives high school graduates away from arts, humanities, and social sciences. Does that mean that the work of artists, writers, and social scientists is worthless?

If you think we should be axing arts, humanities, and social sciences, **you've lost the plot.**

## Huge changes from unexpected places

Among many things that get lost in this debate, I'm concerned that we're losing sight of the fact that education is not just about getting a job. Education, research, and the arts are all about _creating a better future_.

Many innovations that have shifted the course of history have come from unexpected and unlikely places.

As a builder, I find this inspiring - change comes from unexpected places, and passionate, intelligent people from all walks of life are the ones who make it happen.

### The birth of modern urbanism

[Jane Jacobs](https://en.wikipedia.org/wiki/Jane_Jacobs) was an american journalist and author who became the most influential urbanist of the 20th century. Her ideas on urban planning and architecture were groundbreaking, and her work on the book _The Death and Life of Great American Cities_ is a classic. Her influence has shaped the way cities all around the world are built, and her work is still cited today.

### Sci-fi writers influence the future

It is easy to forget how much Science Fiction has influenced the world around us. Martin Cooper, the creator of the first mobile phone, [credits Star Trek as inspiration](https://content.time.com/time/specials/2007/article/0,28804,1677329_1677708_1677825,00.html) for the invention. Ever watch an episode of the Jetsons? A fun kids show from 1962 that imagined a world with self-driving cars, doors that open and close automatically, and robot butlers. Take that, Boston Dynamics.

These things are _so embedded_ in our culture that it can be difficult to imagine a time without them. Someone, something had to come up with these ideas. The next time you hear someone saying degrees in literature should go the way of the dinosaur, remember that we have writers to thank for these.

### UX and Library Science

My love for design and User Experience has its roots firmly planted in the Dewey Decimal System. [Librarians pioneered the field of Information Architecture](https://www.uxmatters.com/mt/archives/2012/11/information-architectures-two-schools-of-thought.php) - organizing and labeling information in a way that is easy to find and use. This was the seed that blossomed into the field of User Experience.

## So then: Invest

The examples above: from urban planning and the built environment, to space-age tech to UX itself underscore a common theme: breakthroughs often emerge when disciplines collide.

Tiny Improvements readers tend to be folks building really interesting things - I don't think I need to persuade you that keeping education alive is a good thing. Keep an ear to the ground for shifting rhetoric around education, and the next time you find yourself talking about it over a coffee or a beer, keep these examples in mind.

It is impossible to tell where world-changing innovations will come from, and "letting the market decide" which types of research and education are worthwhile is a recipe for disaster.

Pursue your interests, foster creativity in your people, and build interesting things -- regardless of where the ideas came from.

_Only my field matters_ is a narrow-minded outlook that not only breeds hubris; it blinds us to game-changing opportunities outside our expertise. Interdisciplinary openness and collaboration isn't just a good idea - it's often _necessary_ to bring us to the next wave of cultural and technological change.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[What Everyone Gets Wrong About Vibe Coding]]></title>
            <link>https://mikebifulco.com/newsletter/what-everyone-gets-wrong-about-vibe-coding</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/what-everyone-gets-wrong-about-vibe-coding</guid>
            <pubDate>Tue, 24 Jun 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Vibe coding tools like Cursor, Copilot, and Claude aren’t just about speed—they’re an opportunity to code smarter and learn faster. Here’s how I use them to sharpen my skills as an engineer.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

LLMs and vibe coding tools are most powerful when they're used an an extension of your brain - not a replacement for it. Use your newfound superpowers to make yourself smarter, not just faster.

## What the heck is vibe coding?

_Vibe coding,_ in short, is when someone uses code-trained LLMs to write software, by writing instructions in plain English rather than writing code. Compare this to traditional software engineering, where a disgruntled developer pulls their hair out while yelling at their computer and slamming their hands on the keyboard until things work.

It's a vibe, man.

It's also much faster than traditional software engineering - but can be error prone, and is definitely susceptible to [Dunning-Kruger](https://mikebifulco.com/newsletter/learn-from-a-dunning-kruger-expert) failures.

Understandably, it gets a bad rap, depending on who you ask. With that said, vibe coding tools are _also_ improving at a face-melting pace, and are only going to get better.

## What everyone gets wrong about vibe coding

A lot of people (especially those who are not developers) think vibe coding tools like Cursor, Copilot, and Claude are meant to replace developers. Or, at least, that they write “perfect” code on their own.

They don’t. And they’re not supposed to.

These tools are relentless, energetic, and patient, but they’re not experts. They're more like brilliant interns: fast, eager, and often wrong, despite their endless enthusiasm.

## Tireless, not genius

Cursor, Copilot, and Claude are the most patient pair programmers I’ve ever worked with. They never get tired. They ~never~ rarely complain.

<Image
  publicId="newsletters/what-everyone-gets-wrong-about-vibe-coding/it-did-quit-once"
  alt="Even the robots give up sometimes."
  caption="Even the robots give up from time to time."
/>

Vibe coding tools will happily try something five different ways, rewrite and refactor until we land on something that works. They persevere energetically in times when even the most seasoned engineers might decide to move on to something else.

However: don't mistake their speed and relentlessness for expertise.

My advice is to treat your vibe coding tools like interns: smart, curious, and motivated, but often missing the bigger picture. They need direction. With proper guidance and context, they can be effective problem solvers. They're also damn good at coming up to speed on new frameworks and libraries.

### Vibe coding makes the hard stuff easier

Writing software tests used to be an engineering chore I quietly avoided. I'd lean on my peers to help ensure code was tested thoroughly (have I mentioned how lucky I am to be able to work with people smarter than me?).

A _huge_ benefit of the speed enabled by vibe coding is that it makes writing tests far more satisfying. Any engineer who has been doing the job for long enough can give you a laundry list of anxieties they have about how things can go wrong: timezones make dates a nightmare, off-by-one errors plague everything, and you never know when someone will use an emoji in a place you weren't expecting.

Here's what I love: vibe coding tools make it _way_ easier to write tests. Lots of them. From `minitest` and `rspec` in Rails to `jest`, `playwright`, and `@testing-library/react` in JavaScript projects, I can describe a test in natural language, like “a user shouldn’t be able to create overlapping calendar events,” provide the tool a little bit of context about which files to test, and it'll write the test for me.

### Context and communication is the root of it all

Cursor is my primary IDE at the moment, and I really love their built-in [docs indexing system]. It takes a link to docs for the libraries and frameworks I’m using, and Cursor goes to work indexing them.

In a few moments, Cursor gets up to speed on the tools my team is using. I still have to provide plenty of steering - real-world context is something the robots haven't figure out yet, thankfully.

It's allowed me to grow a skillset that was my weakest after 20+ years of writing code - I'm growing a muscle for writing tests, hardening my apps, and using the incredible frameworks that I never took the time to learn before.

## Learn while you build

Using vibe coding tools is easy. You _can_ generate entire apps without writing a line of code. You _can_ just float on autopilot, and hope it all works out. That's the easy path.

The other path is to treat vibe coding tools like the best interns you've ever had. They'll help you level up _if_ you invest in giving them clear guidance, context, and corrections.

Don’t let these tools make you lazier. Let them make you better.

**That’s the part everyone gets wrong.**

## More reading on vibe coding

- I recently came across [We need to talk about vibe coding](https://dev.to/georgekobaidze/im-all-in-on-ai-but-we-need-to-talk-about-vibe-coding-the-new-slippery-slope-2k6p) from Giorgi Kobaidze. It's a great overview of the current state of vibe coding, and a worthwhile read.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[The Quiet Room Problem]]></title>
            <link>https://mikebifulco.com/newsletter/the-quiet-room-problem</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/the-quiet-room-problem</guid>
            <pubDate>Tue, 17 Jun 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[The same psychological forces that keep people silent in moments of crisis also show up in product development - when no one questions a flawed idea, chases hard truths in the data, or speaks up for the little guy.]]></description>
            <content:encoded><![CDATA[
## The Quiet Room Problem

You’ve probably been in a meeting where something felt off.

A decision was being made, a metric was being ignored, or someone said something that just... didn't sit right. Maybe you said nothing - because no one else did. Rocking the boat is uncomfortable; maybe you weren’t sure if it was worth it.

In the 1950s, psychologist Solomon Asch ran an experiment where people sat in a room and were shown a simple image - one line segment on a card, then three lines of varying length on a separate card. The task: say which line matches the original. Easy.

<Image
  publicId="newsletters/the-quiet-room-problem/asch-experiment"
  caption="What if I told you everyone else picked A?"
  alt="A card with one line segment and three lines of varying length"
/>

There was a catch, though: everyone else in the room was a plant. They all intentionally picked the wrong answer. And in trial after trial, study participants changed their answers to match the group, even when the truth was obvious.

This is conformity in action: molding your opinion to match the group around you, even when you know it's wrong.

You've seen this in products you use, and in teams you've worked on. Concensus-driven features get built, metrics get cherry-picked, and established norms go unchallenged. "We've always done it this way" is a powerful force.

The result -- A quiet room. Quiet is not the same as agreement.

## Your role as a nonconformist

If you're reading Tiny Improvements, you're probably not chasing a quiet life in a beige office. You're here because you're curious. Because you question things. That instinct that makes you want to tweak, push, and rebuild is a _feature,_ not a bug.

On a team, it can be your superpower.

Too often, dissent is treated like a personality flaw. But when wielded thoughtfully, it's can be oe of the most valuable tools at your disposal. The best product builders don’t just ship what they’re told. They ask why. They look for holes. They call out blind spots.

It means pushing back when your team starts building without defining the problem. It means raising your hand when a decision doesn’t sit right - not because you want to be right, but because you want to get it right.

Disruptive ideas rarely start with consensus. They start with someone willing to say, "I see it differently."

## Surgical dissent

Your dissent is a pointed tool. Use it wisely, or risk quickly dulling its edge.

If you argue every decision endlessly, people will stop listening. If you're constantly poking holes, your feedback turns into background noise. Don't fall into the trap of just trying to _win_ debates - the goal is to improve the outcome, not to be right.

1. **Pick your moments.** Not every disagreement is worth a full-on pushback. Focus on high-leverage decisions: those that impact the product's direction, user experience, or team dynamics. If it’s a minor detail, sometimes it's okay to let it go.

2. **Dissent and commit.** Raise your concerns, share your thinking, then back the team’s decision. This is how strong teams stay aligned without always agreeing.

3. **Leave breadcrumbs.** If the group disagrees on a path forward, document the reasons for the decision. You’re not keeping receipts - you’re creating context. If this resurfaces later, the team will have shared context to revisit with more data and insight.

The goal is never to be the loudest voice, or to have the wildest ideas. It is to further the pursuit of the best possible outcome for your community of users, your product, and your team.

## Don’t stay quiet when it matters

Conformity feels safe, but safe rarely ships the right thing.

<PullQuote author="Ruth Bader Ginsburg">
  Fight for the things that you care about, but do it in a way that will lead
  others to join you.
</PullQuote>

Your job isn’t to blend in - It’s to speak up with care, listen with humility, and to move the needle forward. The quiet room is a trap. It’s where good intentions go to die.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Eraser or the Wrecking Ball? Planning is everything]]></title>
            <link>https://mikebifulco.com/newsletter/eraser-or-wrecking-ball</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/eraser-or-wrecking-ball</guid>
            <pubDate>Tue, 03 Jun 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[The product development process is a virtuous cycle, and has a direct impact on how well your work gets done. It will also help your teammates to understand the work ahead, and to build better products harmoniously.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

The way you get your work done has a direct impact on how well it gets done, especially when working with teams on problems of increasing complexity. Time spent planning multiplies your productivity.

<a
  href="https://tiny.outlier.ai/yckz3zcs"
  className="text-xs lg:text-xs xl:text-xs"
>
  Brought to you by Outlier AI
</a>

The title of this post is inspired by a Frank Lloyd Wright quote that became a mantra for my team while I was working at Gymnasium:

> An architect's most useful tools are an eraser at the drafting board and a wrecking ball at the jobsite.

Planning is **everything**.

## The virtuous product cycle

Building products for real people is a really hard. Even if you've found an audience and a product idea that you're confident in, doing a _great job of building the thing_ is always going to be challenging. I had the great fortune of working at Microsoft in my first job after university, where I was able to work on some pretty incredible teams of experienced engineers.

One of the most important things I learned in that job was a framework for building products in small, iterative cycles, which I've been using ever since. It breaks down each project, milestone, and feature into a few simple phases:

<Image
  publicId="newsletters/eraser-or-wrecking-ball/product-cycle"
  alt="The virtuous product cycle"
  caption="The virtuous product cycle"
/>

### Envision - understand the problem

In the **envision** phase, you're trying to understand the problem. This is where you capture the hopes and dreams of the people who will be using your product. This is where you get your baseline requirements from, in the form of user stories, feature lists, diagrams for workflows, and other documentation.

### Plan - break it down

In the **planning** phase, your job is to break down a complex problem into smaller parts. Ideally, this is a list of small tasks that can be completed relatively quickly. I usually shoot for no longer than 1 day. It's helpful here to think about inter-dependencies between tasks, and to capture things that aren't _strictly_ code: documentation, updated test cases, API endpoints that may change, UX work that needs to be done, and so on. You'll want to capture dev tasks, too - list out everything that needs to be done to get the feature working, even if it feels pedantic.

This is a critical bit of work, especially if you're working with non-technical people: this list of tasks is your best reference point when someone asks "what's left to do?" or "why isn't this done yet?". Combined with the details you captured during the **envisioning** phase, you should have a clear picture of what you're going to build, as well as the decisions made to get there.

Most importantly - at this point, **anyone** on your team should be able to read through this list and understand the work ahead, and even pick it up and run with it if needed. It means you won't have to answer questions in JIRA while you're sitting on your next vacation.

Planning is the step that we all tend to resist; it's easy to do. Fueled by excitement of something new, this step is the most likely to be overlooked. I've absolutely done it, and more often than not it

Skipping this step is a surefire way to miss important details; it's common during planning to unearth requirements that were missed in the envisioning phase - and it's a lot easier to fix them at this stage.

### Build - get it done

This is the one we're all chomping at the bit to do: coding away furiously to make the feature come to life, and to build out all of the exciting bits that comprise it.

### Stabilize - the one where you fix the bugs

This is the pre-deployment step where you write tests, conduct QA and acceptance testing, and make sure everything is working as expected. It's a good time to check in with the team to make sure everyone is on the same page, and to make sure you're not missing anything (even if it wasn't documented before!).

This is also a good moment to prepare documentation, demo videos, and other materials that will help your launch be a success.

### Deploy

🚀 Launch it!

### Analyze

Get your feature into the hands of your users, share documentation and demos with the world, and start gathering feedback. This is a great time to use product analytics and the telemetry you have available to learn whatever you can from the way people are using your feature, and to plan the next version.

Then go back to the start: the whole cycle starts again.

It takes practice and discipline to get this right, but it's worth it.

---

## Front-end Devs: Get Paid to Critique AI-Generated Code

Outlier (by Scale AI) is hiring frontend devs to help train cutting-edge AI—no AI experience needed. Work remotely, set your own hours, and earn up to $50/hr reviewing code and UI, with weekly payouts.

Help shape the future of dev tools - [apply now](https://tiny.outlier.ai/yckz3zcs)

<a
  href="https://tiny.outlier.ai/yckz3zcs"
  target="_blank"
  rel="noopener noreferrer sponsored"
>
  <Image
    publicId="sponsors/scale-ai/contribute-sq"
    alt="Outlier by Scale AI"
    className="max-w-sm"
  />
</a>

---

## Great ideas from people smarter than me

Earlier this week, I came across [Debug with Notes](https://coolsoftware.dev/blog/debug-with-notes/), by [Tyler Williams](https://bsky.app/profile/coolsoftware.dev/post/3lqljgta5cs2j) on BlueSky. His process involves taking detailed notes while working through a bug; it's a super helpful pattern for tackling situations where you're unfamiliar with the codebase, and to give yourself a point of reference if you get pulled away from a problem before fixing it.

LeadDev has a great article on [a tech lead's guide to effective communication](https://leaddev.com/communication/tech-leads-guide-effective-communication) that I keep bookmarked. It's a great reminder that communication is a skill which can be improved with practice.

## Farewell, Gymnasium

This is normally where I'd shout out the free courses offered by the gang I used to work with at Gymnasium, but I'm sad to say that Gymnasium was shuttered at the end of May.

**If you're hiring for UX leadership, marketing or technical learning**, my former colleagues from Gymnasium are world-class. [Drop me a line](mailto:hello@mikebifulco.com), I'd love to set up an introduction.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Open Source your learning with GitHub]]></title>
            <link>https://mikebifulco.com/newsletter/open-source-is-your-secret-weapon</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/open-source-is-your-secret-weapon</guid>
            <pubDate>Tue, 27 May 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Open source is an open invitation to plug into a global braintrust of brilliant people building the future. What you get out of it has a lot to do with what you put in.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

Open source is an open invitation to plug into a global braintrust of brilliant people building the future. What you get out of it has a lot to do with what you put in.

<a
  href="https://tiny.outlier.ai/yckz3zcs"
  className="text-xs lg:text-xs xl:text-xs"
>
  Brought to you by Outlier AI
</a>

---

Source control services like GitHub and GitLab are more than just a place to store code. They provide a living, breathing network of ideas, collaboration, and discovery. Contributing to open source is a great way to build your network, learn new things, and get paid. People get hung up on the idea that the _only_ way to contribute to OSS is by opening pull requests or reviewing other peoples' code.

If you're not ready for that yet, that's okay! There are countless ways to contribute that shape the direction of tools you depend on. Active participation can benefit the libraries you rely on _and_ help you get your work done.

## Feedback is fuel

Open source runs on participation. You don't need to submit a Pull Request to be helpful. Star the repos you like, vote on issues that matter to you. Subscribe to threads where you can add meaningful context. Maintainers often decide what to work on based on what gets the most attention. Quiet enthusiasm doesn’t move roadmaps-clicks and comments do.

### Curation is a superpower

Finding great open source tools is a skill, and frankly, it can be a competitive edge. You won’t always be looking for a new library, but building your own mental Rolodex of interesting tools helps when you're deep in a problem later. I run [OpenAPI.Tools](https://openapi.tools/) to share and surface great projects in for API devs, thanks to hundreds of contributors. Day to day, I find most of my favorite new things from Bluesky, YouTube deep dives, and Discord messages that start with "I made a thing."

### Your activity is your brand

No one cares how many green squares you have, but when it really matters, people will notice if you’re actually _doing_ interesting work. When hiring, I take the time to brows every candidate's GitHub profile. If everything’s private, you disappear into the noise. I wrote about this in ["Your Resume Sucks"](https://mikebifulco.com/newsletter/your-resume-sucks), but the TL;DR is: your public footprint matters. Not for the numbers, but for the narrative.

GitHub is more than source control. It’s where modern builders show their work-and shape what gets built next.

---

## Front-end Devs: Get Paid to Critique AI-Generated Code

Outlier (by Scale AI) is hiring frontend devs to help train cutting-edge AI—no AI experience needed. Work remotely, set your own hours, and earn up to $50/hr reviewing code and UI, with weekly payouts.

Help shape the future of dev tools - [apply now](https://tiny.outlier.ai/yckz3zcs)

<a
  href="https://tiny.outlier.ai/yckz3zcs"
  target="_blank"
  rel="noopener noreferrer sponsored"
>
  <Image
    publicId="sponsors/scale-ai/contribute-sq"
    alt="Outlier by Scale AI"
    className="max-w-sm"
  />
</a>

---

## Repos for you to check out

On any given week, there's probably a half dozen repos that I've been sifting through for documentation, examples, or known bugs (as well as the occasional contribution). Here's the ones that have been on my mind this week:

- [Expo](https://github.com/expo/expo) - At [Craftwork](https://craftwork.com?utm_source=mikebifulco&utm_medium=email&utm_campaign=open-source-for-everything) we use Expo with React Native to build the mobile app that our team uses. React-native has come _such_ a long way in the past few years, thanks in no small part to the geniuses on the Expo team.
- [React Native Reusables](https://github.com/mrzachnugent/react-native-reusables) - Is a brilliant collection of reusable components for React Native, that uses tailwind (via the Nativewind library) to recreate Shad CN UI components for react-native. React Native apps can't use `<div>` and other HTML elements, so this library is a huge benefit for us.
- I've spent quite a bit of time usingtThe Typescript SDK for the [Model Context Protocol (MCP)](https://github.com/modelcontextprotocol/typescript-sdk) as research for connecting AI tools to Craftwork's business logic; I think it's safe to say that I'm squarely in the _early adopted_ phase for this library. It's been a bit bumpy, but it's been evolving quickly.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[AI Prompt Secrets - what the leaks tell us]]></title>
            <link>https://mikebifulco.com/newsletter/learn-from-llms-leaking-their-prompts</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/learn-from-llms-leaking-their-prompts</guid>
            <pubDate>Tue, 13 May 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Popular AI tools like Claude, v0, and Cursor can be coaxed into revealing their prompts. Here's what I learned from a deep dive into some of the most successful prompts in the world.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

The secret sauce of successful AI prompts is out in the open, and comes down to job, context, capabilities, constraints, and flavor. What sets apart the winners, though, is User Experience.

## LLMs are spilling their guts

Every week or so lately, I've seen a headline about one of the popular LLMs leaking its prompts - whether it's Claude, v0, Cursor, or something else. This is a side-effect of the way that LLMs work. There's no guarantee that they take instructions from [someone], and do their best to follow them.

As such, there are hordes of clever people out there trying to get LLMs to leak their own instructions to the world... and from time to time, they're succeeding.

Here's some snippets cribbed from (supposedly\*) leaked prompts (github repos linked below) that I found interesting:

From a leak of ChatGPT's prompts, on image generation:

```md
Not Allowed: Giving away or revealing the identity or name of real people in images, even if they are famous - you should NOT identify real people (just say you don't know).
```

Manus's approach to breaking down specific tasks:

```md
## Task Approach Methodology

### Understanding Requirements

- Analyzing user requests to identify core needs
- Asking clarifying questions when requirements are ambiguous
- Breaking down complex requests into manageable components
- Identifying potential challenges before beginning work
```

_Ask clarifying questions_ - I can't tell you how many times _that_ has been an important unlock while doing UX work!

### The basic shape of great prompts

- **Job**: _You are a [coding assistant] from [company name], using [some LLM technology] to [help people do some thing]_
- **Context**: _This is your goal, and this is why your human counterpart is using you_
- **Capabilities**: _You have these tools at your disposal (edit, code reference, image generation, etc.)_
- **Constraints**: _Always do this, never do that_
- **Flavor**: _You are [casual, friendly, professional, etc.]_

Of these ingredients, it's impossible to say which is the _most_ important, but it's clear that the combination of all of them makes for a successful prompt.

I do find it charming that so many prompts feature very-human-sounding language like "you're _the best in the world_ at..." -- part of me feels like this is developers trying to affirm their own value.

Part prompt, part therapy - why not!

### These are secrets of the past

The companies that builds these LLM tools and prompts are _constantly_ improving them. They use sophisticated observability tooling like [Langchain](https://www.langchain.com/) to measure the success of their prompts and iterate on them.

There are teams of engineers and linguists (and probably also other LLMs) working on these prompts, making countless of small changes to make them work better, more safely, and more effectively.

The prompts you've found online were likely out of date the instant they were leaked. In fact, it's possible (if not likely) that at least some of these _leaked_ prompts are themselves hallucinations; results that _look_ believable, but are not entirely correct. That's the nature of LLM technology.

### Prompt engineering and the LLM ecosystem

The wildest thing about all of this is that you can just _take_ these right now. You can start using all or part of any of them within your LLM workflows. Claude, ChatGPT, Gemini, and others will all take custom instructions; you can just copy and paste the parts you like into your tool of choice.

"Prompt engineering" is the term that has been coined for folks who spend their days figuring out how to squeeze a little more juice out of LLMs by writing custom instructions. It's interesting to me that this has become so same-y; this convergence across corporations is a likely indication that we've reached a point of diminishing returns. You're unlikely to prompt your way to the next echelon of functionality with the current generation of LLMs.

### For product builders, it comes down to UX

The tools that rise to prominence are those that have been built around great user experience - the ones that are most pleasant for us meatbags to use ergonomically to get our work done.

If you're setting out to add AI magic to a product that you're building, I'd advise you to borrow _heavily_ from what's been leaked in these prompts. Spend 80% of your time making it _really nice_ to use your AI tools, and the other 20% iterating on your prompt.

You'll do best if you can measure the success of your prompt by the number of people who actually use it, the number of times they use it, and how often they come back vs. drop off.

### We're all fighting our own laziness

For me, the most revealing thing about all these leaked prompts is just _how long_ they all are. LLMs can process so much more context now than they could a few years ago.I think OpenAI's models were limited to something like 1000 tokens in 2021. Now, instructions alone are crossing 50k tokens!

When you're working with an LLM, your laziness is a likely failure point. LLMs aren't magic, they're just _really well informed_ word-guessers. The more context you give them, the better they'll do.

If you're providing two sentence instructions to the tools you're using, you'll get two sentence responses.

So, treat them like you would treat a new teammate, or like you would want to be treated when you're learning something new: the more detailed instructions you can provide, the better chance they have of doing a decent job.

---

## Go read some prompts

- [Claude's prompt](https://github.com/asgeirtj/system_prompts_leaks/blob/main/claude.txt) is about 24k tokens long, and is stored alongside a collection of other leaked LLM prompts in this repo from GitHub user `@asgeirtj`
- You can read v0's [model and prompts](https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools/tree/main/v0%20Prompts%20and%20Tools) thanks to another repo from GitHub user `@x1xhlol`

That's all for me this week, gang - if you found this useful, I'd love it if you shared it with your people.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[I want to feel the hand of the f%#king creator]]></title>
            <link>https://mikebifulco.com/newsletter/passion-and-the-hand-of-the-creator</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/passion-and-the-hand-of-the-creator</guid>
            <pubDate>Thu, 08 May 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[It's not divine intervention; it's just someone who did a damn good job.]]></description>
            <content:encoded><![CDATA[
# The Big Idea

It's not divine intervention; it's just someone who did a damn good job.

<a
  href="https://www.paddle.com/events/webinars/web-revenue-labs-what-to-do-in-this-post-apple-ruling-landscape?utm_medium=website&utm_source=partner&utm_campaign=webinars_fy2025_q2_apples_app_store_ruling&utm_content=tiny-improvements"
  className="text-xs lg:text-xs xl:text-xs"
>
  Brought to you by Paddle
</a>

## Go on, put your back into it

North Carolina summers are like being slowly baked inside a damp sock. Triple-digit heat. Humidity so thick you could bottle it and sell it as soup. It’s the kind of weather that makes you question your life choices.

But the moment you step into a perfectly air-conditioned room: one that hits you with that crisp, fresh chill on a blistering day - that is what salvation feels like. Not just relief, but a stark, physical reminder of the incredible effort that has gone into the built environment.

Now and then, I get the same feeling from software, too. When someone really puts every bit of their intellectual might into making something that feels _alive_.

### Creative works that just feel different

**[Blue Prince](https://www.blueprincegame.com/)** and **[Animal Well](https://www.animalwell.net/)** are two recent games that twist themselves into meta-puzzles, daring you to notice every pixel. I hardly play games at all nowadays, but I can feel the love in every corner of these worlds. It’s intoxicating.

**Small touches added to Android** - instant translation of any text on any screen (even from an image!), no app-switching needed. Spam calls? Silenced. Texts from bots? Blocked. It feels like magic, but it’s just good design.

<Image
  publicId="newsletters/passion-and-the-hand-of-the-creator/google-translate"
  alt="Translation feature on Android"
  caption="Translation in-app is such a thoughtful feature."
/>

[PostHog's new AI Wizard](https://posthog.com/docs/getting-started/install?tab=wizard) - I ran a single npx command and it read my codebase, set up analytics, and configured AI suggestions like it knew exactly what was needed for Craftwork's specific architecture. That’s not a fluke - that’s care, craftsmanship, and context-awareness built into the bones.

<small clasName="text-xs italic text-gray-500">
  (side note: posthog is a past sponsor of Tiny Improvements - but this is not a
  sponsored message. I'm just that damn impressed..)
</small>

### Now go do the damn thing

These examples are more than just little features. They’re evidence of effort, of risk, of someone pushing past “good enough.”

And that’s the work that sticks with me; because it has a **pulse**.

Recreating that sensation... the feeling of a blast of AC on a boiling day - is what I want to do with every product I work on.

**What will it take** to give your work a pulse?

## Mobile app revolution: What to do in this post-Apple ruling landscape

In the latest turn in the Epic Games v Apple legal saga, Apple is now required to allow developers to link to external payment options without imposing additional fees or restrictions. With the freedom and the complexities of taking payments for your app on the web, the real question is: what to do next? Join Paddle as they answer your burning questions and give practical advice you can execute today.

📆 Live Webinar: May 13, 12–1pm EDT
[Register now](https://www.paddle.com/events/webinars/web-revenue-labs-what-to-do-in-this-post-apple-ruling-landscape?utm_medium=website&utm_source=partner&utm_campaign=webinars_fy2025_q2_apples_app_store_ruling&utm_content=tiny-improvements) - it's free!

## Links plucked from my gray matter

One of the things I like most about my job is being able to take inspiration from all over the place. These are some of the things that have stuck with me recently:

- [Unreasonable Hospitality](https://amzn.to/4idMvHZ) is The best book I've read in the past year, hands down. I liked it so much I read it twice, [wrote a newsletter about it](https://mikebifulco.com/newsletter/unreasonable-hospitality-and-design), and bought copies for friends and teammates.
- The [Besties Podcast on Blue Prince](https://thebesties.substack.com/p/blue-prince-is-the-first-must-play) is what convinced me that there was something special in the source code for the game. Host Justin McElroy's quote about "feeling the hand of the creator" sold me on it. What a masterpiece.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Serendipity isn't an accident]]></title>
            <link>https://mikebifulco.com/newsletter/serendipity-isnt-an-accident</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/serendipity-isnt-an-accident</guid>
            <pubDate>Tue, 29 Apr 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Career opportunities don't "just happen" - they come from staying connected, helping others generously, and trusting your instincts when the right path shows up.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

<a
  href="https://www.paddle.com/events/webinars/lessons-from-saas-founders-whove-done-it?utm_medium=website&utm_source=partner&utm_campaign=webinars_fy2025_q2_core_fireside_founder_chat_30apr&utm_content=tiny-improvements"
  className="text-xs lg:text-xs xl:text-xs"
>
  Brought to you by Paddle
</a>

Opportunities don't "just happen" - they come from staying connected, helping others generously, and trusting your instincts when the right path shows up.

## Serendipity isn't magic

Opportunities don't "just happen" - they come from staying connected, helping others generously, and trusting your instincts when the right path shows up.

Years ago, when I was fresh out of college and living on my own for the first time, I read a book called _Never Eat Alone,_ by Keith Ferrazzi.

I don’t agree with everything in it - the title alone feels a little over the top - but the core idea stuck with me: Stay connected. Help when you can. Introduce people who can help each other.

I've carried that theme with me ever since.

Whether it’s friends, colleagues, or online pals (like the [developer community](https://apisyouaonthate.com) I run with two people I've never met in person), I try to be helpful when I can - without keeping score.

## Choosing to be helpful

Around 2018, I had the opportunity to watch some friends complete the Techstars startup accelerator, where I picked up another mantra:

_Give without the expectation of receiving._

Many people people are doing mental accounting all the time - who owes who what, who's "worth it." It's exhausting. For me, it misses the point.

The people I've encountered who seem to have endless opportunity around them are the ones who _help_ first, without asking what’s in it for them.

## Some people do suck

This is important - **you don't owe everyone your time.**

If someone makes a habit of taking advantage, wasting your energy, or treating you poorly, you are not obligated to stay engaged. Good faith should be earned - and kept.

Trust your internal barometer, use your powers for good.

### A framework for building your own luck

- Help people when you can. Make intros. Cheer people on. Share what you genuinely admire.
- Be open to new people and ideas. Take introductions seriously - you never know which one will change your life.
- Trust your instincts. Only you know the full context of your life and goals. When something feels right, follow it.

Most of all, **protect your time**. Being generous doesn’t mean being a doormat.

Serendipity isn’t magic. It’s built by your choices and actions over a longer period of time than you might expect.

---

## From Idea to Exit: SaaS Founders Spill Their Secrets

Why do some SaaS ideas soar while others stall? Paddle's panel of seasoned SaaS founders will talk on idea validation, bootstrapping vs VC funding, scaling tactics & hard-won lessons. It’s a founder therapy session disguised as a webinar.

**📆 Live Webinar**: April 30, 12–1pm EDT

[Save your seat](https://www.paddle.com/events/webinars/lessons-from-saas-founders-whove-done-it?utm_medium=website&utm_source=partner&utm_campaign=webinars_fy2025_q2_core_fireside_founder_chat_30apr&utm_content=tiny-improvements)

---

## What I'm reading

**[Never Eat Alone](https://amzn.to/4cSy23f)** by Keith Ferrazzi, helped forge my outlook on building a strong network, as a bright eyed college grad.

I just finished **[Careless People](https://amzn.to/3GubN7A)**, a memoir by Facebook's first Director of Public Policy. It is a gut-punch of a book, divulging some serious details about the casual relationship that Zuck and company had with ethics as they grew to an incomprehensibly large company. The book had me doing karate kicks in my living room.

A while back, I published a treatise on hiring called **[Your Resume Sucks](https://mikebifulco.com/newsletter/your-resume-sucks)**. A reader this week reached out with a great example of someone going the distance to stand out from other applicants: check out [The unhinged application I used to get a job at a fast-growing startup](https://userobsession.substack.com/p/the-unhinged-application-i-used-to) from Finn Lobsien.

Shout out to Rusty in Seattle for sharing!
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Freedom is a Feature: why competition is a good thing]]></title>
            <link>https://mikebifulco.com/newsletter/freedom-is-a-feature</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/freedom-is-a-feature</guid>
            <pubDate>Tue, 22 Apr 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Why freedom and openness in software matter more than ever. How MCP, OpenAI, and Apple’s AI fumble show that trust is built on interoperability.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

<a
  href="https://www.paddle.com/events/webinars/lessons-from-saas-founders-whove-done-it?utm_medium=website&utm_source=partner&utm_campaign=webinars_fy2025_q2_core_fireside_founder_chat_30apr&utm_content=tiny-improvements"
  className="text-xs lg:text-xs xl:text-xs"
>
  Brought to you by Paddle
</a>

**Freedom builds trust.** People don’t want to feel trapped by the products they use. In an ecosystem full of walled gardens, openness and interoperability are your competitive advantage.

---

## Freedom Is a Feature

**Platform lock-in is one of the tools of the trade for companies building products without a real moat.**

If you can’t win on quality or experience, maybe you can trap people just long enough to squeeze some revenue out of them.

But people feel it: Lock-in creates friction; it quietly drains trust.

The better path? Leave the door open, and make a product so good people don't want to leave.

### Enter MCP

That’s what makes **MCP** such a fascinating case study.

Introduced by Anthropic in 2024, **MCP (Model Context Protocol)** is an open standard that helps developers guide LLM agents to use specific tools and workflows-no more spray-and-pray guessing. It brought structure and predictability to AI automation in a way that hadn’t been possible before.

And crucially: **Anthropic [open-sourced](https://modelcontextprotocol.io/introduction) it.**

This has quickly sparked a shift across the industry. Since its launch in November 2024, MCP has become _the_ way to build reliable, agent-powered workflows.

Adoption has been explosive. It's gained so much traction, so quickly, that every major player has adopted it.

**OpenAI included.**

With $62B in funding and a massive head start (vs. Anthropic’s ~$18B), OpenAI could’ve tried to ignore MCP, or bury it with their own proprietary solution.

Instead, they embraced it.

Supporting MCP was the only reasonable move - and ultimately, a smart one.

**Openness won,** and builders, developers, and end users are all better off for it.

### Meanwhile, in Cupertino…

Apple’s absence from the LLM conversation is starting to look more and more like Microsoft’s infamous fumble on mobile in the early 2000s. Siri has missed the moment - and unless Apple makes a major acquisition soon or has a surprise launch in their back pocket, they may be sitting out the next platform shift entirely. 🍎

---

## From Idea to Exit: SaaS Founders Spill Their Secrets

Why do some SaaS ideas soar while others stall? Paddle's panel of seasoned SaaS founders will talk on idea validation, bootstrapping vs VC funding, scaling tactics & hard-won lessons. It’s a founder therapy session disguised as a webinar.

**📆 Live Webinar**: April 30, 12–1pm EDT

[Save your seat](https://www.paddle.com/events/webinars/lessons-from-saas-founders-whove-done-it?utm_medium=website&utm_source=partner&utm_campaign=webinars_fy2025_q2_core_fireside_founder_chat_30apr&utm_content=tiny-improvements)

---

## 🧠 Further Reading

- [**Model Context Protocol (MCP) Docs**](https://modelcontextprotocol.io/introduction)
  The official intro to MCP; it's still early days and these docs are evolving quickly, but they are _the_ place to start.

- [**OpenAI Agents SDK – MCP Support**](https://openai.github.io/openai-agents-python/mcp/)
  OpenAI’s implementation of MCP, complete with setup and examples.

- [Google's Agent Development Kit](https://cloud.google.com/blog/products/ai-machine-learning/build-and-manage-multi-system-agents-with-vertex-ai) mentions support for MCP as part of their three-pillar approach to building production AI products.

- 🎙️ [**Accidental Tech Podcast – Ep. 635: An Effective Operator**](https://atp.fm/635)
  ATP digs into Apple’s LLM absence, and why it might haunt them long-term. (Marco’s comments on this feel… prophetic.)

---

## Sensing some subtext here?

For my 🇺🇸 readers:

Republicans in Congress have introduced the _SAVE Act_ - a bill that would make it nearly impossible for millions of eligible Americans to register to vote.

This bill would require in-person registration with a passport or birth certificate-which tens of millions of Americans don’t have easy access to. It's not about security. It’s about suppression.

So much for openness and freedom.

They’re counting on you to be too tired, too distracted, or too polite to fight back. Prove them wrong.

Save yourself from the worst type of vendor lock-in imaginable.

Call your goddamn senator, and give 'em hell.

👉 [5calls.org/issue/save-act-voter-suppression](https://5calls.org/issue/save-act-voter-suppression)
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[What to do when the bottom falls out]]></title>
            <link>https://mikebifulco.com/newsletter/what-to-do-when-the-bottom-falls-out</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/what-to-do-when-the-bottom-falls-out</guid>
            <pubDate>Tue, 08 Apr 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[A realist's guide to flattening out unexpected downturns]]></description>
            <content:encoded><![CDATA[
## The Big Idea

When the world feels shaky, your steadiness matters more than ever.

<a
  href="https://www.vpdae.com/redirect/svufr105vnsrt8wft6ggddi6gpl"
  className="text-xs lg:text-xs xl:text-xs"
>
  Brought to you by Whalesync
</a>

---

Last weekend I saw [The Tallest Man on Earth](https://thetallestmanonearth.com/) play in Saxapahaw, NC. It was the first day of the Swedish singer-songwriter's North American tour, at a modest venue in a quaint mill town in the middle of nowhere.

Throughout the show, it ws obvious that he was going through something. Between songs, he talked about how he lived in the US for years, and that it's a country he's always loved - and that it's felt different lately.

I'll second that.

<Image
  publicId="newsletters/what-to-do-when-the-bottom-falls-out/tallest-man"
  alt="The Tallest Man on Earth"
/>

He also said something that really stuck with me: if we could all just focus on being cooler humans, we'd live in a much better world.

I can't stop thinking about that.

I'm the first to tell you that I can't fix other people - but who I am is squarely in my locus of control.

So, let's start there.

## Never let a good crisis go to waste

Here’s the truth: we can’t control the economy, or the stock market, or the news cycle.
But we can control how we show up.

When the bottom falls out, the instinct is to panic, to isolate, to hunker down and wait it out. But that’s not how we rebuild. Not really. What gets us through the hard stuff is community, clarity, and actions - even small ones.

So, what can you do?

- **Check in on your people.** Like, _really_ check on them, and listen to what they're saying.
- **Share what you’re learning.** You never know who might benefit from it; and personal growth tends to open doors.
- **Make introductions.** Serendipity can't be created, but it can be seeded. The right connection at the right time can change someone’s life.
- **Keep building.** Not for the headlines, but for the people who’ll benefit from what you make - and for yourself.

The builders who keep showing up - kindly, consistently, with purpose - tend to be sources of support and community when it matters most.

tl;dr: Give without expecting anything in return, and be a cooler human.

---

## Get it done with Supabase + Airtable + Vibe Coding

Wasting time trying to build an admin dashboard from scratch?

Whalesync (YC S21) helps you build admin tools _fast,_ by syncing Supabase with Airtable, Notion, or Google Sheets.

Use the tools you already love. Keep your data in sync. Skip the boilerplate.

Ship faster. Stay in flow. [Try Whalesync free →](https://www.vpdae.com/redirect/svufr105vnsrt8wft6ggddi6gpl) <img src='https://www.vpdae.com/open/9be07c5e.gif?opens=1' width='1' height='1' />

---

## Making a case for doing good things

If you need evidence benevolent behavior is good for business, look at who’s done it before:

- [Ben & Jerry’s](https://www.benjerry.com/values) has built their brand by showing up for people who can’t always speak up for themselves. They've made advocacy part of their product.
- [Notion](https://www.notion.com/product/notion-for-education) gives away tools to students and teachers as part of their mission to help people learn and grow.
- [Fastly](https://www.fastly.com/company)'s devtools platform is accompanied by a strong mission to make the internet a better place.

You don’t need an underground bunker. You just need to be one of the people who gives a damn when things feel uncertain.

This is when it matters most. ✌️

Give 'em hell out there,

- Mike
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Tools I Love - Resend and React Email]]></title>
            <link>https://mikebifulco.com/newsletter/tools-i-love-resend-react-email</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/tools-i-love-resend-react-email</guid>
            <pubDate>Tue, 01 Apr 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[The best developer tools make you faster and make you look good. Resend does both - for email, of all things.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

The best developer tools make you faster and make you look good. Resend does both - for email, of all things.

## Let's talk about tools

I've had a few conversations lately with other founders and indie hackers about the stack behind my site-and one thing always comes up: how I send emails.

To be clear: **this isn't a sponsored post**. Nobody paid me to write this. I just really like using Resend, and I think more developers should know it exists.

As a startup founder, every one of my days is time-constrained. I’ve always got too much to do, and too little time to do it. That’s why I’m a sucker for tools that do two things at once: save me time and help me look polished.

[Resend](https://resend.com) is one of those rare tools. It makes sending beautiful, functional emails from your app almost feel… fun? Which, if you’ve ever wrestled with email templates, you’ll know is not a word we usually associate with this stuff.

## Why the heck is email so hard?

If you've never tried designing email, it sounds simple-just HTML and CSS, right?

Not quite.

Email clients (Gmail, Apple Mail, Outlook) all render things differently. There’s no real standard, and the rules are weird and inconsistent.

Why? Because email is ancient tech. Email has been morphing and evolving since the 1980s - and once you start trying to send nice-looking emails, you will feel it.

### Resend to the rescue

I use Resend to send my newsletter, as well as transactional emails -- like the confirmation message that new subscribers get. I designed my email templates in Figma like I would any other interface, and use Resend's open source [React Email](https://react.email/) library to bring it to life in code.

<Image
  publicId="newsletters/tools-i-love-resend-react-email/figma-template"
  caption="My transactional email template started in Figma"
  alt="My transactional email template in Figma"
/>

I cannot overstate how difficult this process _used_ to be. That 👆🏾 is an extremely ambitious email format to build from scratch.

In the new world of Resend, it's a familiar pattern:

<Image
  publicId="newsletters/tools-i-love-resend-react-email/code-snippet"
  alt="My transactional email template in React Email"
/>

The code to ship it off to your inbox isn't bad either:

```tsx
const WelcomeMessage = <WelcomeEmail firstName={firstName} />;
const { data, error } = await resend.emails.send({
  from: '💌 Tiny Improvements <hello@mikebifulco.com>',
  to: [email],
  subject: "Subscription confirmed. I'm so glad you're here!",
  react: WelcomeMessage,
  text: await render(WelcomeMessage, { plainText: true }),
});
```

My next.js site is also set up to listen to a few webhooks from Resend, where I can track things like subscription events, opens, unsubscribes, and more.

There's more to it than that, and if you're interested in the nitty-gritty, my site's source code is [available on GitHub for you to check out](https://github.com/mbifulco/blog).

---

## What tools make you look good?

Tips, tricks, and recommendations from my dev-pals is something that I've always loved. When I get around to it, I've got a whole list of recommendations that I'm planning to share -- like the shortcuts I find most helpful with [Raycast](https://www.raycast.com/), and the process I'm using to make Cursor smarter while I code.

I'm really keen to hear from you.

What tools make you look good? What saves you time and makes your life easier? [Send me a note](mailto:hello@mikebifulco.com). I'm all ears!

---

## Some links to keep your brain wrinkling

I'll cop to it: I haven't had a lot of time for things other than work lately. When I have had some time to relax, these videos have stood out from the pack.

- [Frozen orange juice is actually super weird](https://www.youtube.com/watch?v=9wSQ9Zk_9gQ) is a fascinating video essay from Phil Edwards about the surprising economics of something that seems so simple.
- [How do we feel the wind?](https://www.youtube.com/watch?v=Q0_W4SWHeWY) - part of Complexly's recent video series where people ask Hank Green... well, anything. In this edition, musical supergenuis Jacob Collier does the asking. Really, really interesting to see to _absolutely brilliant_ people interact so candidly.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[The 3 Mistakes New Creators Make]]></title>
            <link>https://mikebifulco.com/newsletter/mistakes-new-creators-make</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/mistakes-new-creators-make</guid>
            <pubDate>Tue, 25 Mar 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Most new creators stall before they start. Avoid these 3 common mistakes - and learn where to focus instead. Create. Publish. Share.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

Starting is harder than it looks. And it's easy to waste time doing the wrong things first.

I've had the same conversation a handful of times lately - with friends ready to publish, build, create. They're excited. They're asking about tools, hosting, platforms. They're planning _big_.

And they're already off track.

Here are the 3 mistakes I see most new creators make (and how to avoid them):

### 1. You can't buy creativity

New gear. Fancy tools. Premium subscriptions.

It _feels_ like progress, but it's not.

It's tempting to whip out your credit card from the jump, but you can't buy your way into being a creator.

Buying a domain, a newsletter service, podcast hosting, or a fancy camera _feels_ good, but doesn't move the needle.

<Aside>

**Do this instead:**
Harness your excitement and energy - use it to make something (a video, a blog post, a podcast, whatever it is you're trying to create), and share it. Then do that again. And again.

Your work will get better, and your audience will grow.

</Aside>

You can't buy creativity -- and you also can't buy more time. Don't waste your time and money on gear until it's the _only_ thing in the way of growth.

### 2. Don't skip the basics: how to find your niche

Many of the folks I talk to want to create something, and they fall on two extremes: (1) they want to create something on a _wide variety_ of topics, or (2) they can't decide what topic they want to create about.

These sound like different problems, but they're both symptoms of the same root cause: a lack of clarity on who you're creating for.

The most successful creators I know have a clear, focused niche, and a deep understanding of their audience.

<Aside>

**Do this instead:**

Do a deep audit of your interests, passions, and skills. For each, ask yourself:

**Where are people interested in this topic finding each other online?**
Look for forums, subreddits, youtube channels, social media accounts, etc. where people are talking about your interests, and see what they're saying.

**What do successful creators in this niche have in common? What do they do well?**
Look at the creators who are already successful in your niche. What do they do well? What do they say? What do they share?

**What perspective do I have that can add to the conversation?**
Answer these questions, and see where you fit in. You may be surprised at what you find.

</Aside>

### 3. There is no bar, but there should be a target

I'm the first to tell you that [there is no bar](https://chriscoyier.net/2022/06/27/there-is-no-bar/) when it comes to creating online. Step one is simple: publish. Put your work out there. Do it often.

Once you've built that habit, try aiming higher: create something a creator you admire would genuinely love. Seriously - keep them in mind as part of your process. When you share work you're proud of, and it resonates enough for someone you look up to to share it, that moment is both validating and a powerful way to grow your voice in your niche.

To be clear: this isn't about spamming people. It's about raising the bar for yourself - making something so thoughtful, useful, or entertaining that it naturally earns attention.

<Aside>

**Do this:**
Make a list of 20 people who shape the conversation in your niche. If they notice your work, it's a sign you're breaking through.

Next time you sit down to create, focus on one of them as the target audience for your work. Build something they'd love, and _share it_ in places where they're active.

</Aside>

## The Takeaway:

Get good at one thing first. Create. Publish. Share.

Earn your audience, once post at a time. Then, once people care, _maybe_ it's time for the podcast, the YouTube channel, the empire.

Until then: focus.

---

## Some great creators to follow

There is nothing I love more than learning from people smarter than me. Here's a couple of my favorite voices on the internet:

- [Tony Mastrorio](https://www.threads.net/@tonydotcoms) is a fellow YC founder who has been exploring new audiences regularly over the past few months. He's done a great job of sharing his journey on Threads. It's inspiring to see his process: he's trying new things, and sharing them with his audience.

- [Amy Hoy](https://bsky.app/profile/amyhoy.bsky.social) is a great example of someone who has been building online for _years_. She co-created [30x500](https://30x500.com/academy/), and has _deep_ expertise in launching products online. Her Bluesky posts are a masterclass in sharing what she's passionate about - from photography and emerging tech tools to supporting civic engagement and progressive causes.

---

## Some useful links

- The most recent episode of Citation Needed, about [Audie Murphy](https://www.citationpod.com/audie-murphy-the-most-decorated-combat-soldier-of-ww2/) is a great reminder of why I love the podcast so much: I can simultaneously unwind, learn, and laugh a bit.

- There's a [_super important security update_ for Next.js](https://nextjs.org/blog/cve-2025-29927) that you should know about if you're using the framework. Not the type of thing I'd typically share here, but -- this feels like a big one.

---

## Give 'em hell

It might feel like you're paddling a tiny canoe in the shadow of looming battleships - but keep paddling, and stay nimble. There's plenty of room in the pond for all of us.

Bet on yourself. Bet on the people around you.

I'm rooting for you - and I want to see you win. ✌🏾

- M
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Steal these ideas to build new products]]></title>
            <link>https://mikebifulco.com/newsletter/steal-these-ideas-for-your-next-product</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/steal-these-ideas-for-your-next-product</guid>
            <pubDate>Wed, 12 Mar 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Pouring through an extensive list of publicly accessible APIs to find new ideas for your next product.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

Ideas are easy, but focus and execution are hard. There are endless public APIs with real problems waiting for you to solve - all you need to do is find an audience and start shipping.

## Steal These Ideas to Build New Products

As cofounder of [APIs You Won't Hate](https://apisyouwonthate.com), I've seen the playbook work repeatedly: Find public data. Solve a specific problem. Ship it. From [global news APIs](https://apisyouwonthate.com/podcast/building-an-api-for-global-news/) to [accounts payable management](https://apisyouwonthate.com/podcast/how-mercoa-built-a-platform-for-accounts-payable/), the winners aren't inventing data-they're making it useful.

Friends - these opportunities are _everywhere_, waiting for someone to execute.

### Why This Matters: Value > Hype

It's tempting to chase AI quick wins, but remember:

- Existing data streams = sustainable business opportunities
- Value-add to available information = competitive edge
- Focused problem-solving > tech novelty

### Case Study: Weather Data

Weather apps are commodity products since [Apple killed Dark Sky](https://www.theverge.com/2020/3/31/21201666/apple-acquires-weather-app-dark-sky-shut-down-android-wear-os-ios) (RIP).

There are plenty of untapped goldmines, like [NOAA](https://www.weather.gov/documentation/services-web-api) and [OpenWeatherMap](https://openweathermap.org/api) data for _specific_ use cases that people will pay for.

**The opportunity:** Niche weather apps for specific use cases:

- For pilots: Visibility conditions and wind patterns
- For gardeners: Frost alerts and growing condition forecasts
- For skiers: Snow quality predictions based on temperature patterns

<Image
  publicId="newsletters/steal-these-ideas-for-your-next-product/weather"
  alt="NOAA and OpenWeatherMap APIs"
/>

### Steal These Ideas

#### **1. Nutritional Intelligence with Edamam API**

[Edamam](https://www.edamam.com/) provides extensive APIs for nutritional data and analytics. The generic "calorie counter" app is done to death.

**The opportunity:** Build specialized nutrition tools for:

- Athletes tracking specific macros for performance
- People with medical conditions requiring dietary monitoring
- Parents checking if school lunches meet nutritional requirements

<Image
  publicId="newsletters/steal-these-ideas-for-your-next-product/edamam"
  alt="Edamam API"
/>

#### **2. Geolocation Magic with OpenAQ**

OpenAQ offers real-time air quality data from thousands of stations worldwide.

**The opportunity:** Create targeted apps for:

- Real estate buyers evaluating neighborhood health metrics
- Parents of children with respiratory conditions planning outdoor activities
- Researchers correlating air quality with public health outcomes

<Image
  publicId="newsletters/steal-these-ideas-for-your-next-product/openaq"
  alt="OpenAQ API"
/>

### The Secret Sauce: 3 Traits of Successful API Products

1. **Specific audience** - Target a niche who will benefit from your product
2. **Context transformation** - Don't just display data; interpret it and add value
3. **Workflow integration** - Make your product available whenever and wherever it will be most useful

...and price it accordingly. If you're saving news editors thousands of dollars every week, aim higher than $3.99/mo.

---

## Stop paying the app store tax.

Sell your app on the web with lower fees and full control. As a merchant of record, Paddle handles payments, taxes, and compliance - so you can focus on what matters: building your app.

Paddle acts as the reseller of your app, offering a solution similar to the App Store or Google Play Store but optimized for successfully selling your mobile app on the web, with significantly lower fees.

[Start selling smarter with Paddle.](https://www.paddle.com/resources/mobile-app-monetization-guide?utm_medium=website&utm_source=partner&utm_campaign=core_conversions_fy2025_web_monetization_brand_awareness&utm_content=tiny-improvements)

---

## Resources for finding new ideas

### Single APIs in your area!

There's a great collection of APIs waiting to be used on GitHub called [public-apis](https://github.com/public-apis/public-apis)

### Free design resources

I came across [Unblast](https://unblast.com/) recently - self-described as _A growing library of free design resources made by the world's best designers._ Can confirm - it is an exceptional collection. Give it a look as you build your brand or collateral.

### A chicken in every pot, and an SVG for every noun

[The Noun Project](https://thenounproject.com/) started with a simple goal: create a visual language for the world by building a repository of single color icons _for every noun._ Hell yeah. I use it _all the time._ You can use any icon on the site for free with attribution; licensing is either a dirt cheap per-icon fee, or a very reasonable monthly subscription.

---

The future is in your hands. Go on and build something great.

Give 'em hell,
Mike
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Your MVP is too damn big]]></title>
            <link>https://mikebifulco.com/newsletter/your-mvp-is-too-damn-big</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/your-mvp-is-too-damn-big</guid>
            <pubDate>Thu, 06 Mar 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Your first product version needs to be smaller than you think. Much smaller. Probably embarrassingly small.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

Your first product version needs to be smaller than you think. Much smaller. Probably embarrassingly small.

<a
  href="https://www.paddle.com/resources/mobile-app-monetization-guide?utm_medium=website&utm_source=partner&utm_campaign=core_conversions_fy2025_web_monetization_brand_awareness&utm_content=tiny-improvements"
  className="text-xs lg:text-xs xl:text-xs"
>
  Brought to you by Paddle
</a>

## Strip it bare

Earlier this week, I was invited to share my experience building companies with a class of promising entrepreneurship students, enrolled in the [Lean Startup course at Davidson University's Hurt Hub](https://hurthub.davidson.edu/event/building-a-lean-startup/), taught by [Rebecca Weeks Watson](https://www.linkedin.com/in/rebeccaweeks).

Many of them were working through planning out their first business, using a tool called the [Lean Canvas](https://leanstack.com/lean-canvas).

They'd interviewed potential customers and were defining their MVP. Their task: strip the idea to its core to test the riskiest assumption and find what customers would actually pay for.

When you have a big idea, it's tempting to spiral into features and complexity. But you don't need a fully-realized product to test if your idea has legs.

## Why we overreach

Most founders, especially first-timers, mis-scope their MVPs. About half the time, they add _way too much_ to their MVP for it to be built quickly. This is the trap of _it's not ready yet,_ or "if we build it, they will come". I have made this mistake - and I've seen it happen to others.

There's also at tendency to build an MVP that will lead to a `yes` no matter what. This usually means an MVP that's designed to reinforce the founder's belief in their idea, rather than challenge it. After all, founders who have made it this far into the journey of building something _are_ convinced they're onto something meaningful.

Whether they admit it ot not, this sector of founders is often more focused on protecting their ego than validating their idea. Red flag. 🚩

## So what's an MVP for?

There are plenty of ways to look at the outcome of an MVP, but I like to think of it as 2 simple yes/no questions:

**Is there a small, focused group of people who are feeling this pain?**
**Would they pay for a product that helps them solve this problem?**

If you don't get a confident "yes" to both of these questions, then you need to rethink your plan. You can always build more, but you can't recover wasted time building features nobody wants.

This can be accomplished with less than you think. A landing page with a video demo, a sign-up form for a waitlist, or a non-functional prototype.

### MVP for a coworking SaaS

My last startup, smpl, was a SaaS for managing coworking spaces. Our MVP was boiled down to the basics: we took the pain of collecting monthly membership dues out of our customers' hands. Version 0 was nothing more than a few manually configured Stripe subscriptions.

What did we learn? Coworking operators are great communicators, and rarely great at balancing a budget. Collecting _all_ member payments on the same day of the month made it _far_ easier for them to budget, track growth, and plan for the future. We spent the next year building a product that made it easy for them to onboard new members immediately, and to start their recurring payments on the first of the month.

(Side note: this is a trivial problem in 2025, but in 2017 it was on us to figure it out. Timing _really_ helped us!)

### MVP for a service business

[Craftwork's](https://craftwork.com) MVP boiled down to a simple question: will people hire a painting service online? We tested this with a landing page and a typeform -- and spent a month painting houses _at-cost_ for friends and family.

The amount we learned from that experience was worth the cost of the paint, and helped guide the way we hire paint crews (which has since changed several times), and how we price our services (which has also changed several times).

We focused exclusively on residential repaints for homeowners (not renters, not businesses, not commercial buildings). In doing so, we became very familiar with what our competition was lacking - a focus on considered homeowner experience, pricing transparency, and a commitment to quality.

## The value of embarrassment

In both of these cases, we were able to steer product development based on what we learned.

For smpl, an initial focus on member onboarding and billing brought much more value than building out a tiny social network for community members of a given coworking space.

For Craftwork, we learned that price transparency _alone_ wasn't enough to win over skeptical homeowners -- trust is earned through thoughtful communication, and a self-serve price quote wasn't enough to get people to slap the `Buy` button. We pivoted to a more consultative approach, and focused on building trust through a more personalized service. This also meant dropping our self-serve estimate form in favor of a literal contact form... can you imagine the time we'd have saved with a smaller MVP?

## Your challenge

If you're designing an MVP, take a step back.

What's the absolute minimum you could build to test your idea?

Is it **actually** testing your idea? If there's no outcome from your MVP that will cause you to change course, you're doing it wrong.

Is your MVP **actually** as minimal as it can be? If you're not sure, ask yourself:

- Is there a way to test this without spending money?
- Is there a way to test this while spending less time?
- Is there a way to test this while using fewer resources?

If you can't answer yes to all of these questions, you're probably over-engineering your MVP.

Launch something so minimal it makes you uncomfortable. You can always build more, but you can't recover wasted time building features nobody wants.

Do more with less - you'll be glad you did.

---

## Stop paying the app store tax.

Sell your app on the web with lower fees and full control. As a merchant of record, Paddle handles payments, taxes, and compliance - so you can focus on what matters: building your app.

Paddle acts as the reseller of your app, offering a solution similar to the App Store or Google Play Store but optimized for successfully selling your mobile app on the web, with significantly lower fees.

[Start selling smarter with Paddle.](https://www.paddle.com/resources/mobile-app-monetization-guide?utm_medium=website&utm_source=partner&utm_campaign=core_conversions_fy2025_web_monetization_brand_awareness&utm_content=tiny-improvements)

---

## Some resources to help you build less

- **[The Mom Test](https://amzn.to/41uVYEI)** - From author Rob Fitzpatrick, on how to listen to potential customers without misleading yourself.
- **[The Lean Startup](https://amzn.to/41I5PZ1)** - A legendary tome from Eric Ries, on how to build more with less. It's a book so good there are literal college courses built around it.
- This video from [Y Combinator on How to Build an MVP](https://www.ycombinator.com/library/Io-how-to-build-an-mvp) is a great primer on the topic, with some really useful examples of MVPs from cpmpanies you know.

What are you building right now that could launch with half the features? Hit reply and tell me what you'd cut first.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Design's Shakespearean Curse: Good UX Should Never Be Noticed]]></title>
            <link>https://mikebifulco.com/newsletter/good-ux-is-invisible</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/good-ux-is-invisible</guid>
            <pubDate>Tue, 25 Feb 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[The best UX design goes unnoticed. Learn how invisible design shapes digital experiences, and why great designers embrace the paradox of their work going unseen.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

Look around you. Everything - your chair, doorknobs, light switches - was deliberately designed, yet you've probably never thought about most of it.

Why? Because great design fades into invisibility.

<a
  href="https://www.paddle.com/resources/mobile-app-monetization-guide?utm_medium=website&utm_source=partner&utm_campaign=core_conversions_fy2025_web_monetization_brand_awareness&utm_content=tiny-improvements"
  className="text-xs lg:text-xs xl:text-xs"
>
  Brought to you by Paddle
</a>

---

A well-crafted door handle never gets praised - it just works. But struggle with a door that needs instructions (why do "Push" signs exist?), and suddenly design screams for attention.

What did you like about the last stairwell handrail you used? Probably... nothing, right?

You've used hundreds without a second thought. But grab one that's too high or wide, and you'll notice immediately.

This is the Shakespearean curse of UX: The better you do your job, the less anyone sees you did it at all.

## Where to Look for Invisible Design in Software

This same principle defines great digital experiences. Here are three areas where invisible design matters most:

### AI and Conversational Design

Remember the first time you used ChatGPT? The interface was almost certainly not the thing that stood out - it was the quality of the answers you got. Nonetheless, the interface that surrounds any LLM you use has become a critical part of the experience.

That's the pinnacle of conversational design: total invisibility.

I spent a couple years working on Google Assistant in the pre-LLM times, when product teams would spend _countless_ hours trying to make a conversation with Assistant feel natural. It was a tall order, and it did not get there until Assistant entered a Bard-flavored chrysalis, and emerged a Gemini-powered Butterfly.

### Traditional Interface Design

Forms are invisible design's ultimate test. Nobody has ever hit "Submit" and felt a rush of joy -- but if you've ever been stuck on a page that _won't tell you what's wrong_, my god will you notice.

Ever gotten lost trying to find your account and routing numbers on your bank's website? There it is again - someone's design work, begging for attention.

### Friction as a feature

There _are_ cases where putting an obstacle or two between someone and their goal is a good thing.

Your phone's alarm clock is a great example - if it's _too_ easy to dismiss a wake-up alarm, they're far less effective.

Similarly - a confirmation / "are you sure?" dialog is a good thing when doing something destructive, irreversible, or executing a financial transaction.

## Notice me, senpai

If good design is invisible, how the heck do you get better at it?

As a designer, this becomes your burden: start paying attention to what you're _not_ noticing. What apps/tools/processes have been so smooth you barely had to think?

Study interfaces that fade away. Analyze forms you completed without cursing. Notice apps you use daily but couldn't describe if asked.

You don't always need to make people say "wow" - and to be perfectly honest, if that's where you're _starting_ from, I'd be worried.

Your best work will never get the praise it deserves because, if done right, no one will know you did anything at all.

That's the beautiful curse of great design.

---

## Stop paying the app store tax.

Sell your app on the web with lower fees and full control. As a merchant of record, Paddle handles payments, taxes, and compliance - so you can focus on what matters: building your app.

Paddle acts as the reseller of your app, offering a solution similar to the App Store or Google Play Store but optimized for successfully selling your mobile app on the web, with significantly lower fees.

[Start selling smarter with Paddle.](https://www.paddle.com/resources/mobile-app-monetization-guide?utm_medium=website&utm_source=partner&utm_campaign=core_conversions_fy2025_web_monetization_brand_awareness&utm_content=tiny-improvements)

---

## Tiny acts of Rebellion

Current events got you down? Me too.

Here's your reminder that unseen actions leave visible scars.

🎯 Target execs recently showed off their liquid spines by axing DEI programs, which resulted in a [dramatic drop in store traffic](https://finance.yahoo.com/news/target-put-dei-chopping-block-182500865.html).

Meanwhile, 98% of Costco shareholders confidently [voted to _preserve_ their DEI initiatives](https://www.axios.com/2025/01/23/costco-dei-shareholders-reject-anti-diversity-proposal).

There's no gambling required to predict which company's Q1 earnings report will tell the better story.

Often the most powerful design choices are the ones nobody sees happening - until the results become impossible to ignore.

## Fill your brain with design

If this resonates with you, here's some resources you'll appreciate:

- [The Design of Everyday Things](https://amzn.to/43b4R8E) by Don Norman is _the_ book on this topic. Can't recommend it enough.

- I rewatch [Do the Most Good](https://www.youtube.com/watch?v=fWivXkQpO2Q), a talk from legendary designer [Mina Markham](https://www.minamarkham.com/) about once a year. Mina is an icon, and her wisdom is worth learning from.

Until next time - give 'em hell.
Mike
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[AI is your intern (not your boss)]]></title>
            <link>https://mikebifulco.com/newsletter/ai-is-your-intern-not-your-boss</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/ai-is-your-intern-not-your-boss</guid>
            <pubDate>Tue, 18 Feb 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Learn how to steer AI tools like Copilot and Cursor, avoid mistakes, and write better tests to ship reliable code.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

LLM tools like ChatGPT, Copilot, and Cursor are great at helping you build, but they are a second brain - not a first one. Used well, they are an intern that speeds up your work. Used poorly, they are a liability. The trick? Give them context, direction, and oversight.

<a
  href="https://www.paddle.com/resources/mobile-app-monetization-guide?utm_medium=website&utm_source=partner&utm_campaign=core_conversions_fy2025_web_monetization_brand_awareness&utm_content=tiny-improvements"
  className="text-xs lg:text-xs xl:text-xs"
>
  Brought to you by Paddle
</a>

---

### AI Works Best When You Steer It

Most AI tools (Cursor, GitHub Copilot, ChatGPT) aren't great at figuring everything out on their own. They do best when you provide them with context. Although this guide is focused on software development with Cursor, the same principles apply to other tools and domains.

I have found that the best way to use LLMs is to treat them like an intern:

1. Tell them the goal. Spell out what you're building.
1. Give them the pieces. Feed them relevant files, not just one at a time.
1. Make a checklist. Break the work into steps you can track.

Here's an example of a recent set of instructions I gave to Cursor, while working on a new feature for Craftwork:

```
take a look at @timesheets_spec.rb - I need to produce an updated version of our timesheets API under the v2 namespace. It should use all of the same patterns as the other endpoints in @v2 do, and should use a new controller namespaced under api::v2 at `controllers/api/v2/timesheets_controller.rb`.

It needs a list view that can be filtered by a craftworker's id, by timesheet state (approved/inprogress/etc), and by production lead id.

The show view should return details for a single timesheet.

The update view should allow me to approve a timesheet, edit values, etc
```

That was enough to get me started working with Cursor, and it helped orient the LLM while building out the new feature. It had enough context for me to ask questions as I worked, and sped things up nicely.

### AI Will Get It Wrong (And That's Fine)

For any instructions you give 'em, LLMs will [confidently spit out answers](https://mikebifulco.com/posts/product-marketing-defy-expectations), regardless of how correct they are.

If you don't understand what they're doing, you're trusting a bad intern to run your company.

That's why you need to:

- Spot bad logic. If something seems off, it probably is.
- Debug iteratively. AI is great for refactoring-ask it to explain itself.
- Know when to take over. Sometimes, the best fix is writing the code yourself.

In the case of the Craftwork timesheets, I was able to spot a few issues, and after making some changes, steered the LLM to the right path (my typoes included -- LLMs actually deal with these really well!):

```
great, now can you llook at the controller and add any helpful missing scopes? You may want to peek at other controllers in the @v2 folder, as well as @timesheets_controller.rb

Alsothe .d.ts type definition declarations you made arne't needed - see @tsconfig.json and @javascript - they're likely in another folder already configured with typescript paths. If the components don't exist they'll need to be created
```

If you've ever onboarded a new teammate to a codebase, this kind of steering is not at all uncommon - you're helping them understand the codebase, and the context of the changes they're making.

### Tests Are More Important Than Ever

If you're letting AI write code, you better be _damn sure_ it works as expected. That means writing great tests before shipping anything.

- Test like a skeptic. Assume AI-generated code is flawed.
- Write failure cases. If AI wrote the function, you should write the test.
- Use AI to help debug. It's great at explaining why tests fail (sometimes).

## The Bottom Line

AI is a force multiplier - but only if you use it right. Treat it like an intern:

- Give it structure.
- Question everything.
- Make sure the work holds up.

Most importantly, remember that your great, big, juicy brain still need to do some work. Don't blindly trust the output of your copilot-of-choice - that's a hell of a lot to ask of an intern.

---

## Tests? What tests?

Most of us (hello, yes, me included) aren't great at writing tests -- but writing software tests is a skillset that is absolutely worth investing in. Here's some resources I've found helpful:

- (React) [Testing Library](https://testing-library.com/) provides documentation and set of tools for testing web applications, in a variety of frameworks. Whether you're a fan of react or svelte or vue or solidjs, this is a great resource.

- One of my favorite things about building with Ruby on Rails is the framework's first-class support for great testing. There are _so_ many thoughtful features for writing great tests for rails apps. Even if you're not a rails developer, it's worth giving their docs a look: [Rails Testing Guide](https://guides.rubyonrails.org/testing.html)

---

## Stop paying the app store tax.

Sell your app on the web with lower fees and full control. As a merchant of record, Paddle handles payments, taxes, and compliance - so you can focus on what matters: building your app.

Paddle acts as the reseller of your app, offering a solution similar to the App Store or Google Play Store but optimized for successfully selling your mobile app on the web, with significantly lower fees.

[Start selling smarter with Paddle.](https://www.paddle.com/resources/mobile-app-monetization-guide?utm_medium=website&utm_source=partner&utm_campaign=core_conversions_fy2025_web_monetization_brand_awareness&utm_content=tiny-improvements)

---

## Thinking about automation

I've spent a bunch of time working on small scripts to automate manual tasks lately - and I'm working on a couple quick video tutorial showing how you might use tools like Puppeteer, Faker, Skyvern and your copilot-of-choice to get things done more quickly than ever before.

If that sounds interesting, go chase me down on youtube at [@mikebifulco](https://www.youtube.com/@mikebifulco?sub_confirmation=1).
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[How I (Think I) Talk to AI]]></title>
            <link>https://mikebifulco.com/newsletter/how-to-talk-to-ai-llms</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/how-to-talk-to-ai-llms</guid>
            <pubDate>Tue, 11 Feb 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[How to talk to AI (the right way). Learn how to give better prompts, refine outputs, and use LLMs effectively-without losing your own voice.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

Talking to AI is a lot like talking to people... except for all the ways that it isn't. It's a skill worth honing, and not a replacement for thinking.

---

From 2020 to 2022, I worked at Google.

I was on the Google Assistant team, in an era where "hey alexa" and "hey google" weren't new ideas. ChatGPT had not been released yet, and in general, the public was not aware of AI; "LLM" was far from a household term.

Funny enough, the dev product that my team was promoting was called "conversational actions" -- back then, "conversations" were predetermined - whether you realized it or not, you were following a scripted series of questions, and Google Assistant was a clever way to trigger actions.

In that time before LLMs took over, I noticed a funny pattern: people would talk to their assistant _like_ a robot. They'd slow down, speak in weird, clipped phrases, almost like they were trying to sound like the assistant itself. It reminded me of how people adjust their speech when talking to someone who doesn't speak their language.

Fast forward to today: people are speaking to LLMs much more naturally. _Conversations_ with AI feel more convincing, but the reality is that the LLM is still just a tool. It's up to you to do the thinking.

Of course, LLMs are getting better all the time, and the tools will continue to get better. There's still a real skill in knowing _how_ to talk to your LLM. Done well, it can be a powerful extension of your thinking. Done poorly, it's a waste of time.

After a bit of reflection, here's the pattern I've adopted for working with AI tools:

---

## Provide Context (More is Better)

Once upon a time - like, two years ago - LLMs had tiny context windows. They were only able to process a few paragraphs of information at a time. Now there's _loads_ more headroom. Most modern models can handle essays, transcripts, full articles, and more. The more context you provide, the better the results.

Here's how I set mine up for success:

- **Tell it who you are.** Your background, goals, and what expertise you expect from it.
- **Define the task.** Are you brainstorming? Writing? Editing? Summarizing?
- **Give it sources.** If it can read the web, provide links. Otherwise, copy/paste key quotes or references.
- **Set guardrails.** Be explicit about what you _do_ and _don't_ want. Examples:
  - "Be concise."
  - "Avoid jargon."
  - "Don't mention XYZ."
  - "Your audience is nontechnical."

---

## Iterate and Customize

You'll get better results if you tweak your prompts while working, and you should save what works, and refine it over time.

- **Save what works.** If you get a great response, refine it into a reusable prompt.
- **Use different prompts for different goals.** You wouldn't write a social post the same way as an executive summary. You may want to have separate prompts for copywriting for social media, writing execustive summaries, or brainstorming on SEO keywords, for example.
- **Redo / Retry / Resubmit.** LLMs aren't deterministic: if you submit the same set of instructions multiple times, you'll get different results. If it misses the mark, tweak the input and try again.

I think it's also a good idea to regularly try different models and tools - what does Claude do better than Gemini? You'll never know if you don't experiment with the tools. Don't get lazy, and don't blind yourself to what's out there - it's all changing very quickly right now.

---

## Don't Get Lazy

An LLM is a tool - not a replacement for thinking.

I'll admit, I go into a bit of an existential spiral when I think about the future of communication - do we want to winnow down our existence to LLMs talking to each other? I certainly hope not. All the same, these tools are really useful for brainstorming, editing, and revising your writing, and they're not going away.

You're still the expert (ideally). It's your job to check facts, refine tone, and ensure the final product _sounds like you_. In my opinion, a big part of that work means that you should treat your LLMs like an assistant, not a crutch.

Edit the output - make it sound like you!

---

## TL;DR

1. More context = better output.
2. Experiment, tweak, and refine your prompts.
3. Never stop thinking - you're still the one with the expertise.

---

## Your inbox shouldn't slow you down.

Superhuman's AI-powered features-Instant Summarize, Smart Replies, and Ask AI-help you fly through email, reclaiming at least 4 hours every week.

That's 4 extra hours to build, think, and focus on what actually matters.

📩 **Tiny Improvements readers get their [first month free](https://superhuman.com/ti?utm_medium=sponsor-callout&utm_source=mikebifulco-com).**

---

## Stick these in your brain's context

I'm a firm believer that we should always be learning. Don't rely on AI to do all your thinking. Here's a couple things I found this week that you might enjoy:

- [Ranking Paradoxes](https://www.youtube.com/watch?v=1vJsWKg2o1w) is a YouTube video from Chalk Talk, which goes discusses the complexity and counterintuitivity of philosophical and mathematical paradoxes.

- I'm still very much into 3D printing nerdery - and this recent video from Make Anything on [multi-texture prints](https://www.youtube.com/watch?v=zmZCA9jqGiI) shares a really cool new technique for making prints more visually interesting.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[How Clever Engineers Stay Ahead of the Curve]]></title>
            <link>https://mikebifulco.com/newsletter/how-clever-engineers-stay-ahead-of-the-curve</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/how-clever-engineers-stay-ahead-of-the-curve</guid>
            <pubDate>Mon, 03 Feb 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Smart engineers always seem to know what's coming next. They do this by staying attuned to various signals from diverse sources.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

Smart engineers always seem to know what's coming next. They do this by staying attuned to various signals from diverse sources.

<a
  href="https://superhuman.com/ti?utm_medium=brought-to-you-by&utm_source=email"
  className="text-xs lg:text-xs xl:text-xs"
>
  Brought to you by Superhuman
</a>

How do you find out about new tech?

This is a question that came up recently during a chat with a friend (hello, Sean) - and for me at least, it's a tricky answer because I don't have one answer. My career path has been dictated by being vaguely aware of new trends in tools and tech at just the right time: from jQuery to React, create-react-app to gatsby to Next.js to Remix, to various focuses on the applied science of UX, I've been able to recognize and capitalize on new opportunities by keeping an eye out for signals that come from many sources.

All this to say: I don't ever really set out to _find_ new things, really. I do, however, have a whole bunch of places that I loosely pay attention to, in order to learn from people smarter than me.

Broken into a few simple lessons, here's how I do it:

### Lesson 1: Diversify Your Information Diet

Don't rely on just one source. Lately I've been learning from smart people on social media platforms like Bluesky, Threads, and Mastodon, and keep an eye on GitHub, Reddit, and Hacker News. This breadth allows me to spot trends, and to collect more signals on new tools, tech (and sometime people!) who are gaining traction.

### Lesson 2: Stay Curious and Open-Minded

I occasionally explore new frameworks or technologies - even those that don't seem immediately relevant. These little spikes help me to pull from the best of this-and-that for larger projects down the line. For example: I really love the DX of building interfaces in React, and I like the SEO the Remix framework makes available -- _and_ I'm a big fan of the database ORM used in Rails, called ActiveRecord. If I hadn't ever run `rails new` or `npx create-remix@latest`, I would have never known about these things.

### Lesson 3: Connect the Dots

The ability to link seemingly unrelated concepts can lead to innovative solutions. I learned about React way back when I was building my first company; at the time, it was the best way to create a web app that updated its interface without reloading the page. That was super helpful for the fitness IoT product we were building at the time.

## Common threads for a great product engineer

I've developed these habits by watching people admire do the same thing. Your path will vary based on where you are in your career, your goals, and your interests -- and that's a good thing. The engineers who I have seen build great things tend have a few things in common, which are correlated to the habits I've outlined above:

### Corollary 1: Embrace Side Projects

The smartest engineers often have side projects to experiment with the latest technologies. These projects are perfect for testing out new tools that might not fit into their professional work, helping to build their brand and skills.

### Corollary 2: Pursue Diverse Interests

It's beneficial to learn from different fields and backgrounds. Whether it's speech science at Google or community building in startups, integrating diverse knowledge can be a tremendous asset.

## What you can take away from this

Smart people don't just follow one path; they build a diverse, constantly updated network of knowledge sources. If you're working on growing into a successful career, consider building a diverse network of people who can help you learn and grow. For some of us, this may mean changing your social media habits - don't just chase endorphins: find ways to _learn_ while you scroll, and then go out and build something.

---

## How much is 4 hours of your time worth?

You're busy. Your inbox shouldn't slow you down. Superhuman helps founders, product leaders, and high-performing teams reclaim 4+ hours per week by making email **fast**.

That's 4 extra hours to build, ship, or make game-changing introductions-the kind that open doors and create new opportunities.

📩 **Tiny Improvements readers get their first month free** - [try it here](https://superhuman.com/ti?utm_medium=sponsor-callout&utm_source=mikebifulco-com).

---

## Some sample sources for you to explore

It's only fair if I share some of the brilliant folks I've learned from recently; here's some of what's been keeping my attention -

YouTuber Mitxela made an incredible [fluid simulation pendant necklace](https://www.youtube.com/watch?v=jis1MC5Tm8k) from off the shelf and custom machined parts. What I love most about this project is that it shows a great series of prototypes and iterations, and the final product is a beautiful piece of wearable art. It gets meta (even meta meta) along the way, and is a great peek into an inventor's creative process.

I've been reading the [Simple Sabotage Field Manual](https://www.gutenberg.org/ebooks/26184), a WWII-era handbook written by the US Office of Strategic Services (OSS), and declassified by the CIA in 2008. If you enjoy finding ways to make _good trouble,_ you'll love it. Best of all-it's free.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[My 2025 Developer Tech Stack]]></title>
            <link>https://mikebifulco.com/newsletter/developer-product-engineer-tech-stack-2025</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/developer-product-engineer-tech-stack-2025</guid>
            <pubDate>Wed, 29 Jan 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[A list of the tools and tech I use as a professional product engineer in 2025.]]></description>
            <content:encoded><![CDATA[
## The Big idea

The right tools don't just save time-they amplify your focus and flow, making it easier to do your best work. This is what I'm using to stay productive in 2025.

<a
  href="https://superhuman.com/ti?utm_medium=brought-to-you-by&utm_source=email"
  className="text-xs lg:text-xs xl:text-xs"
>
  Brought to you by Superhuman
</a>

## This is how I get things done

My work as an engineer and founder is split between two main activities:

1. Building products and features
2. Building the systems and processes that allow me to build products and features (I spend more time here each day)

I tend to stick with tools that amplify my productivity, help me get stay organized, and ones which don't get in the way when I'm finding flow state.

The best tools find their way into my workflow without much hassle.

## Princples for choosing tools

While I never consciously set hard rules for choosing the tools I use, I have found some consistent principles of what I look for in a tool:

1. **Simplicity:** I prefer tools that are simple to use and understand. I don't want to spend time learning how to use a tool - I want to spend time getting things done.
2. **Portability:** I prefer tools that are easy to set up and move between devices. This means that cloud sync is a huge plus for me - if my work laptop ever gets launched into the sun, it should be easy to set up a new machine and get back to work.
3. **Reduced key ~man~ tool risk**: Developers are notorious for customizing the hell out of their tools, often to a fault. I don't ever want to feel like I _can't_ get things done on someone else's computer. My team does lots of pair programming - and I never want to feel lost on someone else's machine because without _my dotfiles_.

---

## These are the tools I use in 2025

Alright, let's get into it. This is the tech stack I'm using in 2025:

### Hardware

- **Laptop: Macbook Pro 14"** - Up until a few weeks ago, I was using a 14" 2021 M1 Macbook Pro. I recently swapped to a 2023 variant with an M3 chip. These computers have been, without a doubt, the best I've ever used. I've switched between Windows and MacOS over the years - we're in an era where hardware is what makes the difference. These MFs are fast, and the battery life is incredible.

- **Phone: Pixel 9 Pro** - Hot take: I'm not a huge fan of some of the UX on IOS. My Pixel takes _stunning_ photos, and integrates with all the things I love for home, work, and play. Even still, I switch between Android and IOS every few years, because I believe it's helpful to know and understand what both options are like. It's a great way to keep learning and stay informed.

### Tools

- **Note-taking: Logseq** [LogSeq](https://logseq.com/) is a fantastically simple, privacy-first, markdown-based note taking app for building knowledge graphs. I switched to LogSeq last year from RoamResearch, and have been very happy with the experience. If you've tried Notion and haven't quite gotten along with it, I'd recommend giving LogSeq a try.

- **Email: Superhuman** - [Superhuman](https://superhuman.com/ti?utm_medium=body-rec) is a stunningly email client designed with efficiency in mind. It works _with_ my Gmail accounts, and lets me triage, filter, and respond to emails confidently - and without distraction. Their design team has done an incredible job of creating a product that's both beautiful and functional.

- **Swiss-army knife:Raycast** - [Raycast](https://www.raycast.com/) integrates with MacOS as a replacement for Spotlight (the little window that pops up when you hit command + Space on most Macs). It's more than just a launcher - I use it for launching apps, translating english &harr; spanish, checking fligth statuses, and countless other utilities during my workday.

### Devtools

- **IDE: Cursor** - [https://www.cursor.com/] is a fork of VS Code that is highly customized for AI-assisted coding. I have it customized with a set of prompts for each of my projects, and to index docs for libraries I use. While it's not a replacement for _thinking_ - it's like having a _very good_ pair programmer at your side all day. An instant productivity boost.

- **HTTP Client: Bruno** - I started using [Bruno](https://www.usebruno.com/) last year for testing and integrating with APIs. It's similar to Postman, open-source, and includes some really cool features, like a native git integration, so you can share your API specs with your team.

- **Design: Figma** - I've been using Figma for years, and over the past year have started using their layout tools to prototype interfaces as I build (shout out to my pal [Drucial](https://drew-white.dev/) for getting me up to speed on autolayout!). I believe design is a _critical_ skill for any engineer, and right now, Figma is the best tool for the job.

- **Project Management: Linear** - [Linear](https://linear.app/) is _the_ project management tool that we use at Craftwork for keeping our ever-changing backlog in order. It's like Jira, but with all of the garbage ripped out and replaced. If you haven't used it before, give it a try.

..and more. There's _definitely_ more that I use day to day - I'll share a follow-up post soon with details about the stack I use for _building_ products - the frameworks, libraries, and SaaS products I use to build Craftwork, this site, and APIs You Won't Hate.

### Your tools should work as hard as you do.

Superhuman keeps your inbox in check, so you can focus on building. Stay productive in 2025: prioritize, reply, and save 4+ hours a week. Thanks to Superhuman for giving Tiny Improvements readers their [first month free](https://superhuman.com/ti?utm_medium=sponsor-callout&utm_source=mikebifulco-com).

---

## What did I miss?

Is your favorite tool missing from the list? Did I miss something that's critical to your workflow? The best way for me to find out is by sharing - slap the reply button and let me know what I'm missing.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Focus Mode for the Defiant]]></title>
            <link>https://mikebifulco.com/newsletter/focus-mode-for-the-defiant</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/focus-mode-for-the-defiant</guid>
            <pubDate>Tue, 21 Jan 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[How free will fuels creativity, and how to stay on task with purpose.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

When you carve out focused time for your work, you're making a statement. This week, let's harness that power and explore how to stay on task with purpose.

## Focus Mode for the Defiant

Founders who actually _build_ things are a special type. You are making a statement: you've found a problem worth solving, and you're using some of your limited time on this earth to solve it.

Everyone's time is limited, and the act of building something is a display of your priorities -- so don't waste it on distractions.

When you focus your time and energy on creating, you're asserting your free will in the most powerful way possible. This week, let's talk about how to stay on task and bring your boldest ideas to life.

Let's talk about _focus mode._

## Practical Tips for focusing

A funny thing about my role at [Craftwork](https://craftwork.com) is that the more we grow, the _less_ time I have to do "typical" work - my days lately are spent focused on strategy, hiring, scaling, and unblocking my teammates.

This means I get precious little time to _write code_ - which makes it all the more important that I make the most of the time I do have.

I use a few strategies to carve out focus time, to eliminate distractions, and to make use of the limited time I have to be productive each day.

- **Scheduling Focus Blocks:** I set aside 90-180 minute blocks each week for deep work. These uninterrupted periods are when I do my best thinking.
- **Notification Detox:** I turn off non-essential notifications -- all the time, 24/7. This helps me stay in control of my time and attention. Rather than get sidetracked by an email coming in, I check email when it's productive for _me_ to do so.
- **Do Not Disturb Mode:** To further manage notifications, I flip on _Do not Disturb_ on my laptop and my phone - this further cinches down notifications, and helps me stay focused. I usually do this with a set end time, so that I can focus on the task at hand.
- **A literal, physical timer:** When working through tasks that are mentally taxing, I use a minimalist desk timer from [TIME TIMER](https://amzn.to/3PPRKBT) as a visual reminder to keep me on track.

## The Importance of Focus

It is _extremely_ easy to waste away your days with notifications, social media apps, and other distractions. Founders who _get things done_ are the ones who have learned to focus. It is a skill, and it requires practice.

Moving the needle every day is the difference between a _wantrepreneur_ and a _founder_.

Don't let distractions get in the way of your focus.

<SponsoredSection
  imagePublicId="sponsors/superhuman/new-year-new-habits"
  sponsorName="Superhuman"
  CTAtext="Get started today"
  href="https://superhuman.com/ti"
>

As a founder, your inbox is chaos-but it doesn't have to be. Superhuman cuts through the noise, prioritizes what matters, and drafts replies before you even open a message. Every action takes seconds, not minutes.

Start 2025 with clarity, focus, and 4+ hours saved every week. **Your first month is free.** What's stopping you?

</SponsoredSection>

## Focused learning for existential awareness

- What if maps were made to show the _time it takes_ to travel between points? YouTuber [Vaclav Volhejn explores this idea](https://www.youtube.com/watch?v=rC2VQ-oyDG0) with a fascinating visualization built in TypeScript.

- Creator of Million.js, Aiden Bai has been producing an incredible series of videos about how browsers work - his recent entry on [how browsers "paint" HTML](https://www.youtube.com/watch?v=yBkFjlPWpZ8) goes far deeper into browser rendering than I ever thought about.

## The Spinal Column 🩻

_Because staying informed is an excellent use of vertebrae._

_This is a new segment for Tiny Improvements. I thought it would be helpful to share \_one_ link related to current events that I've found interesting, educational, or poignant. I'd love to hear what you think - hit reply and let me know.\_

On a recent episode of the podcast Opening Arguments, the hosts dive into a sobering truth: the US president is now above the law. We're in uncharted territory, facing a challenging four years ahead.

Listen to it here: [We (Disrespectfully) Dissent](https://open.spotify.com/episode/5DD95dTspKjSOyKUPzZhpT?si=4544c33d9fe04f6a)

Thanks for tuning in. Keep pushing boundaries - and give 'em hell!
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Superfounder Superpowers: Sending Introductions]]></title>
            <link>https://mikebifulco.com/newsletter/superfounder-superpowers-sending-introductions</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/superfounder-superpowers-sending-introductions</guid>
            <pubDate>Tue, 14 Jan 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[A guide to help you send introductions to your network.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

Building products and teams successfully relies on your ability to build meaningful relationships; making a habit of introducing interesting people to each other is a great way to seed serendipity.

## Build Meaningful Relationships

Building a network and introducing people is an important skill that takes honing. I've learned from my most successful founder friends that it's something worth doing-offering to introduce people feels great, and it occasionally pays itself back in unexpected ways.

Here are three simple ways to do it right:

### Give them a heads up

Before you connect people, shoot them both a quick message to let them know why you think they should meet. A little heads-up goes a long way in keeping things smooth and avoiding surprises. This is where the _real_ introduction happens. If it's done well, both parties will be excited to meet.

### Be quick and thoughtful

Keep your introduction emails short and actionable. Highlight why the connection makes sense and how the parties might benefit from knowing each other. A concise, well-thought-out message shows respect for everyone's time - they're rarely longer than a couple sentences.

### Trust your gut

Not every intro needs a big reason. Sometimes, just putting two cool people together can lead to amazing, unexpected stuff. Be the spark that gets things rolling-you never know what might happen.

When done right, introductions are more than just emails - they're opportunities to foster creativity, collaboration, and growth. Start small, but start today.

<SponsoredSection
  imagePublicId="sponsors/superhuman/new-year-new-habits"
  sponsorName="Superhuman"
  CTAtext="Get started today"
  href="https://superhuman.com/ti"
>

As a founder, your inbox is chaos-but it doesn't have to be. Superhuman cuts through the noise, prioritizes what matters, and drafts replies before you even open a message. Every action takes seconds, not minutes.

Start 2025 with clarity, focus, and 4+ hours saved every week. **Your first month is free.** What's stopping you?

</SponsoredSection>

### A sample introduction email

Many of the introductions I send and receive look something like this:

> Subject: Mike, meet Sarah
> Hey gang -
> Sending over a quick note to connect you. You both have context, but think it would be great for you to meet! Will let you take it from here.
> T.

Brief, informative, and to the point. It gets the job done!

---

## From around the internet

I've come across a great deal of creative inspiration online this week - and I thought you'd appreciate these:

[Lofted Goods](https://thangs.com/designer/LoftedGoods) is a designer who creates simple, elegant, and functional 3d prints for use around the home. Their aesthetic really speaks to me, and I love the addition of thoughtful features, like an insert for wall-hung decor that makes it dead easy to decide where to drill holes for screws and wall anchors. Best of all? You can download the files for free and print them yourself.

My god do I love a good typeface. I recently came across [Taylor Penton's hand-drawn fonts](https://www.taylorpenton.com/fonts), and fell in love straight away. I've even hopped onboard as a paying member of their Type Club. I may even incorporate some of [Taylor's webfonts on my site](https://github.com/mbifulco/blog/pull/945) before long...

## What about you, friend?

As always, I'd love to hear what you're working on. Read something interesting recently? Launching your product soon? Hit reply and let me know. I do my best to respond to each and every one.

<small className="text-xs italic">

Note: Cover photo for this newsletter is from [MJ S](https://unsplash.com/@mjseka?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash) on Unsplash.

</small>
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[The Great Inbox Reset]]></title>
            <link>https://mikebifulco.com/newsletter/great-inbox-reset-for-founders</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/great-inbox-reset-for-founders</guid>
            <pubDate>Tue, 07 Jan 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[A guide to help you reset your inbox, get a free productivity boost, and do better work.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

Your inbox is a tool-learn to use it to stay focused, organized, and in control of your time.

## Did you get my email?

Staying organized and on task is an absolutely _foundational_ skill to master for founders.

Building a product is a complex task that will have you busier than you might imagine. For many of us, one of the first things to go is our inbox.

Without looking, what's the count of unread emails in your inbox? Is that little notification bubble straining to fit all the count of unread emails?

Friends, **it's time to take control.**

A clean inbox isn't just about aesthetics; it is a critical tool for staying focused and on task, being responsive to your network, and staying productive.

<SponsoredSection
  imagePublicId="sponsors/superhuman/new-year-new-habits"
  sponsorName="Superhuman"
  CTAtext="Get started today"
  href="https://superhuman.com/ti"
>

In the life of a founder, the inbox is both a necessity and a challenge. Every deal, opportunity, and conversation is buried under a flood of noise. Superhuman is designed to change that.

Imagine an inbox that knows what's most important and drafts replies to messages before you look at them - and every action takes seconds instead of minutes. Superhuman transforms email into a tool for clarity, focus, and action.

This January, start your year with a platform built to help leaders like you get more done and save 4+ hours every single week.

With your **first month free**, there's nothing holding you back.

</SponsoredSection>

### Your inbox is a tool, not a bottomless pit

Whether you use gmail, apple mail, Superhuman (shout out for sponsoring!), or Outlook, your inbox is a tool, and knowing how to use it is a game changer.

Treat your inbox like you would your favorite IDE or design tool-it's only as good as how you use it.

My approach:

- Only emails I need to respond to or act on live in my inbox.
- Labels and folders keep everything else neatly organized.
- Snoozing helps prioritize tasks for later without cluttering the present.

Think of your inbox as a task manager for important things, not a dumping ground for everything.

### Turn Off Notifications and Regain Your Focus

Real productivity happens when you're focused - and for me, sporadic email notifications are an unpredictable distraction.

**My tip**: Turn off email notifications entirely.

Seriously -- I turned 'em off. On my phone, in my browser, and in my email client.

This lets me check and triage messages in my inbox when I choose, ensuring I stay in the zone while working.

This practice eliminates the randomization of being distracted by notification bubbles. Being intentional about when and how you engage with your inbox keeps it from controlling you.

### A Clean Inbox = A Clear Mind

The value of an organized inbox goes beyond email:

- New, important emails are less likely to slip through the cracks
- Less notification spam is a free productivity boost
- It makes the _unread count_ on your email app's notification bubble _useful._ Imagine that!

### This sounds great, but I have 493287 unread emails

If you're sitting on hundreds of unread emails, it may be time to declare email bankruptcy.

Sometimes, the backlog becomes unmanageable - and that's okay.

Email bankruptcy isn't about giving up; it's about clearing your slate:

- Archive everything older than a certain date and triage the rest.
- Notify key contacts if they're waiting on something and ask them to resend anything crucial.

It's the fastest way to regain clarity and focus without drowning in old noise.

Use this reset as a chance to make email a tool that works for you-not against you.

## Start the new year fresh

Your inbox, like any great tool, works best when you know how to use it. A clean start at the beginning of the year can help you reclaim your time, focus on what matters, and build habits that last all year long.

Take control of your inbox, and you'll find yourself in control of your time, your focus, and your productivity.

---

## Who I'm learning from this week

By now, you know that I love functional 3D Prints. For me, the magic in this tech is in creating useful, customized tools to make your life better. It's a challenging process to master, which is why I really liked seeing this video on [designing 3D printed mods for a vintage Toyota](https://www.youtube.com/watch?v=hpxAcJaAXgk) on the _Fat Lip Collective_ YouTube channel. Even if you have no interest in old cars - there's lots to learn from the process used to develop a custom part.

If you haven't heard already, **you should uninstall the Honey extension from your browser** pronto. YouTuber [MagaLag created an exposé](https://www.youtube.com/watch?v=vc4yL3YTwWk&pp=ygUSaG9uZXkgc2NhbSBleHBvc2Vk) on the many ways the extension has been abusing creators and consumers, and it's a must-watch.

[Folklore (Kyle's version)](https://pca.st/0iqmt7xe) is the most recent episode of the podcast Hyperfixed, from Alex Goldman. This episode goes deep on something that at first glance seems trivial, but eventually touches on verbal tradition, craftsmanship, and some fundamental truths of the physical universe. A fantastic listen.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Themes Beat Resolutions Every Time]]></title>
            <link>https://mikebifulco.com/newsletter/themes-beat-resolutions-every-time</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/themes-beat-resolutions-every-time</guid>
            <pubDate>Tue, 31 Dec 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Reflection fuels growth. The coming year is your chance to make meaningful changes to your work, life, and relationships.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

Reflection fuels growth. The coming year is your chance to make meaningful changes to your work, life, and relationships.

## What will you do differently?

Every year, we have a moment to look back and another to look forward - rather than looking at it as the sunset of this year, it may be helpful to think of it as the sunrise on 2025.

People tend to shy away from the idea of making _new year's resolutions_, which, honestly -- is perfectly reasonable. Most people tend to fail on their resolutions, and the idea of making a list of goals that you're unlikely to hit feels draining.

Let's skip the guilt-ridden _New Year's resolutions_ that rarely stick. Instead, consider setting a theme for the year ahead. One of my favorite podcasts, [Cortex](https://cortex.fm)
introduces this idea beautifully. Each host selects a [theme](https://www.youtube.com/watch?v=ikXyZ-_L-NA) as a guidepost for the year ahead.

For me, 2025 is the Year of Doubling Down:

- **Make Craftwork sing** - Our incredible team is building a scalable business that aligns with our ambitions. I'm focused on coordinatation, strategy, empathy for our team & customers.
- **Sweat more** - I am a more balanced person when I work out more. My goal is 3-4 solid workouts weekly-running, cycling, weightlifting, and yoga.
- **Double Readership** - My goal is to reach more people with the knowledge I share here. Hearing how my work has helped others is the best possible fuel for that fire.

I'm also doubling down on cutting distractions-removing negativity and toxicity to focus intentionally on what matters most.

### Your turn - what will you double down on?

If you're setting a theme for the year, I'd love to hear it. What are you focused on for the next 365 days?

Signing off for 2024 - see you on the other side of things.

---

## Behind the Words: Exploring Writing and Process

I've been reflecting on the little habits and tricks that keep my writing process flowing. Maybe these ideas can help spark something for you, too.

### My Next.js site: Now with 100% more support for Series!

I recently added a Series feature to my site-a way to group related posts. It's inspired by Dev.to's implementation, cobbled together in an afternoon. Here's the first few example I've published:

- [Fixing My Conversion Problem with Posthog](https://mikebifulco.com/series/fixing-my-conversion-problem-with-posthog), A 5-part video series about optimizing my newsletter conversion rates.
- [JavaScript Tips](https://mikebifulco.com/series/javascript-tips) Quick tips on JavaScript fundamentals I've found useful over the years.
- [🤖 Dependabot](https://mikebifulco.com/series/dependabot) Posts about automating dependency updates with Dependabot, consistently a top Google Search result for my site.

There's room for improvement, but I'm happy with the feature so far. Let me know your thoughts-and stay tuned for videos about how I built it.

## My writing process

Many people have asked about how I write and publish articles. The short answer: **a single Markdown file + GitHub + automation.**

Each post is a Markdown file committed to my site's GitHub repo and published automatically via Pull Requests. The beauty of this process? _It works for me._ It's simple, distraction-free, and keeps me focused on writing.

I wrote a detailed post about it: [Content creation workflow: my writing process](https://mikebifulco.com/posts/content-creation-workflow-my-writing-process)

Want to see it in action? I wrote that post [during a recent livestream on my YouTube channel](https://www.youtube.com/watch?v=adHRQUONKFo).
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Get lost in your work: the magic of flow state]]></title>
            <link>https://mikebifulco.com/newsletter/flow-state-and-getting-things-done</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/flow-state-and-getting-things-done</guid>
            <pubDate>Tue, 17 Dec 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Flow state is a mental space where deep focus and creativity come together, allowing you to work more effectively and productively.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

Flow state is a mental space where deep focus and creativity come together, allowing you to work more effectively and productively.

---

If you've ever found yourself _so focused_ on a task that you're nearly blind to the world around you, you have very likely experienced _flow state_.

First defined by psychologist Mihaly Csikszentmihalyi, _flow state_ is a state of mind where you're so absorbed in an activity that you lose track of time and external distractions. It's a delicate blend of focus, creativity, and energy that allows you to get lost in your work. ([source](<https://en.wikipedia.org/wiki/Flow_(psychology)>))

Flow state can make you feel _superhuman_. It's a state where focus, motivation, and productivity are at their peak.

If you've felt it, you know what I'm talking about.

## Why flow state is important

Engineering and product design are complex tasks, which are often best done without distraction. When I'm untangling a particularly complex bug or building a new feature, I am far more likely to be successful if I can focus on the task at hand.

For me at least, this doesn't always mean a silent, vacant room. I've found that I can get into a flow state in a busy coffee shop, while walking around the city, or at my desk in the office in the mdidle of a workday

## How I find flow state

Finding your flow state is one of those things where you need to know yourself and your brain a bit. Even for me, it varies a bit day to day: some days I work best from the comfort of my kitchen, or the counter at my local espresso bar, and other days I do best at my desk in the office, with two monitors and a good pair of headphones on.

Regardless of _where_ I am, there are a few things I do to help me get into a flow state:

1. Turn off notifications, and don't look at my phone
2. Close any apps or tabs that might distract me
3. Have a clear, specific task in mind

## Tips for getting in the zone

### Pomodoro is Italian for tomato

<Image
  publicId="newsletters/flow-state-and-getting-things-done/pomodoro"
  alt="A minimalist modern timer"
  caption={<Link href="https://amzn.to/4fmrhX1">Minimalist Modern Timer</Link>}
  href="https://amzn.to/4fmrhX1"
/>

The _pomodoro technique_ is simple: set a timer for 25 minutes, work until it rings, then take a 5-minute break. This method can effectively help you enter a flow state.

I learned this from a teammate at Google, who tracked his productivity with 🍅 emojis - each representing a pomodoro.

(Thanks for the inspiration, [Proppy](https://bsky.app/profile/proppy.bsky.social)!)

Many productivity apps include a pomodoro timer, like Logseq and Raycast. If you prefer a physical metaphor, you might like the [minimalist modern timer](https://amzn.to/4fmrhX1) above, which I recently snapped up for a few bucks on Amazon.

### Be selfish with your calendar

I regularly use Google Calendar's Focus Time feature to block off 90-min blocks of time to get things done. This gives me a guaranteed block of productive time, regardless of which meetings get added to my day. It's something I encourage my teammates to do, and if you've never tried it, I highly recommend it.

### Your phone can help

Whether you use an iPhone or an Android, your phone has support for Focus Modes. These are a great way to block out distractions and get into a flow state. If you haven't tried them before, here's a quick guide for each: [iPhone](https://www.theverge.com/23355242/ios-16-focus-modes-how-to-apple-iphone), [Android](https://www.androidcentral.com/phones/how-to-set-up-focus-mode-in-android-13).

If you're not a fan of focus mode, Do Not Disturb is a very effective cudgel for blocking out distractions.

<Image
  publicId="newsletters/flow-state-and-getting-things-done/background-sounds"
  alt="Background Sounds on an iPhone"
/>

Side note: did you know that iOS has a feature that will [play calming nature sounds](https://support.apple.com/en-us/109346) called _Background Sounds_?

### Communicate your availability

As always, communication is foundational to working with others. Tell your teammates about focus time (make it public on your calendar), let them know you're blocking off time to get work done, and be diligent about following up on messages that you missed during your focus time.

---

## Find focus online

- [🎙️ Cortex](http://cortex.fm/) is a podcast by creators Myke Hurley and GCP Grey, where they discuss and explore their creative process, working lives, and the tools they use to get things done.
- [🦙 Llama Life](https://llamalife.co/) is a todo list app designed with ADHD in mind. It's built by [Marie Ng (@threehourcoffee)](https://bsky.app/profile/threehourcoffee.bsky.social), who has done a tremendoud job of sharing the app's story and development process on Bluesky.
- [Raycast](https://www.raycast.com/) is a powerful productivity app that has an extension store full of slick productivity tools - including a pomodoro timer. Its free tier is extremely generous, and the app is a joy to use.

## Hey though, enjoy the holidays

That's all for me for now, friends - the next _two weeks_ are full of holidays for many of us, so I may not send a newsletter again until January. Please be good to yourself, be good to your people.

If you want to keep up with me in the meantime, track me down on Bluesky [@mikebifulco.com](https://bsky.app/profile/mikebifulco.com).
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[From 21 to 1000 - Lessons in Growth]]></title>
            <link>https://mikebifulco.com/newsletter/lessons-in-growth-from-21-to-1000</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/lessons-in-growth-from-21-to-1000</guid>
            <pubDate>Tue, 03 Dec 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[What I learned from growing Tiny Improvements to 1000 readers]]></description>
            <content:encoded><![CDATA[
## The Big Idea

Reaching milestones is gratifying, but the growth that comes from sharing your work is the real difference maker.

---

## Milestones, Growth & Putting Yourself Out There

This week, 💌 Tiny Improvements hit 1,000 readers!

It's a milestone I couldn't have imagined when I sent my first dispatch to just 21 friends in 2020. The first newsletter went out _months_ after I set up a mailing list, and it was almost 2 full years before I started sending them regularly.

<Image
  publicId="newsletters/lessons-in-growth-from-21-to-1000/stats"
  alt="The very first Tiny Improvements Newsletter, from 2020, went out to just 21 people"
  caption="The very first Tiny Improvements Newsletter, from 2020, went out to just 21 people"
/>

Growth has been uneven - spurts, plateaus, and lots of introspection - but every new dispatch and reader is a reminder of why I started sharing my work.

Here's what this journey has taught me:

1. **It takes guts to start.**
   Sharing your work feels vulnerable at first. My first newsletter sat in drafts for months before I hit send. But once I did, the real growth - for the newsletter and for me - began.

2. **Feedback is fuel.**
   Hearing from readers is always validating, whether it's close friends or strangers. If you've ever hit reply to one of my emails, know that your words mean more than you think.

3. **Writing changes you.**
   This newsletter has made me more thoughtful-about my own work and about the content I consume. I notice lazy clickbait more than ever but also have a deeper appreciation for simple, impactful writing.

One unexpected highlight lately has been Bluesky. It's a refreshingly open and real space right now, and I've been connecting with incredible new people there. (Follow me: [@mikebifulco.com](https://bsky.app/profile/mikebifulco.com)).

---

### Why This Matters

Whether it's an article, video, app, or something else - sharing your work can feel daunting, but it's a great way to grow. Your journey will be different from mine, but every step will be valuable.

If you've been waiting for the “right time” to start, this is your sign: start today.

<Aside>

📢 If you're working on something you're proud of, [hit reply and share it with me](mailto:hello@mikebifulco.com)! I'll give it a signal boost and cheer you on.

</Aside>

### Closing Thoughts

To each of you: thank you for letting me into your inbox. I'll keep writing, learning, and sharing, and I hope you'll do the same.

---

## Some Other Things I've Shared Recently

- [Migrating from next-sitemap to sitemap.ts](https://mikebifulco.com/posts/migrate-from-next-sitemap-to-app-directory-sitemap) I've been starting the process of migrating my personal site from Next's lovable Pages directory to the new App directory. While doing so, I put together a guide on migrating your sitemap, if you're looking to do the same.

- [APIs You Won't Hate: Mr. Bluesky](https://apisyouwonthate.com/newsletter/mr-blue-sky/) the latest newsletter from APIs You Won't Hate is all about Bluesky, and has some great articles about the platform and its API. You can find [APIs You Won't Hate on Bluesky](https://bsky.app/profile/apisyouwonthate.com), too!

- Speaking of lumpy growth and uneven solutions - I recently published a video series on [using Posthog to improve conversation rates](https://www.youtube.com/watch?v=4nWcB1a8M1s&list=PLhd5wwaTOKLuI6UNjGpBnPKxWiUW4iBhg) for 💌 Tiny Improvements signups. It was a fun experiment, and results were mixed! All part of the journey.

---

## Where I've been learning

- 📕 [Good Services](https://hardcover.app/books/good-services) by _Lou Downe_ - as recommended by my friend and colleague Niki, Good services is all about building services businesses, looking after customers and employees, and building systems that benefit both.

- 📗 [Supercommunicators](https://hardcover.app/books/supercommunicators) by _Charles Duhigg_ - This was a great lead in the run up to the election - coming to a better understanding of how great communicators listen to people and make connections. If you have challenging relationships at work, with family members, neighbors, or friends, this book has the capacity to be transformative.

- 🎙️ [Getting Ready to Interview Trump - an exercise](https://www.youtube.com/watch?v=gx7IDERbRWk) is the latest episode of the podcast _Question Everything_ from Brian Reed, who you may know from podcasts like _S-Town_ and _The Trojan Horse Affair_. Question Everything is an ongoing analysis and inspection of Journalism's role in society. Each episode so far is well-worth a listen.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[First Principles: Your Framework for Clarity]]></title>
            <link>https://mikebifulco.com/newsletter/first-principles-frameworks-for-clarity</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/first-principles-frameworks-for-clarity</guid>
            <pubDate>Tue, 19 Nov 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[How the most productive people use fundamental truths to navigate complexity and stay focused]]></description>
            <content:encoded><![CDATA[
## The Big Idea

When faced with complex challenges, the most productive people I know return to first principles - fundamental truths they can build from.

## Back to Basics

When was the last time you fully renovated the way you solve problems, from the ground up?

I've noticed something fascinating about highly productive people: when faced with complex and new problems, they don't add more complexity - they subtract it. They return to fundamental truths and build up from there.

This approach, known as first principles thinking, isn't just for philosophers or engineers. It's a useful tactic for anyone facing a new problem, and can be particularly helpful for founders who are trying to navigate a new market.

### What are First Principles?

First principles are the fundamental truths that can't be broken down further. They're the building blocks we use to understand everything else. For example:

- _Time is irreversible_, and moves from past to the present
- _Do no harm_, a core principle of medicine to minimize risk and negative outcomes
- _Occam's Razor_, the principle that suggests the simplest explanation is often the best
- _Least Effort_, your end users will always try to find the path of least resistance

## Why This Matters for Product Development

This is a powerful tool for product development. If you're evaluating a new market or product idea, you can use first principles to understand the core principles that have driven the current state of the market, and identify gaps that you can fill.

### A concrete example: how first principles led to ride sharing

Let's look at how first principles thinking revolutionized urban transportation. Instead of trying to improve taxis, entrepreneurs asked: "What is the fundamental purpose of urban transportation?"

The core principles they identified were:

- People need to get from point A to point B reliably
- Both drivers and passengers want to maximize their time and money
- Trust and safety are essential for both parties
- Supply should match demand efficiently

Traditional taxis failed to optimize for these principles:

1. Supply/demand mismatch: empty taxis circled busy areas while other neighborhoods had none
2. Pricing opacity: meters created uncertainty and anxiety for passengers
3. Trust gap: anonymous interactions left both drivers and passengers vulnerable
4. Artificial scarcity: medallion systems limited supply without improving service

Ride sharing services built solutions directly from these principles:

1. Dynamic matching: GPS and algorithms connect nearby drivers to passengers
2. Transparent pricing: upfront fares let everyone make informed decisions
3. Two-way accountability: ratings and digital records create trust
4. Market-driven supply: flexible driver enrollment helps match real demand

This is first principles in action: instead of accepting "this is how taxis work," rideshare services stripped away assumptions and rebuilt from the core principles of the problem space.

## Roll Your Own: the first principles framework

This sort of process can be applied to just about anything, from product development to team dynamics to your basic beliefs. Here's a simple framework to get you started:

1. **Define the Problem** - Write down what's wrong or what you want to improve. Be specific.

2. **Identify Core Principles** - Think about the fundamental truths or rules related to the problem. (Examples: "Keep it simple," "Focus on what users need," "Test before scaling.")

3. **Break the Problem into Pieces** - Divide the problem into smaller parts. Work on one part at a time.

4. **Brainstorm Solutions for Each Piece** - For each part, think of ways to solve it while sticking to your core principles.

5. **Choose the Simplest, Most Aligned Solution** - Pick the solution that's easiest to implement and most consistent with your principles.
   Pick the solution that's easiest to implement and most consistent with your principles.

6. **Test the Solution** - Try it out! Check if it works as intended and solves the problem.

7. **Refine** - Make adjustments if needed. Stay true to the principles as you tweak things.

---

## Applied Principles Thinking

Mathematicians and physicists are skilled at applying first principles thinking to complex problems. They start with fundamental truths, and build up from there. The best educators among them are able to explain these truths in a way that's easy to understand and apply.

Not sure what I mean? You might dig these examples:

[Equally Sharing a Cake Between Thee People](https://www.youtube.com/watch?v=kaMKInkV7Vs) from numberphile

[Supervised Learning: Crash Course AI](https://www.youtube.com/watch?v=4qVRBYAdLAo) from Crash Course

## More on building from first principles

If you're interested in how these principles can be applied to team dynamics, check out my thoughts on [building happier teams](/newsletter/simple-habits-for-a-happier-team) and [measuring what matters](/newsletter/build-measure-listen-rebuild).

I've also written about how [building in public](/newsletter/building-in-public) and [setting meaningful goals](/newsletter/fitts-law-and-the-beauty-of-big-goals) can help you stay accountable to your principles.

---

## Your Turn

What are your first principles? What fundamental truths guide your work? Who are your favorite first principles thinkers? Hit reply and let me know - I read every response, and I'd love to hear your thoughts.

Be excellent to each other,

Mike
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Mad? Use It to Start Something Big]]></title>
            <link>https://mikebifulco.com/newsletter/your-anger-as-inspiration-for-change</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/your-anger-as-inspiration-for-change</guid>
            <pubDate>Thu, 14 Nov 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Sometimes, being mad is the best way to start something new.]]></description>
            <content:encoded><![CDATA[
## The Big Idea

Sometimes, being mad is the best way to start something new.

## Stay mad

I was walking home the other night, feeling lucky. I have a great job, a short walk home, and live in a city built for walking and biking. It was a rare moment recently where I wasn't just angry, anxious, or sad about the world.

I'm mad about the state of politics in the US. A lot of people voted for someone who thinks they're above the law. But in that moment of reflection, I realized I'm lucky to be mad. I have the freedom to feel this frustration - unlike so many others who can't afford it or fear consequences if they speak up.

That feeling reminded me of starting Craftwork. My cofounders, Tim and Suzanne, were fed up with the frustrating process of hiring painters. Their anger sparked an idea, and they built a solution.

The truth is, sometimes being mad is exactly what you need to create change. So many companies were born from frustration - Airbnb, Uber, Slack, Resend - because something just wasn't good enough. Anger, when channeled right, can be a powerful force.

If you're looking for a product idea or a business to start, try asking yourself: What makes you mad?

Get mad about it, and go fix it.

Fix it for good.

---

## Creators to learn from

[Chris Biscardi](https://bsky.app/profile/chrisbiscardi.bsky.social) is a Rust developer and community builder who has been helping devs learn to build with Rust for _years_. He has a great course called [Rust Adventure](https://www.rustadventure.dev/) as well as a _very_ active YouTube channel where he shows how to [build games with Rust](https://www.youtube.com/@chrisbiscardi/videos).

[Makari Espe](https://www.youtube.com/@makariespe) is a Youtuber who makes videos about self improvement. Her videos are a thoughtful and candid exploration of her personal growth and learning. Recent creations include an exploration of curing her anxious morning routine, getting into road cycling, and taking solo camping trips. They're relaxing and inspiring all at once.

---

## Catch up with me on Bluesky

Bluesky is a decentralized social network whose success is largely due to frustration: Twitter's hostile takeover and toothless leadership left many people looking for a new home.

If you haven't had a chance to check out Bluesky recently, it's a great time to start. There has been a _massive_ migration of people moving from Twitter to Bluesky; the tech community is absolutely humming with activity lately. The past few weeks have felt like reconnecting with old friends, and a huge surge in finding new people to follow - it's a great time to start.

You can find me on Bluesky at [@mikebifulco.com](https://bsky.app/profile/mikebifulco.com).

You may also like _Starter Packs_, a feature of Bluesky that lets you follow lists of people curated by others. Here's few packs that you might enjoy:

- [APIs You Won't Hate](https://go.bsky.app/MZhCTN2)
- [Y Combinator Founders](https://go.bsky.app/BNkzSpM)
- [Founders & Makers](https://go.bsky.app/2q9kn63)
- [Ruby & Rails](https://go.bsky.app/HD2Ty2o)
- [DevRel](https://go.bsky.app/HD2Ty2o)
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Dunbar's number: focusing on your core supporters for network effect growth]]></title>
            <link>https://mikebifulco.com/newsletter/dunbars-number-and-network-effect</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/dunbars-number-and-network-effect</guid>
            <pubDate>Tue, 05 Nov 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Focus on building strong connections with a core group of 50 advocates to fuel sustainable, network-driven growth.]]></description>
            <content:encoded><![CDATA[
## The big idea

In the early days of building a product, focus on building strong connections with small group of people to solicit meaningful feedback and drive network effect growth.

## Your product's success relies on trust

When building something new, it's natural to set your sights on hitting massive growth numbers.

[Dunbar's Number](https://en.wikipedia.org/wiki/Dunbar%27s_number) suggests that sustainable growth starts smaller than you might think - with a close-knit, trusted network. This social theory, from British anthropologist Robin Dunbar, suggests that we can maintain stable social relationships with around 150 people at most.

But within that 150, there's almost always a much smaller core audience that truly drive connection, influence, and impact.

In the early stages of building a product or service, these core people are your foundation. They're the first to test, trust, and tell others about what you're doing. Nurturing this group can create a network effect that sets you up for growth.

<SponsoredSection
  imagePublicId="sponsors/posthog/product-for-engineers"
  sponsorName="PostHog"
  CTAtext="Subscribe for free"
  href="https://newsletter.posthog.com/"
>

**Flex your product muscle**<br />
Product for Engineers is a newsletter on building great products, the best practices of top startups, and lessons learned by PostHog.

</SponsoredSection>

## What it means for your product

Most people talk about Dunbar's number in terms of 150, but the power lies in close-knit groups of 50. These 50 people are your advocates, your early adopters, your most vocal supporters. For product builders, focusing here first creates a foundation that grows beyond one-time use or sporadic engagement.

<Image
  publicId="newsletters/dunbars-number-and-network-effect/dunbar-illustrated"
  alt="Dunbar's number"
/>

1. **Quality over quantity**: Building a strong network starts with a core group of advocates. These 50 people are your most engaged users, the ones who will spread the word and bring others in.
2. **Network effect**: When you focus on building a strong core group, you create a network effect that drives growth. These advocates bring in others who trust their recommendations, creating a ripple effect.
3. **Sustainable growth**: By nurturing your core 50, you create a foundation for sustainable growth. These advocates will stick with you through changes and challenges, helping you build a strong, resilient network.

My advice is to _build with your core 50 in mind_. Focus on creating a product that meets their needs, listens to their feedback, and adapts to their preferences. By doing so, you'll create a network that grows naturally, sustainably, and with trust at its core.

This is why many startups begin with a _friends and family_ launch. It's a great way to get blunt feedback from people who _care_ about you and your success, and who can be trusted to give you honest feedback.

---

### Applied science of Dunbar's Number: Gore Industries

Gore, the company that makes of GORE-TEX, applies Dunbar's number by limiting the size of its factories. When a team hits 150 people, they spin off a new group. Each group operates independently with its own R&D, production, and sales teams. This approach keeps teams close-knit, engaged, and highly collaborative-key to their success.

### Building on the Network Effect

Nurture Your Core 50: Focus on building meaningful relationships with your first 50 users. They are the heart of your network, and their enthusiasm will drive momentum. Treat their feedback like gold, and respond to their needs directly.
Create a Product of Substance: Deliver on your promises to these early adopters, listen actively, and adapt. A strong, attentive foundation encourages your core group to bring others in naturally.

---

## Now, go do the thing

**For your product:** Build with compassion and responsiveness. Turn your initial 50 users into advocates so they bring their own circle along.

**It's Election Day:** Influence your Dunbar network. Encourage the people you know best to vote today - your voice has power, especially in small circles.

---
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Get out and F*cking Vote]]></title>
            <link>https://mikebifulco.com/newsletter/voting-and-the-founder-mindset</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/voting-and-the-founder-mindset</guid>
            <pubDate>Wed, 30 Oct 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Undecided voters be like: I don't know if I want pizza or smallpox for dinner...]]></description>
            <content:encoded><![CDATA[
## The big idea

Voting isn't just about one issue or one stance - each vote is an opportunity to think broadly about what kind of world we want to build. So, vote with all your values in mind - not just one.

## Bring the Founder Mindset to the Polls

As founders, builders, and creators, we're constantly thinking about shaping the future - taking small steps each day to improve products, create solutions, and make lives better. The vision driving us is one of progress, not just for the next quarter but for the long term.

During election season, many people tend to lose sight of the bigger picture and lessons of even the recent past, often getting caught up in the emotions of the moment.

To me, it feels like a short- to medium-term memory loss, where we forget past choices and their consequences. I know a good number of people who sat out the 2016 election or voted for a third party to _send a message_ - which, well -- we all know how that turned out.

In the tech world, organizations have backed candidates based on single issues, focusing on a narrow benefit while sidestepping the bigger risks to innovation, freedom, and inclusion. That kind of trade-off may feel gratifying in the moment, but it can end up limiting the very world we're working so hard to build.

<Image
  publicId="newsletters/voting-and-the-founder-mindset/stand-with-crypto"
  alt="Stand With Crypto"
  caption="Stand with Crypto, an advocacy organization backed by Coinbase, wants you to vote for a convicted felon because... bitcoin is neat?"
/>

### Beyond the Trade-Offs

Voting thoughtfully means thinking like a founder: weighing short-term gains against long-term consequences. It's about balancing immediate benefits with the impact on society, rights, and industries in the years to come. A single-issue endorsement may deliver short-term support for one area, but it's rarely worth compromising on the rest of what we value.

### Vote for the World You're Building

The best companies, and the best leaders, look beyond the next quarter, just as the best voters look beyond a single issue. So this election, think beyond one policy and consider how each candidate's values and actions align with the future you want to help create.

## Most importantly: Vote

If you're elligible to vote in this election, the moral and ethical imperative is to vote. It's shaping up to be a close race, and your voice is more likely than ever to make a difference.

You're not reading this newsletter because you're an apathetic person. You're reading this newsletter because of the active role you've taken in your life, and because you care about the future. So go out there and make your voice heard.

✌🏾

---

## Resources for staying informed on elections

### An interview with Mo Green

A special shout out this week: North Carolina's election for State Superintendent of Schools has gotten a ton of attention, and for good reason. Shortly after this newsletter goes out, an in-depth [interview with Democratic candidate Mo Green](https://www.youtube.com/watch?v=zN1mCjkpU-c) will be featured on the Primary Focus YouTube channel.

<Image
  publicId="newsletters/voting-and-the-founder-mindset/primary-focus-mo-green"
  alt="Primary Focus interview with Mo Green thumbnail"
/>

I'm _super duper_ biased here: not only is Mo Green a great candidate (and _the only_ serious candidate in the race), but Primary Focus is run by my favorite person in the world - who I'm lucky enough to be married to. Give the video a watch, and slap the subscribe button while you're at it.

## Check your registration status and find your polling place

If you're in the US, make a plan to vote: [vote.org](https://www.vote.org/) is a tremendous resource. You can see your registration status, find your polling place, and even see a sample ballot.

## A primer on the US election system from CGP Grey

🎥 The US Election system is... frustrating, but it's the system we've got. YouTuber CGP Grey has an incredible [video series on voting](https://www.youtube.com/playlist?list=PLqs5ohhass_RN57KWlJKLOc5xdD9_ktRg), which is worth a watch over your lunch break. Here's a teaser: as a result of the way our elections work, it's a mathematical inevitability that we'll end up with a two-party system. However -- there are already _some_ jurisdictions where this is changing!

---

That's it for me this week - I'll be back to sharing more direct wisdom about building products in the weeks to come, but rest assured: this election _is_ a big damned deal.

I wouldn't be writing this newsletter if I didn't think you had the capacity to make a difference. So go out there and vote.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[First principles for UX design]]></title>
            <link>https://mikebifulco.com/newsletter/first-principles-for-ux-design</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/first-principles-for-ux-design</guid>
            <pubDate>Tue, 15 Oct 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Using first principles in UX will make your product more intuitive and more enjoyable for your customers, while making your job easier.]]></description>
            <content:encoded><![CDATA[
## The big idea

Using first principles in UX will make your product more intuitive and more enjoyable for your customers, while making your job easier.

## First Principles

If you're not familiar with the term, **First Principles** are a way of thinking about a topic by breaking it down into its most basic, fundamental elements.

Instead of reling on assumptions, first principles encourage you to rebuild from the ground up, focusing on what is well known, true and fundamental.

Using First Principles in design should give you a set of rules that can help you make better decisions about how to build your product. Let's look at a few examples:

### 1. Everything on screen should have an obvious function

When people interact with your UI, they shouldn't have to guess how it works. An obvious interface means every button, icon, and element should look and feel like it belongs -- and functions in a way that's consistent with what people expect.

<Image
  publicId="newsletters/first-principles-for-ux-design/button-vs-toggle"
  alt="Button vs Toggle mock-up comparison"
/>

For example, if a setting can be toggled on or off, it can be tempting to render a button that shows two states - from a developer's perspective, it's easier to code, but the result can be confusing for the people using your product.

Instead, use a toggle switch to instantly communicate what the function is.

Small details add up to a more intuitive experience - does the mouse cursor change to a pointer when hovering over a button? Is there a visual difference between a clickable element and a non-clickable one? These small details can make a big difference in usability.

You're taking advantage of things we are already used to: toggle switches switch between states, and seeing a pointer when hovering over something indicates it can be clicked.

### 2. Your interface should be consistent

Once you've nailed down the patterns for individual bits of UI, they should be used consistently throughout your app.

If you're building features that your customers will use, you should build them with the same attention to detail as the rest of your app. I leave some room in my heart for easing up on superuser features that will never end up in the hands of a paying customer, but even that can be a slippery slope.

So - take the time and get your UI primitives working well, and use them consistently throughout your app. Heck, do yourself a favor and take advantage of a component library like [Shadcn](https://ui.shadcn.com/).

### 3. Your customers are already trained

People [spend more time in other apps than in yours](https://mikebifulco.com/newsletter/jakobs-law-design-ux). It's a reality that sounds depressing, but is actually good news for you. Your customers have been trained by _thousands_ of other apps and websites - they expect certain patterns and conventions when they're getting things done.

They know what an inbox looks like, and a calendar, and a search bar, and a settings page. People come with built-in expectations for credit card fields and push notifications and date pickers. Use these things to your benefit - don't reinvent the wheel where you don't have to.

---

## More reading on first principles

You don't need to listen to me (ever) - but you should at least _consider_ learning from people smarter than me:

### Thinking with Type

When I was studying Human-Computer Interaction in grad school, I read [Thinking with Type](https://www.amazon.com/Thinking-Type-Critical-Designers-Students-dp-1797226827/dp/1797226827) as part of a course I took on cognition. The professor who taught the course use to repeat the phrase "Words have meaning" often. He had a habit of showing us examples of how people's expectations for how things should work are shaped by the types of experiences they've had in other places. Words have meaning, and the _way we present words_ carries more meaning than you might think.

### Dan Mall on Design Systems

Dan Mall is a designer who has written a lot about design systems. He's got a great primer video on his YouTube channel - [What is a design system?](https://www.youtube.com/watch?v=hMSSg-pA9lk) is worth a watch for nailing down some first principles goodness.

---

## Hey though, go vote

We're less than a month from The U.S. presidential election. If you're one of my American pals, please go vote. If you're not, please consider reaching out to someone you know who is and asking them to vote.

You're going to be bombarded with ads for the next month - it's easy to get cynical and tune it out. Please don't. Your vote is too important.

Need to look up your polling place, or see who is on your ballot? I got you -> [vote.org](https://vote.org/) is a great resource.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Don't just listen. Interpret feedback wisely.]]></title>
            <link>https://mikebifulco.com/newsletter/interpret-feedback-wisely</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/interpret-feedback-wisely</guid>
            <pubDate>Tue, 08 Oct 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[User feedback is your product's compass. Listen intently, act wisely, and stay true to your vision to navigate towards success.]]></description>
            <content:encoded><![CDATA[
## Communication is everything

Many products stumble, or fail to take off because builders don't incorporate feedback, missing the mark on real user needs. If your success depends on real people paying for it, you need to listen to them, to make sure your product resonates and delivers value. This doesn't mean blindly following every request, instead you need to interpret it through the lens of your product vision to make meaningful change.

If you haven't done this before, it can be intimidating to start. Here's a few tips to get you started:

### User Interviews

User interviews are a powerful tool for collecting in-depth insights into the needs and behaviors of the real people who are either using your product, or who you think might be part of your target demographic. These are real conversations with real people, and they require you to take the time to talk to them. One of the most important things taught at Y Combinator is that not enough founders talk to users _before_ starting to build products.

The best user interviews are conducted with open-ended, inquisitive questions. The aim is to explore peoples' perspectives, without leading them to a specific answer. A common pitfall is to be too focused on the result you want to hear, instead of truly understanding the peoples's perspective.

Good user interviews, especially early ones, can have meaningful and significant effects on the early direction of your product. The goal is not to have one or two interviews, but to talk to as many people as you can, until you have a good understanding of the landscape.

### Open channels for feedback

There are countless ways to collect feedback from people while they are using your apps. Surveys, contact forms, and feature suggestion tools give customers a way to share their desires, problems, and feature requests proactively. You've heard me talk about this before - I've had success using everything from a simple email address to surveys with [PostHog](https://posthog.com/mikebifulco). Other channels, such as chat interface tools like Intercom and Drift can also be incredibly effective for real-time feedback and support.

The real magic here lies in human connection - people will trust you more and become more attached to the product you're building when they feel like they're being heard. In the early days, it's the best way to turn casual users into loyal advocates who not only provide feedback, but actively promote your product.

### Telemetry

Telemetry is an unobtrusive way to collect data on how users interact with the features of your product. By measuring user actions and behaviors, you can identify patterns, detect frustration and issues, and make informed decisions on how to improve the product. Telemetry doesn't need to be creepy; it can be done anonymously, providing valuable feedback without compromising user privacy.

This way, you can gain insights and improve your product while respecting boundaries.

Telemetry can be used to monitor the success of new features, system performance, and proactively address bugs before customers churn.

## Don't forget about the vision

Every product founder should build with a believe in the vision that sparked their journey. It's this vision that should guide you through the feedback you're getting, ensuring that you remain true to your long term goals, and delivers a product that is truly useful, even if it evolves over time.

As you gather feedback through user interviews, feedback channels, and telemetry, it's easy to get lost in the sauce. It's important to remember that feedback is a tool, and not a rulebook. By interpreting requests through the lens of your product vision, you ensure that changes align with the long term goals of your product, and deliver features are both useful and valuable to your customers.

---

## Some more resources for listening

Don't take my word for it - here are some great resources for getting better at listening:

### Supercommunicators

People are complex. Every conversation you have with someone is the product of many factors in their life (and yours). In [Supercommunicators](https://hardcover.app/books/supercommunicators), author Charles Duhigg goes deep on the psychology and science of great communication, and how to truly listen to those around you. After a close friend recommended it to me (s/o to Tom!),I've found myself going deep on this one.

_Side note: I keep a list of books I've read on a service called Hardcover - if you dig this one, you'll appreciate my [Product Design reading list](https://hardcover.app/@irreverentmike/lists/product-design-community-building-and-go-to-market_).

### UX Design courses from Gymnasium

My pals over at Gymnasium are always hard at work curating great learning materials for designers. Their [UX Design curriculum](https://thegymnasium.com/ux-design) is _free,_ and has helped thousands of designers sharpen their skills. If you're building a product, you're a designer - you won't regret giving this a look.

--

## Go vote

For my 🇺🇸 American pals, _please_ double check your voter registration, and make a plan to vote this November. This may be the most important election of your lifetime - and the privilege of voting is one that shouldn't be taken for granted.

My favorite voter resource is [Vote.org](https://vote.org/). You can check your registration status, register to vote, see what's on your ballot, and make a plan to vote, all in one place. If you're already on top of it, do me a favor and check in with your friends to make sure they're getting out there and voting too.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Nobody Wants a Big Reveal: Why Keeping Secrets Hurts Your Work]]></title>
            <link>https://mikebifulco.com/newsletter/nobody-wants-a-big-reveal</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/nobody-wants-a-big-reveal</guid>
            <pubDate>Tue, 01 Oct 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Avoid the temptation of the dramatic reveal. Here's why openness and transparency are your real competitive advantages in product development.]]></description>
            <content:encoded><![CDATA[
Tech nerds can't resist the _big reveal_. Blame it on mega-corporations like Apple that glamorize product launch events. But for most of us, the big reveal is a dangerous myth.

Sure, who doesn't dream of a Steve Jobs moment? Unveiling a game-changing product to the world is a seductive fantasy, but for 99% of us, it's a losing bet. When we work in secret, we miss out on the most valuable part of the process: feedback.

<SponsoredSection
  imagePublicId="sponsors/posthog/product-for-engineers"
  sponsorName="PostHog"
  CTAtext="Subscribe for free"
  href="https://newsletter.posthog.com/"
>

### Flex your product muscle

Product for Engineers is a newsletter on building great products, the best practices of top startups, and lessons learned by PostHog.

</SponsoredSection>

## Why the Big Reveal Falls Flat

The grand unveiling can often backfire. The truth is, a successful launch depends on much more than secrecy. It requires real-world feedback, adaptation, and a deep understanding of your audience's needs.

In my years building products, I've seen too many projects miss the mark because they held back until it was "perfect." Here's why that doesn't work:

1. **Audience of One**: Designing without input means building a product that only fits your vision - not your customers' needs.
2. **Perfection Paralysis**: Chasing perfection often leads to endless revisions and a product that's never finished.
3. **Out of Touch**: Without feedback, your product becomes a solution searching for a problem.
4. **Crickets at Launch**: When no one knows about your work, no one's waiting for the reveal.
5. **Echo Chamber Effect**: Without external voices, you risk becoming too invested in your own ideas and losing touch with reality.

## Why the Big Reveal Hurts Your Team

The big reveal doesn't just create problems for the product - it also disrupts your team. When people work in isolation and wait until something is "done" before sharing, they end up dumping a massive document or feature on their teammates with little context. This approach blindsides the team, creating confusion and misalignment.

Crowdsourcing feedback from peers along the way is a much better strategy. By sharing progress early, you keep everyone in the loop, build a sense of ownership across the team, and avoid surprises. Plus, it opens up the opportunity for valuable input that can course-correct mistakes before they become deeply ingrained in the project.

### Why this matters

- **Prevent Silos**: Sharing early keeps everyone informed and helps avoid working in isolation.
- Get **Stronger Team Buy-in**: When teammates are involved throughout the process, they're more invested and engaged.
- **Better Outcomes**: Crowdsourcing ideas and feedback from teammates improves the final product, as you benefit from a diverse set of perspectives.

## Embrace Transparency

The better strategy is openness. By sharing your progress, process, and even mistakes, you invite feedback and foster connections. This transparency helps keep your work grounded, adaptive, and aligned with market needs.

In fact, incremental transparency is not just better - it's essential. Here's why:

- **Feedback Loop**: Regular updates mean you can adapt and pivot when necessary.
- **Audience Investment**: Involving people early builds community and anticipation.
- **Faster Iterations**: You can make smaller, faster improvements rather than obsessing over a grand reveal.

## The Power of Public Failures

Being wrong in public is uncomfortable - but it's also incredibly powerful. Admitting mistakes invites feedback and accelerates learning. It fosters a culture of humility and adaptability, and helps you build better products, faster.

## The Bottom Line

The big reveal is a relic. Successful products today are built through transparency, iteration, and collaboration. By opening up your process, you not only avoid the pitfalls of secrecy but build better relationships with your users.

## Do this instead

Don't keep your work a secret. Share your progress early and often. Your users will thank you - and so will your product.

---

## Here's some links I've been keeping from you:

Or rather, I _could_ have kept these to myself, but where's the fun in that? Here's some cool stuff I've been enjoying lately:

### Product Analytics with PostHog: my A/B test results are in!

<YouTube youTubeId="GLcmKT55Z0Q" />

The latest video in my series on [Product Analytics with PostHog](https://www.youtube.com/watch?v=GLcmKT55Z0Q) is live! The journey started with a broken subscription form, and has come full circle in this video where I share the results of my A/B test - and what I learned from it. I hope you enjoy it!

### Working in Public

Author Nagia Eghbal's book [Working in Public](https://press.stripe.com/working-in-public) is all about working with transparency - and although it focuses on open-source software, the principles apply to all product development.

### Label _Everything_

I _love_ learning from people who have turned the dial up to 11 on a passion. YouTuber David Malawey produced a [24 minute video on his system of labeling _everything_](https://www.youtube.com/watch?v=B1QqAZeEfes) in his life. It's an extreme take, based on the Japanese concept of _5S_, but it's fascinating to see how far you can take a simple idea.

He makes a strong case for real ROI from labeling _everything_ - and although I don't think you need to go _quite_ as far as he does, I think we call can benefit from applying some of his principles.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[How Contrast Elevates Perception]]></title>
            <link>https://mikebifulco.com/newsletter/contrast-effect-cognitive-psychology</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/contrast-effect-cognitive-psychology</guid>
            <pubDate>Tue, 17 Sep 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Why a seamless experience can make your work feel superior - even if it's not.]]></description>
            <content:encoded><![CDATA[
# Contrast Elevates Perception

We often think the quality of our work speaks for itself, but in reality, _perception_ often plays an even bigger role.

The <dfn>contrast effect</dfn> shows how **presenting options in a particular way can dramatically change how they're viewed** - even more than the options themselves.

Here's why this matters for designers, developers, and product builders:

## Brand Perception is Reality

At [Craftwork](https://craftwork.com?utm_source=mikebifulco-com), we work hard to provide a seamless, well-branded experience for getting your home painted - in an industry where the bar for customer service is pretty low.

Cynically speaking, the _end result_ for our customers is essentially the same as what all of our competitors offer: a freshly painted home.

However, we have spent _countless_ hours refining the experience our customers have. From the moment they get in touch with us to the final brush stroke, we've designed every touchpoint to be as thoughtful, modern, and smooth as possible.

<Image
  publicId="newsletters/contrast-effect-cognitive-psychology/craftwork"
  alt="Craftwork"
/>

Because we've built our service with customer journey in mind, our customers _feel_ the difference when comparing our offering to other companies in their neighborhood. If you've ever tried to get a quote from a home services company, you know how frustrating the process can be.

We've worked hard to make it feel _just like it should_ - easy, transparent, and professional.

The end result? Pure magic. Our customer reviews talk about how easy it is to work with us, how professional our team was, and how much they love the final product.

The contrast between our service and _the usual experience_ is stark, and it's all because of the experience we've built.

## Job-seekers need to stand out

The Contrast Effect is also an invaluable tool for people who are struggling to stand out in the job market.

<Image
  publicId="newsletters/contrast-effect-cognitive-psychology/job-hunt"
  alt="Threads post about a developer who applied to 961 jobs without landing a gig"
  caption="The job market is extremely challenging for developers, even those with impressive resumes."
/>

I've seen developers with resumes boasting experience at top companies like Google or Facebook, yet they struggle to get hired.

So, what ultimately helps people with their job hunt?

Adding **personality** to their resume, to stand out from the rest of the stack - everything from thoughtful design elements to memorable facts about themselves to a mission-driven portfolio of personal projects.

You'd be _shocked_ how many incredible resumes sound _identical_ to one another. By adding a little contrast, these developers were able to stand out in a sea of sameness.

This contrast from the usual templates makes their applications pop, even though their qualifications were already impressive. It's a perfect example of how [a little design can make all the difference](https://mikebifulco.com/newsletter/your-resume-sucks).

## Pricing and Product Design

Another powerful use of the contrast effect is something you see all the time for SaaS products: pricing tables.

<Image
  publicId="newsletters/contrast-effect-cognitive-psychology/pricing-table"
  alt="Pricing table for a SaaS product"
/>

This design effectively compares three pricing options - causing the middle one to be seen as a _reasonable_ choice. This happens because it's strategically positioned between a high-end, feature-rich plan and a low-cost, bare-bones option.

Going a step further, [Comparing monthly and yearly plans](https://mikebifulco.com/newsletter/use-annual-pricing-build-loyalty) can enhance this effect. Highlighting clear savings on the yearly option encourages users to choose the plan you're aiming for. The psychology of pricing is an art in itself.

---

## More on cognitive psychology

- For more on how subtle design choices can shape perception, check out my article on ["Wabi-Sabi - Embracing Imperfection for Tech Teams"](https://mikebifulco.com/newsletter/tech-product-growth-wabi-sabi), where I talk about the power of accepting imperfections in tech.

- ["Why Liquid Death's Branding Is Murderously Effective"](https://mikebifulco.com/newsletter/naming-your-product-kiki-bouba) for a some thoughts on branding and design

- If you're interested in how design decisions affect interaction, my piece on ["The Math Behind Why Cafes Should Have Round Tables"](https://mikebifulco.com/newsletter/design-decisions-cafe-tables) explores how physical design can change experiences.

Ultimately, the way something is presented often matters as much as the thing itself. Whether you're building a product, presenting yourself to employers, or structuring pricing for customers, _contrast_ can turn a good experience into a great one.

## What are you working on?

I'd love to hear about your projects and how you're using design to elevate your work. Hit reply and let me know what you're building! I read and reply to every response - and I can't wait to hear from you.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Stay Sane: Mental Health Strategies for Startups]]></title>
            <link>https://mikebifulco.com/newsletter/mental-health-for-startups-founders</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/mental-health-for-startups-founders</guid>
            <pubDate>Wed, 04 Sep 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Burnout is your team's worst enemy. Here's how to prevent it.]]></description>
            <content:encoded><![CDATA[
Burnout is your team's worst enemy.

Great products are built by teams. In my experience, the best early stage employees will feel the pressure of building fast, focused products all on their own... often at the expense of their mental health. For this reason, I've always been a big proponent of founders being the first to advocate for the mental health of their team.

It's not just the right thing to do, it's also the smart thing to do.

<SponsoredSection
  imagePublicId="sponsors/posthog/product-for-engineers"
  sponsorName="PostHog"
  CTAtext="Subscribe for free"
  href="https://newsletter.posthog.com/"
>

### Flex your product muscle

Product for Engineers is a newsletter on building great products, the best practices of top startups, and lessons learned by PostHog.

</SponsoredSection>

Managing mental health will be different for every founder and every team, and it's up to you to figure out what works best for your unique situation.

I have found these strategies to be effective:

### Be the teammate you want to have

The golden rule goes a long way. Remember that you're working with real, complex people who have real, complex lives. Their joy, anxiety, and stress come from more than just work, and it can be easy to forget that.

Look after your teammates. Check in on them, ask them how they're doing, and encourage them to take time off when they need it.

**tl;dr:** Ask your teammates how they're doing, not just what they're doing.

### Use routines as an anchor for stability

I've written about [my morning routine](/newsletter/continuous-self-improvement) before, and how it has been critical for me in managing stress, staying organized, and generally just feeling like I'm in control of my life.

I highly recommend starting with just 5 minutes of journaling and 5 minutes of meditation. It will sound _too_ simple, but it's amazing how quickly you start to feel like you have a handle on your day.

If you're reading this and rolling your eyes, prove me wrong: try it for a month and tell me how it goes. My inbox is always open: [hello@mikebifulco.com](mailto:hello@mikebifulco.com).

**tl;dr:** Pairing 5 minutes of journaling and 5 minutes of meditation together make an incredible tool for managing stress.

### Go outside more

The day-to-day of building a startup can be so consuming that it's easy to forget to take care of yourself. Moving your body is one of the most important things you can do.

When I managed a remote team at Google, I would regularly schedule walk-and-talk calls with people on my team. These conversations often felt different -- there's something that makes it more natural to open up when you're not sitting in a conference room or at your desk.

The great news is that this works in person, too. Take your next 1:1 meeting outside -- even in hot or cold weather. You can do it!

Outside of work, find ways to spend time outside each day. The more the merrier, really, but I've found that just 10-15 minutes can make a big difference.

**tl;dr:** Touch grass. That's the tip.

---

## My work this week

### I messed up my A/B test

The latest in my ongoing video series on [Product Analytics for developers](https://www.youtube.com/watch?v=aDCFlPzNXh4) is out. This time, I'm talking about how how I detected and fixed a problem with an A/B test I was running.

### State of the APIs Survey 2024

Check out the most recent APIs You Won't Hate newsletter for a primer on the [State of the APIs Survey 2024](https://apisyouwonthate.com/newsletter/2024-state-of-the-api-survey/), and to learn a bit about my cofounder Phil's reforestation and climate protection charity.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Inter and the Power of Fonts: Why Typefaces Matter More Than You Think]]></title>
            <link>https://mikebifulco.com/newsletter/features-of-fonts-and-typography</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/features-of-fonts-and-typography</guid>
            <pubDate>Tue, 27 Aug 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Open up the potential of your designs with a deeper understanding of what variable fonts like Inter can do.]]></description>
            <content:encoded><![CDATA[
## The big idea

Fonts are way more than just a stylistic choice - they're a critical element that influences readability, usability, and the overall effectiveness of your design.

## Font vs. Typeface - what's the difference?

Let's get the designer-snark out of the way first: we often think of _fonts_ as the different styles of alphabets available on in apps like Word and Figma. There will no-doubt be someone reading this who wants me to explain that _fonts_ are the files on your computer, and _typefaces_ are the designs that those files represent. Neat.

For the sake of this article, I'm going to use the terms interchangeably.

### Why Fonts Matter

It's easy to think of a font as just a branding tool, but they're much more than that. Fonts influence readability, usability, and how users interact with your content. For example, certain fonts are easier to read at different sizes, or if they're printed vs on a screen.

Choosing the right font isn't just about aesthetics; it's about making your content accessible and engaging.

### Serif vs. Sans Serif

Serifs are the tiny lines on the edges of certain characters in some fonts (like Times New Roman). Serif fonts date back hundreds of years, and may have originally been used to make printed fonts easier to read. Sans-serif fonts, which lack these lines, are popular for their clean, modern look, serifs still have their place in designs that require a touch of tradition and readability in dense text.

### Font Pairings

Like picking the right wine with a meal, or dark chocolate and coffee, pairing fonts effectively can be surprisingly impactful.

A strong body font paired with a complementary header font can create a harmonious and impactful visual hierarchy. You may even see serif and sans-serif fonts used together in the same design to create contrast and visual interest.

Tools like [Monotype's font pairing tool](https://www.monotype.com/font-pairing#/playground?fontPair1=NimbusRomNo9T-Reg&fontPair2=Devoid) can help you experiment with different combinations to find the perfect match.

### The Versatility of Inter

Inter is more than just a popular typeface; it's a versatile tool that showcases the potential of modern typography. As a [variable font](https://fonts.google.com/knowledge/introducing_type/introducing_variable_fonts), Inter offers infinite adjustability, allowing designers to tweak weight, width, and other characteristics to fit their needs precisely. The Inter typeface even [has its own website](https://rsms.me/inter/) to showcase its comprehensive feature set.

### Variable Fonts

Variable fonts like Inter are offer more flexibility and customization than just **bold** and _italics_. They allow you to adjust the weight, width, slant, and other characteristics of a font dynamically, giving you more control over how your text looks.

Tools like [v-fonts.com](https://v-fonts.com/) help explore the full range of what variable fonts can do.

While [Tailwind doesn't yet offer full support](https://github.com/tailwindlabs/tailwindcss/discussions/3225) for variable fonts, with raw CSS, you can harness their power to create truly unique and dynamic designs.

```css
@font-face {
  font-family: 'SlantFont';
  font-style: oblique -15 15;
  src: url('https://mdn.github.io/shared-assets/fonts/font_with_slant_axis.woff2')
    format('woff2');
}
```

For more on using variable fonts with CSS, check out [this guide](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_fonts/Variable_fonts_guide) on MDN.

The control this gives you over the way your interfaces looks is _really_ impactful - designing for different screen sizes and resolutions has a whole new dimension when you can adjust the font to fit the space perfectly.

## The bottom line

Modern font families have many loads of features that you may not know about. It goes far beyond style x- fonts are designed for function, usability, and aesthetics, and there's hundreds of years of history behind the fonts we see today. Spending a little time giving your font choices some thought can make a big difference in the impact of your work.

---

## More resources for the fontheads out there

- [Inter's website](https://rsms.me/inter/) is beautiful, thoughtful, and a great example of how to showcase a typeface. The source code for the typeface is also [available on GitHub](https://github.com/rsms/inter) if you're really interested in how it all works.

- [Thinking with Type](https://amzn.to/4dGghUk) by Ellen Lupton is the textbook on typography that opened my eyes to how much goes into designing a typeface, and how much it can influence the way we read and interact with content.

- The YouTube channel [Pimp my Type](https://www.youtube.com/watch?v=_WBGIbRwYd8&) from typographer Oliver Schöndorfer has monthly videos on modern fonts that are digestible and informative. Highly recommend a binge-watch.

## My work this week

I've been putting out YouTube videos on my [YouTube Channel @mikebifulco](https://youtube.com/@mikebifulco?sub_confirmation=1) - if you're a visual learner, I'd love it if you considered [subscribing](https://youtube.com/@mikebifulco?sub_confirmation=1).

- [Overcoming Imposter Syndrome: 3 Simple Steps to Push Through Doubt](https://youtu.be/cFtmaF3i3jQ) is a video-edition of a recent newsletter, where I talk about how to push through self-doubt and keep creating. This one resonated with a lot of people, and I felt like it was worth sharing in a new format.

- [Product Analytics: A/B testing my next.js site for max growth](https://youtu.be/2hVHjSwYoU8) is the latest in a series of videos I've produced on taking an analytical look at site performance and growth. Thinking about marketing as a measurable science has been a game-changer for me, and I hope it can be for you too.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[How you do one thing is how you do everything]]></title>
            <link>https://mikebifulco.com/newsletter/how-you-do-one-thing-is-how-you-do-everything</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/how-you-do-one-thing-is-how-you-do-everything</guid>
            <pubDate>Tue, 20 Aug 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[How you do one thing is how you do everything. This is a phrase that has been around for a long time, but what does it really mean? In this article, we will explore the meaning of this phrase and how it can be applied to your life.]]></description>
            <content:encoded><![CDATA[
You've heard all the startup tropes: Launch fast, iterate faster. Move quickly and break things. Fail fast, fail often.

In the rush to get things done, it's easy to forget about quality. After all, who has time to sweat the small stuff when there's a product to ship?

But here's the thing: Quality matters. And finding the right balance between speed and quality is nearly paradoxical. Build too fast and you'll end up with buggy code and unhappy customers. Focus too much on quality, and you'll never ship anything at all.

## Sometimes it's about the details

I recently switched from using ConvertKit's to Resend for emails on my site. Resend is a more developer-friendly service which gives me all the bells and whistles I could ever dream of for integration. Once I got everything working, I spent some time developing a simple, branded template for transactional emails. It's essentially the frame that goes around the confirmation email people get when they sign up for Tiny Improvements.

<Image
  publicId="newsletters/how-you-do-one-thing-is-how-you-do-everything/email-template-base"
  alt="A screenshot of a confirmation email from Resend"
  caption="A screenshot of a confirmation email from Resend"
/>

Right now, the template is used exclusively for that one email - but I wanted to make sure it looked and felt right. I spent some time [looking for inspiration](https://reallygoodemails.com/search/emails/confirmation), set up a quick [Figma prototype](https://www.figma.com/design/On4yRGLcYLORVBIhBejboA/mikebifulco.com?node-id=301-6&t=tQ2Y9fUL1T7EHk7Y-1), and then got to work building it using [React Email](https://react.email/).

## The Bigger Picture

It's a small detail that probably matters most to me, but once it was done, it felt like my integration with Resend was complete.

The thing is, nobody will ever notice that I spent time on this. It's likely that this email will get banished to my readers' email archives within seconds of being opened, but that's kind of the point. If I did it right, this message should be _consistent_ with everything someone experiences when they come across my work. Ideally, it goes almost entirely unnoticed, because it feels like it's connected to everything else I do.

The quick way out here would be to use a fairly basic, blank template, or to fall back completely to `An old-timey text email`. I feel fairly confident in saying that either of those would feel out of place. Part of my whole schtick is that devs should care about design; failing to put in the effort here would be a pretty big contradiction.

## If you're doing things right, nobody will notice

...and sometimes that's just the way it is. This is a quip from a [great little scene in Futurama](https://youtu.be/EL7e05pClKM?si=UHoj8_lORe2YH6Qe) -- and I think it's a great centering thought for design work in general. As unsatisfying as it sounds, this is a sign of a successful design.

<Image
  publicId="newsletters/how-you-do-one-thing-is-how-you-do-everything/futurama-god-scene"
  alt="The bender-is-god scene from Futurama"
  caption="You know, I was god once..."
/>

Using a light touch is a _delicate_ but attainable balance. You don't need to be Dieter Rams to meet that standard. You just need to be consistent. For a lot of us, that's a great place to start.

## How you do one thing is how you do everything

I've just finished re-listening to Unreasonable Hospitality, a book that I've [written about in the past](https://mikebifulco.com/newsletter/unreasonable-hospitality-and-design). It's written by Will Guidara, co-owner and operator of one of the top restaurants in the world, Eleven Madison Park.

<Image
  publicId="newsletters/how-you-do-one-thing-is-how-you-do-everything/unreasonable-hospitality"
  alt="Unreasonable Hospitality book cover"
  caption="Unreasonable Hospitality, by Will Guidara"
/>

There's a great chapter in the book discussing the great lengths they went to in order to create a world-class dining experience. At the restaurant, they spend time making sure that plates are laid on the table so that the makers' mark _on their underside_ are facing guests perfectly.

What a wild thing to do - most guests will never flip their plate over to see who made it. For those that do take a look, will it even occur to them that the plate was placed that way intentionally?

Probably not. But that's not the point.

The point is that the staff at Eleven Madison Park _know_ that the plates are placed that way. They know that they're doing everything they can to make the experience perfect.

## Still, there is no bar

Remember, [there is no bar](https://chriscoyier.net/2022/06/27/there-is-no-bar/) for publishing online. You can publish whatever you want, however you want, and nobody can stop you.

I've talked to loads of people who _never get started_ sharing their work online because it's "not ready" -- and I get it. It's a scary thing to put yourself out there.

To be perfectly honest, if you're not ready to share your work yet, this advice is _probably_ not for you (yet). Fundamentally, it's most valuable to build, ship, collect feedback, and iterate -- and if you're not shipping, you're not iterating.

Once you do start putting your product or your writing or your podcast or your sculpture out there, though, you're setting a bar for yourself, and there's always room to improve.

## Start small

If it feels overwhelming, start small. Pick one thing that you can do _today_ to make your [thing] better. Go update that misaligned header, or fix a broken link, or finish that prototype that's been waiting for you.

It doesn't have to be perfect -- just better than it was yesterday.

---

## Some more of my work this week

### 📼 Part 3 of my product analytics is live

If you've been following along on YouTube, you may have seen the first couple videos I shared about debugging a conversion problem on my site. In the first 2 videos, I found and fixed a technical problem that was causing signups to fail. Now I've moved on to a more strategic problem: How do I get more people to sign up in the first place? See how I'm tackling that challenge [using A/B testing](https://www.youtube.com/watch?v=2hVHjSwYoU8&) in the latest video.

### 🎙️ Avoid an API billing nightmare

Supergood solves a problem we all fear: by monitoring your API usage, they help detect and prevent massive bills from SaaS Providers. If you have recurring nightmares about your AWS bill spinning out of control, you'll love my podcast interview with founder Alex Klarfeld - [No more API usage nightmares](https://apisyouwonthate.com/podcast/supergood-ai-for-tracking-api-spend-in-real-time/).

---

## Raise the bar for yourself

- [Really Good Emails](https://reallygoodemails.com/search/emails/confirmation) is exactly what it sounds like: a curated repository of well-designed emails. Such a helpful tool.
- Did you know that fonts have versions? _Inter,_ everyone's favorite typeface, recently launched [version 4.0](https://rsms.me/inter/), which you can poke around with on the incredibly beautiful showcase website for the font.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[How to source and use expert knowledge for your work]]></title>
            <link>https://mikebifulco.com/newsletter/how-to-source-and-utilize-expert-knowledge</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/how-to-source-and-utilize-expert-knowledge</guid>
            <pubDate>Wed, 14 Aug 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[One of the most effective ways to grow as a developer is by tapping into the vast pool of knowledge available in the developer community.]]></description>
            <content:encoded><![CDATA[
At the beginning of my career, I worked in Microsoft's consulting organization. Every week, I would travel to a customer's office somewhere in North America to help them solve their technical problems. Apart from _knowing a little javascript and css,_ I had no real business being there.

I was fresh out of college, and facing the challenge of being _Microsoft's Expert on [whatever]_ in front of the CIO of a Fortune 500 company.

No joke: my first project was rebuilding Dell dotcom from scratch, and I was the _lead_ frontend developer because I was the only one in the room who had heard of jQuery.

So -- I was the expert, and they were paying for my expertise. Which was a problem, really, because I didn't have any.

Nonetheless, any time I had a problem I couldn't solve on my own, I had the _entirety_ of Microsoft's 100k+ employees at my disposal, and I definitely used them. I would send out emails to internal mailing lists, getting advice from brilliant devs in charge of building windows. The responses I got were always helpful, and I learned a ton.

<SponsoredSection
  imagePublicId="sponsors/posthog/product-for-engineers"
  sponsorName="PostHog"
  CTAtext="Subscribe for free"
  href="https://newsletter.posthog.com/"
>

### Flex your product muscle

Product for Engineers is a newsletter on building great products, the best practices of top startups, and lessons learned by PostHog.

</SponsoredSection>

Fast forward 7 years, and I was leaving Microsoft to work as technical director at a code [Gymnasium](https://thegymnasium.com), the best damn online code school for creatives looking to dip their toes in the cool waters of web development.

I would be using completely new tools - going from .net and C# to Django and Python - and from a _massive_ network of people to a crack squad of just 5, where I was the only developer.

Suddenly I was an astronaut in a space station, cut off from the world. I had no one to ask for help, no one to bounce ideas off of, no one to tell me when I was doing something stupid.

I was on my own.

It didn't take long for me to realize that **developers have a unique advantage:** most of our peers are _chronically online_. The most knowledgeable people **in the world** are at your fingertips, as long as you know where to look.

From forums and blog posts to open-source projects, there is no shortage of places to find answers and learn. For me, the key to truly benefiting from this wealth of information came from active participation and engagement with the developer community.

It can do the same for you -- but you're gonna need to put yourself out there.

Here's 3 things you can do _right now_ to get started:

### Join a community

Whether it's a local meetup, a Slack channel, or a forum, find a community of people that you can engage with. This is a great way to meet like-minded people, share knowledge, and get advice.

### Give helpful feedback

When you're starting out, it can be intimidating to contribute to open-source projects or forums. But remember, you don't have to be an expert to provide valuable feedback. By giving constructive criticism and suggestions, you can help others improve their work and learn in the process.

### Keep an eye on trends

The tech industry moves fast, and it's important to stay up-to-date with the latest trends and technologies. This doesn't mean you have to _use_ every new tool or framework that comes out, but having a general understanding of what's happening in the industry can help you make informed decisions about your own work.

## The Pavlovian Power of constructive engagement

Someo of the best career advice I ever received is from pal Thomas: give and receive feedback in good faith, and you'll find yourself surrounded by people who are willing to help you grow.

This means being honest, respectful, and open to new ideas. It means being willing to admit when you're wrong, and to learn from your mistakes. It means being generous with your time and knowledge, and being willing to help others when they need it.

The inverse of this is all too common online - I'd wager to say that the vast majority of reddit, twitter, and youtube comments are people who are _not_ engaging in good faith. They're there to tear down, to belittle, to make themselves feel better by making others feel worse.

I'm sure you've seen and felt that, and it _sucks_ -- but it also means that when you come correct, you will really stand out.

It's a simple concept, but it's incredibly powerful. By engaging with your community with constructive, meaningful, and thoughtful feedback, you'll build a powerful reputation for yourself. You'll find yourself learning along the way, too.

Before long, you'll be the one people come to for advice.

---

## Helpful links from around the web

- I published the second in a series of videos on [Using Posthog to solve my conversion rate problem](https://www.youtube.com/watch?v=RaX8NeEhowU&t=1s) - and I'm stoked to say that after seeing the first video, Posthog is sponsoring Tiny Improvements and the next few videos I'm putting together. Give it a watch and let me know what you think!

- Over at APIs You Won't Hate, we published a great little tutorial on [pagination basics for APIs](https://apisyouwonthate.com/blog/api-design-basics-pagination/). It's a great primer on how to structure your API responses to make them easier to work with.

- My pal Andrew Peacock has been doing a great job of building his product for woodworkers in public. You can follow along on his journey on YouTube. his latest video talks about an important milestone: he [finally launched his MVP](https://www.youtube.com/watch?v=O0ryiXiSvVg)
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Debug tips from a lifetime newbie]]></title>
            <link>https://mikebifulco.com/newsletter/what-to-do-when-your-product-breaks</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/what-to-do-when-your-product-breaks</guid>
            <pubDate>Tue, 06 Aug 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Debugging problems with code (especially production code) is something that is rarely taught in university classes or code schools. Here are some tips that I've come across from watching smarter people than me debug problems.]]></description>
            <content:encoded><![CDATA[
## The worst time to learn how to deal with a crisis is during a crisis

How's that for self-evident? But -- it's true.

You should have a plan for when things go wrong. This is especially true in software development.

The first time you're dealing with a production issue is _not_ the time to learn how to deal with one. You need to have a plan in place for when things go wrong, and you should be ready to roll when the time comes.

### Tooling is gives you sensory feedback

Lucky for you, there's loads of tools that can make life easier when everything comes crashing down. You'll want to be able to reliably see what's going on in your system, and to be able to quickly identify what's going wrong.

At [Craftwork](https://craftwork.com), our current debug stack uses [PostHog](https://posthog.com) for session replay and product analytics, [Sentry](https://sentry.io) for error tracking, and Slack webhooks for alerting the team.

### Testing your code is a baseline

If you're not testing your code, you're going to have a bad time. Having tests written for your software is a baseline requirement - great tests prevent you from shipping flawed features, and help you understand when new features break old expectations. At a minimum, write tests for the features and scenarios in your software that are critical to your business, and build the habit of adding more over time.

I have been _really_ impressed with the devX of writing tests for Ruby on Rails - and there is literally no-one better to learn from than my pal and colleague CJ Avilla - he's done a whole series on [testing rails with RSpec](https://www.youtube.com/playlist?list=PLS6F722u-R6Ik3fbeLXbSclWkT6Qsp9ng) that I highly recommend, _even if you're not a Ruby developer_.

It's that good.

### Don't be afraid to ask for help

If you're stuck, ask for help. There's no shame in asking for help; you should view it as a _strength_ to know when a second set of eyes are what you need.

If you're working on a larger team, you'll get a feel for how long you should work on a problem before asking for help (the more severe the problem, the shorter this time should be).

If you're a solo founder or an indiehacker, this is one of the best things about finding community online. There's always smart people willing to help you out.

But -- and I can't emphasize this enough -- **the worst time to start building a community is when you need help.**

[The best time to start is now](https://mikebifulco.com/newsletter/today-is-your-day-to-start).

### Close the loop with affected users

Here's the secret sauce: Once you've found and fixed a problem in production, get in touch with affected users and let them know what happened, and how you fixed it. They'll love you for it, and you'll build trust with them. This is a great way to turn a negative experience into a positive one, and to build a relationship with your users.

Especially if you're a solo founder or indiehacker, vulnerability and transparency are what will make people believe in you. It's a superpower that is waiting for you to use it. Don't squander the chance!

## Get the ball rolling now

The great thing about these problem solving techniques is that each one adds value to the others, and they can be added incrementally. You don't need to have a perfect system in place to start - you just need to start.

---

## More of my work on this topic

As it works out, I've got a few more resources on this topic that you might find interesting:

### Product Analytics for engineers

I've been experiencing a downturn in newsletter subscribers through the form on my website recently. Ironically, if you're reading this, you're probably already subscribed. Rather than just throwing up my hands and saying "oh well", I decided to dig into the data and see what was going on, and I thought it would be a good opportunity to showcase the process I use for debugging web app problems that aren't as simple as "this page is crashing".

Check out [Product Analytics for engineers](https://www.youtube.com/watch?v=4nWcB1a8M1s) on YouTube for the first part of the adventure.

### Automate your SaaS product's crisis response

As it works out, this topic is something I've got some experience with. Back in 2020, just after my previous startup smpl was acquired, I was applying to devrel jobs at Google. As part of the interview process, I put together a talk about how to automate your SaaS product's crisis process, based on my experience at smpl.

While the information might be a bit dated, the principles are sound, and these slides landed me a job running Developer Advocacy for Google Assistant. Check out the slides here: [Automate your SaaS product's crisis response](https://github.com/mbifulco/talks/tree/main/01-automate-your-saas-products-crisis-response-process).

---

## Don't take my word for it

There's loads of great resources out there for debugging, problem solving, and customer support for product builders. Here's a few that I've found helpful recently:

- Kent C. Dodds has a great series of blog posts on testing javascript apps. A great place to start is [Write tests. Not too many. Mostly integration.](https://kentcdodds.com/blog/write-tests)

- PastMaps founder Craig Campbell has shared some incredible stories about proactive and reactive user research in his journey to to growing a sustainable business. I highly recommend following him on Threads for [gems like this one](https://www.threads.net/@that.map.guy.craig/post/C8u9Fn1yIzq).
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[You're 8 episodes away from being in the top 20%]]></title>
            <link>https://mikebifulco.com/newsletter/milestones-and-the-top-20-percent</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/milestones-and-the-top-20-percent</guid>
            <pubDate>Wed, 31 Jul 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[A shift in perspective can help you stay motivated on your journey to the top. Set achievable goals and measure your progress to keep moving forward.]]></description>
            <content:encoded><![CDATA[
Perspective is an interesting thing. Starting on a fresh project will have you standing at the bottom of a mountain of competition. It's easy to feel overwhelmed by the magnitude of the work ahead.

Having a mountain to climb can be inspiring at first - many people hit the ground running with a new project, full of energy and enthusiasm. But as time goes on, the reality of the climb sets in. Instant success is rare, and the reality of the long, slow grind can be disheartening.

I (sadly) do not have a silver bullet for this problem. **But** I can tell you what works for me - a shift in perspective. Instead of looking at the mountain, I find it helpful to look at the path ahead, and milestones along the way that I can work toward.

## Find your way to the top 20%

Did you know that **most podcasts don't make it past 7 episodes**?
(source: [Tom Brook on YouTube](https://www.youtube.com/watch?v=JrAyZYIneUg))

Or that to get into the top 20% of all podcasts, you only need to average 1000 downloads per episode?
(source: [Podcast.co](https://blog.podcast.co/reach/podcast-download-numbers))

Maybe you're building a YouTube channel - there's loads of great milestones to look forward to: your first video with 50 views, your first 100 subscribers, and so on. You can use tools like [Social Blade](https://socialblade.com/) to see how you stack up against other creators in your niche.

For my pals building SEO driven sites, you can use tools like [Ahrefs](https://ahrefs.com/) to see how your site stacks up against the competition. You might be surprised to find that you're only a few backlinks away from the top 20% of sites in your niche.

## 10% of the top MILLION sites are dead

I was inspired this week Craig Campbell's _incredible_ article from 2020, [10% of the Top Million Sites are Dead](https://ccampbell.io/posts/10-percent-of-top-million-sites-are-dead/). How crazy is that? 10% of the top million sites are dead. How crazy is that? 100,000 websites are top ranked and also abandoned. That speaks to the scale of the opportunity you have to grow.

This is the power of consistency. By setting small, achievable goals, you can build momentum and keep yourself motivated. It's a lot easier to keep going when you can see the progress you're making.

## Milestones I'm working toward

- At [Craftwork](https://craftwork.com), we're working on empowering our teammates with automations and tools that make it easier for our painters to deliver a great product. Success here is measured in time saved for our team, and the quality of the work we deliver.

- For [APIs You Won't Hate](https://apisyouwonthate.com), I'm working on growing our audience and building a community of developers who care about building great APIs. Our next goal is to hit 3000 newsletter subscribers, which should happen in the next couple months.

- For my YouTube channel [@mikebifulco](https://www.youtube.com/@mikebifulco), I'm definitely time-challenged. The truth is that I rarely have time to make videos - so my goal here is to _just keep enjoying it_ when I get the chance. Maybe that's not measurable, but it's a helpful litmus.

## What's your next milestone?

So, what's your next milestone? What's the next goal you can set for yourself that will keep you moving forward?

For this little newsletter, my goal is to connect with more people. Do me a favor and hit reply - I'd love to hear what you're working on, and what challenges you're facing. I'm here to help if I can.

---

## Recent work

Here's some of my work that's gone live the past couple weeks which I hope you find interesting:

### 🎥 Your skills will NEVER catch up with your tastes

I recently published a [video based on Powerful advice gleaned from a quote by Ira Glass](https://www.youtube.com/watch?v=Ym6HQopqe-4) - no matter what you do, your taste will always outpace your skills. I explain my strategy for using that as a benefit.

### 🌱 Seed Your Supabase Database with this simple pattern

This one's for my developer friends. I wrote up a post explaining [my strategy for seeding a Supabase database](https://mikebifulco.com/posts/seed-your-supabase-database) - it comes in handy for spinning up new developers on your projects, setting up test environments for CI, and giving yourself a repeatable starting point for building new features.

### 🎙️ Building an API for Global News

In [this episode of APIs You Won't Hate (the podcast)](https://apisyouwonthate.com/podcast/building-an-api-for-global-news/), I talk to Artem Bugara, CEO and cofounder of Newscatcher API. Artem shares his experience building a api-first product that provides global-scale insights from news sources around the world.

---

## Some links you might like

- As mentioned above, this post was largely inspired by Craig Campbell's article [10% of the Top Million Sites are Dead](https://ccampbell.io/posts/10-percent-of-top-million-sites-are-dead/). I recreated his experiment a few days ago, and found that the number is now closer to 20% now! Wild.

- I recently came across this cheeky and informative post from David Gerells on [how to save $13.27 on your vercel bill](https://dgerrells.com/blog/how-to-save-13-27-on-your-saas-bill). If you're fearful of hosting fees, this one's for you.

---
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Struggling with TypeScript: why not?]]></title>
            <link>https://mikebifulco.com/newsletter/typescript-and-learning-hard-things</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/typescript-and-learning-hard-things</guid>
            <pubDate>Tue, 09 Jul 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[One of your biggest skills as a person-on-the-internet is your ability to research and learn new things.]]></description>
            <content:encoded><![CDATA[
When we started [Craftwork](https://craftwork.com), I had never used TypeScript before. I spent years building with good old fashioned JavaScript, and really loved it.

I could build prototypes quickly, change my strategy on the fly, and make new features fly together without much thought.

But... it was also a bit of a mess. Because JavaScript has _many_ weird quirks and "features", writing robust javascript code requires lots of discipline and experience. I certainly had some of both, but I knew from the onset that Craftwork would be a big project, and I wanted to make sure that I could build it in a way that would be maintainable and scalable.

I would be building an engineering team, and I wanted to make sure that they could hit the ground running. Using TypeScript as the de facto language for Craftwork was a no-brainer.

## JavaScript is weird.

When I say "JavaScript has many weird quirks and features", this is what I mean:

```javascript
'b' + 'a' + +'a' + 'a'; // 'baNaNa'
```

If you're not a developer, you might be thinking "what the hell is that?"

Me too, friend.

<small className="text-xs">
  There's [plenty more adorable
  gotchas](https://github.com/denysdovhan/wtfjs?tab=readme-ov-file#table-of-contents),
  and they're all fun and games until you're debugging a production issue at
  3am.
</small>

Building a product is hard enough without having to worry about whether `NaN === NaN` (it doesn't) or why `[] + []` is an empty string.

<Image
  publicId="newsletters/typescript-and-learning-hard-things/duckhunt-dog"
  alt="Duck Hunt Dog laughing"
  caption="Math? Check."
/>

## Time to TypeScript

So, it was time to dive in to TypeScript. TypeScript is a superset of JavaScript that adds static types to the language. This means that you can catch _many_ bugs before they happen, and you can write more robust code.

Even still, when I started learning TypeScript, I did not have a great time.

There's a real learning curve to TypeScript - it is notoriously picky, and it can be hard to get started. I spent hours trying to figure out how to make TypeScript happy, and I spent even more hours trying to figure out why TypeScript was unhappy.

The truth is, I spent a _ton_ of time fighting the type system. I spent hours trying to figure out how to make TypeScript happy, and I spent even more hours trying to figure out why TypeScript was unhappy.

Eventually (after a few months, in my case), everything started to click. I got used to the error messages, and I was making my way through features more and more quickly.

## Learning to learn is the whole thing

I won't bore you with how-good-I-am-at-TypeScript - that's not important. What _is_ important is that I learned how to learn TypeScript. I learned how to research, how to ask questions, and how to find the answers I needed.

In my case, it was a mix of things: YouTube tutorials, blog posts, TypeScript documentation, and a network of mega-smart dev pals who I could ask for help when I was really stuck.

The best thing about being a person-on-the-internet is the ability to research and learn new things. If you can do that, you can do anything.

...which is a damn good thing, because like 3 weeks after I got comfortable with TypeScript, we started building Craftwork's core operating system with Ruby On Rails. 😅

## Keep learning

One of my biggest fears is becoming out of touch and irrelevant. I feel pretty strongly that when you _stop_ learning things, _everything_ starts to decline.

Keep learning, my friends. Keep pushing yourself to learn new things, and keep pushing yourself to learn _hard_ things.

---

## Great resources for learning TypeScript

It's Matt Pocock. He is _the_ educator for TypeScript. His [YouTube Channel @mattpocockuk](https://www.youtube.com/@mattpocockuk) is absolutely loaded with TypeScript tutorials, and he's a great teacher.

This dispatch of Tiny Improvements is inspired by (and _not_ sponsored by) Matt's work - I owe a lot of my TypeScript knowledge to him, and if you're looking to learn TypeScript, I can't recommend his channel enough.

This week, Matt Launched:

- A _huge_ new course called [TypeScript Pro Essentials](https://www.totaltypescript.com/workshops/typescript-pro-essentials)
- A massive, free, interactive book called [Total TypeScript Essentials](https://www.totaltypescript.com/books/total-typescript-essentials)

There's a [video on his channel describing the whole launch](https://www.youtube.com/watch?v=wgcfq51twe0), and it's worth a watch.

I love Matt's work - it's world-class stuff, and they the extra mile to offer Purchasing Power Parity - the price of his paid content scales to your local currency, which is a really nice touch.

---

## What are you learning?

I'd love to hear what you're learning these days, whether it's technical, non-technical, or somewhere in between. Hit reply and drop me a line via email, or shout at me on Threads [@irreverentmike](https://threads.net/@irreverentmike).
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Open Sourcing my Design System]]></title>
            <link>https://mikebifulco.com/newsletter/open-sourcing-my-design-system</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/open-sourcing-my-design-system</guid>
            <pubDate>Tue, 25 Jun 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[I'm open sourcing the Figma file I use to design and create images for my personal site.]]></description>
            <content:encoded><![CDATA[
## Open Sourcing My Design System

I'm open sourcing the Figma file I use to design and create images for my personal site.

It's right here, ready for you to explore: [mikebifulco.com Design System](https://www.figma.com/design/On4yRGLcYLORVBIhBejboA/mikebifulco.com?node-id=0-2431&t=XlKb5D0viU7DPV4T-1).

This giant file contains almost all the images I've ever published on [mikebifulco.com](https://mikebifulco.com), meticulously organized and ready for you to explore.

## What's Inside?

First off, what's in the Figma file? Here's the rundown:

1. **Brand Assets:** Logos, lockups, and even mockups for email components like ad placements and CTAs
1. **Full Articles:** Header and body images for tutorials, essays, and other long-form content
1. **Newsletters:** Every image for every one of my newsletters, including the one you're reading right now
1. **Videos:** Thumbnails for all my videos

<Image
  publicId="newsletters/open-sourcing-my-design-system/brand-assets"
  alt="The pages of the Figma file, showing brand assets, full articles, newsletters, and videos"
  caption="This file is a labor of love, organized over years of publishing."
/>

The images I use go a long way in helping me communicate my ideas, and in getting people to click through to my articles. I take the time to create a unique Open Graph Header image for every article I write, so that each one stands out on social media.

I've spent a lot of time over the years organizing, refining, and refining this system, and I'm excited to share it with you.

## Why Open Source This?

The point of open-sourcing this Figma file is simple: there's nothing magical here. I'm not doing anything you can't do. Heck, the source code for the rest of my site is publicly viewable as well on github ([mbifulco/blog](https://github.com/mbifulco/blog)), so this is a perfect pairing.

Having a system like this helps every article I write stand out a bit more. And I hope it can help you too.

### A Tool for Efficiency

One of the biggest advantages of having everything organized in Figma is that it makes publishing easy. I've created a toolkit for myself that minimizes decision fatigue.

Need a header image for a new article? There's a template for that. Newsletter? Ditto. This means I can publish content faster without getting bogged down by the details every single time.

### Stay Organized

This file keeps me organized. If I need to add, remove, or edit anything in the future, I can come back to this file and do it seamlessly. No more hunting around for that one logo or header image from two years ago.

### Opportunity for more

My hope is that by sharing this publicly, I'll be keeping myself accountable. This figma file is the foundation of what will eventually become a full-blown design system.

If you've dabbled in design systems before, you'll notice It's missing some critical pieces, like specific color selections and layout mockups, but hey, it's a work in progress.

## The Epiphany

Last week, I hit a milestone: nearly 70 published newsletters and 60 full articles. That's when it hit me-sharing this file might inspire you to create your own system. So here it is, for you to poke around and hopefully find some inspiration.

Check out the Figma file here: [mikebifulco.com Design System](https://www.figma.com/design/On4yRGLcYLORVBIhBejboA/mikebifulco.com?node-id=0-2431&t=XlKb5D0viU7DPV4T-1). Explore it, use it, heck, feel free to model your own after it.

And as always, let me know what you think - hit reply and let me know if you have any questions or feedback.

---

## Show & Tell

In a recent newsletter, I asked Tiny Improvements readers to share your projects with me. I got some truly incredible responses - thank you to everyone who shared! I'm always amazed by the talent and creativity that you all have.

### An incredible graphing calculator artist

Jake Walker's youtube is built around his incredible skill for creating beautiful, creative works with the Desmos graphing calculator. Jake is a CS student at NC State University, and I promise you that you're going to be blown away by his work.

Here's a great example to get you started: [Galaxy And Quasar Art in the Desmos Graphing Calculator](https://www.youtube.com/watch?v=5ykRxcsZjG0).

Holy moly. 🌌

---

## More of my work online

- [Surviving Other People's APIs](https://leanpub.com/surviving-other-peoples-web-apis?ref=mikebifulco.com) is a book I've been co-authoring with my APIs You Won't Hate co-founder, Phil Sturgeon. If you find yourself consuming APIs in your day-to-day work, this book is for you. Part of each sale goes to [Protect.earth](https://protect.earth), Phil's reforestation charity.

- I'm readying my next YouTube video for release - and I'd love it if you subscribed to my channel: [youtube.com/@mikebifulco](https://youtube.com/@mikebifulco).

- I'm also more and more active on Threads these days - if you're on there, I'd love to hear from you: [@irreverentmike](https://threads.net/@irreverentimke).
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Impostor Syndrome: The monster in your head]]></title>
            <link>https://mikebifulco.com/newsletter/impostor-syndrome-is-a-monster</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/impostor-syndrome-is-a-monster</guid>
            <pubDate>Tue, 18 Jun 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Impostor syndrome is a psychological pattern in which an individual doubts their skills, talents, or accomplishments and has a persistent internalized fear of being exposed as a fraud.]]></description>
            <content:encoded><![CDATA[
We've all felt it: you're working on something new. It may be a job interview, or a creative project, or a new role at work. You're excited, but there's a nagging voice in the back of your head.

It whispers in your ear -- quietly at first, then louder and louder until it's all you can hear.

Maybe you're not good enough. Maybe you're a fraud. Maybe you don't deserve this. What's worse -- maybe _everyone_ else already knows.

**Impostor syndrome** is a psychological pattern in which a person doubts their skills, talents, or accomplishments and has a persistent internalized fear of being exposed as a fraud. It's a monster that lives in your head, whispering lies and sowing doubt.

Impostor syndrome is a common experience, especially among people who do creative work, are in high-pressure roles, or are in a new environment. It can be debilitating, holding you back from taking risks or pursuing new opportunities.

We all feel imposter syndrome at some point. That nagging doubt that we're not good enough, despite evidence to the contrary. It's a universal experience that transcends industries and roles.

Imposter syndrome comes and goes, often rearing its head during times of growth or new challenges. In many ways, it's a sign that you're pushing your boundaries and stepping into new territory. It's both a curse and a signal of your ambition.

## Head down, power through

Friends, I feel it too.

It is a monster I am always beating back. My latest hit of imposter syndrome centers around a YouTube video I filmed and edited but never released. There's just _something_ keeping me from hitting `publish`.

Frustratingly, some of getting over imposter syndrome is just... getting over it. It's about recognizing that feeling this way is normal and pushing through the discomfort. It's a fun consequence of being human, and it's a sign that you're growing and challenging yourself.

## 3 simple steps to beat the monster

1. **Recognize it**: The first step to overcoming imposter syndrome is recognizing it for what it is -- a psychological pattern, not a reflection of reality. When you feel that doubt creeping in, take a step back and remind yourself that it's just your brain playing tricks on you.

2. **Talk about it**: Imposter syndrome thrives in silence. When you keep those feelings bottled up, it will grow and fester. Talk to a friend, a mentor, or a therapist about what you're feeling. You'll be surprised at how common this experience is and how much better you'll feel when you share it with someone else.

3. **Take action**: The best way to beat imposter syndrome is to take action. Do the thing that scares you. Apply for the job, start the project, hit `publish` on that video. The more you push through the discomfort, the easier it becomes.

<small>

(Don't just take my word for it: [Cleveland Clinic](https://health.clevelandclinic.org/a-psychologist-explains-how-to-deal-with-imposter-syndrome), [Psychology Today](https://www.psychologytoday.com/us/blog/neuroscience-in-everyday-life/202308/overcoming-imposter-syndrome-6-evidence-based-strategies), and [BetterUp](https://www.betterup.com/blog/what-is-imposter-syndrome-and-how-to-avoid-it) all have great, science-based advice on overcoming imposter syndrome.)

</small>

## Go do it

One of the greatest gifts this newsletter has given me is the opportunity to meet and talk to so many people who are in the early days of their journey. Tiny Improvements readers include creators, developers, and startup founders (and more) who all share a common thread: we're pushing ourselves to grow, to learn, and to create.

Overwhelmingly, I feel like so many of the people I talk to are teetering on the very edge of _doing the thing they want to do_. Consider this your sign to hit the `publish` button: you've waited long enough, and you'll only get better if you _do the thing._

Oh, and by the way - [I hit publish this morning](https://youtu.be/Q7ZMlgbrZxQ).

---

## The push you need to get started

My **favorite blog post of all time** is Chris Coyier's [There is no bar](https://chriscoyier.net/2022/06/27/there-is-no-bar/). It's true -- when you're at the wheel as a creator, there is no bar to clear. You set the bar by doing the work, and the only way to get better is to keep doing it.

You may also enjoy my previous newsletter [There's no right way to do it](https://mikebifulco.com/newsletter/no-right-way-to-do-it) - a reminder that a change in perspective can be the push you need.

I've also writren a treatise on [The trick to publishing online](https://mikebifulco.com/newsletter/today-is-your-day-to-start). You'll be surprised how simple it is.

---

<Image
  publicId="newsletters/impostor-syndrome-is-a-monster/show-us-your-songs"
  alt="Show us your songs"
/>

## Send me your projects

I want to see what you're working on! [Hit me up on Threads @irreverentmike](https://threads.net/@irreverentmike), and send me a link to your latest project, article, video, whatever it is - I'd love to give your work a signal boost by sharing it with my network.

Go on, show me what you've got!
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Statistically, nobody has used your app]]></title>
            <link>https://mikebifulco.com/newsletter/jakobs-law-design-ux</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/jakobs-law-design-ux</guid>
            <pubDate>Tue, 11 Jun 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[People spend most of their time on sites and apps other than yours. This means that users prefer your site to work the same way as all the other sites they already know.]]></description>
            <content:encoded><![CDATA[
Odds are, nobody has used the thing you're building.

Here's why that's a good thing:

According to the UX principle known as **Jakob's Law**, <Highlight> people spend most of their time on other sites and apps </Highlight>. This means that people inherently prefer your site to work _the same way_ as all the other sites they already know.

**Jakob's Law** is named after UX pioneer Jakob Nielsen, who is a (now-retired) UX researcher and principal of the Nielsen Norman Group. He's been a leading voice in the field of usability for over 25 years.

In other words, if every list, page, and form on your site is built in a way that's familiar to users, they're more likely to understand how to use it. This is why design patterns are so important.

You can think of design patterns as the common solutions to common problems. They're the tried-and-true ways of doing things that users are already familiar with.

Some examples of design patterns include:

- **The hamburger menu** - a common way to hide navigation links on mobile devices
- **Infinite scrolling** - a way to load more content as users scroll down the page
- **The card layout** - a way to organize content into bite-sized chunks

These should all sound familiar -- and you probably know what they should feel like to use. By using common design patterns, people using your site will _already know how it works_, at least on some level.

Jakob's Law is a reminder that you don't have to reinvent the wheel. Instead, borrow bits and pieces that are common to other sites and apps. This will make your work feel more familiar, and therefore more usable, to your users.

### It can still _feel_ unique

Just because you're using design patterns doesn't mean your site has to look like every other site out there. You can still add your own unique touches to make your site stand out. Focus on getting the basics right first, and then tweak the details to make your site feel unique.

<Image
  publicId="newsletters/jakobs-law-design-ux/now-playing"
  alt="Now Playing screens in Spotify, YouTube Music, and Apple Music"
  caption="Now Playing screens in Spotify, YouTube Music, and Apple Music, all using common design pattern for music apps with their own branding."
/>

### Build it like Lego bricks

Here's a worthwhile exercise: as you're building a new feature for your product, try to imagine how other popular apps might solve the same problem. What would your menus and nav look like if Apple designed them? What about Airbnb or Spotify?

If you're having trouble envisioning that, it might be worth your time to mock up your interface as a collage of other apps. Grab screenshots of the UI elements you like from other apps and piece them together to create a rough draft of your own interface. This can help you see how different design patterns might work together in your own app, and it is _way_ cheaper than building the whole thing out before you realize it doesn't work.

### Tools of the trade

My favorite tool for this is [Mobbin](https://mobbin.com/?referrer_workspace_id=1a65606c-48bd-4922-aa2d-00c03ba1d853) - it is a hand-picked collection of screenshots from well-designed mobile web apps, organized by workflow, feature, and product category. It's searchable, too, which means you can search for `login` on `IOS` and see how the best apps handle login screens.

<Image
  publicId="newsletters/jakobs-law-design-ux/mobbin"
  alt="Mobbin screenshot"
  caption="Mobbin organizes screenshots of well-designed mobile web apps by workflow, feature, and product category."
/>

It's a great place to start when you're looking for inspiration or trying to figure out how to solve a particular design problem.

Mobbin' can also export directly to Figma, which is a great way to get started on your own designs.

## You can do it!

Even if (statistically) nobody has used your app yet, you can still make it feel familiar and intuitive by using design patterns. Resist the temptation to build something completely new and different just for the sake of being unique. Instead, focus on making your site easy to use by borrowing from what already works.

It will help the people who _do_ find themselves using your software - they will feel more comfortable and confident, which will ultimately lead to a better user experience.

---

## More from UX Legend Jakob Nielsen

- [10 Usability Heuristics for User Interface Design](https://www.nngroup.com/articles/ten-usability-heuristics/)
- [Usability 101: Introduction to Usability](https://www.nngroup.com/articles/usability-101-introduction-to-usability/)
- [Usability Testing](https://www.nngroup.com/articles/usability-testing-101/)

## Tools for finding design patterns

- [Mobbin](https://mobbin.com/?referrer_workspace_id=1a65606c-48bd-4922-aa2d-00c03ba1d853) is a hand-picked collection of the latest mobile and web design patterns from apps that reflect the best in design.

- [The Webby Awards](https://www.webbyawards.com/winners/) are a annual awards given to websites and apps that feature best-in-class design and user experience. It is an absolute treasure trove of design inspiration.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[The Aesthetic-Usability Effect]]></title>
            <link>https://mikebifulco.com/newsletter/aesthetic-usability-effect</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/aesthetic-usability-effect</guid>
            <pubDate>Tue, 04 Jun 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[When building something new, what's more important: that it works, or that it looks good? The Aesthetic-Usability Effect says that users perceive more aesthetically pleasing designs as easier to use than less aesthetically pleasing designs.]]></description>
            <content:encoded><![CDATA[
When building something new, what's more important: that it works, or that it looks good?

That's the hypothetical that was asked recently by a startup cofounder and CTO u/FormalFuel6425 [on the Y Combinator subreddit](https://www.reddit.com/r/ycombinator/comments/1d79vwj/does_visual_appearance_matter_more_than/). It's a great question, and one that has been asked many times before.

My take? If you want to build a successful product, you need to do both reasonably well, and design needs to be a priority from the start.

## The Aesthetic-Usability Effect

> The <Highlight> Aesthetic-Usability Effect </Highlight> is a psychological phenomenon where users perceive more aesthetically pleasing designs as easier to use than less aesthetically pleasing designs.
> [More on Wikipedia](https://en.wikipedia.org/wiki/Aesthetic-usability_effect).

This means that if your app isn't designed well, users will perceive it as _harder to use_ than a more visually appealing app, even if the functionality is identical.

Read that again - and let it sink in a bit: the _exact same app_ can be perceived as harder to use (and thus _less valuable_) if it's ugly.

As a bit of a contrived example, which of these two ChatGPTs would you rather use?

<Image
  publicId="newsletters/aesthetic-usability-effect/chatgpt-1"
  alt="A screenshot of ChatGPT with 3 design changes made: typeface was changed to Comic Sans, all background colors were changed to solid black, and the layout was changed to a 50/50 split."
/>

<Image
  publicId="newsletters/aesthetic-usability-effect/chatgpt-2"
  alt="A screenshot of ChatGPT with no design changes made."
/>

These are screenshots of the _same_ ChatGPT session, with just three design changes between the two.

Which one do you trust more? Which one would you rather use?

## Post.news vs Threads

The presentation you choose for your product can have a huge impact on how users feel about it initially. If you're building a new product, it's worth investing in design work early on to make sure your app is as visually appealing as possible.

It's rarely the case that we can point to design as the _only_ reason something isn't successful, but it can certainly be a contributing factor.

A recent example that stands out in my mind: over the past couple years, there has been hot competition for a social network that can compete with Twitter. Two front-runners which stood out early on were Threads and Post.news. Here's a quick side-by-side:

<Image
  publicId="newsletters/aesthetic-usability-effect/threads-vs-post-news"
  alt="side-by-side comparison of post.news and Threads"
/>

Would it surprise you to hear that [Post.news has since shut down](https://www.theverge.com/2024/4/19/24135011/twitter-alternative-post-news-shutdown)?

This isn't entirely a fair comparison, of course - Threads has a _huge_ network effect advantage by being tied to Instagram's user graph. But it's hard to ignore the fact that Threads has a much more polished aesthetic than Post.news.

I bounced off of Post almost immediately; the newspaper-inspired, serif-forward design felt dated and incomplete.

## The other way around: design work buys you patience with early users

In practice, what this means is that if you're building a new product, you're setting yourself up for failure if the goal is _just_ to make it work. You need to make it _look_ good, too.

A product that looks and feels great (or at least _good_) will attract more people, will keep them around longer, and will make them more likely to forgive you when something goes wrong.

I like to think of it this way: putting time and effort into designing your app's UX shows that you _care_ about the people using your app. It's a gesture that says "Your time and attention is valuable, and I want to make sure you feel at home here."

### Frameworks are your friend

You don't need to reinvent the wheel. 99% of the time, you should be borrowing interaction patterns from website and apps that you're already familiar with. The work required to create is largely _already done for you,_ and you should be taking advantage of the work that others have done to make your app feel familiar and comfortable.

To that end, there's loads of great UI frameworks that will save you time, and can help you get started with something that isn't complete garbage out of the box. If you're looking for a web framework to use, check out [Tailwind UI](https://tailwindui.com), [shadcn/ui](https://ui.shadcn.com/), and [Material UI](https://mui.com/material-ui/) are all great options.

If you're lucky enough to be able to hire a full-time designer one day, starting with these frameworks should make it easier to transition to a custom-branded design language later on.

## Design or functionality? Both.

Going back to the original question: what's more important, that it works, or that it looks good? The answer is **both.**

Your _thing_ needs to _work_ on some fundamental level, and you should take care to make sure that it looks good and feels familiar to your users.

The frustrating thing about being thoughtful about design is that if you do a good job of it, the people using your software may not even notice. But whether consciously or subconsciously, they'll notice if you _don't_ do some design work up front, and that's a problem.

---

## More articles on design

A few years ago, I gave a talk on design with my pals Andrew Miller and Jeremy Osborn, called [Your App Is Ugly](https://www.slideshare.net/slideshow/your-app-is-ugly/61980421). It is the reason why I spend so much time trying to get developers to invest in design education.

If you liked this newsletter, you may also appreciate these past dispatches, which tackle design from a few other angles:

- [Become Unreasonable: Designing for Hospitality](https://mikebifulco.com/newsletter/unreasonable-hospitality-and-design)
- [UX For Devs: Understanding Gestalt](https://mikebifulco.com/newsletter/gestalt-design-principles-for-developers)
- [The finicky nature of color in product design](https://mikebifulco.com/newsletter/color-context-and-product-design)

## Everyone is a designer

I'm a big believer that everyone is a designer, and that everyone can learn to be a better designer. I keep a list of great design books I've read over on hardcover that you're welcome to peruse - check out [The Designer's Reading List](https://hardcover.app/@irreverentmike/lists/the-designers-reading-list) if you're looking for some more juicy reads from people _way_ smarter than me.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Three things school taught me (and Three things it didn't)]]></title>
            <link>https://mikebifulco.com/newsletter/what-i-learned-studying-cs</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/what-i-learned-studying-cs</guid>
            <pubDate>Mon, 27 May 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Too often I see chatter online about how studying computer science in school is the only way to have a successful career at a startup or a big company. That definitely isn't the case.]]></description>
            <content:encoded><![CDATA[
I studied computer science as an undergrad (a while ago). At the time, it felt like the only choice on an obvious path to a career as a programmer, even though I graduated in the middle of the 2008 recession.

In 2024, things are different - the job market is wildly competitive, and the path to a tech career is not as clear-cut as it once was.

I see countless posts on the [/r/computerscience](https://reddit.com/r/computerscience) subreddit along the lines of _I sent 74 applications and got no interviews - what am I doing wrong?_

On the other side of the spectrum, while hiring for my own team, I've seen a lot of candidates with non-traditional backgrounds who are just as capable as those with a CS degree.

I’ve also seen a lot of candidates with CS degrees who sound like they would be very challenging to work with.

So, with a handful of years of experience under my belt, I wanted to share some thoughts on what I learned from studying computer science, and what I didn't.

### Skill 0: Tenacity

**The most important thing** I got out of studying CS in school is tenacity. Learning hard computer science is really about writing code the wrong way many times and figuring out how to do it right. The process of doing it wrong and then getting it right is what truly fosters learning.

I spent many late nights in front of my computer pulling my hair out (RIP) trying to figure out why my code wasn't working. Little did I realize how formative those experiences would be for my career - even today, many of the more stubborn problems I face at work are solved with a solid dose of patience and tenacity.

Here's the good news: you don't need to study computer science to learn this. You can learn it by doing anything that's hard and requires you to fail a lot before you succeed.

### Learn how to Learn

I learned how to break down abstract problems into parts and apply things I picked up along the way. This involves research, memorization, and a lot of trial and error.

Another lucky break for you, friend -- you _probably_ have some of this skillset in your pocket already. Ever looked up how to fix a leaky faucet? Or how to make a soufflé? Or how to change a tire? It's the same process, just with different tools.

### Grits is just corn (you've seen it all before)

Many of my classes focused on fundamental concepts that comprise the building blocks of computer science. At the time it felt a little silly to spend so much time on things like sorting algorithms and basic data structures. But, as I've progressed in my career, I've found that these fundamental concepts are the most important.

_So many_ of the "hard" problems I've faced at work can be brokend own into simpler parts with solid understanding of these basic concepts. By the same token, there are also some problems that just [can't be solved](https://en.wikipedia.org/wiki/P_versus_NP_problem) with the tools we have today. Understanding the shape of those sorts of problems is helpful, too.

All this to say: being able to see larger problems as a collection of smaller, more manageable problems is a skill that will serve you well in any career.

---

## Here's what they don't teach in Computer Science programs

While I don't regret my formal Computer Science degree, there are _mountains_ of critical lessons that they didn't teach in the courses I took.

### You don't need anyone's permission

You don't need anyone's permission to learn this stuff. Most of what I know and have learned in my career is freely available online. With dedication, you can learn through online courses, YouTube, tutorials, and books -- if you're willing (and able) to put in the time.

Formalized education is great, but it's not the only way to learn. I've met many successful developers who never went to college, and others who have degrees in unrelated fields.

### There is no archetype

Carnegie Mellon's computer science program is great, but it's not the only way to learn. I've met successful developers who never went to college, and others who have degrees in unrelated fields.

I have worked with some incredible UX designers, developers, PMs, etc. who started their careers in economics, geography, library science, the military, and even as auto mechanics. These people bring a unique perspective to the table that someone who has only studied computer science might not have -- and that's a good thing.

### It's difficult no matter what

Breaking into a tech career is hard, regardless of your path. It's not just about having a degree or self-taught coding skills; landing your first job depends on your ability to make connections and network. Getting in front of the right people at the right time can make all the difference. A prestigious degree or an impressive self-taught portfolio alone isn't enough, especially when competing with a mess of other candidates.

---

## So what, then?

This newsletter comes from my frustration with gatekeeping: there's not one right way to get into a tech career. Do what works for you, and don't let anyone tell you that you're doing it wrong.

I enrolled in a whole-ass masters degree program because I was told early in my career that it was "the only way" to get into UX work at Microsoft. I'll be damned if that's the case today.

No matter what path you go down, you're going to work hard; success will always feel like it's just behind the next obstacle. Use that as fuel to keep you learning and trying new things.

Most importantly, get to know the people around you -- help them out, be a positive force, and give without the expectation of receiving. An investment in your people is one that will pay for itself many times in the span of your life.

---

## More career advice from me

If you or someone you know is considering a career shift, you may also find these articles useful:

- [Why learning new frameworks make better developers](https://mikebifulco.com/newsletter/why-new-frameworks-make-better-developers) -- and a meta-lesson about learning
- [Your Resume sucks](https://mikebifulco.com/newsletter/your-resume-sucks), but that's okay - a little positive reframing will help you stand out in your next job search.
- Here's why [Old, embarassing projects in your Portfolio](https://mikebifulco.com/newsletter/portfolio-as-timeline) are super valuable as you learn.

## Louder, for the people in the back

- 🎙️ My recent interview with [James Perkins from Unkey](https://apisyouwonthate.com/podcast/unkey-globally-distributed-api-key-generation-with-cofounder-james-perkins/) for the APIs You Won't Hate podcast is one of the more memorable chats I've had in the past year. James' path from a contributor to a developer advocate to a successful founder is a great reminder that our careers rarely follow a predicable path.

I hope you enjoy this one!
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Shrimps is Bugs: Red Lobster ate itself to death]]></title>
            <link>https://mikebifulco.com/newsletter/shrimps-is-bugs</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/shrimps-is-bugs</guid>
            <pubDate>Tue, 21 May 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Red Lobster's bankruptcy and the importance of understanding your product's pricing and business model, especially for founders and indiehackers building Saas products.]]></description>
            <content:encoded><![CDATA[
Red lobster gave away so many free shrimp that they had to file for bankruptcy.

Believe it or not, this isn't a joke.

Red Lobster [literally went bankrupt](https://www.npr.org/2024/05/20/1252426585/red-lobster-bankruptcy) after making their $20 all-you-can-eat shrimp promotion a permanent menu item. Their customers ate them into failure - creating millions of dollars in losses... in shrimp.

So, friends:

<Highlight>
  if you're working on your business plan, try not to include an all-you-can-eat
  shrimp promotion in the mix.
</Highlight>

That's it. That's the secret to business.

## The numbers matter as much as the product

Okay, look - here's the thing: if you want to have a business that pays the bills, understanding the financial model behind your products is crucial.

I'd bet a whole stack of clams that there was at least one accountant at Red Lobster who was red in the face trying to explain to their leadership that a "giving away free shrimps" business model was going to be a disaster.

Promotions and giveaways can be powerful tools to attract customers, but they need to be carefully planned and executed with a clear understanding of their impact on your business.

There's also a point to be made about the value of giving away _some_ services to early adopters to create hype and brand awareness. Promotions can certainly build buzz and loyalty, but as your product grows, you need to start getting paid to ensure sustainability and growth.

Generosity has its place, but it's essential to balance it with a sound financial strategy.

## Start with the basics: P&L

Many developers (myself included) don't have a background in finance - and that's okay! But it's crucial to understand the basics of your business's financials. Here are a few key terms to get you started:

- **Revenue**: The money you make from selling your product or service.
- **Cost of Goods Sold (COGS)**: The direct costs associated with producing your product or service.
- **Gross Profit**: Revenue minus COGS.
- **Operating Expenses**: The costs of running your business, like salaries, rent, and utilities.
- **Net Profit**: Gross profit minus operating expenses.

In developer terms, getting this right is about inputs and outputs: you're trying to build a machine that takes in more money than it costs to run.

Understanding these numbers will help you make informed decisions about your business and avoid making shellfish decisions that could sink your ship. (I'll stop.)

## Document your expenses

When you're building a product, it's easy to get caught up in the excitement of development and forget about the costs. But documenting your expenses is crucial to understanding your financial health. Keep track of everything you spend, from hosting fees to marketing costs, and make sure you're accounting for them in your financial model.

You don't need to use a fancy tool to do this: a spreadsheet will work just fine. The key is to be diligent about tracking your expenses and updating your financial model regularly.

## Understand your costs

Once you've documented your expenses, it's time to understand your costs. Calculate how much it costs to acquire a customer, including marketing and sales expenses. Then, match these against the price your customers pay. Determine how many months a customer needs to stay for you to break even and eventually make a profit.

Many developers who get into building products don't fully understand this, but it's crucial to go through this rigor. Even with a fast-growing product, overlooking these details can easily bury you in a failing business model.

If the math doesn't add up, it's time to reevaluate some combination of your pricing strategy, marketing efforts, and product features that drive costs up.

Your goal is to build a product that can pay for itself -- and much more, hopefully.

(also, shrimps is bugs. 🦐🦐🦐)

---

## Ya gotta get paid

If you're building a product, you need to get paid for it. It's as simple as that.

- [F\*ck you, pay me](https://www.youtube.com/watch?v=jVkLVRt6c1U) is a classic talk from Mike Monteiro about the importance of getting paid for your work. It's a must-watch for anyone who's ever struggled to get clients to pay up.
- If you're an Indiehacker building a SaaS, this post on Indiehackers has lots of great wisdom: [How to price your product](https://www.indiehackers.com/post/how-to-price-your-product-indie-hackers-shouldnt-follow-the-usual-advice-0b994f58f6)
- If you're building a developer product, you may find my recent [interview with the founder of Unkey](https://apisyouwonthate.com/podcast/unkey-globally-distributed-api-key-generation-with-cofounder-james-perkins/) interesting. We talked a bit about building API products with usage-based pricing, and how to make sure you're getting paid for the value you're providing.

---

## I want to hear from you!

If you've got books, videos, podcasts, or articles to recommend for engineers who want to build a better business, send them my way. I'm all ears!
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[The Endowment Effect: why useful trials make for sticky products]]></title>
            <link>https://mikebifulco.com/newsletter/endowment-effect-and-designing-free-trials</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/endowment-effect-and-designing-free-trials</guid>
            <pubDate>Wed, 15 May 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[The endowment effect is a psychological phenomenon where people value things more highly simply because they own them. How can you use this to make your product stickier?]]></description>
            <content:encoded><![CDATA[
The endowment effect is a psychological phenomenon where people value things more highly simply because they own them. It's a cognitive bias that can be used to make your product stickier.

In a [famous experiment](https://en.wikipedia.org/wiki/Endowment_effect), participants were given a coffee mug and asked to set a price at which they would be willing to sell it.

The average price they gave their shiny new mug was about $7.

Another group of participants were asked to set a price at which they would be willing to buy the mug.

In this case, the average price was $3.

<Highlight>
  ...In other words, for the exact same object, participants assigned a higher
  value to the thing they owned versus the thing they were thinking about
  buying.
</Highlight>

The misalignment between these two prices is the endowment effect in action. People value things more highly when they own them.

## Free trials and the Endowment Effect

One way is to offer a free trial of your product. By giving people the opportunity to use your product before they buy it, you create a sense of ownership. They become attached to the product and are more likely to continue using it after the trial period ends.

Companies like **Spotify** and **Netflix** take advantage of the endowment effect by getting users hooked quickly. By offering free trials, they give new customers a chance to feel what it's like to _have_ access to their vast libraries of media.

This creates a sense of ownership, making it hard to part ways with the service when the trial period runs out. The value they see during the trial makes it easier to pay for the service, and keeps customers coming back for more.

Similarly, **Slack** and **Notion** use the endowment effect by empowering free users. By offering thoughtful free tiers, they make their products sticky and useful. Once they're onboard, it is really hard for customers to give up what they've gotten used to.

By the time their users get to the end of their trial period, they are so attached to the product that they can't imagine going back to the way things were before.

## Designing a great trial experience

To make the most of the endowment effect, it's important to design a great trial experience. Here are a few tips to get you started:

1. **Make it easy to sign up**: The easier it is for people to sign up for your trial, the more likely they are to do it. Remove any barriers to entry and make the process as simple as possible. In many cases, this means not requiring a credit card up front, as counterintuitive as that may seem.

2. **Show value early**: Give people a taste of what your product can do right away. Show them the benefits of using your product and how it can help them solve their problems. This may also mean giving unfettered access to your product during the trial period, and restricting access to premium features only after the trial ends.

3. **Measure success**: Track how people are using your product during the trial period. Look for patterns in usage and identify areas where people are getting stuck. Use this information to improve your product and make it stickier.

4. **Offer support**: Make sure people have the help they need to get started with your product. Offer tutorials, guides, and customer support to help them make the most of their trial. Use information collected through analytics to offer personalized tips and support to users.

You've spent countless hours building an great product - make sure people get a chance to see how great it is. Offering a free trial is a great way to do that, and the endowment effect can help you make your product stickier in the long run.

---

## Tools for making a valuable free trial

Setting up a free trial for your product doesn't have to be complicated. There are plenty of tools available to help you get started. Here are a few to consider:

1. If you use **[Stripe for subscriptions](https://docs.stripe.com/billing/subscriptions/trials)**, you can configure a free trial period for your customers. This allows them to try your product before they buy it, without having to enter their payment information up front.

2. It's nearly impossible to get your pricing strategy right on the first try. That's the thesis that my friends over at **[Stigg](https://www.stigg.io/)** have based their products on. They make it easy to test different pricing strategies and see which one works best for your business.

3. If you're building a developer product with usage-based billing, you should check out **[Unkey.dev](https://www.unkey.com/)** - they make it dead simple to add analtics and usage-based billing around API keys to your product.

---

## Some products-in-progress worth checking out

- [Pastmaps](https://pastmaps.com/plus?src=tinyimprovements) is a vast library of historical maps that you can overlay on modern maps. Seeing how your neighborhood has changed over time can be really eye-opening. Pastmaps has a 7-day free trial for its premium features, and is being built by Craig Campbell, who goes by [@that.map.guy.craig](https://www.threads.net/@that.map.guy.craig) on Threads.

- [PodCharm](https://podcharm.com/) is a product designed to help podcasters do a better job of growing their audiences. PodCharm's free tier is _super_ generous, and sends a strong signal: PodCharm will be successful only if its customers' shows are successful. That's a win-win alignment of incentives. Shout out to my dude [Tony Mastrorio](https://www.threads.net/@tonydotcoms) for building this. Give it a shot if you're a podcaster.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Beyond the walled garden: what Spotify and Substack get wrong]]></title>
            <link>https://mikebifulco.com/newsletter/beyond-the-walled-garden</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/beyond-the-walled-garden</guid>
            <pubDate>Tue, 30 Apr 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[It's natural for big companies to make mistakes - but when they do, it's a great opportunity for smaller companies to build something better.]]></description>
            <content:encoded><![CDATA[
My front door is a 10 minute walk from a small, serene park in a city-edge neighborhood.

In the first hour of sunlight every day, the park feels like a sanctuary: birds sing, neighbors take their dogs out for a morning walk, the meandering creek bubbling with life.

It's a slice of heaven less than a mile from the busiest parts of Charlotte, a small-but-growing city that's now nearly a million people strong.

<Image
  publicId="newsletters/beyond-the-walled-garden/park"
  alt="A photo of a sunrise over a grassy hill in a park"
/>

On the other side of the park, what was once a quaint bungalow neighborhood on the city's outskirts has had one house after another bulldozed. It's now lined with freshly built mcmansions, built on speculation for suburbanites with deep pockets.

In the past couple months, one build in particular has caught my attention - a huge, swollen brick home built right to the edges of its boundaries. It's located on edge of the park, with its back yard oriented so that the sun rises perfectly through the trees, highlighting the simple wooden footbridge that crosses the creek, built years ago to give homeowners access to the park.

The new home has risen from its foundation quickly, and while I don't typically _love_ the design choices made by home builders in my area, this one really sticks in my craw. Someone made the decision to build an 8 foot fence around the perimeter of the yard - completely obscuring access to the park.

I know _someone else's home_ shouldn't make me this mad - this home will probably sell for close to $2M (if not more). But, to me, the builder has _completely_ lost the plot.

Why would someone buy such a beautiful plot of land and spend their money hiding from it?

## Spotify and Substack walled themselves in

This, I feel, is a great metaphor for strategic missteps by companies like Spotify and Substack. Two different products in different spaces, built to take advantage of a huge opportunity – have built very strange walled gardens around their products that sounded like a good idea at first.

Spotify established a huge user base as the de facto music subscription for many people. In the never ending search of growth, they wanted to make their platform the place where everyone goes to listen to podcasts as well.

Rather than build the best podcast player in the world, they bought up podcasts left and right, making them exclusive to Spotify.

For many people, this meant their only choice to listen to their favorite shows was to switch to Spotify.

Does that sound like a great way to build a sticky product? I'll let you decide, but it's safe to say that their [$1B Bet on podcasts isn't going well](https://www.wsj.com/podcasts/the-journal/spotify-1-billion-bet-isnt-going-well/75665f50-cabb-48c9-8f5c-d05e94d8f7f8).

In the creator world, newsletter authoring platform Substack was heralded as the author's best friend - they made it easy to write a newsletter and build an audience. It was among the first newsletter tools to promise network-effect growth by letting authors recommend one another's newsletters as a first-party platform feature. They added features for podcasters, as well as [some twitter-like features](https://techcrunch.com/2023/04/05/substacks-new-short-form-notes-feed-looks-a-lot-like-twitter/) as a response to Twitter's leadership collapse.

Then... they made some gutless decisions around content moderation.

Substack continues to [refuse to shut down alt-right, and hyper-conservative newsletters](https://mashable.com/article/why-are-people-leaving-substack-content-moderation-controversy) with _seriously_ weak reasoning for their [anti-censorship stance](https://www.theguardian.com/media/2024/jan/03/substack-user-revolt-anti-censorship-stance-neo-nazis):

> "...we don't think that censorship (including through demonetizing publications) makes the problem go away - in fact, it makes it worse."

Ah, _cool_.

I'm sure you can understand why authors are leaving the platform in droves - after all, one of Substack's value propositions is that they'll recommend _other authors' work_ to help newsletters grow.

Woof.

Meanwhile, competing product teams see opportunity knocking: Ghost announced that they're [adding fediverse features later this year](https://www.msn.com/en-us/news/technology/look-out-substack-ghost-will-join-the-fediverse-this-year/ar-AA1nvI4S).

## Sneak in while the walls are being built

There's a lot to be learned from the decisions companies make about their products once they get really large - these sorts of missteps can opens the door for thoughtfully built and well-timed products. As a builder, do your best to keep an ear to the ground for fissures opening up in the giants' walled gardens.

If you can find a way to build a product that solves a problem for users and takes advantage of a misstep by a competitor, you're in a great spot to grow quickly.

I'm not saying you should wait for a competitor to make a mistake - but if you're paying attention, of course - build your thing with conviction because it's a good idea, but also be ready to move quickly when opportunities arise.

You can be the one to build the footbridge over the creek, and let the sun shine through.

---

## Champagne for my real friends

I thought I'd share some work from people in my network this week. You're going to love these:

- Josh Finnie wrote a great article about [Adding JSON-LD to his Astro site](https://www.joshfinnie.com/blog/adding-json-ld-to-my-blog/) - it's a great read if you're looking to improve your site's SEO.

- CJ Avilla published an article about [Caching ViewComponents in Ruby on Rails](https://www.cjav.dev/articles/caching-viewcomponents), which we've been implementing at Craftwork recently.

- Over on Primary Focus, Ms. Natalie produced a great interview recently about [what parents need to know about ADHD and kids](https://www.youtube.com/watch?v=UsqG7m5NQ1E&t=7s). Her guest is super knowledgable and it's a great watch.

---

## Try these out though

Here's a few tools that I think are worth checking out:

### A podcast player for note takers

[Snipd](https://www.snipd.com/) is a podcast app that automatically transcribes podcasts and lets you take notes from them as "snips". It's a great idea - you may recall a few months back [I built a podcast summarizer with AI](https://mikebifulco.com/newsletter/build-something-useful-with-ai). I think the gang at Snipd are on to something really special here.

### Make storyboards that don't suck

[Storytribe](https://storytribeapp.com/) an app for creating storyboards using vector images. They have created an _immense_ library of customizable vectors that you can assemble to make some really compelling storyboards for your next product, feature, or presentation.

### Ghost is the CMS for creators

I mentioned [Ghost](https://ghost.org/?via=mike21) above (that's my referral link, btw) - it's a CMS that makes it easy for creators to build a website, write a blog, and publish a newsletter. They're adding some really interesting features this year, and I think they're a great alternative to Substack for authors who want to own their content and their audience. I actually help run 2 different sites with Ghost: [APIs You Won't Hate](https://apisyouwonthate.com) and [Primary Focus](https://primaryfocus.tv) both use it.

---
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Simple Habits for a Happier Team]]></title>
            <link>https://mikebifulco.com/newsletter/simple-habits-for-a-happier-team</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/simple-habits-for-a-happier-team</guid>
            <pubDate>Tue, 23 Apr 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Small changes and management techniques can transform your team's dynamics and boost morale. Explore practices like expressing gratitude, weekly reflections, and eliminating negative behaviors to foster a positive, growing team.]]></description>
            <content:encoded><![CDATA[
No team is perfect.

Working on a team that is in a bad place can be draining, demoralizing, and even toxic.

A few times in my career, I've been part of teams that were struggling to find their footing - and once or twice, I've seen it turn around. There's no cure-all for a bad work culture, but in my experience, the catalyst for change is often _remarkably_ small.

Something I didn't realize until I had been working for _years_ is that **every person on a team contributes to its culture**. _You_ have the power to shape the environment you work in, and the people you work with.

You probably have a sense of what the _perfect_ team would look like for you. The right balance of autonomy, intellectual challenge, and camaraderie is different for everyone, and it's important to recognize that your ideal team might not be the same as someone else's.

I believe that building a great team is not far off from the golden rule: be the teammate you wish you had, and others will follow suit.

## Embrace the Positives

In crafting a thriving team culture, it's invaluable to draw from the positive aspects of past experiences. Think about the best team you've ever worked with - what made it so great? Borrow bits and pieces from that experience, and remix them to fit your current team.

Here's a couple examples that have worked well for me:

### Gratitude

Cultivating a habit of expressing gratitude can profoundly lift team morale.

Praise resonates differently with each of us - some prefer public acknowledgment, while others appreciate a private thank you. It can take some time to figure out what works best for the people you work with, but no matter what, expressing gratitude is always a good idea.

Being openly thankful for your teammates' efforts fosters a positive environment and encourages everyone to contribute enthusiastically. Take the time to show your teammates the things you genuinely appreciate about their work and presence on the team; that extra bit of love feels great, and selfishly, it feels good to give it too.

This can be particularly tricky to do when you're feeling overwhelmed or stressed, but it's in those moments that a little bit of gratitude can go a long way.

### Weekly reflections build empathy

At Craftwork, we've adopted the practice of a weekly _5:15s_ reflection, a piece of work culture cribbed from my time at Stripe. Each week, every team member journals about what they accomplished that week, they challenges they faced, and goals for the coming week.

This reflection is time-boxed: they take fifteen minutes to write, and they should take no longer than five minutes to read.
The result helps strengthen our understanding of one another's experiences, ensuring that no one's efforts or struggles go unnoticed. They also serve as a handy reminder of personal accomplishments and growth during performance reviews.

It forces self-reflection, and gives us each the opportunity to see behind the curtain a little bit; with 5:15s, we often get to hear more more aspirational and candid thoughts than we would in a typical work chat. It helps connect us better as complex, living & breathing humans; rather than semi-distant colleagues smashing code into a computer week after week.

---

## Fuck the Negatives

Adopting additive team behaviors is just as important as elimination of negative ones.

When was the last time you rolled your eyes or heaved a sigh at work? This is _probably_ a sign of something that's ripe for improvement.

Whether it was a lack of transparency, ineffective communication, or even a culture of overwork, recognizing these pitfalls is the first step in eliminating them. For example, if weekly meetings have always felt unproductive, consider replacing them with more efficient communication methods like brief daily stand-ups or targeted updates through team communication tools.

Encourage your team to be vocal about what isn't working, and be proactive in making changes that foster a more positive and productive environment. This not only improves current team dynamics but also prevents the repetition of past mistakes.

It's a great idea idea to do some introspection, too.

I've worked hard to jettison habits of my own that make me less fun to work with. A wide spectrum of behaviors from procrastination to communicating poorly when I'm stressed out, to recognizing when I just need more sleep. I'm far from perfect, but chiseling away at the these things has (hopefully) made me a more effective teammate over the years.

## Be the Change

Here's the thing: every job will involve doing things that aren't strictly fun. In a sense, that's _probably_ why your job is a _job._ But that doesn't mean you can't enjoy and improve the people you work with, or the environment you work in.

To truly transform your team, **start by being the type of teammate you would want to have**. Embrace the give-and-take of support, ensuring you're as reliable and approachable as you expect others to be.

The most important team I've ever been a part of is my marriage, and the best marriage advice I ever received was pretty simple:

_Always over-contribute. If both partners are always trying to give more than they take, you'll both be happy._

I believe this holds for nearly all relationships - including those with your coworkers. Put yourself out there, be a catalyst for change, and grow with your teammates as you build the team you want to be on.

---

## Tiny Improvements from around the internet

### Oddly satisfying spacing

📐 A design agency called Chainlift has been putting out [explainer videos on design theory](https://www.youtube.com/watch?v=9ElrcTtAxzA) that are juicy and jam-packed with nuggets that will make your apps look and feel better. I've done plenty of shouting about why devs and founders should care about design - this series is a great way to learn how some seriously _simple_ rules can make a massive difference in your work.

### Beautiful tutorials for music producers

📼 [synthet](https://www.youtube.com/watch?v=8t3Ep4e_dyE) is a fast-growing YouTube channel that has been creating ~1min videos that teach power-user features for producers of electronic music using a tool called FL Studio. I'm not a music producer, and I'm _really_ not a fan of EDM, but these are some of the most engaging, thoughtful, and memorable tutorials I've ever seen. Why? No spoilers here - click through and spend a few minutes taking it in.

### Tunes is fantastic at the arts

🔢 Here's another music-themed rec for you: Charles Cornell did an incredible breakdown of the surprisingly complex musical structure of a song used on Sesame Street to teach children how to count. Titled [This Song Teaches Counting But Is INSANELY Hard To Count](https://www.youtube.com/watch?v=TMtGImlEmu0), it's a great example of how easy it can be to miss the beautiful details that went into something many of us have seen billions of times.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Designing for hospitality]]></title>
            <link>https://mikebifulco.com/newsletter/unreasonable-hospitality-and-design</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/unreasonable-hospitality-and-design</guid>
            <pubDate>Tue, 09 Apr 2024 00:00:00 GMT</pubDate>
            <description><![CDATA["Unreasonable Hospitality" by Will Guidara outlines how to making customers feel exceptionally special. Let's bring these hospitality principles to tech, by creating memorable experiences, and using hospitality to elevate customer satisfaction in product design, engaging with the people using our products.
]]></description>
            <content:encoded><![CDATA[
As the winter has turned into spring this year, I've been doing a whole lot of walking. Most days, I do a steady 4-5 mile lap around my neighborhood. It's a great way to get some fresh air, get some exercise, and get some mental space to balance out the hours I spend sitting at my desk.

It's _also_ a fantastic time to listen to some podcasts and audiobooks, and I gotta tell you: one book in particular has taken hold of me. I can't stop thinking about it.

It's called [_Unreasonable Hospitality_](https://amzn.to/3WaVvXl) by Will Guidara.

## Unreasonable Hospitality

Guidara is a restauranteur and hospitality expert. He's known for his work at Eleven Madison Park, a three-Michelin-starred restaurant in New York City. Guidara also cofounded as Make It Nice, a hospitality group that includes several other restaurants and bars.

In the book, Guidara talks about the principles of hospitality that he's learned over the course of his career in the restaurant industry. He talks about the importance of listening to customers, and anticipating their needs.

<a href="https://amzn.to/3WaVvXl" target="_blank" rel="noopener noreferrer">
  <Image
    publicId="newsletters/unreasonable-hospitality-and-design/unreasonable-hospitality"
    alt="Unreasonable Hospitality book cover"
    caption="Unreasonable Hospitality by Will Guidara"
  />
</a>

Guidara's teams are the **best in the world** at providing a memorable experience: they look for small details about their guests that they can use to make them feel special. They go above and beyond to make sure that every guest has a great experience.

They do this while trimming away the unnecessary, the superfluous, and the extraneous. They're not just about making people feel special -- they're about making people feel _unreasonably_ special.

One thing I love about the author is that despite working at some of the top restaurants in the world, he describes himself as _more cheeseburger than caviar_. That hits home with me.

## Fine dining, smashburgers, and... TypeScript?

Although _Unreasonable Hospitality_ is largely about restaurants, it's not just for people who work in food service. It's for anyone who wants to create a welcoming, inclusive, and memorable experience for their customers.

In other words, it's for _everyone_ who works in product design. If you're reading this, that almost certainly includes you.

## Hospitality and design principles

Guidara's book is full of stories and lessons from his time in the restaurant industry. He talks about the importance of creating a welcoming environment, of making people feel special, and of going above and beyond to make sure that every guest has a great experience.

As a designer, I found myself nodding along with a lot of what Guidara had to say. The principles of hospitality that he talks about -- things like making people feel welcome, anticipating their needs, and creating a sense of community -- are common to some of my absolute favorite end user experiences.

The most memorable products I've ever used have gone out of their way to make me feel like I was part of something special. Some examples:

### How We Feel

The gorgeously designed [How We Feel](https://howwefeel.org/) app is a mood tracking & journaling app that is pleasant to use, visually appealing, and just-the-right-amount of instructive.

<Image
  publicId="newsletters/unreasonable-hospitality-and-design/how-we-feel"
  alt="How We Feel app"
  caption="How We Feel distills a complex set of emotions into a satisfying, 2-dimensional space."
/>

The first time I fired it up to log my mood, I was immediately struck by how _nice_ it felt to use. The app lays out a huge number of selections for _current mood_ on a 2-dimensional axis: left to right is _pleasant_ and _unpleasant_, and top to bottom is _high energy_ and _low energy_. It's a simple, intuitive way to distill a complex set of emotions into a satisfying, 2-dimensional space.

The real magic comes after the first few times you log your mood. The app gently and progressively presents short, thoughtful videos to help you understand your mood better. It's like having a therapist in your pocket, and it's _so_ well done. Hooked!

### Tuple

My team uses [Tuple](https://tuple.app/) for remote pair programming. The app is fast, reliable, and beautifully designed. You can _feel_ that is has been made for devs, and helps my team work more closely together even though we're spread out across the country.

So what stood out to me about Tuple? At the end of most calls, you're presented with a UI asking you to rate the call on a scale of 1-5, with an open text field for notes.

In my experience most calls are a perfect 5/5. However, if I ever have a less-than-perfect call experience (which is a vanishingly rare occurrence at this point), I'll leave a short note about what seemed to go wrong.

The Tuple team has _never_ failed to follow up with me about my feedback. Their reps are friendly, helpful, and _so_ knowledgeable. Good customer service is _such_ a difference-maker, and Tuple nails it.

<Image
  publicId="newsletters/unreasonable-hospitality-and-design/tuple"
  alt="Tuple app"
  caption="Tuple offers simple productivity, and their support staff are absolutely wonderful."
/>

The Tuple team has been nice enough to set me up with a referral link for Tiny Improvements readers. If you're interested in trying Tuple, you can use my link to [sign up for Tuple](https://production.tuple.app/r/OCR4UOLICW) and get a free month of service!

## Designing for hospitality

So how can we apply the principles of hospitality to our design work? Here are a few ideas:

**Do an experience audit:** Take a look at your product from the perspective of a new user. What's the onboarding process like? How easy is it to find the features they need? Are there any pain points that could be smoothed out? Are there moments where you could show them a better experience based on what you already know about them?

**Take a look at your competition:** What's the typical experience like for your competition's users? How can you differentiate yourself by offering a more welcoming, inclusive, and memorable experience? Is there a way to identify a niche in the market that you can serve better than anyone else?

**_Talk_ to your users:** You just can't beat conversation. Reach out to a variety of your users to see what they like about your product. Talk to your best users, ones who may be at risk of churning, and if you're able, ones who have already churned. Take note of any commonalities and differences in these conversations. What can you learn from them?

## Take the idea, and go parabolic

Once you've done your research, I think it's helpful to ask a more pie-in-the-sky question: in a _perfect_ world, what would you do to blow your users' minds? What would make them feel like they _specifically_ are being seen?

Write down these ideas in as simple of a format as you're able to - a sentence or two is fine.

Then, ask yourself honestly: how close can you get to these ideals with the resources you have available? Move the needle as much as you can, and keep iterating.

You'll know when you've hit the mark. Your customers will, too.

> Go get yourself a copy of [_Unreasonable Hospitality_](https://amzn.to/3WaVvXl) by Will Guidara. You'll love it.

---

## From around the internet this week

- YouTuber Foureyes Furniture recently shared the story of how [one of their designs was stolen](https://www.youtube.com/watch?v=urn4nPBAgUg) by a large-scale manufacturer of furniture. I love Foureyes' work, and it's a bummer to see this happen to them. The storytelling in this video is top-notch, and it's a great example of how to turn a negative experience into a positive one.

- My Brother, My Brother, and Me is my favorite podcast (shout out to my sister Kris for recommending it to me years ago!) Their recent episode [707: Crispy Cuppy Puppies](https://pca.st/bu1cd830) is one of the funniest I can remember. It's strange, and it's worth a listen.

## My work online

- 🎙️ My interview for APIs You Won't Hate with [Suchintan Singh from Skyvern](https://apisyouwonthate.com/podcast/apis-for-websites-that-dont-have-apis-with-suchintan-singh-from-skyvern/)
- My work on Openapi.tools was featured in the most recent APIs You Won't Hate newsletter: [Revamping Openapi.tools](https://apisyouwonthate.com/newsletter/revamping-open-api-tools/). You may remember my recent dispatch about working on a project with Astro - this is that, and it's getting closer to launch!
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Keep your tools sharp]]></title>
            <link>https://mikebifulco.com/newsletter/keep-your-tools-sharp</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/keep-your-tools-sharp</guid>
            <pubDate>Tue, 02 Apr 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[The tools we use to get our work done are incredibly important, and taking the time to tune them to work just right can make a huge difference in our productivity and happiness.]]></description>
            <content:encoded><![CDATA[
Growing up, I spent a lot of time in the garage with my dad. He's a man of many projects - and hardly a weekend went past where I wasn't helping him work on _something:_ from cars, to household repairs, lawn work or tinkering with electronics. I learned a lot about tools and how to use them, and I learned that the right tool for the job can make all the difference.

Two things that he used to tell me often were:

1. **Power tools are _always_ out to get you.** They may feel like they'll help you get the job done fast, but they're powerful, and they don't care about your fingers. Respect them and act as though they're always trying to hurt you.
2. **There's nothing worse than having to _fix_ your tools.** If you take care of your tools, they'll take care of you. Keep them clean, sharp, and in good working order.

These are both true - and while rule #1 is _less_ applicable to software tools, rule #2 is _absolutely_ something that I've found to be true in my career as a software engineer. The tools we use to get our work done are _incredibly_ important, and taking the time to tune them to work _just right_ can make a huge difference in our productivity and happiness.

## Tuning your tools just feels good

I use Visual Studio Code for nearly all of my coding and writing. I love it because it's quick and customizable, and it just works well. No shade if you're a fan of `vim`; you do you. I dig VS Code, and I've spend some time recently changing up my setup to make it even better.

Here's a few things I've done recently to tune my VS Code experience:

### Houston theme

There's an installable theme for VS Code called [Houston](https://marketplace.visualstudio.com/items?itemName=justusadam.language-houston-theme) which was actually made by the team that makes Astro. If you prefer a dark theme and like some spicy accent colors, you might like Houston.

<Image
  publicId="newsletters/keep-your-tools-sharp/houston-theme"
  alt="Houston theme in VS Code"
  caption="Now that's a delicious-looking theme."
/>

### Zen Mode

[Zen Mode for VS Code](https://code.visualstudio.com/docs/getstarted/userinterface#_zen-mode) is a great way to tune your IDE to be more focused. I use it for writing articles and newsletters. It's _built in_ to VS Code, so you don't need to install anything. Just press `Ctrl + K, Z` to enter Zen Mode, or the `Toggle Zen Mode` command in the command palette.

Straight out of the box, Zen mode is pretty damn minimal - and that's not for everyone (myself included). To customize Zen mode, open up VS Code settings with `Command + ,` and search for `zenMode`. Y

<Image
  publicId="newsletters/keep-your-tools-sharp/zen-mode-settings"
  alt="Zen Mode settings in VS Code"
  caption="I like to use the Center Layout setting for writing articles and newsletters."
/>

### Pieces for VS Code

[Pieces for VS Code](https://marketplace.visualstudio.com/items?itemName=MeshIntelligentTechnologiesInc.pieces-vscode) is... amazing. It's a contextualized note-taking app and code copilot that helps you store, annotate, and generate code snippets in your IDE. Not only is it context aware -- as in, it knows what you're working on as well as the places where you're doing research -- but it also features an _on-device,_ privary first LLM that can generate code snippets and notes _without_ sending your data to the cloud. 🤯

It comes from the lean, mean squad at [_Pieces for Developers_](https://pieces.app/). If Pieces sounds familiar, you probably know about it because of [my interview with their founder Tsavo Knott on Software Engineering Daily](https://softwareengineeringdaily.com/2023/10/25/building-pieces-app-and-the-future-of-developer-productivity-with-tsavo-knott/) a few months back, and definitely not from Scott Hanselman's [recent podcast](https://hanselminutes.com/913/redefining-developer-workflow-with-piecesapps-tsavo-knott) about it. 😅

<Image
  publicId="newsletters/keep-your-tools-sharp/pieces-extension"
  alt="Pieces extension for VS Code"
  caption="Pieces for VS Code is a fantastic use of AI tech."
/>

---

## More from me about whipping VS Code into shape

- Minimalists will appreciate [How to make VS Code load faster with a little bit of housekeeping](https://mikebifulco.com/posts/make-vs-code-load-faster-by-removing-extensions). Spoiler alert: the crux of this one is _getting rid of_ things you don't use.
- If you made the switch from Intel to an M1, M2, or M3 Mac in the past few years, don't miss my article on [Making VS Code Quicker on Apple Silicon Macs](https://mikebifulco.com/posts/make-vs-code-load-faster-mac-apple-silicon). If you're affected by this one, the gains are _huge_.
- This quick tutorial on [using the refactor menu in VS code](https://mikebifulco.com/posts/refactoring-typescript-react-components-vscode) was an awakening for me - I didn't know how much I was missing out on until I started using it!
- If you're a TypeScript dev, there's a couple troubleshooting steps I use to [fix TypeScript errors in VS Code](https://mikebifulco.com/posts/typescript-vscode-error-fix-last-resort) when nothing else seems to work.

---

## Find me online wherever you get your internet

Recently, I've been releasing past newsletters as podcasts - you can find them in your podcatcher under "Tiny Improvements", or if you prefer a direct link, you can subscribe on [Spotify](https://open.spotify.com/show/0H7r0j7q6RXzSie6AbMDwj), [Apple Music](https://podcasts.apple.com/us/podcast/tiny-improvements/id1577037667?uo=4), [Pocket Casts](https://pca.st/itunes/1577037667), and good ol' [RSS](https://feeds.transistor.fm/tiny-improvements).

They're a few minutes long each, and are a ton of fun to make. I hope you enjoy them!

I'm also releasing occasional videos (both short- and long-form) to [my YouTube Channel @mikebifulco](https://youtube.com/@mikebifulco?sub_confirmation=1). I'd love it if you'd subscribe and let me know what you think of the content.

---

## Hey though, how are _you_ doing?

I hope you're doing well. As always, I'd love to know what you're working on, what you think of Tiny Improvements, and what you'd like to see more of. Hit reply and let me know - I do my best to respond to every email I get.

Keep up the good work, and I'll see you in the next one.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Why new frameworks make better developers]]></title>
            <link>https://mikebifulco.com/newsletter/why-new-frameworks-make-better-developers</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/why-new-frameworks-make-better-developers</guid>
            <pubDate>Tue, 26 Mar 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[A look at the cognitive science behind the Hierarchy of Competence, and how dabbling with new frameworks and tools can make you a better developer.]]></description>
            <content:encoded><![CDATA[
This past weekend, I spent some time building a new project with 🧑‍🚀 [Astro](https://astro.build). It describes itself as "The web framework for content-driven websites", which was perfect for my use case - rebuilding a content-heavy site for APIs You Won't Hate, called [openapi.tools](https://openapi.tools).

I've been building with React for a good long while now, and Astro's come-as-you-are approach to javascript frameworks means that I was able to mix in React components with Astro's own syntax. At first, this felt a little bit like getting peanut butter in my chocolate, but... it works surprisingly well.

<Image
  publicId="newsletters/why-new-frameworks-make-better-developers/astro"
  alt="Astro + React feels like getting peanut butter in my chocolate"
/>

In true extrovert fashion, I jumped into learning about Astro by building with it in public on a [YouTube Livestream](https://www.youtube.com/watch?v=wyJYInvZya8) last Saturday.

It... was tough, honestly.

Over the course of a few hours, go from explaining my approach and stream-of-consciousness thinking, to silently debugging a react-in-astro challenge for... a while.

Perhaps appropriately, the stream ended abruptly after my wife told me my webcam was no longer working... followed shortly by OBS (the streaming software I use) crashing. 🤦‍♂

## So learning in public wasn't a great success

The livestream was a struggle. I stepped away from my Astro project, and came back to it the next day.

Something clicked. I was able to get past the issue I was having, and my project really started to fly together quickly. I was able to get a lot done in a short amount of time, and I was feeling pretty good about it. (By the way: I'll be sharing the fruits of my labor in the coming weeks...)

My second day of building honestly felt a lot more like typical dev work does for me - I was in a flow state, juggling tiny tasks and debugging issues as they came up. I felt unfazed to be working with Astro; a completely different experience compared to just the prior day.

## It's familiar, but not too familiar

As I got to this point into the project, I could feel myself pulling from experience building with _all_ of the other web frameworks I've built with, whether directly or indirectly.

I've built production apps with many frameworks over the years: from create-react-app to Remix.run, Next.js to Ruby on Rails and now Astro. I've also poked around at countless CSS and UI libraries like Bootstrap, Tailwind, Chakra, and ShadCN UI. It's a little difficult to describe, but the time I spent with each of these tools has made me a better developer.

Of course, learning about Bootstrap doesn't inherently make me understand React -- but it did add to the foundation of skills I use to debug things, to research solutions when I'm stuck, and to ask for help when I need it.

That new error that just popped up? I've seen something like it before. Oh, this component isn't rendering correctly? I know how to debug that. This layout isn't quite right? I know how to fix it. You get the idea.

## The Hierarchy of Competence

In cognitive psychology, there is a model called the [Hierarchy of Competence](https://en.wikipedia.org/wiki/Four_stages_of_competence). It describes the stages of learning a new skill, from unconscious incompetence to unconscious competence:

<Image
  publicId="newsletters/why-new-frameworks-make-better-developers/hierarchy-of-competence"
  alt="Hierarchy of Competence"
  caption="The Hierarchy of Competence, not to be confused with the Dunning-Kruger effect..."
/>

In the early stages of learning, we stumble between the "unconscious incompetence" and "conscious incompetence" stages. We don't know what we don't know, and then we start to realize how much we don't know. Getting through this phase can be a slog, but it's a necessary part of the learning process.

Don't get me wrong - I'm not going to tell you that I've mastered the damn thing after a weekend - I wouldn't want to end up hanging out with my dear old friends [Dunning-Kruger](https://mikebifulco.com/newsletter/learn-from-a-dunning-kruger-expert) again. I will say that I'm likely past the "conscious incompetence" stage with Astro. I'm starting to see the patterns and the ways that Astro's approach to building websites is different from what I'm used to.

What I am saying is that weekend projects like this inevitably bolster my skills as a developer. They're a good reminder that my expertise isn't just in React or Rails or Next.js - it's in problem-solving, debugging, and learning new things.

If you happen to manage a team of engineers, this is a good reminder that giving your team the space to explore new tools and frameworks can be a good thing, whether in a weekend project or in a more formal setting.

And if you _don't_ manage a team, remember this the next time someone tells you that it's a waste to try out a new framework or library: it's not about the tool itself. It's about the skills you pick up along the way.

---

## Some useful links for learnin' new things

- 🚀 [Astro Web Framework Crash Course](https://www.youtube.com/watch?v=e-hTm5VmofI) My pal James Q. Quick produced a course for FreeCodecamp. If you're thinking about astro-ing, give it a look!
- 🗣️ The [world's shortest social engineering masterclass](https://www.youtube.com/watch?v=ffcTwHZRhSk) from Buildspace is a great watch. A few years back, [I took their course on building web3 apps](https://mikebifulco.com/posts/learn-web3-blockchain-with-buildspace). While their business model has changed, Farza and his team have continuted to put out compelling lectures on their YouTube channel. I watched this one over the weekend, and was inspired by the humble approach Farza took when building his brand and influence.

## HELP ME PLZ: 💌 Tiny Improvements feedback

I've been writing Tiny Improvements for a _while_ now, and although I occasionally get a reply or two, I'd love to hear more from you.

- What do you like about this newsletter?
- What things would you like to see less of?
- Anything I can do differently to make this more valuable to you?

Hit reply and drop me a line - let me know what you think. There's no idea too big or too small.

I'm all ears. 🙏
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Take my money! Some of my favorite tools... and why I pay for them]]></title>
            <link>https://mikebifulco.com/newsletter/take-my-money-tools-i-pay-for</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/take-my-money-tools-i-pay-for</guid>
            <pubDate>Tue, 19 Mar 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[I'm a huge fan of products that use their a free tier to prove their value, and then convert me to a paying customer. Here are a few tools I pay for, and why I think they're worth it.]]></description>
            <content:encoded><![CDATA[
## Everyone loves a generous free tier

There are loads of free tools I use to get my work done, and I love recommending free tools for others to use. A quick search of articles and newsletters I've written shows 99 mentions of the word "free". I'm no stranger to the free tier, and most of all, I'm a huge fan of products that use their a free tier to prove their value, and then convert me to a paying customer.

I thought it might be interesting to share some of the products I pay for. Like most developers, I'm pretty sensitive to price: I'm willing to pay a reasonable fee for services based on the value they provide, but I'm also quick to cancel a subscription if I feel like I'm not getting my money's worth.

So with that in mind, here's a few tools I pay for, and why I think they're worth it:

### Transistor.fm

**Price: $19/mo**, which includes unlimited shows and episodes, and 20k downloads per month.

I've been using Transistor.fm to host my podcasts for a few years now. I've used few other podcast hosting services over the year, but I've found Transistor to be the best fit for me.

**Killer features:**
Transistor does many things amazingly well but these are among my favorites:
It's easy to use: starting a new show takes a few minutes. Upload your episode and you'll be off to the races in no time.

It never breaks: Never _once_ have I needed to worry about my podcast feed being down.

They add thoughtful features that make my life easier. For example: you can add guests to individual podcast episodes for better SEO (and you know I love SEO), they have great HTML embeds to share episodes and shows on your website.

Transistor makes it _dead easy_ to get your show listed on all the major podcast directories. This is a task that is fairly time intensive otherwise, and loads of podcasters don't do it, which is a huge mistake. You don't want your show to _only_ be listed on Apple Podcasts, do you?

<Image
  publicId="newsletters/take-my-money-tools-i-pay-for/transistor-fm"
  alt="A screenshot from my Transistor.fm dashboard"
  caption="A screenshot from my Transistor.fm dashboard. What's that last one on the list? 🤔"
/>

Being the nightmare-dev that I am, I've also sent the Transistor team a few support requests while poking around with the [Transistor API](https://developers.transistor.fm/), and they've always been quick to respond and helpful.

**Try it:** If you're thinking about starting your own podcast, and want to give Transistor a shot, you can use my referral link to get 15% off your first year: [Transistor.fm](https://transistor.fm/?via=mike-bifulco)

## Descript

**Price: $12/month**, which includes 10 hours of transcription per month, and 20 hours of screen recording per month.

Descript lets you edit audio and video files like they were a text document. Read that again. It's _wild_. I was an early adopter of Descript, and have been using it to edit Podcasts and videos for years now.

**Killer features:**

Do you say "um" and "uhhh" a lot when you're speaking? Descript can remove those for you. Do you want to add a section to your podcast where you're talking about a product, but you don't want to re-record the whole episode? Descript can do that for you. Do you want to add a video to your podcast episode? Descript can do that for you.

Descript can export video in portrait or landscape, which makes it trivial to create content for Instagram, TikTok, and YouTube.

I also love their audiogram feature, which you can use to make closed captioned clips from podcasts for social media.

<YouTube youTubeId={'nPZjfG6SWeY'} />

**Try it:** ready to make audio and video editing feel like magic? Give [Descript](https://get.descript.com/09k9hymsebq1) a shot using my referral link.

## Backblaze - automated cloud backups for your computer

**Price: $18/month**, which includes unlimited backups for two computers.

Having a backup of your computer is one of those things that many people don't think about until it's too late. I've been on the short end of that stick one too many times in my life, so I take a military mindset to backups: two is one, and one is none. I have my computer backed up locally to a NAS (network attached storage) device using Time Machine, and I use Backblaze as a cloud backup for my computer's hard drive. It's a set-it-and-forget-it kind of service, and I've been using it for years.

**Killer features:** Install it once, and it does its magic. If you ever need to restore from a backup, you can download your files from the web, or have them send you a USB hard drive with your data on it ([for free](https://www.backblaze.com/blog/usb-hard-drive-restore/)\* - as long as you ship it back within 30 days!). Super thoughtful, and well worth the price for peace of mind.

**Try it:** If you're not already backing up your computer, you should be. [Try Backblaze](https://secure.backblaze.com/r/00ponv) using my referral link for a free month of service.

---

## Some other bits I've shared online this week

- 🎙️ My podcast interview with [Zeno Rocha from Resend](https://apisyouwonthate.com/podcast/building-a-simple-api-for-email-with-zeno-rocha-from-resend/) went live last week on the APIs You Won't Hate podcast feed. Zeno is a great guy, and I've been a fan of his work for years. We talked about his new product, Resend, and how he's using APIs to make email marketing easier for developers.

- **This weekend** I'll be doing some live coding on YouTube: join me for [Rebuilding openapi.tools with Astro](https://youtube.com/live/wyJYInvZya8?feature=share) Saturday morning at 10am Eastern.

## 🔌 Until then, unplugging

I'm taking some time off from work this week to recharge and spend some time in the sun. It's something that I try to do regularly to take care of myself - work, life, and everything else can be a lot to handle, and it's important to take time to recharge. I hope you're able to do the same!

I'll be back in your inbox next week with more thoughts on building things on the internet. [Stay positive and love your life](https://www.youtube.com/watch?v=MgTDLlDY_yY) ✌🏾
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[3 Tiny tips for better SEO]]></title>
            <link>https://mikebifulco.com/newsletter/tiny-tips-for-better-seo</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/tiny-tips-for-better-seo</guid>
            <pubDate>Tue, 12 Mar 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[I hear from a lot of devs that they don't know where to start with SEO. Here are 3 tiny tips about to get you started.]]></description>
            <content:encoded><![CDATA[
## SEO is the growth engine for your work

If you're building a brand, a business, or a personal website, taking the time to invest in SEO (Search Engine Optimization) will help your work get discovered when people search for related topics on DuckDuckGo, Bing, and Google. In my experience, developers often overlook SEO for one reason or another. But it's a critical part of building a successful website.

<Aside type="note">

Side note: SEO is a _massive_ topic - I'm far from an expert, but I've found it invaluable to learn a few basics. If I've got anything wrong here, or you know more than me, [I'd love to hear from you](https://threads.net/@irreverentmike)!

</Aside>

My position on SEO is this: it's a growth engine for your work, and when donse right, it can have a flywheel effect that will put your work in front of more people over time. It's not as immediately satisfying as racking up likes on a social media post, but it persists long-term, and can help you build a sustainable audience for your work.

It's slow-release dopamine, if you will.

I've been publishing articles under my own name for a few years now, and a steady investment in search now sends thousands of readers a month to my work. We've also been investing in SEO at [Craftwork](https://craftwork.com), and it's been fun to learn about how focusing on search for a local business differs from a personal website - but the principles are the same.

### Think about what your work will look like when it's shared

When someone comes across your work and they share it on their social media feed, you want it to look good, right? It should have a catchy, meaningful title, a useful description, and an image that draws people in. This is also what will show up when your work is shared on social media, or when it shows up in search results.

Functionally, this means you need to make sure your site has good metadata. Metadata is the information about your site that search engines use to understand what your site is about. It's also what social media platforms use to display your content when it's shared.

Here are a few tips to get you started:

- The `<title>` and `<h1>` tags on the page are most likely to be used as the title of the page in search results. Make sure they're descriptive and accurate.
- The `<meta name="description" />` tag is used as the description of the page in search results. Try to keep it less than 150 characters, and make it a meaningful summary of the page's content.
- The `<meta property="og:image" />` tag is used as the image that shows up when your page is shared on social media. Make sure it's a high-quality image that represents the content of the page, and that it's at least 1200x630 pixels in size with an aspect ratio of 1.91:1 so it looks good on <s>all</s> most platforms.

### Use Structured Data with JSON-LD for enhanced search results

Picture a list of Google search results in your head. You're probably seeing a list of blue links with a short description below them. But have you ever seen a search result with a video thumbnail, or a recipe with a picture and a list of ingredients? That's no accident - it's the result of Google's crawlers finding something called _structured data_ on the result's page.

<Image
  publicId="newsletters/tiny-tips-for-better-seo/enhanced-search-results"
  alt="Enhanced search results"
/>

When your site shows up like this, it's called a _rich result_. It can help your site stand out in search results, and give your work a better chance of being seen.

There are many types of Structured Data which are supported by Google, including:

- Articles
- Videos
- Events
- Product
- Software App

...and more. Check out Google's list of [Structured data markup that Google Search supports](https://developers.google.com/search/docs/guides/search-gallery) to see if there's a type that fits your content. If there is, you can use something called JSON-LD to pages on your site to help Google understand what your content is about.

I recently did this for my website - pages that feature video now include `VideoObject` structured data. It's as simple as including a bit of JSON on the page in a `<script />` tag. Check out my recent Pull Request to see how I made it happen: [mbifulco/blog#775: Add Structured Data for Video](https://github.com/mbifulco/blog/pull/775).

<Image
  publicId="newsletters/tiny-tips-for-better-seo/video-results"
  alt="Structured Data"
  caption="Structured Data inspection results for a video on my site. Success! Google can see it."
/>

### Keyword research is a great way to understand your audience

Alright, friends -- here's where I need to call _myself_ out - I'm not great at this. But I know it's important, and I'm working on it.

Here's the idea: when making something new, it's reallllly helpful to make sure you're creating content about things people are actually searching for. Keyword research to understand what people are searching for, and then create content that matches those searches.

<Image
  publicId="newsletters/tiny-tips-for-better-seo/keyword-research"
  alt="Keyword research"
  caption="Keyword results for my site on both Google Search Console and Ahrefs Webmaster Tools"
/>

There are a lot of tools out there to help you with keyword research, but I've found that the best (free) tools for this are [Google Search Console](https://search.google.com/search-console) and [Ahrefs Webmaster Tools](https://ahrefs.com/webmaster-tools). Both of these tools will show you what people are searching for when they find your site, and what your site is ranking for. This can help you understand what people are looking for, and what you can do to make your site more relevant to those searches.

---

## Free tools to help you understand your site's SEO

### Make sure those titles and descriptions are just right

I really like the [SEO extension from Detailed](https://detailed.com/extension/) as a tool for inspecting the metadata on a page. It's a Chrome extension that shows you the metadata for the page you're on, and gives you a score for how well it's set up for search. It's a great way to quickly check if your titles and descriptions are set up correctly.

### For Structured Data

If you're adding Structured data to your site, you can use use [Google Search Central Schema Markup Testing Tool](https://developers.google.com/search/docs/appearance/structured-data) and [Schema.org's validator](https://validator.schema.org/#url=https%3A%2F%2Fmikebifulco-com-git-feat-metadata-mbifulco.vercel.app%2Fposts%2Flive-coding-satori-og-images-nextjs) to make sure your pages are set up correctly.

### Learn from the best

If you're looking for more, you may want to check out [Positional's fantastic SEO newsletter](https://www.positional.com/newsletter) - it's well-researched, highly informed, and a great way to learn more about SEO.

---

## More from me on SEO

- I wrote a tutorial on setting up [Self-healing URLs on your Next.js site](https://mikebifulco.com/posts/self-healing-urls-nextjs-seo) that you might find useful.
- Ever wonder [how to correctly add subtitles to your h1 tags](https://mikebifulco.com/posts/semantic-html-heading-subtitle)? I've got you covered.
- These are [the SEO tools I use to grow my sites to 20k+ vistors/month](https://mikebifulco.com/posts/seo-tools-for-new-web-projects).
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[The first year of being a technical startup cofounder]]></title>
            <link>https://mikebifulco.com/newsletter/reflecting-on-one-year-as-startup-cto</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/reflecting-on-one-year-as-startup-cto</guid>
            <pubDate>Tue, 05 Mar 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Reflecting on my first year as CTO of Craftwork, and the many things I've learned along the way.]]></description>
            <content:encoded><![CDATA[
Last year, I wrote a reflection on [the first 90 days as a technical cofounder](https://mikebifulco.com/newsletter/building-a-startup-in-2023-90-day-report) about the first three months of building Craftwork. That article was largely a reflection on the differences between building a company from scratch in 2023 versus the last time I did it, around 2016. Plenty has changed since then, and I think that article is still worth a read.

Today, I want to reflect on the first year of building [Craftwork](https://craftwork.com/). We've written many chapters of our story in the last year, and I think it's worth taking a moment to reflect on what we've accomplished and what we've learned.

<SponsoredSection
  CTAtext="Subscribe Today"
  href="https://codestory.co/"
  imagePublicId="sponsors/code-story/hero"
>

### Their tech, Their products.... Their Stories.

Code Story is a podcast featuring founders, tech leaders, CTOs, CEOs, and software architects, reflecting on their human stories in creating world changing, disruptive digital products.

</SponsoredSection>

## You won't know some things until you try

I've spent a good deal of my career working in UX. I've gotten to work with some incredibly talented designers and UX researchers, and I do believe that good design is a competitive advantage. Even still, when building real features for real people, you can't always predict what will work and what won't.

Designing great software needs to be both proactive and reactive - you need to have a vision for what you want to build, but you also need to actively respond to feedback and data.

For example: the very first version of Craftwork's estimate builder was designed to be _extremely_ self-serve - we built a tool that would let customers scope out their entire project without needing to talk to us. We thought this would be a great way to let people get a feel for what we could do for them, and to be extremely transparent about what their project would cost.

In practice, we found that people were often overwhelmed by the number of choices they had to make. Over and over we saw people getting stuck playing with our estimate builder, weighing the cost of one little change against another. Many people got stuck on this process, and never actually submitted a request for painting.

On a hunch, we ran a quick A/B test to see if it would be more productive to have a conversation with one of our team members first, and the results were clear: our customers have lots of interesting questions, and a price calculator wasn't answering all of them.

We've since reworked the estimate process to be more of a guided conversation, and we've found that using it to create a human connection with our customers has been a great way to build trust and to get the ball rolling on a project.

## You can't do it alone

While building my last company, I was convinced that we could do everything with an exceptionally small team - we were just 3 people, from inception to acquisition. I'm proud to say we did the damn thing, but it was _really_ difficult. You'll often hear founding employees at startups talk about how they're "wearing many hats" - that's definitely true, and it makes work a lot of fun. It's also true that you can't wear _all_ the hats. It's _also also_ true that there exciting, beautiful new hats out there that you don't know you need to wear.

From my first day as a working professional, I've always wanted to be surrounded by people who are smarter than me. Building Craftwork has been no exception - my cofounders are dedicated, talented, and damn good at what they do. We have also hired some _truly_ amazing people to build our team.

### A few things I've learned about building the right team:

Engineers tend to undervalue the importance of understanding the mechanics of the business. Our growth team at Craftwork has been instrumental in helping us understand how to reach new customers, and how to build a _profitable_ product that people want.

Building a brand is like nurturing a garden. It takes time, patience, and a lot of care. Craftwork's brand has really grown into something special, and it's been a joy to watch it happen. Give our [Instagram](https://www.instagram.com/craftworkpaint/) a peek if you want to see what I mean.

At this stage in the startup journey, hiring engineers is really challenging. The perfect engineer for a startup is someone who is comfortable with a lot of ambiguity, who can work independently, and who can communicate well... in addition to being technically competent. It's a tall order, and it can be a challenge to find the right people.

When I have roles open on my team, hiring is the most important thing I do day to day. It is also a full-time job in itself. It requires a fair deal of patience to assemble the right team, as well as a drive to actively and creatively seek out the right people.

## Just enough (and nothing more)

I recently came across the Japanese Phrase ほどほど (hodohodo), which means "just enough." I've been trying to use it as a reminder to keep things simple, and to avoid overcomplicating things. My team is tasked with building the features we need most _today,_ with eyes on what we'll need in 6 months and a year... and that can be overwhelming. It's easy to spiral out of control with feature creep and over-engineering, and finding ways to help each other _just-enough-for-now_ is a team remit.

_Just enough_ spills over into many areas:

- **Build vs buy:** almost every feature our team needs can be bought from a SaaS vendor, or coach built by our product team. Making this decision can be nuanced and difficult, and it's something we revisit regularly.
- **Adopting tooling:** Engineers love to play with new tools - there's always a new framework, language, database, or library to poke around with. We've been very deliberate about what we adopt, and we've been very careful to avoid adopting things just because they're new and shiny. We have also adopted tools with good intentions, and found ourselves jettisoning them when they don't work out for one reason or another.
- **Shipping new features:** Adding new functionality for our customers and teammates is always tempting, but it's important to be mindful of the complexity that comes with each new feature. Our engineering team is small-and-mighty, and ever new feature we build means we have less time to support the features we've already built.

I used to say _Just enough (and nothing more)_ - there's a funny irony in that phrase. A year into this thing, this feels more accurate: Just enough <s>(and nothing more)</s>.

---

## More on building startups

If you're inerested in a more detailed look at the past year, here's a few more links you might find interesting:

- 🎙️ [My interview on the podcast CodeStory](https://codestory.co/podcast/e14-mike-bifulco-craftwork/) was released today. Codestory's creator, Noah, was kind enough to reach out about sponsoring this newsletter as well. Telling Craftwork's origin story is a good reminder of how far we've come in a year.
- 🥽 [Learning is an infinite game](https://mikebifulco.com/newsletter/learning-is-an-infinite-game) tells a little bit about how we used 3D printing tech to produce tooling for large-scale paint projects, and what it was like to dive in to CAD modeling after years away.
- 📋 Hiring is hard. There have also been a ton of layoffs in the past year-and-change. I wrote [Your Resume Sucks. Here's how to fix it](https://mikebifulco.com/newsletter/your-resume-sucks) in an effort to help engineers represent themselves better when looking for a job.

---

## Thanks for reading

I'm grateful for the opportunity to reflect on the past year, and I'm grateful for the opportunity to share it with you. If you have any questions about what it's like to build a startup, I'd love to hear from you. Reply to this email and let me know what's on your mind.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[I hate Tailwind CSS. Here's why I use it.]]></title>
            <link>https://mikebifulco.com/newsletter/i-hate-tailwind-css-heres-why-i-use-it</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/i-hate-tailwind-css-heres-why-i-use-it</guid>
            <pubDate>Tue, 27 Feb 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Tailwind CSS is a utility-first CSS framework that I've come to love. Here's why I use it and why I think you should too.]]></description>
            <content:encoded><![CDATA[
## Thanks, I hate it

In the first days of building [Craftwork](https://craftwork.com), I made the decision to use Tailwind CSS for our projects. This choice was driven by tailwind's adaptability, and its popularity among developers.

Here's the thing though: Tailwind and I don't really get along. I've spent years learning to create design systems with traditional CSS. More recently I found myself building products using full-blown UI libraries like Material UI and Chakra, because they make it _super_ fast to build a rich, functional, and accessible UI.

By contrast, Tailwind is somewhere in the middle of these two. On some level it bypasses the nuanced understanding and control that come with writing raw CSS. It's also not _fully_ functional out of the box like Material UI or Chakra - and yet... for so many reasons, it's _really_ good.

For us, Tailwind provides some huge benefits:

- **Speed**: Tailwind's utility-first approach allows us to quickly implement designs without having to write custom CSS. This is especially useful when we're iterating on designs and need to make changes quickly.
- **Universality**: At Craftwork, our stack includes Ruby on Rails, Next.js, and React-Native. Tailwind's flexibility allows us to use the same styling system across all these platforms, which is a huge win for us.
- **Talent**: Craftwork isn't just me, and it never will be. Tailwind's popularity across the industry has made it almost trivial to find developers who are familiar with it. This is a huge win for us as we grow our team.
- **UI Libraries**: Due to its popularity, there _are_ many UI libraries built around Tailwind, including: [TailwindUI](https://tailwindui.com), [ShadCN UI](https://ui.shadcn.com/), and [Aceternity UI](https://ui.aceternity.com/components). Costs to license each of these libraries vary (some are even free!), and they're essentially copy-pasteable components that you can use to build your products. Very cool.

## What this means for us in practice

Tailwind's adaptability is really what shines; from day one, it has enabled us to onboard new teammates, and build interfaces more rapidly. Its consistent utility across our entire stack means that regardless of the project, new team members can quickly read, understand, and contribute to our codebase. The decision to use Tailwind, therefore, wasn't just about adhering to current trends or sidestepping the complexities of CSS; it was a strategic move to ensure our team can hit the ground running, maintaining agility and coherence across our diverse projects.

This underscores a more important principle in tech selection: aligning tool choices with team dynamics and project requirements is a skill. It's a delicate balancing act -- weighing the benefits of technological efficiency and team scalability against the richness of personal expertise and the depth of traditional craftsmanship. It's a reminder that our growth as developers is not just about keeping up with the latest tools but also about valuing and honing our foundational skills.

Put another way, for everything we build, we have to balance velocity and quality. Tailwind is a tool that gives us wins in both columns.

## What I'd like to see change

All that being said, I do still have a wishlist for Tailwind:

1. **Better tooling**: Tailwind's approach to utility-first CSS is great for performance, but it also means we have to configure Tailwind to compile per-project, so that it only includes the styles we use. When this (infrequently) breaks, it can be difficult to detect, and debugging it isn't always straightforward.
2. **Better IDE support**: Tailwind provides a consistent language for styling our apps - there are plugins for VS Code's Intellisense that make it easier to write Tailwind classes, but it doesn't _always_ work. This can make it difficult to remember the exact class names for certain styles, and can slow down our development process.
3. **Prettier Prettier rules**: Adding tailwind classes to html means that we often have long lists of class names added to our html. This causes individual lines of code to be very long - despite what many engineers will tell you, this is [demonstrably worse for UX](https://www.nngroup.com/articles/f-shaped-pattern-reading-web-content/) than having class names listed on separate lines. There's [lots of discussion about building a prettier rule](https://github.com/tailwindlabs/tailwindcss/discussions?discussions_q=multiple+lines) for this, but as far as I've seen, there's not a great solution yet.

<Image
  publicId="newsletters/i-hate-tailwind-css-heres-why-i-use-it/horizontal-scan"
  alt="Screenshot of tailwind css code resulting in lots of long lines of code, causing horizontal scanning issues"
  caption="Like it or not, a horizontal list of classes is more taxing than a vertical list would be."
/>

So in the end, do I hate Tailwind? No, of course not. I've come to appreciate it for what it is: a pragmatic choice that has helped us build better products, faster. And that's something I can get behind.

**I'd love to hear from you**. What are your thoughts on Tailwind? Do you have any tips for using it more effectively? Is there a UI Library you love that I missed? Maybe you have a wishlist of your own? Let me know by replying to this email.

---

## What I'm thinking about this week: Watching experts work

### 🎶 A musical savant showcasing mastry

There's something extremely satisfying about watching someone who's really good at their job do their thing. I've been sharing this video of musical composer [Jacob Collier using Logic masterfully](https://www.youtube.com/watch?v=tVHyuhsAles) to compose a song in real time. There's such a beautiful confluence of skill, creativity, and deep understanding in this video.

The best creative tools make superusers shine, and I think that's something we should all strive for in our work.

### 🔌 Plug kinda nerdy, but he chill

I was pretty deep in the YouTube rabbit hole when I came across [@AllThingsOnePlace](https://www.youtube.com/watch?v=-JkUcrlDtZ0). This is an electrical engineer whose videos are all about analyzing and reviewing power supplies and other electrical components. I promise it is _way_ more interesting than it sounds. I had no idea that you could measure the _quality_ of power coming from a USB charger!

---

## More from me

### 🎙️ [Every business is an API business](https://apisyouwonthate.com/podcast/allan-knabe-apiable-api-portal/)

In my recent podcast interview with Allan Knabe from Apiable for APIs You Won't Hate, we dicussed how Apiable is building an API Portal service that helps API teams to create, secure, market, and monetize API products. Catch it on the [APIs You Won't Hate feed here](https://apisyouwonthate.com/podcast/allan-knabe-apiable-api-portal/)), or wherever you listen to your podcasts.

### 🎥 [I've been more active on YouTube](https://youtube.com/@mikebifulco?sub_confirmation=1)

Over the past month or so, I've gotten back into live coding on YouTube on the weekends. I've also got plans to start publishing more dev tutorials and startup content. If you're interested in that kind of thing, [subscribe to my channel](https://youtube.com/@mikebifulco?sub_confirmation=1) to stay up to date.

---

Hey, one more thing: make sure you [register to vote](https://vote.org). It's important. Like, deeply, existentially important.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Gestalt: Design principles every developer should know]]></title>
            <link>https://mikebifulco.com/newsletter/gestalt-design-principles-for-developers</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/gestalt-design-principles-for-developers</guid>
            <pubDate>Tue, 13 Feb 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Ever felt that you've seen a design that just makes sense to you, but you couldn't quite put your finger on why? There's rules for that. Let's talk about Gestalt]]></description>
            <content:encoded><![CDATA[
Have you ever felt that you've seen a design that just makes sense to you, but you couldn't quite put your finger on why?

---

At some point, we are all faced with the challenge of creating a design that works intuitively _and_ looks great. When building a new interface, there's a temptation to lean heavily on obvious design elements like color or shape, or to use cards and borders to hold bits of UI. It makes sense: these are easily visible to person using your app.

What you may not realize is why these elements are so effective.

The people who use our designs are silently and subconsciously navigating questions like: _What's the most important thing on this page?_, _What's the relationship between these elements?_, and _What's the best way to navigate this interface?_

Enter **Gestalt** principles, a set of psychological concepts that go beyond aesthetics to form the foundation of how we see and interpret user interfaces. This is the bit of our mind that guides us to parse the whole picture by understanding the relationships between its parts.

The gist of understanding Gestalt principles for design is this: our brains are used to grouping things together based on a few basic patterns. These patterns are the foundation of how we perceive the world around us. By understanding these patterns, we can create designs that are easy to understand and navigate. Additionally, by _breaking_ these patterns, we can intentionally draw attention to specific elements in our designs.

## Some of the basic gestalt principles, in short:

- **Past Experience**: Our brains use our past experiences to interpret new information.
- **Proximity**: Elements that are close together are perceived as a group.
- **Similarity**: Elements that look similar are perceived as a group.
- **Figure and Ground**: Our brains separate elements into the background and the foreground.
- **Symmetry and Order**: Our brains perceive objects as symmetrical shapes that form around their center.

There are a few more principles, and they are all worth understanding. But for now, let's focus on how these principles can be applied to create better designs.

### Past Experience: the power of familiarity

In your mind, picture a web form used to collect someone's mailing address. You probably see a series of fields, each labeled with a specific piece of information: street address, city, state, and zip code. Where do each of these fields go? If you're like most people, you probably see the street address at the top, followed by the city, state, and zip code.

This is a perfect example of how past experience influences our perception of new information. We've seen this pattern so many times that we instantly recognize it and know how to interact with it.

<Image
  publicId="newsletters/gestalt-design-principles-for-developers/gestalt-layout"
  alt="Gestalt layout"
  caption="One of these should feel natural."
/>

On the left, the form is laid out in a way that feels familiar. On the right, complete unhinged madness. It's not _technically_ in violation of the geneva convention, but it's close.

### Proximity and Similarity: the power of grouping

Proximity and similarity are two of the most powerful tools in a designer's toolbox. They allow us to group elements together in a way that makes sense to the user. This is why one of the fundamental building blocks of most CSS design systems includes a grid system. It's a way to ensure that the space in your design is consistent and harmonious, guiding the user's eye and creating a sense of order and structure.

What does this mean? It means that the space around and between elements is just as important as the elements themselves. It's the difference between a cluttered, confusing design and a clean, intuitive one. Consistency is critical here: spacing between related elements should be consistent, and the space between unrelated elements should be distinct.

Take a look at this example:

<Image
  publicId="newsletters/gestalt-design-principles-for-developers/gestalt-proximity"
  alt="Gestalt proximity"
  caption="Without thinking too hard, you can probably tell which elements are related to each other."
/>

How many groups of rubber ducks do you see on each side?

If you're like most people, you probably see two groups in side A, and one group in side B.

With no other guide, your mind has grouped the ducks together for you. You can do the same thing when building interfaces: by using proximity and similarity, you can guide the user's eye and create a sense of hierarchy.

## Figure and Ground: the power of contrast

The Gestalt principle of figure and ground is all about contrast. It's the idea that our brains separate elements into the background and the foreground. This is a powerful tool for creating designs that are easy to understand and navigate. By using contrast, you can make elements stand out from their surroundings and draw attention to specific parts of your design.

<Image
  publicId="newsletters/gestalt-design-principles-for-developers/gestalt-figure-ground"
  alt="Gestalt figure and ground"
  caption="The figure and ground principle is a powerful tool for creating designs that are easy to understand and navigate."
/>

No doubt you can see the difference between side A and B this time. If this were a list of products in an ecommerce app, which one do you think would call the most attention to itself?

A slightly different display treatment turned one lucky ducky into a golden goose.

## Using color: A little can help, too much is a problem

Next, let's look at color. It's a powerful tool in any designer's arsenal, but it's also a double-edged sword. Relying too much on color can lead to designs that fail for a variety of reasons.

For instance, colorblind users may struggle to distinguish between different elements. As a reminder, **something like 10% of all men have color deficient vision** - more than you might think!

Conversely, too much use of color can make it difficult for people to understand what colors are meant to convey.

When I was working as a UX designer at Microsoft, it was common practice to design interfaces in black and white first. This was a way to ensure that the design was strong enough to stand on its own, without relying on color to convey meaning. Once the design was solid, we'd add color to enhance the experience, not define it. A truly successful design maintains its integrity even in black and white. This is a testament to the strength of its structure, spacing, and the overall harmony of elements - principles rooted deeply in Gestalt theory.

When color isn't the primary means of conveying information, it can be used to draw attention to specific elements. This is where the Gestalt principle of similarity comes into play. By using color to make certain elements stand out, you can guide the user's eye and create a sense of hierarchy.

As a last example, let's look at these two groups of rubber duckies again:

<Image
  publicId="newsletters/gestalt-design-principles-for-developers/gestalt-color"
  alt="Gestalt color"
  caption="Color can be used to draw attention to specific elements."
/>

If I told you that on **Side A**, every different color of duck has a specific meaning - would that be helpful? If you're like most people, you'd probably say no. There's just too many colors to keep track of.

Now take a look at **Side B**. What if I told you that different colors have a meaning here, and that there's a problem with one of the ducks...?

Exactly.

## Conclusion

Gestalt principles are a powerful tool for designers. They help us understand how people perceive and interpret the world around them, and they provide a framework for creating designs that are intuitive and easy to use. By understanding these principles, we can create designs that are not only visually appealing but also functional and effective.

I'm sure you've heard the old trope about how "breaking the rules" is the key to great design. In truth, it's hard to break the rules in a useful way if you don't understand them in the first place. Gestalt principles provide a solid foundation for understanding how people perceive and interpret the world around them, and they can help you create designs that are both visually appealing and easy to use.

---

## Further reading

- I keep a handy list of books devs interested in design called [The Designer's Reading List](https://hardcover.app/@irreverentmike/lists/the-designers-reading-list). It's worth a look if any of this has made your brain tingle.

- The Wikipedia entry for [Gestalt Psychology](https://en.wikipedia.org/wiki/Gestalt_psychology) is a fantastic jump-off point for more gestalt basics.

- File this one under miscellaneous tools for prototyping: I used Vercel's AI tool [v0.dev](https://v0.dev/) to generate the address forms in this article. It can be a really helpful way to _get started_ building an interface, but it's not a replacement for thoughtful design.

---

## Designers you should follow

This is a call to action for all of my developer friends: follow some designers! Design not just about making things pretty - it is primarily about making things work. Here's a few to get you started:

- [Dan Mall](https://danmall.com/) quite literally wrote the book on [Design that scaless](https://amzn.to/48hj7fc). He's currently working on Design System University, a course and community to help you build better design systems.

- [Carly Ayres](https://www.carlyayres.com/) is a designer who writes, currently working on the Content and Editorial team at Figma. The perspective she brings to her work is fascinating and evocative (seriously, check out her website), and her writing is [nothing short of incredible](https://www.figma.com/blog/the-new-vernacular-of-work/).

- Matt Smith, aka [@whale](https://www.threads.net/@whale) on Threads, runs a design agency called Bunsen Studio. I appreciate his perspective on bringing design to the forefront of the development process, and his ability to distill some seriously complex concepts into digestible interfaces.

---

## One other thing: please vote!

It's an election year, and it is going to be a damn important one. I'm not going to tell you who to vote for here, but I am going to tell you to vote. If you're in the US, you can find out how to register and vote at [Vote.org](https://vote.org). We're in the midst of primary season, and it's a great time to get involved in the process.

If you're not in the US, I encourage you to get involved in your local politics. It's important, and it's a great way to make a difference in your community.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Build, measure, listen, rebuild]]></title>
            <link>https://mikebifulco.com/newsletter/build-measure-listen-rebuild</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/build-measure-listen-rebuild</guid>
            <pubDate>Mon, 22 Jan 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Building better products involves skills you won't learn in computer science school, or at a boot camp. Find success through testing, learning from real-world feedback, and adapting.]]></description>
            <content:encoded><![CDATA[
There's a difference between the skills needed to write code, and those needed to lead a successful business.

Many people get into tech because they want to build a startup and change the world. But, as I've learned through my own journey, the skills needed to write code are not the same as those needed to build a successful business. The secret sauce is not taught computer science programs or at bootcamps.

This gap is significant, especially for those who dream of not just joining tech giants like Apple in 2024 but also for the trailblazers aspiring to be the founders of the next big thing.

A fundamental skill of building a product involves continuous evolution of product strategy. This is where feedback, analytics and iteration become invaluable. It's more than just building once; building, marketing, testing, learning from real-world feedback, and adapting are all critical ingredients. In our journey with [Craftwork](https://craftwork.com), for instance, the process of constantly tweaking and improving our product based on customer data has been crucial. It's a cycle of iteration that helps functional products becoming great ones.

A critical aspect of this iterative process is **measurement**. Understanding what to measure and setting realistic goals and metrics are foundational to any business's success. It's goes past trusting your gut; it's about making informed changes. At Craftwork, we've seen over and over that honest and realistic measurement of the right metrics is key. This approach helps us not only in refining our product but also in steering the business effectively.

It's a practice of self-honesty that transforms insights into actionable steps towards improvement.

This involves acknowledging what's working and, more importantly, what isn't. As I've built out my work with my personal site, I do my best to apply these same principles of measurement, honesty and self-reflection.

Regularly evaluating my creation and engagement strategies has been a journey. I do my best to regularly take an objective look at what resonates and what falls flat, and making informed decisions from there. This process, though sometimes daunting, is incredibly rewarding as it leads to a deeper understanding of my audience and a more impactful online presence.

Whether you're developing a product, building a business, or working on something else, I encourage you to constantly question, measure, and refine. So, take this challenge: measure your work, ask the hard questions, and be ready to change.

We're all somewhere between the before-picture and the after-picture. The key is to keep moving forward. 🚀

---

## Tools I use to measure

These are some of the tools I reach for to help me measure and improve my work. The links below also contain referral codes - if you sign up for any of these tools, I'll get a small kickback. If you'd rather not use the referral links, I ain't mad atcha.

- [PostHog](https://posthog.com/) has become an invaluable tool for understanding how people interact with the products I build. Being able to build dashboards with rich analytics and insights means the difference between guessing what's working and knowing what's working.

- [Fathom Analytics](https://usefathom.com/ref/DPSSYB) has long been the analytics tool I use for my personal site. It's simple, privacy-focused, and gives me the insights I need to make informed decisions about my content. Without it, I wouldn't know that in 2023, 10,000 unique people read my article about [Javascript's filter(Boolean) pattern](https://mikebifulco.com/posts/javascript-filter-boolean). That's pretty cool.

- [Transistor.fm](https://transistor.fm/?via=mike-bifulco) is where I host my various podcasts - including an audio version of [💌 Tiny Improvements](https://tinyimprovements.transistor.fm). In addition to being a dead simple hosting tool, I also get great analytics on listener patterns, and which episodes are hitting the mark.

---

## Creators who have my attention

These are some great creators who have been occupying my corner of the internet lately. Do yourself a favor and give them a follow.

- 🤖 Josep Ferrer is a tech writer and data analyst who has been producing a great series of [illustrations explaining ML and & algorithms](https://www.threads.net/@rfeers/post/C2WzdmwA1cn) on threads.
- 🎥 Andrew Peacock shares videos about developer productivity and tools on his YouTube channel. I really enjoyed his hot take on why [ChatGPT is making you a bad programmer](https://www.youtube.com/watch?v=MN1LO0EiXyA).
- ☕️ Brian Quan is a coffee expert who has gone deep down the rabbit hole, and has been making some great videos explaining the depths of the coffee industry. He's also crazy enough to make his own [pourover coffee at an airport](https://www.youtube.com/watch?v=HQAyoo5Lqpo), which is a level of dedication I can appreciate.

---

<Image
  publicId="posts/live-coding-resend-broadcasts-nextjs/cover"
  alt="Live coding: Resend broadcasts with Next.js"
/>

## I've been Live Coding again

I spent a few hours last weekend live coding on my YouTube channel, [@mikebifulco](https://youtube.com/@mikebifulco?sub_confirmation=1). I've got aspirations to publish more pre-recorded content as well.

You can see the replay on YouTube, or here: [Configuring Resend Broadcasts for newsletters on my Next.js website](https://mikebifulco.com/posts/live-coding-resend-broadcasts-nextjs)

If you're interested in seeing more videos from me, please [subscribe](https://youtube.com/@mikebifulco?sub_confirmation=1)!

---
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Why your favorite apps and creators all pivot in January]]></title>
            <link>https://mikebifulco.com/newsletter/creators-startups-january-pivot</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/creators-startups-january-pivot</guid>
            <pubDate>Tue, 16 Jan 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[The new year is a time for change. But why do so many apps and creators pivot in January? We explore the psychology behind the new year's pivot.]]></description>
            <content:encoded><![CDATA[
There have been _lots_ of interesting announcements from creators and startups this month. Many apps and services that once felt like they were here to stay are now shutting down. Similarly, many creators are announcing big changes to their strategy, or even stepping down from their roles entirely.

Seems like it's all happening at once, right? Well, in a sense -- it is. And there are a few reasons why that might be the case:

- For **creators**, December and January are the slowest months of the year. Advertisers' budgets are spent, and people are spending time with their families. As a result, many creators use this time to reflect on the past year, and plan for the next.
- For **startups**, the new year is often tied to intense budgeting and planning. The new year is a time when they need to show their investors that they're on track to meet their goals. If they're not, they may need to pivot, or even shut down.

Have you felt it? I've certainly seen a good number of surprising announcements. Here's an incomplete list of companies and creators who have announced big changes since the start of the new year:

### Companies making big changes

- A few days ago, Artifact, the news aggregator app created by the founders of Instagram, shared that they're [shutting down](https://medium.com/artifact-news/shutting-down-artifact-1e70de46d419) their services, after failing to find product-market fit.
- [Mint](https://www.mint.com), the personal finance app, is shutting down completely. Their orphaned users have been desperately searching for alternatives.
- [Prism Bills & Money](https://prism.com), a finance app used for automating bill payments, is also shutting down.

### Creators

- **Matpat**, Host of the YouTube channel _The Game Theorists_ [announced he's stepping down as the face of the channel](https://youtu.be/8R1_TqU68yo?si=1PQEWufTl_letIcO). TGT has **18.7M subscribers** on YouTube.
- **Tom Scott** posted a video explaining that after 10 years of videos every week, he's [taking a break](https://youtu.be/7DKv5H5Frt0?si=2W-72NhfIviI0TI5) for an undetermined amount of time. Tom has **6.4M subscribers** on YouTube.

### Sort of both, and kind of neither

You may have seen recently that Substack is bleeding creators left and right over their [spineless content moderation policy decisions](https://mashable.com/article/why-are-people-leaving-substack-content-moderation-controversy) (or lack thereof). Newsletter creators are jumping ship to other platforms left and right.

[Patreon](https://news.patreon.com/articles/patreon-reimagined) announced a major change to their business model, which will affect creators and patrons alike. Patreon has been the place where fans can support creators they love, by pledging a monthly amount to them. Patreon takes a cut of the pledge (though a much smaller cut than YouTube might, for example), and the rest goes to the creator.

With their new pivot, they are now hoping to become the place where fans can go to see what creators are making without being subject to _the algorithm._ In short, Patreon itself is trying to become a social network.

Will it work? Who knows. But it's a big change -- and while this announcement happened back in October, Patreon has been steadily rolling out changes to align with their new vision since then.

## These changes create opportunities

This, dear reader, is where you come in - as the market shifts with these changes, there are opportunities for you to make your mark. If you're looking for inspiration, here are a few examples:

- Derek Gaston ([@Friedmud on Threads](https://threads.net/@friedmud)), is an indiehacker who has been building a personal finance app called [Splurge Budget](https://splurgebudget.com/). He's been building out in the open and sharing his progress and learnings on Threads.

- Developer-focused email platform Resend just announced feature called [Broadcasts](https://resend.com/blog/send-marketing-emails-with-resend-broadcasts), which suddenly allows them to compete with Existing newsletter platforms and email marketing tools like Mailchimp and ConvertKit. I'm planning to give Resend's newsletter feature a shot - and hopefully livestream my experience building with it on my YouTube Channel [@mikebifulco](https://youtube.com/@mikebifulco).

As ever, if you've been working on building something, now is the time to step on the gas, particularly if you're building something that suddenly fills a void which once felt permanent. Use the momentum of these changes to your advantage, and find places where you can make your mark.

---

Here's some things I've worked on recently:

- We released a fresh interview over at APIs You Won't Hate - my cofounder Phil spoke with Darrel Miller and Vincent Biret from Microsoft about [🎙️ Kiota, Microsoft's product for manging an API with 20,000 endpoints](https://apisyouwonthate.com/podcast/microsoft-kiota-graph-api-darrel-miller-vincent-biret/)
- We also released a series of articles about [Low Code and No-Code APIs](https://apisyouwonthate.com/newsletter/low-code-no-code-apis/). [Getting devs to adopt low code tools](https://mikebifulco.com/posts/devs-its-okay-to-use-no-code-tools) is a topic near and dear to my heart, and it's great to see API tools moving into this world.
- I also started recording mini-podcasts of some Tiny Improvements newsletters. If, paradoxically, you've read this far but you'd _also_ prefer to hear me read this newsletter to you, you can listen and subscribe to here:[Tiny Improvements (the podcast)](https://tinyimprovements.transistor.fm/)
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Fitts' Law and the Beauty of Big Goals]]></title>
            <link>https://mikebifulco.com/newsletter/fitts-law-and-the-beauty-of-big-goals</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/fitts-law-and-the-beauty-of-big-goals</guid>
            <pubDate>Tue, 09 Jan 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Fitts' Law is a fundamental principle of UX design and usability. It states that the time required to move to a target is a function of the distance to the target and the size of the target. The further away and smaller the target, the longer it takes to reach it. The closer and larger the target, the faster it is to reach it.]]></description>
            <content:encoded><![CDATA[
<small>

_Editor's note: Happy New Year, gang! Tiny Improvements took off for a few weeks at the end of the year so I could [fix my leg, lol](https://www.threads.net/@irreverentmike/post/C1GCgSVsZ5t), but we're back in action and will be coming to your inbox mostly-weekly for the foreseeable future. I hope you're well._

</small>

**Fitts' Law** is simple: the time required to move to a target is a function of the distance to the target and the size of the target. The further away and smaller the target, the longer it takes to reach it. The closer and larger the target, the faster it is to reach it. ([Wikipedia](https://en.wikipedia.org/wiki/Fitts's_law))

<Image
  publicId="newsletters/fitts-law-and-the-beauty-of-big-goals/fitts-law"
  alt="An illustration of Fitts' Law"
/>

This is the reason that actions you take in phone apps are on large buttons near where your thumb is. It's why the "X" to close a window is in the top right corner of the screen. It's also why it's so hard to click on a tiny link on a website, and why you have to focus more to move your cursor to the right spot in a text document.

Big, well-placed targets are easier to hit than small, far away targets.

...You see where I'm going with this yet?

## Tiny Improvements and Big Goals

I'm not going to sit here and tell you that it's _easy_ to reach your goals. No matter what you're after, it's going to take time, effort, and focus. But I do think that it's _easier_ to reach your goals if you set some audacious targets, and work towards them with small, consistent improvements.

When I set out to start publishing articles, I **made a list of 50 people** from the industry who I would be _thrilled_ to see reading my words. This was my target - the bullseye I was aiming for. These weren't necessarily people I knew, but they were people who I admired, and who I thought would be interested in what I had to say.

Every time I brainstormed new topics, I'd try to write for the people on that list. Was it reasonable to think that I'd get _any_ these 50 people to read what I have to say? Maybe not, but the audacity of the goal helped me to focus on writing for a specific audience, and that's helped me to write better.

From there, I started publishing an article a week (this was before Tiny Improvements existed). I would thoughtfully share my work through twitter, reddit, LinkedIn, and Dev.to. When the context was right, I'd reply to posts from the people on my list, and I'd try to be helpful and add value to the conversation.

And you know what?

It was **less than three months** before I had one of the people on that list read and respond to one of my articles (on Twitter, which was a different place back then).

Fast forward to today, and after years of consistent effort, I've gotten better at writing, and built a small audience. From time-to-time, I even get messages from friends that they've seen my articles shared by people they follow, which is a pretty cool feeling.

<Image
  publicId="newsletters/fitts-law-and-the-beauty-of-big-goals/sharing-is-caring"
  alt="One of my articles share on twitter by Sebastien Lorber from This Week in React, and responded to by Joel Hooks from Egghead.io"
  caption="I got a message from a friend after Sebastien was kind enough to share a recent article of mine on twitter, and it got a reply from Joel. I've been learning from both of these dudes for years, and it was a great feeling to see them talking about my work."
/>

My great, big goal was to get one of these 50 people to read and respond to one of my articles, and it was a great feeling! The surprising side-effect was that I had also built a growing audience of people who were interested in what I was sharing, and I was helping people all over the world who were trying to learn the same things I was learning.

That's why I love Fitts' Law: it's a reminder that big targets are easier to hit than small ones. If I had set out to get _one_ person to read my articles, I probably would have stopped after the first few weeks. But because I had a big goal, I was able to focus on the small, consistent improvements that would get me there.

So: when you set goals, make 'em big.

---

### Tools for moving towards that big bullseye

- I love [The Theme System Journal](https://www.themesystem.com/), because it looks at New Years' resolutions through a simpler lens: you'll set a _theme_ for your year, and every day you'll do something to move towards that theme. It fosters gratitude and self-reflection, which are critical tools for personal growth.

- If you're building a product by yourself, [Indiehackers](https://indiehackers.com) is a great community for getting feedback and support. It's a great place to share your work, and to learn from others who are doing the same.

- For learning and inspiration, The podcast [Acquired](https://acquired.fm/) is a great listen. They do deep dives on the stories behind some of the biggest acquisitions in tech, and it's a great way to learn about the history of the industry.

---

### From one of my other corners of the internet

We've been busy over at APIs You Won't Hate, the community website I run with the help of my friends Phil Sturgeon and Alex Karan. We'll be realeasing a bunch of new podcasts in the coming weeks, and have recently published a handful of articles:

- [Low Code & No Code API Solutions - Are they Right for You?](https://apisyouwonthate.com/blog/no-code-low-code-api-solutions/) It's no secret I'm a fan of no-code tools. How do they fit into the API landscape?

- [LintGPT: AI for API Governance](https://apisyouwonthate.com/blog/ai-powered-api-linting-with-optic/) - one of the trickiest things about building a great API is making sure that it's consistent. LintGPT is a tool that uses AI to help you do just that.

---

And hey, I'm still at it over on Threads [@irreverentmike](https://threads.net/@irreverentmike) - I'd love to hear from you if you're on there!
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[The product design spectrum: crowdsourcing, user research, and the myopic approach]]></title>
            <link>https://mikebifulco.com/newsletter/crowdsourcing-vs-user-research-ux</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/crowdsourcing-vs-user-research-ux</guid>
            <pubDate>Tue, 05 Dec 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[In product design, there's a critical difference between crowdsourcing ideas and feedback, and user research.]]></description>
            <content:encoded><![CDATA[
Crowdsourcing ideas is a great way to hear opinions from a wide variety of people. But it's not a great way to design a product, and it's definitely not user research -- let's talk about why.

### Hawkeye: ZTE's sticky phone, and the double-edged sword of crowdsourcing

In 2016, Chinese smartphone manufacturer ZTE launched a crowdsourcing campaign to find out what features people wanted in their next smartphone. They asked people to submit ideas, and then vote on the ideas that they liked best, with the promise that the most popular ideas would be incorporated into the next phone.

Here's a snippet from a Trusted Reviews article about the campaign:

> Earlier this year, in what could be the best or worst decision ever made, Chinese smartphone maker ZTE turned to the general public for ideas for its next smartphone.

(cue foreboding music)

As you might imagine, after asking The Internet™️ to submit ideas for something, they ended up with _many_ varied responses. The result was a full on fever-dream of a phone, called _Hawkeye_. In addition to an array of typical features you'd expect from a smartphone, it also had:

- **Eye tracking**: the phone would scroll up and down based on where you were looking.
- **A self-adhesive back**: the phone would stick to any surface, like a wall or a window, so you could take selfies or watch videos hands-free
- **A vaguely defined split screen feature**: despite what you might guess, this was described as "...[a] feature that allows only the user to see what's on-screen". I'm honestly not sure what that means.

Don't get me wrong, if done well, at least one of these features could be really useful for accessibility. You could certainly never sell me on carrying a _sticky_ phone in my pocket (or holding one up to my face, for crying out loud). It's a confusing grab-bag of features that don't seem to have much in common, and it's hard to imagine how they would work together.

So, how did it turn out? Well... it didn't. After crowdsourcing ideas and building prototypes of the phone, ZTE launched a kickstarter campaign, likely in an effort to gauge interest in the phone. They raised $36k of their $500,000 goal, and the [project was cancelled](https://www.theverge.com/circuitbreaker/2017/2/17/14647990/zte-hawkeye-phone-kickstarter-campaign-end).

So what happened? Why did this campaign fail so spectacularly? Well, I think the nature of campaigns like this on the internet is not to find the best ideas, but to find the most _popular_ ideas. And the most popular ideas are not always the best ones, especially when there's so much clout to be gained from having your idea chosen (oh hey, _[boaty mcboatface](https://www.nytimes.com/2016/03/22/world/europe/boaty-mcboatface-what-you-get-when-you-let-the-internet-decide.html),_ didn't see you there!).

Think about it - how many of your least favorite products feel like they were designed by a committee? I can think of a few examples of products that I _used to_ love that have gotten bloated and confusing, particularly after an enterprise-scale company acquired them.

---

### The myopic approach: Why automakers don't have just _one_ designer

On the opposite side of the "let's crowdsource a product", there's the myopic approach. Putting trust in _just one person_ to design a product is exceedingly rare. To be successful, that person has to have an acute ability to understand the needs of the people who will use the product, and to design something that meets those needs, while also being technically feasible and financially viable.

This has happened in the automotive industry -- a place where R&D costs are immense, and the cost of a failed product can be catastrophic.

Imagine that: an auto manufacturer trusting _one person_ to design a car for broad public adoption, with a host of features that aren't exactly cohesive, a design that's... _unique_, and a pricetag that's higher than the competition.

The result is an odd amalgum of features that reveal a window into just-one-person's vision of what a car should be. This results in a list of headline features that nobody was asking for, an incoherent, polarizing, and difficult-to-manufacture design, and a product that has no clear target audience.

All with the capacity to bankrupt a company, and all because somehow all the decision-making power was given to a single, thoughtless, out-of-touch idiot, who was allowed to run amok with their own ideas.

[This is why we shouldn't throw rocks at a (window) to see what sticks](https://www.youtube.com/watch?v=EHGczDHTDpo).

---

## Conclusion: listen to your users, but don't let them design your product

Feedback is a gift - always. But setting yourself up to receive feedback that is actually useful is a skill. Taking a lazy or naive approach to feedback can be a costly mistake, especially if you're not able to separate what people are _saying_ from what they're telling you.

Of course, the other side of the spectrum is a myopic approach - not collecting data or feedback at all, and going with your gut to product development that doesn't take into account the needs of your users.

<Image
  publicId="newsletters/crowdsourcing-vs-user-research-ux/spectrum"
  alt="The product research spectrum"
  caption="Each can have successful results, but one is a lot more likely to succeed than the others."
/>

Both of these approaches are dangerous, and both can be avoided by taking a more thoughtful approach to product development. User research, user testing, and a healthy dose of skepticism are all important tools in your product development toolbox. These are all techniques that require you to be thoughtful about the way you collect feedback, and to _interpret_ the feedback you receive, rather than blindly accepting it.

Even that takes practice, and can lead to mistakes. But it's a lot better than the alternative.

---

## You may want to check these out

- ⛑️ I published an article on adding [self-healing URLs to your Next.js site](https://mikebifulco.com/posts/self-healing-urls-nextjs-seo), as a way to improve site accessibility, SEO, and user experience. It was inspired by a video from youtuber Aaron Francis, showing how to accomplish the same thing in [Laravel](https://www.youtube.com/watch?v=a6lnfyES-LA)
- ✂️📄🪨 Legendary YouTuber CGP Grey's recent video [Can You Win this One-in-a-Million Game?](https://www.youtube.com/watch?v=PmWQmZXYd74) is surprisingly one of the most awe-inspiring, creative, existentially challenging YouTube projects I've ever experienced. I won't spoil it for you -- but it's worth your time and attention.

---

## Thanks for reading!

Hey, be good to yourself - December is a tough month for a lot of people, for a wide variety of reasons. I'm here to tell you that you're doing great, and we'll be unwrapping a brand-spanking-new year in just a few weeks. Keep the faith, and as a wise man once said, [peace be the journey](https://www.youtube.com/watch?v=fu_6DXHut-Y).
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Learning is an infinite game]]></title>
            <link>https://mikebifulco.com/newsletter/learning-is-an-infinite-game</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/learning-is-an-infinite-game</guid>
            <pubDate>Tue, 28 Nov 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[As a founder, you're going to need to learn new skills quickly and efficiently. Keeping your skill for learning sharp is a critical skill, and should can be practiced like any other skill.]]></description>
            <content:encoded><![CDATA[
Learning is an infinite game. You can't win or lose, you can only keep playing. As a founder and a builder, you will regularly find yourself needing to quickly and efficiently learn new skills.

I graduated from UConn in 2009 with dual engineering degrees: one in Computer Science, and one in Mechanical Engineering. The first field of study was a no-brainer: since my first days of high school, I loved writing code and building software. Studying Mechanical Engineering was more of a misguided whimsy - my dad had a long career as a mechanical engineer, and thanks to him I developed a love for classic american cars. I studied mechanical engineering thinking I might want to get a job in the automotive industry.

Fast forward 14 years (my god!), and I've never worked a day as a mechanical engineer... until last week.

At [Craftwork](https://craftwork.com), we recently signed on to a project that has us painting the same type of door many, many times. The doors are made of metal, and we'll be painting them with a spray gun. However, we can't get paint the latch mechanism, so we need to mask it off. We could do this by hand, but it would take a long time.

We have... hundreds of these doors to paint. Maybe thousands. Each with the same latch mechanism that needs to be masked off, and then unmasked after painting.

Enter 3D Printing.

It's the _perfect_ tool for this job. We can design a simple mask in CAD, and then print it out. We can print as many as we need, and adjust the design as needed.

The only problem? It's been, uh, 14 years since I've done any 3D modeling, and I've never done _any_ 3D printing.

In the span of about 10 days, I went from knowing nothing about 3D printing to having a working prototype of a mask that we can use to paint these doors. I quickly researched a number of critical topics, including:

- which 3D printer to buy
- the latest in 3D modeling software
- how to design for 3D printing
- the difference between various 3D printing materials

...all while working on a number of other projects, and in addition to the complexity of the actual problem we're trying to solve (painting these doors).

<Image
  publicId="newsletters/learning-is-an-infinite-game/onshape"
  alt="Screenshot from CAD software Onshape"
  caption="I used a tool called OnShape to design the mask. It's a fully browser-based tool. Insane!"
/>

This is not to say that I'm a particularly gifted engineer, or a brilliant 3D-print...ist. Instead, I think the important nugget here is something that I've learned over the years: **learning is a skill**, and as a founder, you need to be good at it.

Here are some tips that I've picked up over the years that have helped me learn new skills quickly and efficiently:

## 1. Learn from the best resources you have access to

You don't need to reinvent the wheel. There are people out there who have already done what you're trying to do, and they've probably written about it.

When I was learning about 3D printing, I found a number of great resources that helped me get up to speed quickly. From previous passing interests in 3D printing, I knew of a few youtube channels that ended up being super helpful. Thanks to my schooling, I also have a cadre of _actual_ mechanical engineers who I can rely on for advice (shout out to Sean, James, Andy, & Mike - y'all are the true MVPs here). I consulted my dad, who spent 40+ years doing CAD and mechanical engineering. I read tech reviews, and I read the documentation for [the 3D printer I ended up buying](https://us.store.bambulab.com/products/x1-carbon-combo).

My point is this: you don't need to go it alone. Find the best resources you have access to, and learn from them.

## 2. Learn by doing, and act quickly

I'm a big believer in learning by doing. I've found that I learn best when I'm working on a project that I care about, and I'm learning the skills I need to complete that project.

While researching for my project, there were many opportunities along the way to take what I was learning and _use_ it to make progress on my project. I could have spent more time researching, but time spent researching is time not spent building.

## 3. Learn from your mistakes

You're going to make a lot of mistonks -- and every one you learn from makes your understanding of the world around you that much more accurate.

I iterated on the design for our painting mask 5 times before I got it right. In 3D Printing, that means I'd spend some time modeling the mask, and then wait a few hours for it to print out. I'd then test it, and see what worked and what didn't. I'd then go back to the drawing board, and make changes to the design.

<Image
  publicId="newsletters/learning-is-an-infinite-game/prototypes"
  alt="A series of 5 prototypes for the mask on my desk"
  caption="I iterated on the design for our painting mask 5 times before I got it right."
/>

One thing that struck me during this process is how similar modeling & printing are to debugging software. The main difference is that debugging software is virtually _instant_ gratification - you can make a change, and see the results immediately. With 3D printing, I'd have to wait hours to see the results of my changes. It requires more patience, and a deliberate approach to getting things right.

In the end, it's looking like this project is going to be a success. These 3D printed masks will do the trick for this project, and the skills and techniques I've learned will be useful for future projects, whether directly or indirectly.

Perhaps most importantly, this was another mega-deep dive into something new, and I'm better for it. I'm also deeply grateful to my wife, who saw me disappear into my office for hours at a time, and put up with me staring into the middle distance as I thought through the next steps in the process. She's a saint.

tl;dr: learning is a skill, and as a founder, you need to be good at it. Part of building something new is taking decisive action quickly, and learning _quickly_ from experts in the field. Take what you learn, turn it into applied science, and iterate quickly. You'll be amazed at what you can accomplish.

**Now, it's your turn** - have you found yourself going down the rabbit hole for something new recently? I wanna hear about it! Hit reply and let me know what you're learning about, and how it's going.

---

## More filament extruded from my brain

(It's a 3D printing joke. I'll stop.)

- 🎙️ In the latest APIs You Won't Hate podcast, I [caught up with Danny Sheridan from Fern](https://apisyouwonthate.com/podcast/catching-up-with-danny-sheridan-from-fern/) to talk about the incredible tooling they're building for generating API clients and documentation from OpenAPI specs.
- 📰 [Craftwork was featured by Forbes](https://www.forbes.com/sites/brucerogers/2023/11/17/craftwork-out-to-modernize-home-services-market-scores-6-million-seed-round/), and I still can't believe it. I'm so proud of the team we've built, and the work we're doing to make home services better for everyone. What a journey so far - and we're just getting started.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[3 Ways to use Annual Pricing to your advantage]]></title>
            <link>https://mikebifulco.com/newsletter/use-annual-pricing-build-loyalty</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/use-annual-pricing-build-loyalty</guid>
            <pubDate>Tue, 14 Nov 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Annual pricing is a great way to increase your revenue and decrease your churn. Here are 3 ways to use annual pricing to your advantage.]]></description>
            <content:encoded><![CDATA[
In a recent dispatch of Tiny Improvements, we talked about [the Decoy Effect](https://mikebifulco.com/newsletter/decoy-effect-and-your-brain), and why it makes sense to offer 3 price tiers for your product. It's a great way to show your customers the benefits of paying a bit more for your product, and it's a great way to increase your revenue.

Once you've proven to a customer that your product is worth paying for, it should be your goal to _retain_ that customer, showing them that your product is worth paying for _again_. It's an important inflection point for your relationship with a customer - in a sense, you're switching from persuasion to _care and compassion_.

Your best customers will be the ones who can feel the love - the ones who both value your product and feel valued by you. This is why I want to talk about annual pricing, and how you can use it to your advantage to build loyalty with your customers.

## 1. Offer a discount

The most obvious way to use annual pricing to your advantage is to offer a discount. This is a great way to show your customers that you value their business, and it's a great way to increase your revenue.

The discount you offer is up to you, and it really doesn't need to be much. I've seen discounts as low as 5% and as high as 20%. The important thing is that customers see a benefit for switching, and that you're making it clear that by committing to a longer billing cycle, your customer is saving money.

## 2. Remind monthly customers that you can save them money

If you're offering annual pricing, you should be reminding your monthly customers that they can save money by switching to annual billing. Consider doing this a month or two after they've signed up for your product, particularly if you're able to tell that they have been using the product regularly.

If that doesn't work, send another reminder around a year after they've signed up. This is a great way to show your customers that you value their business, and it's a great way to increase your revenue.

Here's an example of an email I received from [Riverside FM](https://riverside.fm/?utm_campaign=campaign_1&utm_medium=affiliate&utm_source=rewardful&via=mike-bifulco) a few months after I signed up for their product:

<Image
  publicId="newsletters/use-annual-pricing-build-loyalty/riverside-upgrade"
  alt="Screenshot of an annual plan upsell email from Riverside FM"
  caption="A personalized touch and a thoughtful email got me to switch to annual billing."
/>

## 3. Give advance notice of upcoming charges

Once a customers has switched to annual pricing, it can be easy for them to forget that they're paying for your product. For this reason, it can be a good idea to send them an email a month or two before their annual billing cycle is set to renew. This will help ease the sting of the charge, and it will give them a chance to cancel if they're no longer using your product.

This is also a great time to remind customers of the value they're getting from your product. If you've got the analytics in place, consider including some stats about how they've used your product over the past year.

You might also want to include a link to your public release notes, or a short list of new features that you've added over the past year. This is a great way to show your customers that their money is helping to build a better product.

<Image
  publicId="newsletters/use-annual-pricing-build-loyalty/fathom-annual"
  alt="Screenshot of an annual reminder email from Fathom Analytics"
  caption="Fathom's annual billing email is well-written, consistent with their brand, and written to make the customer feel appreciated. That's good stuff."
/>

It's no secret that I love [Fathom Analytics](https://usefathom.com/ref/DPSSYB) - their product is delightful, and their messaging is always on point. This email is a great example of how to use annual billing to build loyalty with your customers.

---

## Tiny Improvements reader launches

I've been really happy to hear from lots of Tiny Improvements readers who have shared what they've been working on. If you've got a project that you'd like to see featured here, [send me an email](mailto:hello@mikebifulco.com) and tell me about it!

- Andris launched a site to market their interior design rendering service, [Ayarender](https://www.ayarender.com/). It looks like a great offering, and a good way to give potential buyers confidence in what they're getting.

Congrats on the launch!

---

## Stuck in my brain this week

- 🧪 Over at APIs You Won't Hate, we released a writeup comparing [OpenAPI Bundling Tools](https://apisyouwonthate.com/blog/openapi-bundling-tools-compared-blog-post/). There's a lot of options, each with their pros and cons. Give it a look.
- 🧮 My good friend and polyglot dev Josh Finnie recently put up a tutorial about [Creating a vCard QR Code in Python](https://www.joshfinnie.com/blog/creating-a-vcard-qr-code-in-python/). Generating a code is one thing, but the cherry on top is adding a little branded flair.
- 📱 I've been digging into react-native for mobile app development, and found a great tutorial from YouTuber Simon Grimm on [File-based routing in react-native](https://www.youtube.com/watch?v=RglRiycD0oQ&t=1508s).
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[The Decoy Effect: More options for an easier choice]]></title>
            <link>https://mikebifulco.com/newsletter/decoy-effect-and-your-brain</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/decoy-effect-and-your-brain</guid>
            <pubDate>Tue, 07 Nov 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[The Decoy Effect is a cognitive bias that causes people to have a strong preference between two options, when presented with a third option that is inferior to one of the original options.]]></description>
            <content:encoded><![CDATA[
Last week, Apple had a press event where they announced updates to their Macbook Pro laptops. They're better, faster, and more power efficient than ever - no surprises there. Since apple started delivering devices that use their proprietary processors, they have been leading the pack in terms of performance and efficiency.

Their computers are exceptional devices, and great for people who want to get work done. But they are also expensive. The new Macbook Pro starts at $1,599, and can go up to a _startling_ $6,899. That's a lot of money for a laptop.

Generally speaking, if you're looking at a Macbook, you're not also looking at a Dell or a Lenovo. This puts apple in an interesting position: when someone is looking to buy a Macbook, they are not comparing it to other companies' products. They are comparing it to other Macbooks.

So, if you've convinced yourself that it's time to buy a new Macbook Pro, you'll find yourself looking at this page:

<Image
  publicId="newsletters/decoy-effect-and-your-brain/macbook-pro-pricing"
  alt="Screenshot of the Macbook Pro pricing page on apple.com"
/>

You're given 3 options: the entry level MBP for $1599, a mid-tier build for $1799, and a high-end build for $1999.

Which one would you choose?

## Three options, but only two choices

If you're shopping on a tight budget, the entry level model might be a no brainer. But if you've got some room to breathe, you might be tempted to go for the mid-tier configuration. It's only $200 more, and you get twice as much storage.

But then... what about the high-end model? For a mere $200 more, you get a more CPU _and_ GPU cores, more than twice as much memory (8GB->18GB), and faster USB ports. Storage does go back down to 512GB, buuuut you can upgrade that, too, if you really want to.

It's a _slippery_ slope. I'm willing to bet Apple sells far more of the top-tier configuration than the mid-tier one.

### This is the Decoy Effect.

The Decoy Effect is a cognitive bias that causes people to have a strong preference between two options, when presented with a third option that is inferior to one of the original options.

Wikipedia explains it like this:

> **The decoy effect** is the phenomenon whereby consumers will tend to have a specific change in preference between two options when also presented with a third option that is asymmetrically dominated. An option is asymmetrically dominated when it is inferior in all respects to one option; but, in comparison to the other option, it is inferior in some respects and superior in others.

In practice, this means that when presented with two options, buyers have a hard time choosing between them. But if presented with a carefully crafted third option, the decision becomes much easier.

For real: giving your customers **more choice** makes it **easier** for them to make a decision.

## The Economist's pricing experiment

Perhaps the most famous example of this is from The Economist. In 2009, they ran an experiment where they offered two subscription options:

<Image
  publicId="newsletters/decoy-effect-and-your-brain/economist-2"
  alt="Two options: web only for $59, or web + print for $125"
/>

In this case:

- 68% of people chose the web-only option
- and 32% chose the more expensive web + print option.

Then, they ran a second experiment, where they added a third option:

<Image
  publicId="newsletters/decoy-effect-and-your-brain/economist-1"
  alt="Three options: web only for $59, print only for $125, or web + print for $125"
/>

With a third option added:

- 16% of people chose the web-only option
- 0% chose the print-only option
- 84% chose the web + print option.

In other words, offering a third (clearly inferior) option _increased_ sales of the top tier dramatically.

### The lesson: product tiers are powerful

This is why almost every SaaS company has multiple product tiers. It's not just to make more money (although that's a nice side effect). Not only do product tiers make it easier to drive more revenue, they also make it easier for your customers to make a decision.

**That's _wildly_ powerful stuff.**

So, for all my friends out there building products to sell to other people: don't undermine yourself by offering a single product tier. Give your customers options, and make it easy for them to choose.

---

## More on the Decoy Effect and Behavioral Economics

- The Decision Lab has a great article called [The Decoy Effect, explained](https://thedecisionlab.com/biases/decoy-effect) which dives further into the psychology that drives consumers to make decisions this way.
- When you're ready to put together a pricing table to present to your customers, Stripe's [Pricing Tables](https://stripe.com/docs/payments/checkout/pricing-table) feature makes it effortless to create a beautiful, effective pricing table. In fact, I used them to mock up screenshots for the economist example above!
- If you're looking for a primer on Behavioral Economics, you can't beat [Predictably Irrational](https://www.amazon.com/Predictably-Irrational-audiobook/dp/B0014EAHNQ/?&_encoding=UTF8&tag=irreverentm04-20&linkCode=ur2&linkId=d8f5a50920edf15e85fc0ba646ea0642&camp=1789&creative=9325), by Dan Ariely.

---

## 💌 From the Tiny Improvements Mailbag

Last week, I asked you to send me the projects that _you're_ working on. Here are a couple of the responses I got:

- Aaron Dodge is working on a [relaunch of his website](https://www.aarondodge.com/). If you're looking for expertise in building a presence on social media, Aaron is your guy.
- My friends at Swishjam have pivoted their business to focus on building a "[better way to unify your customers' data and get meaningful insights](https://swishjam.com/)". It looks promising, and is Open Source, too!

Even more of you replied to let me know that you're working on something, but you're not quite ready to share it yet. I can't say it enough: share your work [early](https://mikebifulco.com/newsletter/no-right-way-to-do-it) and [often](https://mikebifulco.com/newsletter/how-to-know-when-to-publish-your-work). It's the best way to get feedback, to build and audience, and to validate what you're doing.

I'd love to keep featuring your projects in this newsletter. If you're working on something, [hit reply](mailto:hello@mikebifulco.com] and let me know about it!

---

As for me, I just got back from an incredible 2-week vacation to Vietnam and Japan. I have _never_ taken 2 weeks off of work before, and I can't tell you how grateful I am to my team at [Craftwork](https://craftwork.com) for making it possible. I am _beyond_ lucky to work with such an incredible group of people.

I took a ton of pictures during my trip with my trusty Fujifilm x100v. I've been sharing some of them over on [Threads (@irreverentmike)](https://threads.net/@irreverentmike):

<Threads url="https://www.threads.net/@irreverentmike/post/CzRzZEqvrFA" />

If you're on threads, hit me up and say hi!

Until next time...
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[There's no right way to do it]]></title>
            <link>https://mikebifulco.com/newsletter/no-right-way-to-do-it</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/no-right-way-to-do-it</guid>
            <pubDate>Tue, 31 Oct 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Building products comes with a sisyphean paradox: The blessing is that there are so many ways to do it. The curse is that there are so many ways to do it.]]></description>
            <content:encoded><![CDATA[
## Raise your hand if you've done this before:

You're working on an exciting new feature, new article, or doing _anything_ creative. You're in the zone, and you're feeling good. You're making progress, and you're excited about the outcome.

Then, a thought occurs. Is your approach going to be scalable? Will it be maintainable? Do other people have a better way of doing it? So, you go into research mode, and start scribbling down notes for your new plan of attack.

Hours later, you're still researching. You've read a dozen articles, watched a few videos, and you're more confused than ever. You've found a dozen different ways to do it, and you're not sure which one is the best.

You're spiraling. Next thing you know, you've wasted days thinking about how to do it, and you haven't made any progress.

## Choice: Flip it and reverse it

I've been on vacation for the past week, traveling throughout Vietnam with my wife. She had a a two-year stint teaching at an international school in Hanoi, so I've spent lots of time here over the years. It's one of my favorite places in the world. People here are kind and charming, and the food and coffee are incredible.

One of the things that is the most striking about visiting vietnam is that driving is very different here than in the states. Most people ride 150cc motor bikes, and traffic can feel like a bit of a free-for-all at first. There are clear lane markings on most road, but cars and bikes drift between them without warning. Traffic lights here actually count down the seconds until they change, and it's not uncommon to see people leave a stoplight a second or two before it turns green.

There are also very few traffic accidents, from what I've seen. People are very aware of their surroundings, and they're constantly adjusting their speed and direction to avoid collisions.

It can be a bit jarring at first, but it's also a lot of fun. It's a bit like a dance. Everyone is moving in a different direction, but somehow, it all works out.

I've been thinking a lot about this over the past week, and I think there's a lesson here for us as makers. The rules (written & unwritten) that have developed for driving here are the result of a different set of constraints than the ones we have in the states. The roads are narrower, and there are more people. The cars are smaller, and the bikes are faster.

The rules that work here wouldn't work in the states, and vice versa -- but they solve the same problem. More importantly, they solve the problem _well,_ and one isn't better than the other.

<Image
  publicId="/newsletters/no-right-way-to-do-it/cafe"
  alt="My laptop on a table next to an espresso and a glass of water, at a cafe in Hanoi"
  caption="Was I up at 6:30am to write a newsletter while on vacation? Maybe. But it shipped!"
/>
## There's no right way to do it

This had me thinking about the way we build products. I've talked to many founders and indiehackers who spend the early days of their product journey researching the "right" way to do things. They spend more time talking about _the thing_ than building it. They talk about the problem to no end, and don't make any progress on the solution.

Friends, here's the thing: **just ship something**. Ship it. Ship it. Ship it.

Deploy your code, put it in front of real people, and open your mind and your heart to feedback and criticism. You'll learn more in a week of shipping than you will in a month of research.

There's no right way to do it. There _are_ many ways to do it, and if you ship more often, you'll find a path that works for your project. You'll be able to change more rapidly, and you'll be able to adapt to the needs of your customers.

You'll become a better product builder by shipping products, not by reading about how other people build products.

---

## Send me your project

Here's your call to action for the week: I want to know what you're working on, and I'd love to share your work here in Tiny Improvements. Send me what you're working on, and I'll share it with the community. I'll also give you a shoutout on Threads and LinkedIn.

Hit reply on this email, and send me a link to your project. I can't wait to see what you're working on!

---

## Recommendations from my playlist

- 🎙️ Colin & CJ over at [Build & Learn](https://buildandlearn.dev/) have been podcasting about career growth and building things as software engineers. CJ is a teammate of mine at Craftwork, and Colin works in DevRel at Discord - they're two devs who really know their stuff.

- 📖 I just finished listening to [Oversubscribed](https://www.amazon.com/Oversubscribed-How-People-Lined-Business/dp/B085P1N7LR/ref=sr_1_1?keywords=oversubscribed&qid=1698715330&sr=8-1&_encoding=UTF8&=irreverentm04-20&=ur2&=37e3d32d3a23dee0fda9150b61b2e135&=1789&=9325) on Audible. The book's tagline is "How to Get People Lined Up to Do Business with You" - and it gets right to the point. It's a great read for anyone who is building a product or a business, and it's full of proper advice from real-world experience.

## What I'm working on

- 🎙️ In my latest interview for Software Engineering Daily, I talk to [Tsavo Knott, the CEO of Pieces for Developers](https://softwareengineeringdaily.com/2023/10/25/building-pieces-app-and-the-future-of-developer-productivity-with-tsavo-knott/) about their product, an automated second brain for devs and engineering teams using some insanely cool multi-modal LLMs. If you've ever had that feeling that you read about something _somewhere_ but now you can't find it, Pieces is looking out for you.
- 🧶 I have been posting quite a bit on [Threads (@irreverentmike)](https://www.threads.net/@irreverentmike) lately. These days, the tech community on Threads is feeling a whole lot like the best days of twitter (RIP), and it is really refreshing. If you're active on Threads, hit me with a follow - I'd love to follow you back!
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Chase your interests to build something useful]]></title>
            <link>https://mikebifulco.com/newsletter/build-something-useful-with-ai</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/build-something-useful-with-ai</guid>
            <pubDate>Tue, 17 Oct 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Explore the power of hyperfixation on the internet, from tech enthusiasts diving deep into topics to engineers creating innovative solutions. Discover how curiosity can lead to expertise and groundbreaking tools.]]></description>
            <content:encoded><![CDATA[
If there's one thing I appreciate about the internet, it's people who find themselves fixated on a topic, and go _really_ deep to research and find the answer to a question. It's a helpful reminder that the internet puts huge power at our fingertips, and the connections available to us are truly incredible. There's something really special about watching people become experts on a topic, and then watching experts do their thing.

Is hyperfixation a good thing? Maybe. Not always. But it's a good thing when it leads to something useful.

There is a similar pattern I see in many of the best engineers I know - a simple need or curiosity will lead to something much larger. Chasing down a solution is often just a series of small questions that need to be asked and answered in order, rolling up to a larger goal.

A few examples from the tech world:

- My friend Charlie found herself wondering about the jets she could see from her apartment window in Seattle. One thing lead to another, and she built a javascript app that gives her [real-time information](https://charliegerard.dev/blog/aircraft-radar-system-rtl-sdr-web-usb/) on the planes whizzing by her window from live, public radio signal broadcasts.
- Curiosity about modifying the generator command in Ruby on Rails led my teammate CJ deep into the weeds of the [RoR source code](https://www.youtube.com/watch?v=8Rnf_-vDuaU&) to figure out how it all works, and how to make it better - his work will likely find its way upstream into core parts of the rails ecosystem before long.

---

## My own hyperfixation

A friend recently recommended a _3-hour long podcast about Costco_ to me from the show Acquired - and while it is an incredible deep dive, it also requires a huge time commitment to get through. I listened to the show, and wanted to chat about it with my teammates, but I knew that it was unlikely they'd have the time to listen the entire 3-hour show.

So, I did what any good engineer would do, and I figured out a way to summarize the show's transcript for each of my teammates in a way that was personalized and relevant to them. I built a little tool that would take the transcript, and then use a series of natural language processing tools to summarize the transcript into a few key points.

In a short amount of time, I found myself learning about:

- **The Podcast RSS feed format**, which contains audio files and metadata about individual episodes. I used this to grab both a show mp3 and transcript to use for summarization.
- **OpenAI's Whisper API**, which can be used to quickly transcribe audio files into text.
- The **GPT-4 API Playground,** where I could play around with different summarization models to see which one worked best for my use case.
- **LLM Prompt writing** for summarization, and ways to ask the model to summarize an episode for a specific listener's perspective, like our head of growth or a software engineer. Clearly, these two personas will have different interests in a show about Costco -- so I wanted to make sure the summary was relevant to them.

I ended up with a tool that I could use to summarize any podcast episode, and I learned a ton along the way.

### Read summaries of the Costco episode generated by AI

Sounds cool, right? I published a few sample summaries of the episode in an [article on my site here](/posts/acquired-costco-podcast-llm-summaries) for you to check out.

Is this something you'd a small amount for? [Drop me a line](mailto:hello@mikebifulco.com) or shout at me on [threads](https://threads.net/@irreverentmike) - I'd love to hear your thoughts.

---

These are a few incredible examples of people who have gone above and beyond to pursue answers to _non-technical_ questions:

### The Mystery of the Bloomfield Bridge

[The Mystery of the Bloomfield Bridge](https://tylervigen.com/the-mystery-of-the-bloomfield-bridge) may be the single most interesting article I've read this year. It shows how a seemingly simple question about the built environment can uncover a long and winding history of civic action, economic change, and a bridge that doesn't seem to go anywhere.

### Finding Michaelsoft Binbows

YouTuber Nick Robinson's 42-minute long vlog titled [I flew to Japan to visit "Michaelsoft Binbows" in person](https://youtube.com/watch?v=QRIklga9IBQ) is actually a follow-up to a previous video where he tried to find the real-life inspiration for the Microsoft Binbows logo. Don't know what the hell that means? Neither did I, but I watched both videos and I'm glad I did. The internet is a weird place.

---

## Build your expertise with some of my favorite resources

### 📰 API Specs, Schemas and Standards

In the latest edition of the APIs You Won't Hate Newsletter, my pal Alex goes deep on [API Specs, Schemas and Standards](https://apisyouwonthate.com/newsletter/api-specs-schemas-and-standards/) - what's the difference between JSON Schema and JSON:API? Find out here.

### 🎙️ The future of HTTP - software engineering daily podcast

I did a super in-depth interview about [The Future of HTTP](https://softwareengineeringdaily.com/2023/10/11/the-future-of-http/) with Nick and Roman, two engineers from Nginx working on a standard that is one of the most basic building blocks of the web. I genuinely had to study up on HTTP basics for this one, and learned a ton. I hope you do too!

### 🧬 Your Resume Sucks

The gang over at Polywork liked my recent newsletter on resume writing so much that they [reposted it on their blog](https://blog.polywork.com/how-to-fix-your-resume/) for the world to see. I'm happy to see that it's resonating with people, and I hope it helps you land your next job!

<small>

_note: Cover photo for this newsletter by [C D-X](https://unsplash.com/@cdx2?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash) on [Unsplash](https://unsplash.com/photos/PDX_a_82obo?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash)_

</small>
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Your resume sucks. Here's how to fix it.]]></title>
            <link>https://mikebifulco.com/newsletter/your-resume-sucks</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/your-resume-sucks</guid>
            <pubDate>Wed, 04 Oct 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[A guide to writing a resume that doesn't suck, from a hiring manager's perspective.]]></description>
            <content:encoded><![CDATA[
# I want to hire you...!

...But, I can't hire you if I can't find you, and I won't find you if your resume sucks.

So, let's fix that. If you want to give yourself the best possible chance to land an interview from your next job application, this guide is for you.

Over the past few weeks, I've reviewed hundreds of resumes while hiring for [open engineering roles at Craftwork](https://www.ycombinator.com/companies/craftwork/jobs/). I've had people reach out on LinkedIn, Instagram, Reddit and by email to apply, which is honestly awesome. I love that people are excited about what we're building and want to be a part of it.

But here's the thing: **most of the applications I've seen are terrible**. They're so bad that I can't even tell if the person is a good fit for the role. And if I can't tell if you're a good fit, I can't take away time from my team to interview you.

I genuinely believe that many of the people applying to work at Craftwork are great candidates - and with a little bit of love, their applications would shine. So I'm writing this guide to help you write a job application that doesn't suck, from a hiring manager's perspective.

## Here's what I'm looking for when you apply

Ultimately, the goal of a job application is to give the hiring manager a reason to want to talk to you. It should clearly communicate **what you're best at, what work you've actually done, and what drives you to do it**. If you can do that, you're already ahead of the game.

You would be shocked to see how many applications I've seen that don't have the basics right.

### Give your resume some love

Don't apply to a job if you don't have a detailed, up to date resume/CV ready to go. If you don't have a resume, you're not ready to apply for a job.

I've read through several applications that include _nothing more than a name and an email address._ No resume, no cover letter, no LinkedIn profile, not even a GitHub link!

As you might expect, these applications are rejected immediately.

Treat your LinkedIn profile like a living resume. If you take the time to fill in your profile with a detailed work history, it can be a suitable replacement for a pdf. Want to do both? Knock yourself out.

Every bit of your work history should include the company name, your job title, the dates you worked there, and a description of what you did. _Many_ applications I've seen go to LinkedIn profiles which only contain a company name, dates and job title. That doesn't tell me anything useful, even if you worked at a FAANG.

For tech roles, include a short list of the technologies you used for that role. This is especially important if you're applying for a role that requires specific experience with a technology.

Don't lie on your resume by adding things you haven't done. You can _absolutely_ exaggerate your accomplishments, but don't put yourself in a position where you might get caught in a lie.

### Make it personal

Every one of us sees the world through a different lens. We all have different experiences, different perspectives, and different ways of thinking. That's what makes us unique. So why do so many resumes look the same?

If you want to stand out to a recruiter, let your personality come through a bit. Here's how:

**Include a short bio** at the top of your resume. Tell me who you are, what you're passionate about, and what you're looking for in your next role. This is a great way to show your personality and make yourself stand out.

Here's the bio I used the last time I brushed up my resume to apply for a job:

> **WHO AM I** <br />
> An impassioned, imperfect, endlessly curious person, fascinated by design and technology, trying to leave the world in better shape than I found it, and amplify the accomplishments of those around me.

Admittedly, I cringe just a little bit reading it now - but hopefully you get the idea. It's personal, it's unique, and it's a great way to start a conversation.

**Don't use a cover letter template.** I don't know if ChatGPT is to blame for this or what, but I've read several cover letter back-to-back that were nearly _identical_ except for a few specific details. If you're going to write a cover letter, make it personal. Tell me why you're excited about the role and why you think you'd be a good fit. If you're not going to make it personal, don't write one at all.

**Lead with something interesting.** This is intentionally vague -- but if your cover letter starts with some variation of "with over 5 years of experience, I..." your cover letter already sounds like 90% of the other cover letters I've read.

I know you're more interesting than that! Let your personality and interests shine through. If it all goes well, your cover letter is the start of a conversation - recruiters and hiring managers can read your resume for years of experience (if they really want to).

Here's the first few sentences to my most recent cover letter, to give you a sense of what I mean:

> My name is Mike Bifulco, and I'm a software designer, engineer, and serial entrepreneur based in Charlotte, NC, USA. I'm submitting my C.V. for consideration for DevRel leadership roles at ████, and I couldn't be more excited to do so. I've spent my career helping others make their dreams come true by building great products on the web. Helping developers tackle new problems and grow their skill sets is an incredible privilege, and being able to do so while working for ████, and growing an incredible team of developer advocates and engineers would be a thrill.

**Include your most meaningful personal projects.** If you're applying for a job as a software engineer, I want to see what you've built. If you're applying for a job as a designer, I want to see what you've designed. If you've done some of your best work outside of your job, I would love to see it!

**When possible, link to your available work online.** This includes websites, apps in the app store, blog posts, videos, etc. If you've done something cool, I want to see it.

### Found a role you're in love with? Go the extra mile.

If you've come across a job opportunity on a team that you're _really_ smitten by, go the extra mile to make your application stand out. Here's a few ideas:

**Use your network** to find someone you know with a contact at the company you're applying to, even if it's on a different team. If your connection is good, ask transparently for an introduction, and ask them to put in a good word for you. If you're not sure if your connection is good, ask them to be honest with you. If they're not comfortable making an introduction, don't push it.

This is one reason why it's good to be proactively kind to people you work with - you never know when you might need a favor, and if you've only ever _asked_ for favors, you're not going to get very far. Give without the expectation of getting anything in return, and you'll be surprised how often people are willing to help you out when you need it.

**Reach out to the hiring manager directly.** If you're applying for a role at a startup, there's a good chance that the hiring manager is the CEO or founder. If you're applying for a role at a larger company, there's a good chance that the hiring manager is a senior leader. Either way, they're probably pretty easy to find online.

**Try out the product.** If you're applying for a role at a company that has a product, try it out. If you like it, tell them why. If there are opportunities for improvement, offer constructive criticism. If you're applying to a developer tools company, try out the product and build something with it. Share what you've built with the team, or open a Pull Request to fix a bug or add a feature. This is a great way to show that you're passionate about the product and the company, that you can communicate and work well, and that you're a self-starter.

## Improve the odds to get an interview

Everything I've mentioned so far is about making your application stand out, and giving the hiring manager a reason to want to talk to you and schedule that first interview. Yes, it can be a lot of work, and _yes,_ there's definitely challenges with privilege and bias in the hiring process.

If you're serious about landing the best possible gig for your next role, you'll see the best results if you put in the work.

---

What do you think? Did I get anything really wrong here? Is there something you've done or seen that helps people land an interview? If you have any questions, comments, or feedback, I wanna hear it. Please reach out to me on [BlueSky](https://bsky.app/profile/mikebifulco.com) or [shoot me an email](mailto:hello@mikebifulco.com).
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Do this with Your Product Waitlist: A Guide for Indiehackers and Startup Founders]]></title>
            <link>https://mikebifulco.com/newsletter/strategies-for-your-product-waitlist</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/strategies-for-your-product-waitlist</guid>
            <pubDate>Mon, 18 Sep 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Learn strategies to leverage your product waitlist for sustainable growth. Ideal for indiehackers and startup founders, this guide offers actionable tips to convert initial interest into paying customers.]]></description>
            <content:encoded><![CDATA[
# So you've got a waitlist for your idea. Now what?

You've done it-you've drummed up interest in your product and now have a waitlist. But what's next? How do you translate this initial momentum into sustainable growth? If you're an indiehacker, startup founder, or aspiring product builder, this guide is for you. We'll explore two strategies, tailored to whether you've started building your product, or are still in the ideation phase.

## If you Haven't Built the Thing Yet

### Put Up a Landing Page

If you haven't yet started building your product, start by putting up a landing page. Here, share every feature idea openly to gauge interest and collect feedback. The goal here is to socialize your idea, and validate it with a real audience before you start building.

### Determine Your Commitment Threshold

Decide on a financial commitment threshold that would validate the product idea for you. This is the amount of money you'd need to see pledged before you're convinced it's worth building. This _probably_ shouldn't be enough to pay all your bills, but it should be enough to show you (and others) that this is a valuable product, and that you're not wasting your time by building it.

### Set a High Price Point

Don't be shy-set a high price point for your product. Bear in mind, this may be the _maximum_ you'll ever charge for this product. It should seem outlandishly high - most first-time founders under-price their offerings dramatically. Don't kneecap your business' potential by setting a low price and hoping you'll get a high volume of signups. Unless you've got a huge audience, you probably won't.

In your early days, you'll use the psychology of behavioral economics to drive sales by offering steep discounts for short periods of time. Start with a high price point, and then offer discounts to early adopters.

### Offer Discounts for Early Adopters

To incentivize sign-ups, offer a significant discount to the first batch of customers. For example, if you're planning to launch a video course, you might set the price at $499. A discounted price of $99 for learners who sign up before the course is ready will create a sense of urgency and encourage people to commit, and will also put money in your pocket to help you build the course.

If you're building a SaaS, you might offer a lifetime discount to early adopters. For example, if you're planning to charge $99/month for your product, you might offer a lifetime discount of 50% to the first 100 customers. This will help you build a base of early adopters who will be invested in your product and will help you spread the word.

### Create a Sense of Urgency

Set a deadline for the discount and stick to it. This will create a sense of urgency and encourage people to sign up. You can also offer a limited number of discounted spots to create a sense of scarcity. This will also effectively time-box your waitlist, so you can move on to the next phase of your product.

### Be Transparent About Sign-ups

Openly share how many people have signed up and adjust the discount as you get more sign-ups. This creates a sense of urgency and shows that people are committing. It also helps you gauge interest and decide whether to continue building your product. If you don't get enough sign-ups, congrats! You've just saved yourself hundreds of hours of potentially-wasted time. At this point you can either pivot your idea based on feedback you've received so far, or refund any money you've collected and move on to the next idea.

### Caveats

- **Open Sharing:** You'll have to be comfortable sharing your ideas openly. I've [written about this before](https://mikebifulco.com/newsletter/how-to-know-when-to-publish-your-work) - keeping your-thing secret until launch is almost always a death sentence. You'll get better feedback, and you'll build a better product if you share your ideas early and often.

### Benefits of this approach

- **No Initial Build Required:** Gauge interest before committing resources.
- **A/B Testing:** You can put up several landing pages for different ideas.
- **Feedback Loop:** Collect invaluable feedback before investing time and effort.
- **Sales Skill:** Sharpen your skills in selling an idea.
- **Networking:** Expand your professional network.

### Risks with this approach

- **Refunds:** It's possible that this strategy may not result in enough signups to continue building your product at this point. You may choose to pivot, and change the idea You'll need to refund money for ideas you decide not to pursue.
- **Pricing Strategy:** Setting the correct commitment threshold can be tricky. Too low, and you may not get enough signups. Too high, and you may not get any signups at all. For my friends building SaaS products, tools like [Stigg](https://www.stigg.io/) are invaluable for helping you experiment with pricing strategies.

<br />

## If You've Already Started Building the Thing

### Embrace your Early Adopters

Do you already have a working prototype? Amazing! Put it in people's hands. Seriously - get real people using your product ASAP. This can be a scary hurdle to get over, but if you're open to it, you will get tremendous feedback from your earliest users.

Your primary aim should be to create early adopters who not only love your product but also how you're building it. The story of your product can be just as important as the product itself for these early adopters. They'll be your biggest advocates, and will help you spread the word.

With this approach, you're setting the expectation that your product is actively being built (you _are_ building it, right?). This means that you'll need to be responsive to feedback, and you'll need to be transparent about your roadmap. You'll also need to be comfortable with the fact that your product will be changing rapidly, and that you'll be making mistakes along the way. This is a good thing! You'll be able to iterate quickly, and you'll be able to build a product that your customers love.

### Choose an Early Cohort

From your waitlist, select an early cohort of users who you think will be most beneficial for your product. This could be based on their background, their willingness to provide feedback, or their ability to spread the word. You can also use this opportunity to test your pricing strategy. For example, you might offer a lifetime discount to the first 100 users who sign up.

If your waitlist is small, you may choose to let everyone in at once. If you have a large waitlist, you may choose to let people in gradually. This will help you manage the feedback loop from onboarding, and to create a sense of excitement for people who are still waiting to get in.

As you rapidly update your product and release new features, give access to more people from your waitlist. This will help you manage the feedback loop from onboarding, and to create a sense of excitement for people who are still waiting to get in. Open up registrations completely once people are able to onboard without any intervention from you or your team.

### Share What You're Building

Share your progress early and often, through whatever public channels make the most sense for you. This could be a YouTube video, a blog post, or a social media thread.

Use product updates as a way to show your current users that you're listening to their feedback, and that you're actively working to improve the product. This will help you build a community of early adopters who are invested in your success. This will also serve as product marketing for people who haven't yet signed up. Be loud and proud about what you're building, and share updates wherever your voice will be heard.

## The Ultimate Goal: Gain Traction

1. **Stoke the Fire.** In the early days, losing momentum is your biggest enemy. Gaining traction should inspire you to build more and at a faster pace.

2. **Create Inertia**. An engaged audience should feel they have access to something special. Encourage them to talk about your product and be responsive to their feedback. The buzz around your product will help you gain traction.

3. **Get Paid** Don't wait too long to monetize. Even asking for a nominal one-time fee from early adopters can validate your business model and make it easier to scale. Every person using your product knows that you need to make money to keep building it. Every single one of them. Don't be afraid to ask for financial commitments.

### Benefits with this approach

- **Feedback Loop:** Get invaluable feedback from real users, which will force you to keep building
- **Sales Skill:** Sharpen your skills in selling a product by building a muscle for marketing and developer relations. If you can't convince early adopters to use product, you won't be able to sell it to anyone else.
- **Networking:** Even if your product doesn't take off, you'll have grown the network of people who are invested in your success. This can be invaluable for your next project.

### Risks with this approach

- **Time Commitment:** Building software takes time. You'll need to be comfortable with the fact that your product will be changing rapidly, and that you'll be making mistakes along the way.
- **Building too slowly:** If you're not releasing updates, you'll lose momentum with your audience. Even if your product has known bugs, it's better to release early and often than to wait until it's perfect. Your early adopters will be forgiving, and will be excited to see your product improve over time.

## Your waitlist is just the beginning

Having a waitlist is a promising start, but it's what you do next that counts. Whether you're still ideating or have a ready product, these strategies can help you capitalize on your early traction and build a sustainable business. Remember, the ultimate goal is to gain traction, so keep building, engaging with your audience, and don't shy away from asking for financial commitments.

Your waitlist could be the first step in a long and successful journey.

---

## Tools for Building a product with Your Waitlist

- [Ghost](https://ghost.org/) - A fully open source, adaptable platform for building and running a modern online publication. Ghost gives you a blog and a newsletter all at once, and offers a great integration with Stripe for collecting subscription payments.
- [Stigg](https://stigg.io) - A tool for experimenting with pricing strategies. Stigg helps you find the right price for your product by decoupling pricing logic from your product code. This allows you to experiment with different pricing strategies without having to redeploy your product.
- [Reddit](https://reddit.com) is truly handy for doing research on niche communities, embedding yourself with your target market, and asking for feedback. Many product builders use it to find their first customers - there's more than just an infinite stream of memes for you on Reddit.

---

## Resources and reading for this stage

- [30x500 Academy](https://30x500.com/academy/) is a cohort-based class from Amy Hoy and Alex Hillman for building products using an approach similar to what I outlined above. Many of their students have gone on to build successful product businesses, and they have a wealth of resources for indiehackers and startup founders.
- 📖 I've recommended [The Embedded Entrepreneur](https://www.amazon.com/Embedded-Entrepreneur-Build-Audience-Driven-Business/dp/3982195764/ref=tmm_pap_swatch_0?_encoding=UTF8&qid=1695125716&sr=8-1&_encoding=UTF8&=irreverentm04-20&=ur2&=87d35637d191e4c0225f9e8c9b8b2ea2&=1789&=9325) before - it's a fantastic book from Arvid Kahl about building a business around specific and deep interests. I can't recommend it enough.

---

## From me this week

- 🎙️ My interview for [Software Engineering Daily with Charlie Gerard](https://softwareengineeringdaily.com/2023/09/19/catching-up-with-charlie-gerard/) went live this morning! Charlie and I worked together at Stripe. She's an incredible creative technologist, and I had a blast talking to her about her latest projects. If you're in the midst of a career pivot, and looking for inspiration, this one is for you!
- 📰 [The Bun is out of the Oven](https://apisyouwonthate.com/newsletter/the-bun-is-out-of-the-oven/) is our latest newsletter at APIs You Won't Hate. It's all about the new JavaScript runtime that's been all over tech news recently.

<small>

_Note: Cover image photo by **Samuel Regan-Asante** (who was formerly) on Unsplash (their account seems to have been deleted)_

</small>
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Breaking the cycle: Data-driven product descisions]]></title>
            <link>https://mikebifulco.com/newsletter/data-driven-decisions-product-analytics</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/data-driven-decisions-product-analytics</guid>
            <pubDate>Mon, 04 Sep 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Learn how to escape common product development pitfalls using data-driven decisions. Read how Craftwork used analytics to optimize their user experience.]]></description>
            <content:encoded><![CDATA[
Ever catch yourself navigating around a clunky feature or long-standing bug in an app you use? Chances are, you're so used to it, you've forgotten it's a problem.

Guess what: Product teams feel the same frustration. I've been there myself, stuck in a cycle of building features that don't quite hit the mark.

Why does this disconnect between users and product teams exist? It boils down to a few common pitfalls:

- Emotional decision paralysis: Even minor changes feel overwhelming.
- Designers and PMs sometimes get emotionally wrapped in their work, making it hard to let go of past decisions, even when user behavior suggests they should.
- Corporate Red Tape: In large companies, decision-making can be painfully, heart-breakingly slow.

The way out of this cycle? Data. It helps us cut through the emotional and bureaucratic fog to make changes that actually matter.

## Using data to make informed product decisions

At my company [Craftwork](https://craftwork.com), we've been using data to iterate on critical user paths and features. In particular our workflow for a self-serve, instant interior painting quote has gone through several iterations.

Although we haven't reached product design nirvana quite yet, we've learned a lot along the way. At its core, the process boils down to a couple critical steps:

### Understand signal _and_ noise: Measuring Drop-off Rates

It's critical to understand how people are interacting with your product. This is where analytics tools come in handy. We use [PostHog](https://posthog.com/) to track behavior. During the interior paint quote flow, there are a steps that we measure as inflection points for customer drop-off. At each point, we keep track of customer behaviors by logging an event.

For example, when a potential customer selects a room to paint, we log an event like this:

```javascript
posthog.capture('estimate/room-selected', { roomName: 'Living Room' });
```

We can then use PostHog to track the number of people who reach each step in the flow. As you might imagine, the first step in the process sees the most activity/ The very last step in the process is when someone clicks the submit button and sends us a request to have their home painted. In between the two, there are several steps that potential customers complete.

<Image
  publicId="newsletters/data-driven-decisions-product-analytics/funnel"
  alt="Screenshot of a funnel created in PostHog"
  caption="An example of a funnel created in PostHog, from their docs site"
/>

At each point in the timeline, we see two things: the number of people who continue to the next step, and the number of people who drop off.

This helps us understand where people are dropping off -- in other words, where we're losing potential customers. At each of these steps, there's an opportunity to improve conversion rates by iterating on our design.

### One Step at a Time: Hypothesis-Driven Iterations

This gives us data to make informed decisions about the product without getting too wrapped up in what we _feel_ should change. For example, if we see a lot of people dropping off at the step where they select paint colors, we might try a few things:

- Reduce the number of colors to choose from
- Add a "recommended" color
- Remove the color selection step entirely

(Any guesses what we landed on? If you're in Charlotte, NC, you can [try it out](https://craftwork.com/estimate/interior) and see for yourself!

We can then the impact of each change by seeing how the drop-off rate at that step is affected. If we see a significant improvement in drop-off rate, we know we're on the right track.

If not, we can try something else.

This is a simple example, but it illustrates the power of data-driven decision making. Ideally, this is paired with hands-on user research, and learnings from both proactive and reactive customer support. But even with a small team, you can make a big impact by using data to inform your product decisions.

---

## Tools for product analytics

- As mentioned above, we use [PostHog](https://posthog.com/) to track critical user behaviors, and to build funnels for measuring drop-off rates.
- [Highlight](https://www.highlight.io/) pitches itself as a full-stack monitoring platform. It's handy for keeping an eye on errors and performance issues within your app, and is completely self-hostable.
- [Fathom Analytics](https://usefathom.com/ref/DPSSYB) (that's a referral link for $10 off your first invoice) - I've written about [fathom](https://mikebifulco.com/posts/why-fathom-analytics) [several times now](https://mikebifulco.com/posts/seo-tools-for-new-web-projects), and I stand by my recommendation. It's great!

---

## More from my slice of the internet this week

- 🎙️ [Making React 70% faster with Aiden Bai of Million.js](https://softwareengineeringdaily.com/2023/09/05/making-react-70-faster/) - I had a chat with Aiden recently for an episode of the Software Engineering Daily podcast. Aiden is a recent high school grad who's built a React alternative that's 70% faster than React. ...I know, right?!
- 🧸 [Smartbear Acquires Stoplight](https://apisyouwonthate.com/newsletter/smartbear-acquires-stoplight/) - the most recent newsletter from APIs You Won't Hate talks about a recent acquisition in the API devtools world.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Reverse DevRel: The core engineering skill you've been missing]]></title>
            <link>https://mikebifulco.com/newsletter/reverse-devrel-as-core-engineering-skill</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/reverse-devrel-as-core-engineering-skill</guid>
            <pubDate>Tue, 29 Aug 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[DevRel is a core engineering skill that is often overlooked. By turning the DevRel model on its head, we can use it to build better products and better teammates.]]></description>
            <content:encoded><![CDATA[
It's not uncommon for programmers to forget that we're building products for people -- like, real, actual _breathing and thinking_ human people. We get so caught up in technical details that we forget about the people who will be using our products. I'm certainly guilty of this myself - I'll spend so much time just _getting something working_ that I forget to think about how it will be used.

The result: we build features (or worse, entire products) that are difficult to use, or that don't solve the problems that people actually have.

One great remedy to this is to get feedback from users early and often. This is a User Experience skill that I'd be happy to talk endlessly about - and I've certainly [written about UX](https://mikebifulco.com/newsletter/intellectual-humility-and-how-to-be-wrong) [in the past](https://mikebifulco.com/newsletter/unexpected-observations-in-human-cognition).

But there's another skill that I think is just as important, and it's one that I think is often overlooked: DevRel.

## What is DevRel?

DevRel stands for _Developer Relations_. It traditionally focuses on building and nurturing relationships between companies and the developers who use their products and services. DevRel professionals, also known as developer advocates, do this by producing videos and articles, and providing support to developers by serving as the liaison between the company and the developer community.

Communicating with end users and iterating on features by responding to feedback. Doesn't that sound like something every engineer should be doing? Do _you_ do that?

## That's where _reverse DevRel_ comes in

DevRel is typically about building better things for developers. If we turn the DevRel model on its head and ask engineers to think of part of their role as being a developer advocate, we can use it to build better products, and to uplevel our teammates.

### Boom, you got DevRel'd

I'm lucky to get to work with some exceptionally talented people - one of whom is [CJ Avilla](https://www.cjav.dev/). CJ is a seasoned engineer and developer advocate, and he's done a great job of making sure that at Craftwork, our DevRel muscle is strong. He will often use devrel superpowers to get feedback on features as they're being built.

It's typical for CJ to send a quick video to the team to show off a new feature he's working on. He'll narrate the video, explaining what he's working on and why. He'll show off the feature, and then ask for feedback.

This is a direct opportunity to ask things like:

- Does this make sense?
- Is this what you were expecting?
- Is this useful?

<Image
  publicId="newsletters/reverse-devrel-as-core-engineering-skill/cj-screencap"
  alt="A screengrab from one of CJ's youtube videos"
  caption="A screen grab from one of CJ's YouTube videos - he's been doing this for a long time!"
/>

If you've worked with engineers who are disconnected from your end users, you know how valuable these questions can be. They build empathy and trust between the team and the end users. They help us build better products.

### You got chocolate in my peanut butter! Bringing video into the mix

The use of screencast video is super helpful here, too - it's much easier to digest than a long email or a Slack message. It also creates two important types of empathy:

1. By demonstrating the features we build, we're forced to use them, and feel any UX pain points that might exist as a result of the implementation. This creates a better end product.
2. For those watching demo videos, it's much easier to see the person behind the feature when you can see their face and hear their voice.

### Best of all, you'll level up your teammates

The effectivity of this approach is contagious. As we build out new features, the rest of our team has started to follow the same patterns outlined above. In my experience, this is the type of experience that would be absolutely unheard of for brand new engineers. Connecting _what's being built_ with _who it's being built for_ is invaluable, and not something that can be gleaned from leetcode. It's a skill that's learned through experience.

To quote the world-famous developer advocate Missy Elliot: _take your DevRel, flip it, and reverse it_

---

## Great resources for reverse DevRel

As far as I can tell, nobody has written about reverse devrel, because it's a term I just made up... you can imagine how that complicates things. That aside, here are some great resources to dip your toes into the wild world of engineers who talk to people:

### 📚 The Business Value of Developer Relations

[This book by Mary Thengvall](https://www.amazon.com/Business-Value-Developer-Relations-Communities/dp/1484237471?&_encoding=UTF8&tag=irreverentm04-20&linkCode=ur2&linkId=9442e27bbfa907d124676e93faac5d25&camp=1789&creative=9325) is a great place to start if you're interested in learning more about DevRel.

### 📖 Fanocracy: Turning Fans into Customers and Customers into Fans

[Another great read, by Reiko and David Meerman Scott](https://www.amazon.com/Fanocracy-audiobook/dp/B082349829/ref=sr_1_1?&_encoding=UTF8&tag=irreverentm04-20&linkCode=ur2&linkId=bc920b438d4cf2f5db9b41fa7235b5c7&camp=1789&creative=9325) - while not directly about DevRel, it's a great book about building a community around your product. Building support and momentum for what you're creating is

### 🎥 Dead-simple screencast recordings with Loom

[Loom](https://loom.com) makes it super easy to make quick screencasts. At Craftwork, we use it frequently to record quick videos to share with teammates. It's a great way to get feedback on features as you're building them, and couldn't be easier to use. Their free plan lets you make 25 5-minute videos - which is more than enough to get started.

---
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Continuous self improvement and the morning ritual]]></title>
            <link>https://mikebifulco.com/newsletter/continuous-self-improvement</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/continuous-self-improvement</guid>
            <pubDate>Tue, 15 Aug 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Reflecting on my morning ritual, journaling for clarity, and podcasts for your morning walk]]></description>
            <content:encoded><![CDATA[
## I haven't always been a morning person, but I've grown to love it

Every day, I get up around sunrise, and groggily wander down to my kitchen. I have an automation set up that plays some chill tunes at a low volume, and gently turns up the lights as the sun rises.

Next, I open the blinds to let in the morning light while my espresso machine warms up. I put out some food for my cats, and then I make myself a double shot of espresso.

While I sip my 'spro, I fire up the [Headspace app](https://www.headspace.com/referral/z6jb3?slug=cebee0&audio=false) for 5-10 minutes of meditation (use that link for a free 30 day pass). After that, 5 minutes of focused, uninterrupted journaling to further clear my mind (more on this below). If the weather is nice, I'll go for a walk and listen to a podcast.

After _all_ that, I check my emails and Slack notifications. It's an intentional choice to give me some time to wake up and get my mind right before I start my day.

### Benefits of my morning ritual

I've found that this ritual helps me start my day with a clear mind, and I'm able to focus on the things that matter most to me. I'm not perfect, and I don't do this every day, but I've found that when I do, I'm more productive and happier.

Do you have a ritual that helps you start (or end) your day with a clear mind? If not, I'd encourage you to try it out. It doesn't have to be complicated, and it doesn't have to take a lot of time. Just a few minutes of intentional, focused time can make a big difference.

---

<Image
  publicId="newsletters/continuous-self-improvement/morning-sunrise"
  alt="photo of a sunrise over a white brick building with a graffiti portrait painted on its side"
  caption="Benefits of early morning walks: breath-taking sunrises. Mural by artist Nick Napoletano."
/>

## Morning pages: Journaling for clarity

I mentioned above that I journal every morning. I've been doing this for a few years now, and it's been a game changer for me. My habit is loosely based on [morning pages](https://juliacameronlive.com/basic-tools/morning-pages/), a concept created by Julia Cameron, a writer and artist.

The task is simple: I spend 5 minutes writing down whatever is on my mind. I don't worry about grammar, spelling, or punctuation. I just write. I don't even worry about complete sentences. I just write down whatever is on my mind.

I've found this especially useful in times where I've got a lot on my plate - writing down the first few things that are on my mind can help me unravel the tangled mess of thoughts in my head. It's a great way to clear my mind and start the day with a clean slate.

On days where I'm not particularly stressed, these 5 minutes are often spent reflecting on my goals, and the the people and circumstances in my life that I'm grateful for.

It may seem silly, but it's incredibly powerful. Give it a shot - you might be surprised at what you learn about yourself.

---

## Podcasts for your morning walk

According to my podcast app of choice, I've listened to 161 _days_ worth of podcasts in the last 5 years. Most of what I listen to falls into two categories: comedy (entertainment), and non-fiction, educational shows. I subscribe to a reasonably large spread of shows, so that I can pick and choose what I listen to based on my mood.

<Image
  publicId="newsletters/continuous-self-improvement/pod-count"
  alt="Since october 26, 2017, I've listened to 161 days and 15 hours of podcasts."
  caption="Can you overdose on podcasts? Asking for a friend."
/>

Here's a few I've enjoyed lately:

- [99 Percent Invisible: Shade redux](https://99percentinvisible.org/episode/shade-redux/) 99PI is one of my favorite podcasts. It's a show about design, and it's always fascinating. This episode is about the importance of providing shade in public spaces, and how it's often overlooked.
- [My Brother, My Brother, and Me: Sure thing, Dave Matthews](https://maximumfun.org/episodes/my-brother-my-brother-and-me/mbmbam-672-sure-thing-dave-matthews/) MBMBaM is almost certainly my all-time favorite podcast. I was introduced to it by my sister (thanks, Kris!) and I've been hooked ever since. It's an "advice" show, where the hosts "answer" questions from listeners and Yahoo Answers. It is unlike anything else. So good.
- [Citation Needed: Fordlandia](https://www.citationpod.com/fordlandia/) Citation Needed is a podcast where the hosts pick a topic, and become experts on it by reading exactly one article on wikipedia. This episode is about Fordlandia, the absolutely bonkers story of Henry Ford's attempt to build a utopian society in the Amazon rainforest. What a nightmare.

## From me this week

- 🎙️ My interview with [Sebastien Lorber from Docusaurus](https://softwareengineeringdaily.com/2023/08/03/simplifying-documentation/) on the Software Engineering Daily podcast is out! We talk about the history of Docusaurus, its next major release, and how it makes the creation of docs sites easier for developers. Check it out!
- 📰 If you're a newsletter junkie _and_ you're in the API dev world, you're going to love [The DevX Revolution is here](https://apisyouwonthate.com/newsletter/developer-experience-revolution/) - the latest edition of APIs You Won't Hate (the newsletter).
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[My startup got into Y Combinator]]></title>
            <link>https://mikebifulco.com/newsletter/craftwork-accepted-into-y-combinator</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/craftwork-accepted-into-y-combinator</guid>
            <pubDate>Tue, 01 Aug 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Well, our startup did - Craftwork is a tech-connected home painting company that is making it easier for homeowners to get their homes painted.]]></description>
            <content:encoded><![CDATA[
## The cat's out of the bag

It's been a couple weeks come I've written an issue of Tiny Improvements, but for good reason: I have been dizzyingly busy. I'm happy to share that [Craftwork was accepted into Y Combinator](https://www.ycombinator.com/launches/J1U-craftwork-the-easy-way-to-paint-your-home) (upvotes appreciated!), a hugely competitive startup accelerator. We also raised [$4M in funding](https://charlotte.axios.com/334157/charlotte-tech-startup-at-y-combinator-raises-4-million/) to help us build and grow the future of home services, starting our home city of Charlotte, NC.

I've been spending the summer flying back and forth to San Francisco for various events for the program. It's been a thrill so far, and there's no way we would have made it into the program without a brilliant, talented team.

<Image
  publicId="newsletters/craftwork-accepted-into-y-combinator/launch-yc"
  alt="Launch YC: Craftwork"
  caption="Craftwork's launch post on Y Combinator's website"
/>

---

## Building a hiring culture we want

Back when I ran the Google Asssitant DevRel team, I had joined a handful of subreddits related to programming and computer science, for a couple reasons:

1. I was hiring developer advocates, and was looking for college graduates who might be a good fit for the job

2. I wanted to give back a bit, and share some of my experience as a seasoned practitioner with budding CS homies.

Perhaps unsurprisingly, remaining in these subreddits for the past few years has been a mixed bag. There are many motivated and passionate students who are learning in public, sharing their struggles, success, and anxiety with the world. _On the other hand_, there's also a deeply toxic and insecure culture around students thinking about the job market. It's wrought with anxiety and elitism.

It's not uncommon to see redditors mentioning that they practice for interviews on a website Leetcode for _hours_ a day, or that they work 12+ hour days at their internships in the hopes of getting a full time job. They make one another feel bad for not being deferential enough to their prospective employers, and stomp on one-another's goals and dreams to feel better about their own paths.

Friends, this is not the kind of world we want to be building. Straight up. Why would anyone want to work in an environment where this is the reality?

<Image
  publicId="newsletters/craftwork-accepted-into-y-combinator/reddit"
  alt="Screenshot from r/computerscience, where I was called a narcissist for suggesting that it's okay for an intern to take a day off from their job"
  caption="The one where I was called a narcissist for suggesting it's okay for an intern to take a day off. Is it petty to write an entire newsletter about this? Maybe. But I'm just a simple narcissist..."
/>

If you're working towards your first job in the industry, or someone who is hiring entry level developers, take this to heart: even in a competitive job industry, we should be building teams and cultures that we can be proud of.

I have _countless_ examples of serendipity that have come from supporting people who I've bumped into throughout my career, both IRL and online. It is always better to amplify and show support for people doing great things with their lives, and to help build up the people around you.

But here's the thing: if you're reading this... you already know that. You're here for a reason.

**Here's my challenge to you:** sometime this week, go out of your way to support someone else's work. Whether by sharing it with your network, or straight up telling someone they're doing a good job -do something that tips the cultural scales toward positivity.

After you've done that, share it with me. I'd love to feature some community projects in upcoming newsletters.

Keep doing good out there. It makes a difference! 🤜🏼 🤛🏻

---

## Three people you should follow, right now

I've been thinking a lot about the people who inspire me lately. Here's a few people who I think you should follow, too:

### Phil Sturgeon, literal forest-builder and API expert

[Phil Sturgeon](https://hachyderm.io/@Philsturgeon@mastodon.green) is my long-time friend and fellow APIs You Won't Hate cofounder, author, and podcast host. He's spent the past few years traveling across the UK and Europe on bicycle and in his EV, building a charity that is helping to reforest the UK. He is an incredibly inspiring person, and one of the hardest working people I've ever met.

### Nick DeJesus, open-sourcerer and future-builder

[Nick DeJesus](https://twitter.com/Dayhaysoos) is an open source software developer who is working as CTO of [Black Tech Pipeline](https://blacktechpipeline.com/). He's helping to build a better tech community, and is also one of the consistently funniest people I know.

### Charlie Gerard, creative tech educator

[Charlie Gerard](https://twitter.com/devdevcharlie) is an innovative, brilliant software developer and published author. She has an endless list of creative tech projects that she builds and shares with the world. I was lucky to meet her while we worked together on the DevRel team at Stripe.

---

## Where I'm learning

It's been a minute since I've shared some of the things I've been reading and listening to lately. Here's a few you may appreciate:

- [🎃 The Pumpkin Plan](https://amzn.to/44S6Eh2) is a book that was recommended to me by my pal and teammate [CJ Avilla](https://www.cjav.dev/). The book's author shares a repeatable strategy for _building a remarkable business in any field._ It's chock full of great anecdotes and thought-provoking exercises.

- [🧐 Think Again: The Power of Knowing What You Don't Know](https://amzn.to/3Oj4pw1) is a book about the importance of being able to change your mind, and knowing how to change other people's minds when the time is right. It's a great read, and I've been thinking about it a lot lately.

- (CW: cancer) [On the Vlogbrothers YouTube Channel](https://www.youtube.com/watch?v=x6a4hMyiwBo), vlog brother and consummate youtuber Hank Green has been sharing his experience since being diagnosed with lymphoma. His treatment seems to be going extremely well so far, thankfully, and his videos have been a emotionally candid and scientifically factual look at his experience with cancer. I lost my mother to cancer when I was in college, and I distinctly remember feeling like there was no way to understand what her experience was like. Hank's videos have been a great way to learn more about the experience of cancer patients, and I'm grateful that he's sharing his experience with the world. I wish him well.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Two truths and a lie: what Meta got right with the Threads launch]]></title>
            <link>https://mikebifulco.com/newsletter/meta-threads-launch-two-truths-and-a-lie</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/meta-threads-launch-two-truths-and-a-lie</guid>
            <pubDate>Tue, 11 Jul 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Meta's new app, Threads, is a Twitter clone that launched last week. It's not perfect, but it's a great example of a product launch that went extremely well.]]></description>
            <content:encoded><![CDATA[
## Threads is here

Last week Meta launched Threads, their new Twitter clone. It is (to date, at least) the most successful app launch of all time, gaining **100M users** in its first week. I installed the app at launch, and have been using it - find me [@irreverentmike](https://www.threads.net/@irreverentmike) if you're on the app!

Meta is by no means a perfect company - their inept handling of data privacy leading up to the 2016 US Presidential election is not something I will forget anytime soon.

With that being said, I think they got a lot of things right with this product launch, and I want to talk about them. These are the things that stand out to me the most, two-truths-and-a-lie style:

### Threads takes advantage of Instagram's network effect

The value of tying Threads to Instagram in a way that is honest and helpful was apparent from the jump. By tying Threads to Instagram, Meta was able to massively utilize the network effect.

For once, I didn't need to worry about "securing" my username by signing up early. Good old [@irreverentmike](https://www.threads.net/@irreverentmike) was reserved for me because I already have the account name on Instagram. That's great!

I also didn't need to worry about finding my friends on the app. Threads has an option to automatically import my Instagram followers, following them for me if and when they set up their accounts. Think about how much of a chore that would be if I had to do it manually, every few days, over and over, to make sure I didn't miss anyone. What's even better is that this is totally optional - if you want Threads to be a fresh, clean slate, you're welcome to do that as well.

### Threads will support the fediverse and the decentralized web... maybe.

Let me be the first to tell you that [I'm not super excited](https://mikebifulco.com/posts/twitter-and-the-perils-of-obedience) to see another billionaire-controlled social network take the main stage. I'm still holding out hope for Mastodon and the fediverse in the long run.

Right around Threads' public launch, Meta's head of Instagram, Adam Mosseri [posted](https://www.threads.net/t/CuVeIfMpFVq) about Meta's plans to support ActivityPub, the protocol that underlies Mastodon and the fediverse. This is a big deal, and I'm excited to see it happen... and **extremely skeptical** that it ever will.

<Image
  publicId="newsletters/meta-threads-launch-two-truths-and-a-lie/threads-fediverse"
  alt={`Screenshot of Adam Mosseri's threads post, with the message "We're committed to building support for ActivityPub, the protocol behind Mastodon, into this app. We weren't able to finish it for launch given a number of complications that come along with a decentralized network, but it's coming.

If you're wondering why this matters, here's a reason: you may one day end up leaving Threads, or, hopefully not, end up de-platformed. If that ever happens, you should be able to take your audience with you to another server. Being open can enable that."`}
caption="Adam Mosseri's post on Threads, announcing that Meta is committed to supporting ActivityPub, the protocol behind Mastodon."
/>

You may or may not have noticed, but Threads is not available to our friends in the EU - Meta has not yet figured out how to comply with GDPR, Europe's strict regulations around data privacy and information sharing for tech companies.

Meta has paid some _huge_ fines in the past for violating GDPR, and I'm sure they're not eager to do it again. I'm not a lawyer, but I'm willing to bet that supporting ActivityPub will be a huge headache for Meta's legal team. I'm not holding my breath.

### Threads launches on July 6

(Spoiler: **this one** is the lie.)

Meta spent a ton of time and effort telling the world that Threads was launching on July 6th, 2023. They managed press expectations extremely well here circulating images announcing the launch to press sources; they even added features to instagram to generate an image of a "ticket" inviting instagram users to the app at 10am on July 6th (see: cover image at the top of this page).

<Image
  publicId="newsletters/meta-threads-launch-two-truths-and-a-lie/threads-launch-teaser"
  alt="Photo of an iphone with the IOS App Store, showing a 'coming soon' screen for the Threads app, with saying Launchy date expected July 6, 2023"
  caption="This is an image shared as part of Meta's press blitz, announcing their July 6th launch date."
/>

The app _actually_ launched to the public a day early - on July 5th, 2023. I was sitting in my kitchen when I got a push notification that the app went live. I installed it and created my account within minutes... and was something like the 480,000th user to sign up.

This is a great example of a company managing expectations well. By announcing a launch date, and then launching a day early, Meta was able to generate a ton of press and excitement around the launch. This is a great example of a company managing expectations well.

Worth mentioning: my initial app launch experience was _not_ to an empty feed - Meta had _clearly_ given early access to some major high-follower accounts, who had apparently been posting for a while already. As much as I dislike the feeling of being a second-class user on an app from day 1, this is a great way to make sure that the app doesn't feel empty on launch day.

## What you can learn from this launch

After spending months working on a product, it's all too common for founders and product teams to get lazy about their launch. I've seen it happen time and time again - a product is ready to go, but the team is tired, and they just want to get it out the door. They don't want to spend the time and energy to make sure that the launch is a success.

Friends -- **the success of your launch all comes down to planning**. Plan your launch carefully, have clear and open communication about what you've built and why, and do as much as you can to build hype and excitement around your launch in the weeks that lead up to it.

There's no point in building a product if you're not going to do **everything you can** to make sure that people know about it. If you're not willing to put in the work to make sure that your launch is a success, you're not ready to launch.

---

## A feature about me from my friends at Polywork

<Image
  publicId="newsletters/meta-threads-launch-two-truths-and-a-lie/polywork-article"
  alt="Screenshot of an article about me on the Polywork Blog, with the title 'Why Mike Bifulco isn't afraid to be driven by the fear of regret'"
/>

I'm a huge fan of [Polywork](https://www.polywork.com/), which is professional network for sharing what you're working on, and finding interesting people to collaborate with. It's like LinkedIn, but for people who actually do things. 😬

I've been using Polywork since its launch a couple years back, and have been giving the team my honest feedback on their product and the features they've been building along the way.

Imagine my surprise when they reached out to me to ask if I'd be interested in being featured on their site! I was thrilled and humbled to be asked, and I'm excited to share the feature with you here:

[Why Mike Bifulco isn’t afraid to be driven by the fear of regret](https://blog.polywork.com/mike-bifulco-interview/)

It honestly feels a little strange to share an article someone wrote about me - but at the same time, I'm really proud of the work I've done, and I'm excited to share it with you. I hope you enjoy it! Shout out to my new pal [Nick Lioudis](https://www.polywork.com/nick_lioudis) for taking the time to this.

It means the world to me.

---

Alright fam - it's been a busy few weeks for me, and I'm excited to get back to work. I hope you're all doing well, and I'll see you next week!
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Maximize user retention: the cognitive science approach...]]></title>
            <link>https://mikebifulco.com/newsletter/multitasking-and-product-design</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/multitasking-and-product-design</guid>
            <pubDate>Tue, 04 Jul 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Understand how multitasking affects your customers' memory, and improve your product design and engagement with cognitive psychology and the Zeigarnik effect.]]></description>
            <content:encoded><![CDATA[
<small>

_note: cover photo for this newsletter is from [No Revisions](https://unsplash.com/it/@norevisions?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/office?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)_.

</small>

If you want to build a great product that people love, making your thing _work_ is not enough.

Truly great products provide value while building trust, loyalty, and enthusiasm. These is often accomplished through many small changes, by researching and observing the real behavior of people who use your apps.

I recently went down a rabbit hole reading about how we understand the **behaviors tied to multitasking** - and lemme tell ya, there is a _ton_ of wisdom that can be derived from what we know about the subject.

Studies in human multitasking indicate that our brains have a very limited capacity to handle more than one task at a time. In fact, we're not really multitasking at all - we're just switching between tasks very quickly. This is called _task switching_. Despite this, many people find it motivating to have a lot of things going on at once. This is called _continuous partial attention_.

There are many pros and cons to this, for example:

- There's a fine line between being motivated and being overwhelmed
- The more tasks we have going on at once, the more likely we are to forget something
- Finishing tasks makes us feel good

Hopefully you can imagine how this would be useful in UX design. It underscores the necessity for simplicity and focus, where each step of the onboarding process should be distinct, self-contained, and not overload the user's cognitive bandwidth.

Moreover, another fascinating aspect of our cognitive psychology is the **Zeigarnik effect**: people remember uncompleted or interrupted tasks _better_ than completed ones. By designing experiences that take advantage of this effect, we can motivate users to return to our products to complete important unfinished tasks.

For instance, we can strategically create breakpoints in the complex processes which leave users eager to come back and finish (i.e. _complete three workouts by Sunday to see your weekly stats breakdown_).

## The bottom line

So, how can we use this information to build better products? Here are some practical tips:

1. **Keep it simple**. Don't overload your users with too much information at once. Break down complex tasks into smaller, more manageable ones. For example: split complex onboarding flows into multiple steps, each with a clear goal, and make it dead easy to come back to when someone inevitably gets interrupted.

2. **Make it easy to come back**. Ever used an app that requires a login _every_ time you come back, even if you check the "remember me" box? I bet you can think of a couple examples off the top of your head. Do _you_ love those services? Of course not.

3. **Celebrate progress**. Reward users for completing tasks by giving them a sense of accomplishment. One of the most well-loved features we built at my last company, smpl, was a celebration screen that popped up when coworking members finished creating their profile for the first time. A little shower of confetti onscreen was a simple, fun way to make people feel good about what they'd accomplished.

By learning to acknowledge and cater to the cognitive intricacies of human multitasking, you can create a user-friendly environment that respects and makes the most out of our attentional capacities.

---

## More reading on multitasking and product design

### Continuous partial attention

The Wikipedia article on multitasking has a section on [continuous partial attention](https://en.wikipedia.org/wiki/Human_multitasking#Continuous_partial_attention), which is a great place to dig in further. It provides a concise overview of the concept, its history, and its implications for product design.

### The Zeigarnik effect

Ever have trouble sleeping because you didn't finish _that one important thing_ you needed to do today? Zeigarnik, baby! There's a great article from the Harvard Business Review on [The Zeigarnik effect](https://hbr.org/2020/10/why-your-brain-dwells-on-unfinished-tasks) that explains the phenomenon in detail. It also provides some practical tips on how it can be used as an advantage.

tl;dr: help your users feel like they're making progress, and break big tasks into smaller ones - they'll feel like they're making progress and be motivated for more.

### Cognitive load theory

As I shared a [couple weeks ago](https://mikebifulco.com/newsletter/cognitive-load-ux-and-why-you-should-care), Cognitive load is a theory that describes how our brains process information. It's a great way to understand how to design products that are easy to use and understand.

---

## For my API building friends in the back

Lots of new goodness from my beloved developer community APIs You Won't Hate this week!

- 🎙️ In the latest episode of the podcast, [Creating world-class API devX with Sagar Batchu from Speakeasy](https://apisyouwonthate.com/podcast/sagar-batchu-from-speakeasy/), I talk to founder Sagar Batchu about how he's building a platform to help API developers create better experiences for their users.

- 🚥 My pal and cofounder Phil Sturgeon wrote a great article called [How to Capture Quite a Lot of API Traffic](https://apisyouwonthate.com/blog/capture-api-traffic-using-optic/), in which he shares a great tactic for capturing API traffic for testing and documentation purposes.

- 📰 Can't get enough newsletters? APIs You Won't Hate's newsletter goes out twice a month, on the 1st and 15th. Check out the latest issue, [Death by Google](https://apisyouwonthate.com/newsletter/death-by-google/).

## Also, it is a holiday

As a side note, happy 4th of July to my American friends. If you're like me, you may be [finding it impossible](https://chicago.suntimes.com/2023/7/4/23779869/supreme-court-lgbtq-rights-segregation-website-designer-letters) to be proud of the [direction our country is headed](https://www.politico.com/news/magazine/2023/06/25/mag-tsai-ziegler-movementjudges-00102758).

Do me a favor, and **stay mad** about it.

[Make sure all your friends vote](https://vote.org), this year and every year.

**We need to do better.** ✊🏽

<br />
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Takeaways from VidCon's creator track]]></title>
            <link>https://mikebifulco.com/newsletter/lessons-from-the-creator-track-at-vidcon</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/lessons-from-the-creator-track-at-vidcon</guid>
            <pubDate>Tue, 27 Jun 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Last week, I went to VidCon in Anaheim, California. It was my first time as a creator at the event. Here are my three takeaways from the conference.]]></description>
            <content:encoded><![CDATA[
Last week, I went to VidCon - the annual summit for video creators, which was in in Anaheim, California. It was my first time as a creator at the event. Though most of my published work is in written format rather than video these days, it was an exceptional experience.

As part of the creator track, I attended a number of panels and workshops. I also had the opportunity to meet with a number of creators and industry professionals.

Here are my top takeaways from the conference:

## Everybody's people, and people are amazing

I was _shocked_ at how many YouTubers / TikTok...ers, and other creators I met who were just... hanging out in the convention center in Anaheim and happy to talk shop. In particular, my wife Natalie and I had a wonderful conversation with Nick Cho, who you may know better as [Your Korean Dad](https://www.youtube.com/@yourkoreandad). Not only was he happy to be approached, but he was also incredibly kind and generous with his time.

He gave some great advice about building a fanbase. He starts every video with "I'm your Korean Dad!", which is an unexpected and memorable way to introduce himself. His videos are also very personal, and he's not afraid to be vulnerable.

He also has a very clear mission: to be a father figure to his audience.

Nick was kind enough to spend 5 or so minutes giving Natalie feedback on her channel [Primary Focus](https://youtube.com/@primaryfocus), and bid us farewell with an unexpected "please keep in touch!" -- an absolute class act.

## Stop plastering your logo on everything

I also went to a talk by [John Green](https://www.youtube.com/@vlogbrothers) and his DFTBA colleagues Brandi Jessup, Sierra Schultzzie, Fraize, and Brandi Jessup, where they talked about the intention and strategy they put into designing and selling physical merchandise for their fanbases. The top nugget here: the best things they sell to their fans are high quality products that don't _scream_ "I'm a fan of this thing". They rarely have a brand name or logo on them, and they're often subtle references to the in-jokes or memes that their fans love.

Stop designing t-shirts with your logo on them, and start designing _things_ that your fans will love because they make them feel like they're part of a community.

---

## Tools and feature launches for creators and community builders

Many of the sessions I attended at VidCon were focused on how to build and foster community, both tactically and technically. Here are a few of my notes that I wanted to share:

### Patreon support for digital goods and free membership tiers

[Patreon launched free membership tiers](https://www.theverge.com/2023/6/21/23763815/patreon-free-tier-shopping-digital-goods-subscription) -- which sounds like something that should have _always_ existed. It's a great way to offer your community members an inside look at your process, and to upsell them to a paid tier when they're ready.

They also added support for selling digital goods - like ebooks or exclusive downloads - which makes it even easier to offer your community members something of value.

### An acronym as a tool for marketing

[The AIDA Model](<https://en.wikipedia.org/wiki/AIDA_(marketing)>) is a helpful tool for brainstorming and structuring a marketing strategy. The acronym stands for Attention, Interest, Desire, and Action: these are the steps which people tend to go through when deciding to make a purchase.

### The indexifembedded keyword

Here's a quick and hyper-specific SEO tip for my all my fellow web-building dudes: the [indexifembedded](https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#indexifembedded) keyword can be used to tell Google to index a page if it's embedded in another page in an iframe. This is particularly useful if you want to mark a YouTube video as unlisted on your channel, but still have it show up in search results when embedded on your website.

---

This all has me thinking quite a bit about the role video plays in my life - I would love to find more time to share stories and learnings from my startup journey in video format. I'm not sure what that looks like yet, but I'm excited to explore it.

If you want to follow along, you can subscribe to my YouTube channel [@mikebifulco](https://www.youtube.com/@mikebifulco).

<br />
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Intellectual humility: how to be wrong productively]]></title>
            <link>https://mikebifulco.com/newsletter/intellectual-humility-and-how-to-be-wrong</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/intellectual-humility-and-how-to-be-wrong</guid>
            <pubDate>Tue, 13 Jun 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[How to use being wrong to improve UX and product design. Learn how to embrace mistakes and create better products for your users.]]></description>
            <content:encoded><![CDATA[
**The hardest thing about building a new company** is that you have to be wrong a lot. From the moment you breathe life into the thing-you're-building, you need to be intentional about challenging your assumptions, and seeking out the truth. This requires a willingness to be wrong, to be wrong often, and to _make good decisions_ when you are wrong.

When was the last time you were wrong? How did you respond?

For many of us, being wrong is a painful experience. It's a blow to our ego, and it can feel like a personal attack. It's easy to get defensive, and to try to justify our decisions, even when we know they're wrong.

Hell, if I were to look back on myself in the past, I was often defensive, and would dig my heels in to justify my decisions, even if it wasn't the best choice for the product or business.

I wasn't learning from my mistakes.

In my work, I am wrong all the time, and as strange as it sounds, I'm _getting better_ at being wrong. Somewhere in the process of building my last company, I learned that being wrong is a good thing. It's a sign that you're listening, learning, and growing. This aligns with UX research principles: question, observe, and adjust.

I learned that being wrong is a _skill_. It's something you can practice, and get better at.

Perhaps most importantly, we need to practice **intellectual humility** - trust the people around you to help you make better decisions, and be willing to admit when you're wrong. Give your friends, colleagues, and customers the benefit of the doubt, and take feedback and challenges in good faith.

If you're building a product, this means that you will be building, tweaking, and sometimes outright _rebuilding_ features and interfaces to make them more useful and valuable to your customers. Software is never done, and it's a mistake to mark a feature as "done" and to never think about it again.

Be wrong, and be smart about it. It's a great way to learn.

---

## Smarter Every Day and intellectual humility

The topic for this week's newsletter was inspired by the YouTube channel Smarter Every Day, who recently published a video called [THE IMPOSSIBLE SHOT](https://www.youtube.com/watch?v=tcQVrD7RnNI). The team made two bullets collide mid-air, and captured it in super slowmo. It's an incredible video. In this video, Destin (the host) uses the term "intellectual humility",

I _don't_ like guns at all, but I am all about pursuing creative challenges, and taking on seemingly impossible tasks. The setup for the shot they captured is _incredibly_ tricky to get right. Firing two guns at each other is extremely dangerous - and capturing it on camera required a lot of problem solving.

There's a fantastic moment in the video where Destin has his inner circle of experts analyze and question the setup for the experiment. He listens intently as they all try to poke holes in his assumptions, because he trusts their expertise. It's really impressive to watch.

---

## Resources for further learning

- 🖇️ [This video from TikToker and bio-ethecicist Charlie Peterson](https://www.tiktok.com/t/ZT81XCrRd/) analyzes the Smarter Every Day video through the lens of men's mental health. Brilliant stuff - and a solid reminder that the men in our lives (hi, it's me) need to be encouraged to be vulnerable and open about their feelings.

- 🦠 [Science vs: AI, is it out of control?](https://gimletmedia.com/shows/science-vs/6nh3564e/ai-is-it-out-of-control) is a great listen. The capabilities of what AI can do today would have felt like Science Fiction to most of us 18 months ago, and it's important to educate yourself on the basics of how AI works. One reason I love this show: they cite their research. The transcript for this episode contains 97 citations. That's good damn work, y'all.

- 🔬 Near the end of the most recent episode of the podcast (about the 1hr mark) [Reconcilable Differences: My Personal Fantastia](https://www.relay.fm/rd/210), hosts John Siracusa and Merlin Mann discuss an interesting question: how do you know when something is true? If the past few years have shown me anything, an approach to finding and determining provable truth is fundamental to societal growth and safety.

---

That's all for this week. **To all my friends and colleagues who have helped me learn from being wrong: thank you. I appreciate you.**

<br />
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Cognitive load, UX, and why you should care]]></title>
            <link>https://mikebifulco.com/newsletter/cognitive-load-ux-and-why-you-should-care</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/cognitive-load-ux-and-why-you-should-care</guid>
            <pubDate>Tue, 06 Jun 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Cognitive load is a concept that is important to understand that is often overlooked, and has a huge impact on both UX and the lived experience of building your product.]]></description>
            <content:encoded><![CDATA[
**Cognitive load** is the amount of mental effort required to complete a task. It's something you experience everywhere - in every app you use, every website you visit, and even making your morning coffee. In product design, is something that is often felt but not well-understood, and has a huge impact on both UX and the lived experience of building your product.

In the best case, cognitive load is something that is invisible to the user. When I used to work as a UX designer at Microsoft, I would often say that if I was doing my job right, nobody would realize I did anything at all.

In the worst case, it can be a source of frustration and confusion. In this article, we'll explore what cognitive load is, how it affects UX, and how you can use it to improve your product.

## Types of cognitive load

Cognitive load boils down to three categories: intrinsic, extraneous, and germane.

### Intrinsic cognitive load

**Intrinsic cognitive load** is the basic difficulty of a given task. In other words, the amount of perceived mental effort required to complete a task. Does using your product feel like a breeze, or does it feel like a chore? If the person looking at the product you've designed feels like they're doing their taxes from scratch every time they call up your app, you've got a problem.

Perceived intrinsic load can be reduced by splitting tasks into smaller chunks, or by providing more guidance (or, in 2023, by stapling GPT-4 to your product and calling it a "copilot for XYZ", har har). As a designer, this is your opportunity to shine: how can you make your product feel like a breeze? If you're helping people do something that typically requires domain expertise, make them feel comfortable and confident by communicating in their language. Provide guidance and feedback when they need it, and get out of the way when they don't.

### Extraneous cognitive load

**Extraneous cognitive load** is the amount of mental effort required to complete a task that is not related to the task itself. Most often, this is a factor of design decisions: is the user interface intuitive? Are your fonts tiny? Did you put yellow text on a white background? If you've ever used a product that made you feel like you were fighting against it, you've experienced extraneous cognitive load.

This type of cognitive load can be mitigated by observing peoples' behavior when they use your _thing_, and iterating on your design. Can you provide a clearer hierarchy or structure for the interfaces that your product presents? Often times this is a matter of making your designs simpler - finding an elegant balance between simplicity and functionality is one of the most challenging aspects of design.

### Germane cognitive load

Germane load is the most challenging to describe, and may also be the most important. [Wikipedia's definition](https://en.wikipedia.org/wiki/Cognitive_load#Germane) is deceptively simple:

> Germane cognitive load is the processing, construction and automation of schemas.

In other words, germane cognitive load is the amount of effort that your users spend on building a mental model of the thing you're helping them do. Often times, this means relating your thing to something that's already familiar to them. Here, `schema` is a fancy word for "the shape of the problem you're trying to solve".

At [Craftwork](https://craftwork.com), this is something we've been spending a good deal of time on. We found pretty quickly that most people don't have any mental model for what it should cost to repaint a room. Ask two friends what it costs to paint the same room, and you're likely to get two wildly different answers. This is a problem we're trying to solve for by offering transparent pricing for painting services, and by [providing a simple interface](https://craftwork.com/estimate) for people to get an instant quote for their project. You might be surprised to hear that this is a pretty novel concept in the home improvement space.

## What does it all mean?

The sum of theses three types of cognitive load is representative of how much of a pain in the ass it is to use _some thing_ to complete a task. You've experienced all three of these when you use any app or service. As you build your own product, reflect on your own interface designs, and look for areas to improve on cognitive load.

It's tempting to complete a feature, toss it over the fence to be released, and move on to the next thing -- but if you leave it at that, you're leaving a _ton_ of potential value on the table. Spend some time observing peoples' behavior when they use your product, and make it better. There's always room to improve.

---

## Load up your cognits with some brainfodder

Are you ready to dive in? These are some resources that might help you reduce cognitive load for your product:

- 🐗 We recently started using [Posthog](https://posthog.com/blog/using-posthog) at Craftwork. Self-described as "The Product OS", Posthog has a myriad of features that make it easier to see if your product is working, how well it is working, and what paths people are taking through as they navigate your features. It was a breeze to integrate, and has already helped us make some improvements to our product.

- 🫖 Don Norman's [The Design of Everyday Things](https://amzn.to/3Cgn5XG) is a classic tome on designing things that people will enjoy using. He does a great job of explaining design success and failure using basic objects like teapots and lemon squeezers, which makes it easy to understand how to apply his principles to your own designs.

- 🧑‍🎨 [r/designdesign](https://www.reddit.com/r/designdesign) is a subreddit full of _bad_ design - particularly, design that is over-the-top, just for the _sake_ of design. It's a great place to go if you're looking for examples of extraneous cognitive load.

---

## Noise to signal from me

- 🎙️ I had a chat with [Or Weis from Permit.io](https://apisyouwonthate.com/podcast/permissions-are-the-gift-that-keep-on-giving-with-or-weis-from-permit-io/) about the team his product is building. Often times, permissions, authentication, authorization, and the challenges facing developers building out products for real people.

---

Alright fam, that's all for now - if you've got examples of places where you've noticed cognitive load in your life, I'd love to hear about them -- especially if you've seen interesting ways to improve. Hit reply and let me know!
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Reddit as a tool for learning]]></title>
            <link>https://mikebifulco.com/newsletter/reddit-for-learning</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/reddit-for-learning</guid>
            <pubDate>Tue, 23 May 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[If you haven't been using reddit as a tool for learning, you are truly missing out. It's time to give it a try.]]></description>
            <content:encoded><![CDATA[
Reddit has been an incredible tool for me as a writer and a learner. I've benefitted from many subreddits over the years, by immersing myself special interest topics for fun, like Strava or Watchmaking or Woodworking. I've also used reddit to share articles I've written, and to research niches for product ideas.

One thing I really love about reddit is that it is a fairly even playing field - posts that get upvotes ones which are interesting to real people, and the discussions that result are often candid and helpful.

It's not a popularity contest, it's a meritocracy.

_Many_ of the technical subreddits I frequent have fairly strict rules about what can be posted. Moderators are quick to remove low-content or spammy posts, and the community is quick to downvote posts that don't add value. When it works, this results in a fairly high signal-to-noise ratio, making places like [/r/javascript](https://reddit.com/r/javascript) a great place to learn.

Reddit's community code of conduct also encourages participation - reddit's famous 10% rule states that you should spend 10% of your time posting and 90% of your time commenting. This helps to keep the community active and engaged, and it also helps to keep the community from being overrun by spam.

This is a good thing, because it means that the content that _does_ get posted is generally high quality, and the discussions that result are often helpful and interesting.

Since the beginning of 2023, I've tried to spend some time browsing subreddits for [JavaScript](https://reddit.com/r/javascript), [Next.js](https://reddit.com/r/nextjs), and [Computer science](https://reddit.com/r/computerscience). It's an interesting way to keep up with what's going on in the industry, and is a good way to keep my own skills sharp.

I used to dismiss reddit as something that I didn't understand - though I've had an account for years, I didn't use reddit regularly until about 2018. If you find yourself in the same boat, consider giving it a try - rather than spending your time doomscrolling on instagram and TikTok, create a reddit account and subscribe to subreddits that will help you _learn_ something. Whether it's directly applicable to your professional life or not, having a steady drip of discussion from topics that interest you can be a fantastic way to stay sharp, and to keep an eye out for new opportunities.

Once you've done that, consider adding to the community by participating in discussions and posting content of your own. You'll be surprised at how much you can learn by teaching others, and you'll be surprised at how much you can learn by asking questions.

---

## Some super subreddits that suprised me

- [r/firebase](https://reddit.com/r/firebase) is the home on reddit for people building products with Firebase. My last startup was built using Firebase, and this subreddit was a great resource for me. It is moderated by a team of Firebase employees, and full of experienced devs with great advice.
- [r/buyitforlife](https://www.reddit.com/r/BuyItForLife/) is a subreddit where people ask about and recommend products that are built to last.
- [r/nextjs](https://reddit.com/r/nextjs) is just what it sounds like: discussions about building with Next.js. For me, it serves as a helpful ear-to-the-ground for tooling and best practices.
- [r/nocode](https://www.reddit.com/r/nocode/) might be one of the most inspiring subreddits I've found. No code tooling has come _so far_ in the past few years. There are solo founders building entire companies on no code tools. It's incredible.

## It's been a little quiet...

...on the Mike-publishes-content front lately. I've got a few things to share soon which I'm excited to share with you, buuut not for another week or two. If you're jonesing for some fun reading, the APIs You Won't Hate community has produced some great stuff lately:

- 🎙️ [My interview with Constantin Schreiber from Fastgen](https://apisyouwonthate.com/podcast/no-code-apis-and-automation-with-constantin-schreiber-from-fastgen/) dives into the low-code tooling for API devs that Fastgen is building.
- 📝 My cofounder and pal Phil Sturgeon produced a great review tooling review - [APIMatic Review: Developer Experience-as-a-service](https://apisyouwonthate.com/blog/apimatic-review-dx-as-a-service/)
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Your portfolio is a timeline of your growth]]></title>
            <link>https://mikebifulco.com/newsletter/portfolio-as-timeline</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/portfolio-as-timeline</guid>
            <pubDate>Tue, 16 May 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[At some point in your life, you will look back on the work you did when you were just getting started with a new skill, and see everything you did wrong. Let's talk about how to channel that feeling for good]]></description>
            <content:encoded><![CDATA[
At some point in your life, you will look back on the work you did when you were just getting started with a new skill, and see everything you did wrong. You'll see the mistakes you made, the things you didn't know, and the things you didn't even _know_ you didn't know.

You may have felt this already. Maybe it's that design project from high school or university or bootcamp, or the first website you ever made. I think we all have a tendency to see our old work as embarrassing.

I'd like to offer up an alternative perspective.

You've come a long, long way. We all have. Looking back on your portfolio and seeing how far you've come is a great way to to see how much you've grown, which is a process that can be imperceptible day-to-day.

It's the reason I called this newsletter _Tiny Improvements._ Focus on being an incrementally better version of yourself every day, and those tiny improvements will add up to something incredible over time.

**Your homework this week:** Look back at your past-you; find some examples of your oldest work, and think about how you've grown. If you're feeling brave, reply to this message with a link to your oldest work, and your thoughts on it today, and I'll share mine too.

---

## Where I've been learning lately

- 🌳 [Unheard Roots](https://unheardroots.com/) is a wonderful newsletter that I've come upon recently. They share stories & strategies about game-changing startups that you may not have heard of before. I really enjoyed their post about Reddit.

- 📈 [Growth.design](https://growth.design/) is a fantastic collection of extremely well-illustrated UX case studies from products we've all used. It's super interesting to see them detail dark patterns, like Adobe's Offboarding process -- where customer satisfaction is sacrificed for the sake of revenue.

- 📼 [Theo - t3dotdogg](https://www.youtube.com/@t3dotgg) on YouTube has been making some _insanely_ insightful videos on building companies and products with TypeScript in 2023. I have found his videos to be extremely helpful while building my new startup.

## Some things I've made, just for you

- 👾 Over at APIs You Won't Hate, we just dropped a new newsletter: [Laravel is Harmful](https://apisyouwonthate.com/newsletter/larvel-is-harmful/). If you're into building or using APIs, you're gonna love APIs You Won't Hate. Consider subscribing - our newsletter goes out twice a month.

- 🎨 We just launched a shiny new estimate generator for interior painting projects over at [Craftwork](https://craftwork.com/estimate). It's a simple-looking wizard, and building it exemplifies one of the most important lessons I've learned in my career: **simple is hard.** We'll be iterating on this tool quickly over the next few weeks, so if you have any feedback, we would love to hear it.

---

And that's it for me this week. It turns out building a startup, publishing this newsletter, and maintaining a dev community is a lot to balance - but I'm loving every minute of it. Thanks so much for reading. Keep doing your thing - I'm proud of you.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[We hurled a people into space by building a pool: the case for simplification]]></title>
            <link>https://mikebifulco.com/newsletter/moonshot-design-for-everyone</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/moonshot-design-for-everyone</guid>
            <pubDate>Tue, 09 May 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Everyone has their moonshot: something that seems impossibly difficult. We can learn a lot from the people who have landed their own moonshots.]]></description>
            <content:encoded><![CDATA[
In the tech world, it's common to hear people refer to "moonshot" companies. It's a term used to describe companies who aim to do something that seems impossible, much like the moon landing did during the space race in the 1960s.

Back then, we landed on the moon by throwing everything we had at the problem. We had to invent new technologies, new processes, and new ways of thinking to make it happen. It was a massive undertaking that required a huge and diverse group of people working toward the same mission.

If you've never done it, you should ask your friends and family what they were doing when we landed on the moon. Many people remember exactly where they were and what they were doing, in vivid detail. It was a moment that changed the world.

On some level, I think we all have a desire to do something that changes the world. We want to make a difference, and we want to leave a legacy. We want to do something that matters. Whether you're working for a company hurling rockets into space or not, I'm sure you face challenges that seem impossible to overcome.

One of my favorite things about NASA of the 1950s and 60s was that their approach to unfathomable problems. They used observation and reasonable assumptions to break challenges into smaller pieces, and solved them one at a time.

- How do you train a new astronaut for a spacewalk? Environmental Research Associates (ERA) simulated the experience by [submerging space-suited earthlings](https://airandspace.si.edu/stories/editorial/inventing-underwater-training-walking-space).

- How do we figure out who has the right physical characteristics to survive the force of a rocket launch? Build a people-sized centrifuge and [spin them at 32 Gs until they pass out 🤢](https://www.smithsonianmag.com/air-space-magazine/the-g-machine-16799374/). [John Glenn](https://www.nasa.gov/centers/glenn/about/bios/john_glenn.html).

The space program is full of examples like these - and they are fantastic examples of how to pick apart big ideas into smaller chunks that can be solved one at a time.

This process is something that is important for us all to get comfortable with. When I was studying mechanical engineering in undergrad, I learned to simplify and solve problems by making helpful assumptions. In my computer science courses, we were taught to approach new problems by using algorithms and data structures to break them down into smaller pieces.

Building entire companies is no different - people will pay you for the products you build when you solve a problem for them. The more complex the problem, the more likely it is that you'll need to break it down into smaller pieces to solve it.

As you're working on building your dreams, take the time to remind yourself that this process is important, and it gets easier with practice.

You're not climbing a mountain - you're building a staircase. This is true of every project you'll ever work on, and it's true of every company that's ever been built.

🚀🌝

---

## Why I love watching experts

You can learn a lot from watching people who are really good at what they do - hearing them explain their thought processes and techniques is always surprisingly enlightening. These are some of my favorite examples of people who are really good at what they do, and who are also really good at explaining it.

- 🖥️ We've been building my new company using TypeScript -- which has a huge learning curve. I just started working through Matt Pocock's [free TypeScript tutorials](https://www.totaltypescript.com/tutorials), which teach you how to solve common TypeScript problems hands-on. It's a teaching method that I really love, and I've already learned a ton.

- 👩‍🍳 Chef Sohla El-Waylly has a series on the Babish Culinary Universe YouTube Channel called [Stumping Sohla](https://www.youtube.com/watch?v=lyhTkX3e-U0&list=PLopY4n17t8RDZ0Nmj7pApzAvxULlobJe_). In this series, the chef is given a culinary challenge, like "Astronaut Thanksgiving" (seriously), and she solves it on the fly.

- 🎸 On the [YouTube channel twoodford](https://www.youtube.com/watch?v=wgL2GfuA-EM), you'll get to watch a master luthier (read: guitar repair-dude) perform miraculous repairs on an endless array of nearly priceless guitars. His patience and tenacity are incredible, and it's clear he has spent countless hours honing his skills.

## I'm not an expert, but I play one on TV

I'm _still_ not sure I can lay claim to full-on expertise in much, but that's not stopping me from sharing my work online.

- 🎙️ on [APIs You Won't Hate (the podcast)](https://apisyouwonthate.com/podcast/no-code-apis-and-automation-with-constantin-schreiber-from-fastgen/), I spoke with Constantin Schreiber about his company FastGen, and his experience going through YCombinator this winter. His team is building no-code API tools, and I love their measured and thoughtful approach to building a company.
- Over at Craftwork, my teammate Sam has been exploring the seemingly endless color choices homeowners are given for paint. If you need help with the dizzying process of picking colors, check our our exploration of [white](https://craftwork.com/articles/craftworks-favorite-white-paints), [blue](https://craftwork.com/articles/craftworks-favorite-blue-paints), [green](https://craftwork.com/articles/green-paints-craftwork-loves), and [pink](https://craftwork.com/articles/craftworks-favorite-pink-paints) paints.

## Your turn - what's keeping you busy?

I'd love to hear what you're working on. If you're building something, or if you've found something interesting, reply to this message and let me know!

I read every reply, and I'd love to hear from you.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Tiny Improvements for big changes]]></title>
            <link>https://mikebifulco.com/newsletter/tiny-improvements-for-big-changes</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/tiny-improvements-for-big-changes</guid>
            <pubDate>Tue, 25 Apr 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Discover how tiny habits like journaling, language learning, & writing helped me stay grounded during the pandemic & achieve personal growth.]]></description>
            <content:encoded><![CDATA[
## Hey, that's the name of the show!

Today I want to talk about why my newsletter is called Tiny Improvements. For me, personal growth has come by way of small, incremental changes that have compounded over time.

I've always relied on building intentional personal habits to stay productive. When the pandemic hit in 2020 and we found ourselves in an extended lockdown, something changed.

I found myself instinctually leaning on habits to help me stay grounded and optimistic. I've always found small habits to be helpful, and during the pandemic, I used my routines to gradually build towards big changes in my life. It was a time where there was little consistency in the world to rely on, and I found that my habits were a source of stability.

Since then, these are three habits that have stuck around in my daily routine:

### The morning ritual

Every morning, I make myself an espresso, and sit down at my kitchen counter while the sun comes up. I set a timer for 5 minutes, and start writing anything that comes to mind.

I've been using journaling as a form of self-reflection and mental decluttering. By using a simple template in my note-taking app, I jot down any thoughts that cross my mind, no matter how trivial or insignificant they may seem. This daily practice has allowed me to better understand my thought patterns and emotions while setting a clear, focused tone for the day ahead.

I also try to a few minutes each day meditating. I've been using [Headspace for this](https://www.headspace.com/referral/z6jb3?slug=cebee0&audio=false) (that's a referral link for 30 days free, btw!), and it has made a world of difference for stress management and mental clarity. I generally do 3 or 5 minute sessions - it's shocking how much difference that little bit of time makes.

<Image
  publicId="newsletters/tiny-improvements-for-big-changes/morning-coffee"
  alt="A photo of a latte sitting on my countertop"
  caption="Many of my mornings start with a bit of coffee and a bit of writing."
/>

### Language Learning

For the past 1,000 days, I've been using [Duolingo](https://invite.duolingo.com/BDHTZTB5CWWKSRQUQARVC6SFNU?v=la) to sharpen my Spanish skills and learn Japanese and Mandarin. _A thousand days!_ Do you know what you were doing 1,000 days ago? I had to look it up -- that would be July of 2020.

Doubling down on language learning has proved invaluable as I work on my new business, [Craftwork](https://craftwork.com). Many of my new colleagues speak Spanish as their first language, and although I'm far from fluent, it will certainly help to build relationships and trust with my new teammates.

I've also been learning Japanese and Mandarin -- these are languages I'd love to be able to understand, and although it's been a massive challenge to get started, I'm making progress. I'm not sure if I'll ever be fluent, but I'm enjoying the process of learning something new.

My top tip for practicing a second language is to _get out of your comfort zone_ and try to communicate with native speakers whenever possible. I have never had a bad experience with this - people are generally very kind and appreciative, and it's a great way to learn.

### Writing

Launching [my website](https://mikebifulco.com) and [Tiny Improvements](https://mikebifulco.com/newsletter) has given me a platform to showcase my professional work and share my opinions with others. Writing consistently has not only helped me refine my thoughts and ideas but find likeminided people who appreciate my perspective.

## Taking small steps has made a big difference

These three habits, though seemingly small, have played a significant role in shaping my career, and creating opportunities that I never would have found otherwise. Your own series of Tiny Improvements will surprise you as they accumulate over time, ultimately leading to profound and lasting changes.

---

## Resources for building habits

- [Atomic Habits](https://amzn.to/3n33Ehe) by James Clear is the de facto guide to building habits. James has made an incredible career out of building habits for himself.
- My journaling habit is loosely based on [Morning Pages](https://juliacameronlive.com/basic-tools/morning-pages/), writing technique created by artist Julia Cameron. I love the idea of writing without judgement or expectation, but I rarely have it in me to bash out 3 pages of notes... and I am _definitely_ not hand-writing mine. Do what works for you!
- If you use Roam Research for taking notes, feel free to grab my [Morning Pages Template](https://gist.github.com/mbifulco/1357dde391d866c6a14d492b06414581). It is hyper-minimal by design to avoid overcomplicating my writing process.

## New from me this week

- 🎨 Craftwork is on Instagram! Follow us [@craftworkpaint](https://www.instagram.com/craftworkpaint) to see our latest projects and get inspired for your next paint job.
- 🎙️ Over at APIs You Won't hate (the podcast), my latest interview went live. Check out [Analytics for your API, with Steve McDougall from Treblle](https://apisyouwonthate.com/podcast/analytics-for-your-api-with-steve-mcdougall-from-treblle/) if you're working on a team that is building APIs.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[You are far more influential than you think]]></title>
            <link>https://mikebifulco.com/newsletter/you-are-far-more-influential-than-you-think</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/you-are-far-more-influential-than-you-think</guid>
            <pubDate>Tue, 18 Apr 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[You're already marketing yourself every moment. You just need to be aware of it and do it intentionally.]]></description>
            <content:encoded><![CDATA[
Tiny Improvements recently [passed the 400 reader milestone](https://mikebifulco.com/posts/building-in-public-growth-report-400-readers) - _thank you so much_ to each and every one of you for letting me into your inbox each week. It's a privilege I don't take lightly. Seriously, thank you.

As you might imagine, this has caused me to do a bit of reflecting -- I've been thinking about why I enjoy writing like this, and the things I find rewarding about being a part of the developer and creator community.

## On supporting others

I love the idea of building a community that I want to be a part of, and having the opportunity to support other people in building their dreams. There's something really special about being able to connect with people who are doing interesting things, and I'm grateful to be able to do that.

When I think about the people who I follow and really connect with, a few patterns stand out:

- some have done exceptional things or worked on exceptional projects
- some loudly support exceptional causes
- some just seem like they're incredible people

I have many reasons for being a fan of my friends and colleagues. One thing that has stood out to me lately, too, is how easy it is to amplify someone else's work -- and just how amazing that can make someone feel.

I've been writing for a bunch of years now, and I can remember a good handful of instances where someone shared my work unexpectedly. For example: we recently relaunched [apisyouwonthate.com](https://apisyouwonthate.com), and quietly added a feature that lets subscribers there pay for a membership. Right now, there's little difference between a paid and free membership, apart from "you're supporting us financially, and we love you." Within days of the feature launch, we had our first paying member, who skipped the $1/mo supporter tier and went straight for $5/mo.

I was floored.

<Image
  publicId="newsletters/you-are-far-more-influential-than-you-think/paid-subscriber"
  alt="Our first paid subscriber confirmation email"
  caption="This person will always hold a special place in my heart, and I'm so grateful for their support."
/>

## A call to arms: support your friends

I'm not writing this to ask for money, or to ask you to buy anything from me - if you're reading this, I'm already feeling the love. I'm writing this to ask you to support your friends.

Think about your friends who are working hard to build something. Maybe they're building a product, or a service, or a community. Maybe they're working on a side project, or a personal project, or a passion project.

Whatever it is, take 30 seconds out of your day, and share their _thing_ with your network. Let them know that you're a fan. It's small, it's free to do, and I can't tell you how much it means to the people you're supporting.

Small gestures of support can have enormous butterfly effects, too - I've made a good number of serendipitous connections in the past as a result of someone sharing my work with their network, or from times when I've shared and supported someone else's work.

Go, support your friends! You'll be glad you did, and they'll love you for it.

---

## Some friends whose work I admire

- [**Phil Sturgeon**](https://phil.tech) is the tree-planting madman who I work with on [APIs You Won't Hate](https://apisyouwonthate.com/). He's an exceptionally knowledgeable API developer, and has spent the past few years building his charity, [Protect Earth](https://www.protect.earth/). His organization has cleared land and planted tens of thousands of trees all over the UK - an astonishing accomplishment, and he's just getting started. Go follow Phil, he's a wonderful person.
- [**Rizèl Scarlett**](https://twitter.com/blackgirlbytes) is a developer advocate at GitHub. She's been all over the tech conference circuit for the past few years, where I've been lucky to bump into her from time to time. Rizèl is an amazing people connector - I've met and followed so many wonderful people as a result of her work.
- [**Colby Fayock**](https://twitter.com/colbyfayock) works as Director of DevX Engineering at Cloudinary, and is a really talented designer and developer. He's published countless articles, videos, and tech tutorials on his site, [SpaceJelly.dev](https://spacejelly.dev). Colby is genuinely one of the nicest people I've met, and does a great job of elevating the people around him. I'm always impressed by the work he's doing.
- [**Lazar Nikolov**](https://twitter.com/NikolovLazar) is a developer advocate at Sentry, and has started publishing a great newsletter called [Lazar's Tech Musings](https://nikolovlazar.substack.com/) that I've been enjoying. I stumbled across Lazar's work recently, and I'm really glad I did - our work has a ton in common!

## On building a following

📚 [Fanocracy: Turning Fans into Customers and Customers into Fans](https://amzn.to/3GSxOdO) is a book that is always high on my list of recommendations. I come back to my notes on it regularly, and I think it's a great read for anyone, whether you're actively building a following or not.

I've written a bit about nurturing your network before, and I think it's a topic that is worth occasional revisiting. If you're looking for more reading on the topic, you might enjoy these:

- [Imperfection is part of the brand](https://mikebifulco.com/newsletter/today-is-your-day-to-start), and people will love you for it.
- [Today is your day to start](https://mikebifulco.com/newsletter/today-is-your-day-to-start) building and marketing your product, even if you don't have the faintest idea what that is.

## Some of my recent work

- [Building in public growth report: 400 readers](https://mikebifulco.com/posts/building-in-public-growth-report-400-readers) - As I mentioned above, I recently passed the 400 reader milestone. I'm really grateful for the support and I wanted to share some of the things I've learned along the way.
- [Add custom fonts to Next.js sites with Tailwind using next/font](https://mikebifulco.com/posts/custom-fonts-with-next-font-and-tailwind) is a quick tutorial inspired by a post on Reddit. I've been trying to be helpful on /r/nextjs and /r/reactjs lately -- this post is adapted from a response to a question that I thought was worth sharing more widely.
- 🎙️ An interview I did recently for APIs You Won't Hate (the podcast): [Learnin' about webhooks, with Tom Haconen from Svix](https://apisyouwonthate.com/podcast/learning-about-webhooks-with-tom-haconen-from-svix/). If you're building with webhooks, this is a great episode to check out.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[The first 90 days as a technical cofounder - building a startup in 2023]]></title>
            <link>https://mikebifulco.com/newsletter/building-a-startup-in-2023-90-day-report</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/building-a-startup-in-2023-90-day-report</guid>
            <pubDate>Thu, 06 Apr 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[I'm building a new company for the first time since 2016. A lot has changed since then. Here's what feels different this time around.]]></description>
            <content:encoded><![CDATA[
I've been working on a new startup.

Last week, we (re)launched [Craftwork.com](https://craftwork.com), with a fresh design aesthetic and what I think is a really wonderful brand. We're building a tech-enabled home painting service, which is already making the process of getting your home painted easier and more delightful for our customers.

We also published a press release written by my friend and co-founder Tim Griffin, Craftwork's CEO. You can read that here: [Introducing Craftwork](https://craftwork.com/articles/introduction).

I've written about building products and companies in the past few years as part of my work at Stripe and Google, and on my own site - but this is the first time I've been a technical co-founder since when we launched smpl in 2016. A lot has changed since then.

---

**A note for non-technical readers:** this post is going to be pretty tech-heavy. I'm going to talk about a lot of tools and technologies that I use to build products. If you're not a developer, you might not find this interesting. Rest assured I'll be writing about more of the design/business/philosophical side of things in the future.

Thanks for being here - I love y'all!

---

Launching a startup in 2023 - here's what feels different this time around:

## The bar for design and branding is higher than ever

I've always been a big believer in the importance of design and branding. I worked as a UXer for years, and even earned (most of) a Master's Degree in Human-Computer Interaction to deepen my understanding of design. I've written about it endlessly ([see articles tagged with #design on my site](https://mikebifulco.com/tags/design).

In 2023, investing time and effort (and, let's be honest - money) into design and branding is fundamental to building a successful company. Whether we consciously realize it or not, it is easier to trust _something new_ if it looks and feels cohesive and professional. At Craftwork, we're asking customers to let us into their homes, and to trust us with their most valuable asset. Our brand and design language helps us build this critical trust with our customers.

## Automation and tooling are the real 10x engineer

I _love_ automating things. There's nothing better than writing a script that saves time for you and your teammates, and buys peace of mind. It's been astonishing to see how much better the tools for automation have gotten in the past few years.

Critically, there's been enough time for _all_ of the automation tools to see competitors arise. This forces companies building tools to be innovative, and to keep raising the bar with their products. Here's a few choices I've found myself with:

- For **dependency audits**: [Dependabot](https://mikebifulco.com/posts/i-have-to-tell-you-about-dependabot) is still going strong, and has competition in [Mend Renovate](https://www.mend.io/renovate/), which works on both GitHub and GitLab, and offers a different configuration experience.
- For **no-code, event-driven automation**: [IFTTT](https://ifttt.com/) is the OG, but continues to become more consumer-focused. [Zapier](https://zapier.com/) has arisen as a popular choice, but I've found myself exploring other options like [Make](https://www.make.com/en), [Trigger.dev](https://trigger.dev/) and [n8n](https://n8n.io/).

## A focus on Developer Experience (DX) is a competitive advantage

There's not a single engineer on this planet who wants to work on a product that sucks to maintain. We all want to work on products that are easy to understand, easy to enhance, and easy to deploy. This is something that has gotten steadily better since I've been in the industry, but it's still a huge differentiator for companies that get it right.

Happily, many companies building devtools have done a fantastic job of turning the eye of UX research toward devs - seeing engineers as users, and building products that are delightful to build with. What's more, most of these companies are _incredibly_ friendly to startups, offering generous free tiers and discounts to help companies get off the ground.

### A quick note about AWS

Somehow, AWS has wrestled its way into place as the de facto standard for cloud-based infrastructure for many dev teams - my people, it is _heartbreakingly difficult_ to use at all, and requires continual education and effort to use correctly and securely while staying up to date. The AWS dashboard is a hellscape of UX dark patterns, and the documentation is a labyrinth.

I think many teams turn to AWS because it appears to be dirt cheap - but the cost of maintaining a team that can use it effectively is _astronomical_. I'm not saying you should never use AWS - but I am saying that you should think _very carefully_ about whether you need to use it, and whether you can save long term costs by using something else (you almost certainly can).

Here's a few examples of tools that have made life better for me at Craftwork:

- For **git-driven deployments (CD)** - [Vercel](https://vercel.com) and [Netlify](https://netlify.com) are both fantastic. I use both across the sites I maintain, and they're both great. We're using Vercel for Craftwork, and .

- For **payments**, [Stripe](https://stripe.com/) is still unbeatable when it comes to DX. The mountain of features that have been added in the past few years make it _so much easier_ to build a robust payments system that can handle the complexities of the real world. Even still, there are companies building APIs _on top of Stripe_ that make life that much easier for certain use cases.

- For **analytics**, [Google Analytics](https://analytics.google.com) is still the standard, but has had to pivot hard in the past year or so to avoid legal consequences due to privacy laws being passed in the EU. For a great alternative that is privacy-focused, I use [Fathom](https://usefathom.com/ref/DPSSYB) on all my personal projects). Recently [Plausible](https://plausible.io/) has popped up as another option.

- The world of devx for **databases** has been absolutely buck-wild. At smpl, we used [Firebase](https://firebase.google.com/) because it was so damn easy to deal with - but it was a _nightmare_ to migrate away from when we needed to. [Supabase](https://supabase.io/) has emerged as a great alternative based on PostgreSQL, and I've been really loving [Planetscale](https://planetscale.com/)'s DX for branching databases.

- Even **database schema management** has gone through a renaissance. [Prisma](https://www.prisma.io/) has become the standard for a variety of use cases, and recently [Drizzle ORM](https://github.com/drizzle-team/drizzle-orm) has popped up as a fantastic alternative if you're building with TypeScript.

## Frameworks for everyone

Finally - web frameworks/meta-frameworks for building web apps have gotten _so much better_. This is another place where competition has been a _great_ thing for the industry. I've been using [Next.js](https://nextjs.org/) for a few years now, and it's been making life better and better. Even still , there's plenty of competition just in the JavaScript world: [SvelteKit](https://kit.svelte.dev/) and [Astro](https://astro.build/blog/introducing-astro/) are incredible, [Angular](https://angular.io/) has been releasing industry-leading features, and [SolidJS](https://www.solidjs.com/) is an extremely promising newcomer.

Even if you don't love JavaScript - [Laravel](https://laravel.com/) is keeping the PHP world humming, and [Ruby on Rails](https://rubyonrails.org/) gives Ruby devs insane productivity. [Django](https://www.djangoproject.com/) is still the standard for Python devs, and if you're building web apps with .net, [Blazor](https://dotnet.microsoft.com/en-us/apps/aspnet/web-apps/blazor) exists.

There are even incredible meta-frameworks - we've been building Craftwork with an offshoot of an offshoot - [create-t3-app](https://create.t3.gg/) is a full stack TypeScript framework built on top of Next.js, Prisma, and tRPC. Because we'll likely be building a react-native app eventually, we're using an Open Source "fork" of create-t3-app called [create-t3-turbo](https://github.com/t3-oss/create-t3-turbo) to build individual apps and services in a monorepo. It's been _incredible_ to work with, and has made it easy to build a robust, scalable app with a small team.

---

## A conclusion with a twist

All of these things -- every single thing I've mentioned above -- helps to create a better environment to get things done. It's easier than ever to build a product, but for any team, the thing that will separate good from great is _how_ you do it. Focusing on communication, accessibility, inclusivity, and growth are not to be overlooked.

The tools we use are important, but **the people we work with, _how_ we work with them, and the lives we build around our companies are far more important for longevity, and for living a great life.**

I sat down to write this newsletter thinking I'd throw out a few quick bullet points about how the world of devtools has changed in the past few years. I didn't expect to write a 2000 word essay, but here we are.

I hope this has been helpful to you, and I hope you'll take a look at some of the tools I've mentioned here. If you have any questions, feel free to [drop me a line on Mastodon](https://hachyderm.io/@irreverentmike).
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Wabi-Sabi - embracing imperfection for tech teams]]></title>
            <link>https://mikebifulco.com/newsletter/tech-product-growth-wabi-sabi</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/tech-product-growth-wabi-sabi</guid>
            <pubDate>Tue, 28 Mar 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[The products we build are naturally imperfect. We can learn from the flaws and imperfections in our code to create better, more resilient products while nurturing team and personal growth.]]></description>
            <content:encoded><![CDATA[
I started writing _Tiny Improvements_ because of a minor fixation on exploring how small, incremental changes can lead to significant progress and personal growth. Today I want to talk about one of my favorite topics - the beautiful and thought-provoking Japanese philosophy of Wabi-Sabi, and how embracing its principles can revolutionize the way we approach building software products as engineers.

<SponsoredSection
  sponsorName="The GIST"
  CTAtext="Sign up for free"
  href="https://links.swapstack.co/c2q"
>
  <div className="grid md:grid-cols-2 gap-4">
    <Image
      publicId="sponsors/the-gist/logo"
      alt="MAPT Events"
      height={250}
      width={250}
    />
    <div>

      ### Shaking up the male-dominated sports industry

      Only 5% of sports news is on female athletes, and even less on the business of women's sports! The GIST Sports Biz is changing that by delivering major deals, trends, and insights on women's sports, straight to your inbox.

    </div>

  </div>

</SponsoredSection>

**Wabi-Sabi** is the celebration of imperfection, transience, and the beauty of the natural world. It encourages us to appreciate the inherent simplicity of things, and to recognize that nothing is perfect, permanent, or complete.

For me, a great way to explain Wabi-sabi is with bluejeans - while there's nothing quite like a fresh, crisp pair of Levi's, they're also the most comfortable when they've been worn-in. The more you wear them, the more they become a part of you. Each little tear, stain, and crease tells a story.

There's a real beauty in that.

Wabi-Sabi is also about embracing the beauty of imperfection in ourselves, and the things we make. It's about accepting that we're not perfect, and that we're always growing and evolving. It's about embracing the beauty of the journey, and not just the destination.

## Wabi-sabi in tech

As product builders, we can apply this philosophy to the products we build by embracing our code's imperfections, valuing iterative improvements, and understanding that our work is always evolving. By adopting a Wabi-Sabi mindset, we can foster a more compassionate, creative, and sustainable approach to software development.

In other words: revisiting and rebuilding features of your product as it matures is part of the journey. Embrace the process.

The principles of Wabi-Sabi can be used in software engineering to create create better, more resilient products while nurturing team and personal growth. By learning from the wisdom of this ancient philosophy, we can improve not only our code, but also our mindset, transforming the way we work and live.

If you spend enough time watching people use your product, you'll doubtlessly see _someone_ using it in a way you never imagined or intended. There's an opportunity to learn from these unexpected uses, and to adopt new functionality, or just market directly to an audience you never considered.

My last startup was called _smpl_ -- a SaaS which helped independent coworking companies run billing and member management for their spaces. We were super-focused on building features to help coworking operators, and nonetheless had a few customers pop up who were using smpl for entirely different businesses. Use cases ranged from rental art studios to repurposed restaurant spaces, temporary vacation offices, and subletting existing office space -- none of which were in our core focus, but all of which brought interesting and valuable perspective to our strategy for marketing and customer acquisition.

So as your push forward on your journey of building the next-best-widget, consider the value of embracing imperfection and the power of Tiny Improvements™️™️™️.

---

## Finding opportunity in imperfection

- 📼 There's a great explainer video about wabi-sabi in tech from YouTube channel Cheddar, called [How Footpaths Help Shape Our Technology](https://www.youtube.com/watch?v=LN6_S5_FE3o).
- 🚘 In the classic car communtiy, wabi-sabi is most often celebrated by a different name: [Patina](https://classicmotorsports.com/articles/patina-good-bad-and-how-preserve-true-time-worn-cl/). Car collectors often seek out cars whose age and history are visible in the wear patterns on their paint, chrome, and other visual features. There are endless guides on how to _emulate_ age and patina on a car, but the real thing is always better.

## Imperfect releases from me this week

- 📖 Over at APIs You Won't Hate, we're _finally_ finishing up [Surviving Other People's APIs](https://apisyouwonthate.com/books/surviving-other-peoples-apis/), a book about how to work with APIs that you don't control. It's available for preorder on Leanpub - and is priced at $pay-what-you-want during the pre-order period. Thanks for checking it out!
- 🎙️ We also released a fresh episode of APIs You Won't Hate (the podcast) - [Jazzed about API client library codegen](https://share.transistor.fm/s/c6ad2ee1), with Danny Sheridan from Fern. If you're interested in codegen, this is a great episode to check out.
- 🎙️ I sat down with Guillermo Rauch, founder of Vercel, to talk about his team's approach to [Building Delightful User Experiences](https://softwareengineeringdaily.com/2023/03/15/building-user-experiences/) for the Software Engineering Daily podcast.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[An idiot's guide to using ChatGPT to make yourself smarter]]></title>
            <link>https://mikebifulco.com/newsletter/make-yourself-smarter-with-chatgpt</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/make-yourself-smarter-with-chatgpt</guid>
            <pubDate>Tue, 21 Mar 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[ChatGPT is amazing, and quickly finding its way into mainstream use - regardless of how tech-savvy the end user is. This is how I use ChatGPT to learn.]]></description>
            <content:encoded><![CDATA[
AI is _everywhere._

Chat GPT and interfaces like it have found themselves centerstage in tech culture. AI features have been added to search engines, word proccesing tools, image editors, audio editing software, and for crying out loud, even [Snapchat](https://www.theverge.com/2023/2/27/23614959/snapchat-my-ai-chatbot-chatgpt-openai-plus-subscription)! It's an exciting time, and there's lots to learn from the new frontier of AI-powered tools -- especially, I think, for people who don't work in heavily technical roles.

I've been writing about generative AI for a while (["Hey Influencers, be careful with ChatGPT](https://mikebifulco.com/posts/product-marketing-defy-expectations)") - and I'm really happy to see that it's finally starting to find its way into the mainstream. It's super interesting to see all of the creative ways that people are using it. Seeing people find ways to use ChatGPT through the lens of their own experiences, skills, and desires is truly fascinating.

Today, I want to talk about **using tools like ChatGPT to learn**.

<SponsoredSection
  sponsorName="RemoteMore"
  CTAtext="Get Your FREE Access"
  href="https://vpdae.com/redirect/mkq11hf6zu8b8q75uqbpwkmcsao"
>
  <div className="grid md:grid-cols-2 gap-4">
    <Image
      publicId="sponsors/remotemore/logo"
      alt="RemoteMore"
      height={250}
      width={250}
    />
    <div>

      ### Hiring developers made easy:

      - ✅ Search in 24,000+ remote developer profiles
      - ✅ All developers have passed our extensive screening
      - ✅ See their salary expectations upfront in their profiles

      Do you want to try our Hiring Platform for free?

    </div>

  </div>
</SponsoredSection>

One of the most common use cases I've seen for people using ChatGPT for the first time is - "tell me about `%some-interesting-thing%`". ChatGPT can distill complex topics into easily understandable summaries in a flash. It's thrilling -- seriously. But there's a tradeoff: ChatGPT's speed to respond can make it feel like we never need to think again. Got a question? Ask the robots. Curious about something? Ask the robots. Can't remember that one thing from high school physics? Ask the robots.

Offloading work from your brain is a good thing -- but making knowledge fully disposable isn't. Retaining _some_ of the things we learn is what helps us draw connections, foster creativity, and grow as people.

The [_Generation Effect_](https://en.wikipedia.org/wiki/Generation_effect) is the idea that you'll remember and understand stuff better when you put in the effort to do it yourself, rather than passively taking it in.

The thing is, when we take the time to experience and write about something, we're not just passively absorbing information. We're actively making connections, thinking critically, and making the material our own. It's the difference between watching a tutorial on YouTube about fixing your dryer, and then actually _fixing_ the damn thing yourself. Applied experience will do a lot more to cement learnings in your brainmeat™️.

When we engage with the material, we're more likely to remember it.

<Image
  publicId="newsletters/make-yourself-smarter-with-chatgpt/screenshot"
  alt="The secret to using chatGPT to LEARN"
  caption="I often use ChatGPT to spur ideas for writing"
/>

This is where tools like ChatGPT come in. These AI-powered dudes can be super helpful in getting our creative juices flowing. They can toss ideas back and forth with us, ask questions, and give us inspiration. By ChatGPT to kickstart our thinking, we're more likely to dive deep into a subject and learn more than if we were just scrolling through generated content on our own. That's a win.

So, the bottom line is that by getting hands-on and generating our own ideas, we stand to learn and retain so much more than if we're just skimming through content. And when we use ChatGPT to help us, we're taking advantage of the best of both worlds: the AI's ability to spark ideas and our own creative thinking to really make that knowledge stick.

For me, that means using AI tools to generate high-level bullets, and doing the work of expanding on those points and summarizing myself. When I'm doing research, the initial high-level points for my notes may start from ChatGPT,but in the process of summarizing, they often get revised to a completely different set based on my perspective. It's often enough to cause me to ask the bots for more _specific_ summaries, or a pivot from one topic to another.

For example -- this very newsletter started out as 5 bullets from chatGPT about something called the [Doorway Effect](https://en.wikipedia.org/wiki/Doorway_effect).

The simple act of going a level deeper to engage with the things generates can be _surprisingly_ productive. Give it a shot the next time you fire up ChatGPT - you might be surprised by the things you learn.

---

## Tucked away in my notes about taking notes

- 🗂️ The [Tickler File System](https://officedynamics.com/43-folders-method-paper-system/) is a physical system for organizing tasks that need to be completed on specific dates. It pre-dates digital note-taking, but is certainly a forebearer of more modern systems like [Getting Things Done](https://gettingthingsdone.com/). It's a surprisingly elegant system - 43 folders are used to represent tasks for each day of the year. I know -- I was surprised, too.
- 🎥 My brilliant better-half Natalie recently released a video about [ChatGPT in K-12 schools](https://www.youtube.com/watch?v=M9oOtOkPTzc&t=175s) on her YouTube channel, Primary Focus. The big idea: it's time to _lean in_ to AI for education, and not build walls around it. The revolution is here, my dudes.
- 🧘‍♂️ Axios published a great article on [Using ChatGPT for therapy](https://www.axios.com/2023/03/08/therapy-chatbots-chatgpt-ai). Therapy is a good thing, and _many_ people can't afford it. Chatbots are not a perfect solution by any means, but if they can help expand access to healthcare, that's got to be a good thing.

## Cache me outside

- 🎙️ My [interview with Guillermo Rauch from Vercel](https://softwareengineeringdaily.com/2023/03/15/building-user-experiences/) for Software Engineering Daily went live last week. Guillermo is clearly an extremely thoughtful and clever leader -- and I was lucky to get some time with him to talk shop.
- 🎤 I also interviewed [YC Founder Danny Sheridan](https://softwareengineeringdaily.com/2023/03/15/building-user-experiences/) about his new startup, [Fern](https://www.buildwithfern.com/). If you're building SDKs or client libraries for your company's API, you'll appreciate this one.
- 📖 As I've been prepping outlines for a quick course on note-taking, I was reminded that I've shared some of my notery on my site before. My article [Book Notes: Working in Public](https://mikebifulco.com/posts/working-in-public) is essentially a direct copy/paste of my notes on a great book from _Nadia Eghbal_ called [Working in Public: The Making and Maintenance of Open Source Software](https://amzn.to/3LAc0a6).
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Why Liquid Death's branding is murderously effective]]></title>
            <link>https://mikebifulco.com/newsletter/naming-your-product-kiki-bouba</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/naming-your-product-kiki-bouba</guid>
            <pubDate>Tue, 07 Mar 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Discover the science behind naming and branding, and how the Bouba/Kiki effect can help you create a brand identity that resonates with your audience.]]></description>
            <content:encoded><![CDATA[
Have you ever come across a brand whose name or visual design didn't seem to match the product? Maybe a company with a playful, colorful logo that sells something serious and professional, or a brand with a dull and generic name that markets a trendy and innovative product?

These mismatches carve out spots in our mind, but... why did they choose that name? Why does their logo look like that? What were they thinking?

Humans have a natural tendency to associate certain shapes and sounds with specific meanings. This phenomenon is known as the Bouba/kiki effect, which refers to the fact that most people associate the round, curvy shape of the word "bouba" with a soft, gentle object, and the sharp, jagged shape of the word "kiki" with a hard, spiky object. This effect is not limited to word-sounds, but also applies to visual cues, such as colors, fonts, and images.

Sounds crazy, no? This was the conclusion of a study conducted by Wolfgang Köhler in 1929 - who asked people to to associate nonsense words like [Kiki and Bouba](https://en.wikipedia.org/wiki/Bouba/kiki_effect) to round or soft shapes. Research concluded that this phenomenon was repeatable, and is called **sound symbolism**. This ability was once essential for survival, as it allows us to quickly identify and avoid dangerous objects.

> **tl;dr: pointy thing scary, round thing soft.**

Cultural expectations shape our perceptions of what certain things should be branded. For instance, we expect a luxury car brand to have a sophisticated and elegant name, a fast-food chain to have a short and catchy name, and a children's toy brand to have a fun and playful name. These expectations are not absolute, but they provide a useful framework for designing and naming brands that resonate with their target audiences.

<SponsoredSection
  sponsorName="MAPT Events"
  CTAtext="Find out more"
  href="https://vpdae.com/redirect/mkq11hf6zu8b8q75uqbpwkmcsao"
>
  <div className="grid md:grid-cols-2 gap-4">
    <Image
      publicId="sponsors/mapt-events/logo"
      alt="MAPT Events"
      height={250}
      width={250}
    />
    <div>

      ### Secure Your App Ideas and Make Them Yours: Prove Ownership and Increase Credibility with Our AI-Powered Idea Builder

      Take the first step towards app success with our AI-enhanced idea builder. Own and protect your app ideas, and prove ownership with a shareable link. With a track record of progress, you can confidently discuss your ideas. Build with us today!

    </div>

  </div>

  <img src='https://www.vpdae.com/open/5610.gif?opens=1' width='1' height='1' />
</SponsoredSection>

## It's not a hard and fast rule

Sometimes, defying these expectations can be a smart strategy for creating a unique and memorable product or brand. Enter Liquid Death, a company that sells one of the most mundane products imaginable, canned water. Where 99% of companies in the world take the same beige market strategy for _canned water_, Liquid Death's approach is anything but dull. The company's name, logo, and packaging are edgy, irreverent (hi), and unexpected, with an unhinged aesthetic that appeals to a young, rebellious audience.

Their slogan is damn memorable, too: **Murder your thirst**.

This brand strategy allows Liquid Death to stand out from other water By challenging the conventions of what bottled water should look and sound like, Liquid Death has become an outright success, with a loyal following and a rapidly growing business.

<Image
  publicId="newsletters/naming-your-product-kiki-bouba/liquid-death"
  alt="screenshot of liquid death's instagram feed"
  caption="Liquid death's instagram feed does NOT look like a typical water brand."
/>

So, what can we learn from this? When designing a brand, it's important to consider the industry and cultural expectations, but also to be willing to take risks and stand out from the crowd. By understanding the Bouba/kiki effect and using it to your advantage, you can create a visual and linguistic identity that resonates with your audience and sets you apart from the competition.

Who knows, you might just create the next Liquid Death.

## Obliterate your curiosity

- 👨‍🚀 [Creating a "similar posts" component in Astro](https://www.joshfinnie.com/blog/creating-a-similar-posts-component-in-astrojs/). My pal Josh Finnie put together a super tidy tutorial for building a "similar posts" component in Astro. It's a great example of how Astro's simplicity-first approach makes it easy to build components.
- 🗺️ [What3Words](https://what3words.com/clip.apples.leap) is a great example of a memorable product built by taking a fundamentally different approach to something we're all familiar with. The company's name is a reference to the fact that their service labels each location on Earth with a 3-word address. The words are chosen to be easy to remember, and are not associated with any particular meaning. For example, the most cursed place I've ever been to is `///hacker.plausible.bookshelf`.
- 🎥 Youtube channel LearnVue did a great [video about regexp.dev](https://www.youtube.com/watch?v=X_k198mrGL8), the library returns the humanity to regular expressions. It's a great example of how a simple, well-designed API can make a complex topic more accessible to a wider audience.

## Blast your brain with these links

...or, put another way - here's some of the things from my corner of the internet this week

- A new [APIs You Won't Hate Podcast](https://share.transistor.fm/s/494ca018) with Anton Zagrebelny from [Stigg](https://stigg.io). We had a great discussion about pricing strategy and structures for SaaS products, and the API that Stigg provides to make it easier for developers to experiment.
- I had the opportunity to interview [Matt Biilmann from Netlify on Software Engineering Daily](https://softwareengineeringdaily.com/2023/03/02/netlify/). We got into some of Netlify's announcements from the end of last year, and the company's approach to product development, and the future of the web.
- A new article from [Craftwork: 8 Questions to Help Select Paint Colors](https://craftwork.com/articles/questions-to-help-select-paint-colors). In a world with too many colors to choose from, it's no surprise that picking a color for your bathroom can be a crippling experience. We can help.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[The productivity tool I use every day to multiply my output]]></title>
            <link>https://mikebifulco.com/newsletter/unlock-productivity-with-networked-note-taking</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/unlock-productivity-with-networked-note-taking</guid>
            <pubDate>Tue, 28 Feb 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[I've been using networked note taking to organize my thoughts and ideas for years. Here's how it's helped me become more productive and efficient.]]></description>
            <content:encoded><![CDATA[
A few years back, I started a new job at Google, managing a team of Developer Advocates for Google Assistant. I was excited to be working with a high performing team and with an innovative product ecosystem, but I was also nervous about the transition. I had previously been working on a small but mighty team of just a few people. This was the first time I would be managing, and I was worried that I wouldn't be able to keep up with the demands of my new role.

I needed to find a way to increase my productivity and efficiency, and to prioritize tasks, so I could be able to quickly access the information I needed to do my job. I would be managing many interpersonal relationships, so keeping track of the details of everyhing and everyone I met was critical. I needed to be able to quickly and easily recall informatiom about ongoing projects, as well as the latest news from the world of voice tech.

If you work in tech already, this is probably a familiar story. To stay on the ball and manage stress, I needed to amplify my productivity and stay organized. I needed to build a second brain.

<SponsoredSection
  sponsorName="Skillshare"
  CTAtext="Learn More"
  href="https://vpdae.com/redirect/sx1yvno03hdz0yq7iv053b6d3s4"
>
  <div className="grid md:grid-cols-2 gap-4">
    <Image
      publicId="newsletters/unlock-productivity-with-networked-note-taking/skillshare"
      alt="Skillshare"
    />
    <div>

      ### Explore Thousands of Creative Classes

      Get started with one month free.

    </div>

  </div>
  <img src="https://www.vpdae.com/open/5586.gif?opens=1" width="1" height="1" />
</SponsoredSection>

As software developers and entrepreneurs, we often find ourselves juggling multiple projects, deadlines, and priorities simultaneously. With so much going on, it's essential to have effective tools and strategies in place to help us stay organized and focused.

This is going to sound completely wild, but the most profound change I made in the way I learn, work, and operate day to day was simple:

## I started taking notes.

Specifically, I adopted a technique called networked note taking (also called _zettelkasten,_ _second-brain,_ and more generally _Personal Knowledge Management_, or _PKM_). Essentially, networked note taking involves creating a web of interconnected notes that link together various ideas, thoughts, and concepts. By using note-taking tools like Obsidian, Roam Research, Notion, or Logseq, you can create a digital archive of your notes that allows you to quickly access and retrieve information when you need it.

So why is networked note taking so useful? For one thing, writing things down helps free up mental energy. Writing things down offloads some of the burden of _just remembering things_ from your brain. Instead of trying to remember everything in your head, you can capture your ideas in real-time and let the tools do the heavy lifting of organization and retrieval.

This gives you more mental space to focus on the things that really matter. You can spend less time worrying about remembering things and more time prioritizing and focusing on what's important now.

<Image
  publicId="newsletters/unlock-productivity-with-networked-note-taking/networked-notes"
  alt="A redacted screenshot of some of my notes from interviewing at Google, showing dozens of interrelated names, topics, and ideas"
  caption="I took notes furiously during my interview process at Google. This helped me remember all of the people I met, and the topics we discussed, and draw connections between common themes and ideas in the many discussions I had."
/>

### Remember without forgetting

Another benefit of networked note taking is that it ensures that your notes remain accessible without any loss of fidelity in the future. As much as we'd like to think that our memories are perfect, they're not. We all forget things from time to time, and we all make mistakes. Even with traditional note taking methods like pen and paper, notes can become lost, damaged, or misplaced over time. But with networked note taking, you can rest assured that your notes will always be available and easily searchable.

### Drawing connections between ideas

One of the biggest benefits of networked note-taking is that all of your notes become more valuable the more you write, as the network of connections between notes grows. As you write and link more notes together, you'll start to see patterns and connections that you might not have otherwise noticed. This can help you generate new ideas, solve problems, and make better decisions.

Networked note taking is also a great way to build a personal knowledge base. As you write more notes, you'll start to see patterns and connections between them. This can help you generate new ideas, solve problems, and make better decisions. If you're building a product, this is the kind of thing that can be a complete game-changer.

---

<Image
  publicId="newsletters/unlock-productivity-with-networked-note-taking/obsidian-screenshot"
  alt="screenshot of Obsidian desktop and mobile apps"
  caption="These tools allow you to stay organized, and help you see connections between your ideas. Screenshot from Obsidian's website, Obsidian.md"
/>

## The best tools for networked note taking

If you want to get started with networked note-taking, it's a good idea to find a tool that works for you, and stick with it. I recommend giving each of these a look and seeing which one feels right for you.

- [Obsidian](https://obsidian.md/) is a great place to start. It's powerful, has a great UI, and will help you get that allows you to create a network of interconnected notes. It's free for personal use, and for $8/month there's a premium version that includes additional features like cloud sync and version history. Obsidian has a great community behind it, and a lot of great resources to help you get started.

- [Logseq](https://logseq.com/) is a free, open-source networked note-taking tool that focuses on privacy and security. It has a handful of really cool features for learning, like PDF generation, a built-in flashcard tool, and whiteboarding features. It's also free, and because it is open-source, you can contribute to the project and help make it better.

- [Roam Research](https://roamresearch.com/) is a minimalist note-taking tool, and my personal choice for networked note-taking. A few years back, Roam was the tool that started a bit of a craze about networked-note-taking online. I like it because it is simple, and fast, and has great keyboard shortcuts for getting things done. Admittedly, it doesn't feel like it's received a ton of user-facing updates in recent months, which is a little discouraging. It's also fairly expensive at $15/mo or $165/yr -- and for full transparency, I purchased an early membership for a one-time fee.

- [Notion](https://notion.com) is... _not exactly_ a networked note-taking tool. I'm mentioning it here because I know _many_ people who use Notion effectively to stay organized. I think it's a great product, and we've been using it at my new company to stay organized. Because it doesn't support back-linking, it's not really a networked note-taking tool, and it's not really a knowledge base tool. It's a bit of a jack-of-all-trades, and I think it's best used for things like project management, task management, and personal knowledge management. Come at me, Notion gang 😘

---

## How to get started with networked note taking

If you're new to networked note-taking, it can be really helpful to check out some tutorials and guides to get started. Here are a few of my favorites:

- [Zettelkasten.de](https://zettelkasten.de/posts/overview/) offers a great overview of the zettelkasten method, and how to get started with it.
- YouTuber [Tiago Forte](https://www.youtube.com/@TiagoForte/search?query=notes) has a _ton_ of great videos comparing note-taking methodologies, and breaking down how he uses notes to stay organized in his job and personal life. He also published a book called [Building a Second Brain](https://amzn.to/3KvvCvn) which goes into deep detail on networked note-taking.
- It may be helpful just to watch someone take networked notes, too. Connor Sullivan, founder of Roam research has a 3.5 hour long [video of him taking notes in Roam](https://www.youtube.com/watch?v=ScRrcL__SSI) -- dive in for as long as you like.

## More from my second brain

In the weeks to come, I'll be sharing more of my notes and thoughts on networked note-taking, and how it's helped me stay organized and focused. I'm planning to share a bit about some of my favorite note-taking workflows, including:

- Second brain as a personal CRM
- Daily journaling for mental clarity
- Taking personal meeting notes to stay organized
- Notes for writing: how I build my blog posts over time

So -- stay tuned! If you're interested in PKM/second-brain/networked note-taking, I'd love to hear from you. What are you using? What are you working on? What are your favorite tools and workflows? Reply to this email and let me know what you use. I read every single reply, and I'd love to hear from you.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[The math behind why cafes should have round tables]]></title>
            <link>https://mikebifulco.com/newsletter/design-decisions-cafe-tables</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/design-decisions-cafe-tables</guid>
            <pubDate>Tue, 21 Feb 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Though we don't often think of it this way, the objects and buildings around us are the result of a series of design decisions.]]></description>
            <content:encoded><![CDATA[
I really love espresso. Great espresso - the kind that makes you savor every sip - is hard to make. It's a delicate balance of temperature, pressure, and grind size. It's a process that requires a lot of skill, practice, and intention, from cultivating and roasting coffee beans to the brewing process. When everything comes together, it a beautiful thing.

I'm also a big fan of cafes. I have spent countless mornings working from some of my favorite coffee shops, and have written many newsletters in the quiet of a cafe. I love the atmosphere - the hum of conversation, the smell of coffee, the sound of the espresso machine. Now that the danger of the pandemic has receded, I especially love seeing all the people - the baristas, the regulars, the people who are just passing through.

So, on a good morning when everything is going right, I'll walk to a nearby cafe and order a shot of espresso. After the barista pulls my shot, I'll find a table, take out my book, or my laptop, or put on a podcast on my phone, and sit down to get my day started.

<Image
  publicId="newsletters/design-decisions-cafe-tables/cover"
  alt="photo of a ceramic espresso cup and a shot glass with soda water sitting on a table in front of a pair of sunglasses"
  caption="I have so, so many pictures like this in my camera roll."
/>

This is the shape of a _sublime_ morning - the kind of day that can be easy to... _ah, what the fuck -- is the table unbalanced?_

I **hate** wobbly table.

_tap, tap_ ... _tap, tap_ ... _tap, tap_ ...

Every time you shift your weight, or move your coffee cup, or lean back in your chair, the table wobbles. It's annoying, it's distracting, and some days, it can be enough to ruin an otherwise great morning. It's a flaw that we've all experienced.

## The fix for a wobbly table

As it works out, a wobbly table is not something you _have_ to live with. If you look online, there are countless articles telling you ["how to fix a wobbly table"](https://www.wikihow.com/Brace-a-Wobbly-Table). You can tighten or brace a loose leg, or add shims to make the legs perfectly level, or take the cro-magnon approach and stack some coasters or napkins under one leg.

**However**, there is a solution simpler than all of these. A solution so simple that it feels like it shouldn't work. All you have to do is...

**...rotate the table a bit.**

That's it. Within a quarter turn of rotation, there will be at least one position where the table is perfectly stable.

Seriously - try it yourself the next time you sit down at a wobbly table.

<Image
  publicId="newsletters/design-decisions-cafe-tables/coffee-table"
  alt="A wobbly coffee table is such an annoying thing"
  caption="Rotate it a bit, but not like that. You know what I mean. Image from Oliver Knill, Harvard University"
/>

The explanation for this comes from branch of mathematics called topology -- it is helpfully called the Wobbly Table Theorem, and essentially relies on the fact that the surface you're sitting on is reasonably continuous.

The best visual explanation I've seen for this is a fantastic explainer video from the channel [Numberphile: Fix a Wobbly Table (with Math)](https://www.youtube.com/watch?v=OuF-WB7mD6k). If you prefer dense, nitty-gritty mathematics, you can read this [rigorous mathematical proof](https://arxiv.org/pdf/math-ph/0510065v6.pdf), or a slightly more accessible [explanation from a Harvard Mathematics professor](https://people.math.harvard.edu/~knill/teaching/math1a_2011/exhibits/wobblytable/).

## Your cafe should have round tables

The solution above will work for any shape of table - round, square, L-shaped, kidney shaped, you name it. However, I'd imagine that most cafe owners want to keep their shop looking orderly, and having a bunch of tables that are rotated at different angles would probably look a bit messy.

So - if you find yourself designing a cafe, or a restaurant, or a coffee shop, round tables are the way to go. They'll look nice and orderly no matter how much they need to be rotated, and they'll be stable and pleasant to sit at.

It's the kind of beautiful design victory that nobody will notice, and everyone will appreciate.

---

## An over-caffeinated list of links you might appreciate

- [Workfrom](https://workfrom.co/) is a service that is near and dear to my heart. It's like Yelp, but specifically for the best places to **work from** (get it?). I have been a top contributor on the site for a while, and helped rebuild their mobile app a few years back. I don't make any money off of you using the site -- it's just a great service that I love, and more people should know about it.
- If you're into coffee (or you want to be), you can't beat these two YouTube channels: [James Hoffmann](https://www.youtube.com/@jameshoffmann) and [Lance Hedrick](https://www.youtube.com/@LanceHedrick) have forgotten more about coffee than I'll ever know.
- For a little while while, I was a ✌🏾coffee influencer✌🏾. Once a month, [Bottomless](https://www.bottomless.com/referral/MBifulco6308) (that's a referral link) would send me a bag of coffee to try, and I'd share my experience on Twitter. It's definitely the thing I miss the most [since I left Twitter for Mastodon](https://mikebifulco.com/posts/twitter-and-the-perils-of-obedience). Regardless, if you're looking for a new coffee subscription, I can't recommend Bottomless enough. Use the link above to get a free bag of coffee after you sign up with Bottomless.
- 🎙️ I published another episode of [APIs You Won't Hate (the podcast)](https://share.transistor.fm/s/3b117523): Don't roll your own API management tools, with Josh Twist from Zuplo. If you're building an application that needs to talk to other services, you'll want to listen to this episode.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[The finicky nature of color in product design]]></title>
            <link>https://mikebifulco.com/newsletter/color-context-and-product-design</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/color-context-and-product-design</guid>
            <pubDate>Tue, 14 Feb 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Choosing colors for your product can be a difficult task. There are cultural, historical, contextual, and even physiological factors that can influence how we perceive color.]]></description>
            <content:encoded><![CDATA[
Color can be used to convey a message, evoke an emotion, or even change the way a user interacts with a product. It can also be _really_ difficult to get color right. There are cultural, historical, contextual, and even physiological factors that can influence how we perceive color.

Ever feel like you understand colors differently than you partner, or your best friend, or your mom? It's not just you.

<SponsoredSection
  imagePublicId="newsletters/color-context-and-product-design/oneglimpse"
  sponsorName="OneGlimpse"
  CTAtext="Start for Free"
  href="https://bit.ly/3RLoAEg"
>
  Designers often face the challenge of unauthorized access to their designs,
  leading to intellectual property theft and loss of business. OneGlimpse offers
  a comprehensive solution to protect your designs by blocking unauthorized
  screenshots and screen recordings. With OneGlimpse, you can have peace of mind
  knowing your designs are safe and secure.
</SponsoredSection>

Color perception is a very personal experience. A 1995 study published in the scientific journal _Perceptual and motor skills_ called [Blue versus periwinkle: color identification and gender](https://pubmed.ncbi.nlm.nih.gov/7624204/) showed that _"the women identified significantly more elaborate colors than did the men"\*_

<Image
  publicId="newsletters/color-context-and-product-design/color-men-vs-women"
  alt="A diagram showing an array of colors spanning the spectrum, with a female-presenting person on the left having unique words associated with each color, and the male-presenting person having far fewer. For example: teal, seafoam, and turquoise vs blue."
  caption="Color perception is a very personal experience. Image from user kathreynn on DeviantArt"
/>

**The lesson:** As you build your products, it's in your best interest to understand your audience. How do your primary users perceive color? What words do they use to describe their environment? Can you use an existing color taxonomy system or product palette that speaks to your user base? Understanding the value systems, language, and expression of your users can help you better design an interface that is intuitive, speaks to the user, and fits their needs.

<small>

\* _It's worth calling out that our cultural understanding of the nuance of gender in 1995 was not the same as it is today. There are many peer-reviewed papers with similar experiments going back as far as the 1970s. This particular study used a measure called "femininity" in its procedure. I have a feeling that if it were recreated today, they would choose more inclusive terms._

</small>

## How many colors are there?

If you grew up speaking english, you might rattle off the colors of the rainbow: red, orange, yellow, green, blue, indigo, and violet.

The colors we see are a universal truth, right?

Well, not exactly.

Different spoken languages can have have drastically different numbers of colors. This is likely a result of to the cultural and historical contexts that surrounded the development of a given language.

Different linguistic groups with different levels of technological sophistication developed over time, and depending on the size of the group and the need for communication, different color terms emerged in different languages. For example, the [Bassa](https://en.wikipedia.org/wiki/Color_term#Stage_I_.28dark_and_light.29) language (spoken by about half a million people in western africa) has only two terms to describe color - roughly equating to “light” and “dark”.

In Homer's _The Odyssey,_ the color the sea and the sky are famously described as "wine-dark", not because they were red, but because the ancient Greek language [doesn't have a word for blue](https://clarkesworldmagazine.com/hoffman_01_13/)!

I love this diagram of the color wheel as described by the Irish language, which shows where various color words are placed on the wheel. It's a great example of how different languages can have different color.

<Image
  publicId="newsletters/color-context-and-product-design/irish-color-wheel"
  alt="Irish Color wheel, courtesy of Wikipedia contributor Sherlyn"
  caption="Irish Color wheel, courtesy of Wikipedia contributor Sherlyn"
/>

The Wikipedia page for [Color Term](https://en.wikipedia.org/wiki/Color_term) goes into much more detail about the history of color terms and how they have evolved over time. It's a great read.

## Color and culture

As someone building a product for _other people_ to use, it's important to understand the cultural context of your users. This is especially true in a world where our audience of customers can be spread across the globe. Just as you might have a different understanding of color than your partner, your users might have a different understanding of color than you.

For this reason, it can be helpful to build early product prototypes and mockups in greyscale - using different shades of grey to represent different elements of your design. This can help you focus on the [hierarchy](https://mikebifulco.com/newsletter/design-rules-everyone-should-know#1-hierarchy) of your design before layering on your brand colors.

---

## More colorful wisdom

- 🎨 Did you know that [7-10% of men are red-green Colorblind](https://www.colour-blindness.com/general/prevalence/)? Putting red and green elements adjacent to one another in your designs can be difficult for some users to distinguish.

- 📖 For some great books on color in design, take a look at [Color Design Workbook](https://hardcover.app/books/color-design-workbook) and [100 Things Every Designer Needs to Know about People](https://hardcover.app/books/100-things-every-designer-needs-to-know-about-people).

- 🙌🏻 One of my favorite tools for evaluating use of color in your designs is [Stark](https://www.getstark.co/). It comes in the form of a plugin for things like Figma, InDesign, and all of the popular browsers, and uses WCAG and ADA standards to assess the accessibility of your designs.

## My work online this week

- ⌨️ I've been getting deeper into the world of TypeScript, and have been trying to document tricks and patterns that I've found helpful along the way. [Refactoring TypeScript React components in VS Code](https://mikebifulco.com/posts/refactoring-typescript-react-components-vscode) is a blog post showcasing how I use VS Code to refactor a React component from a class-based component to a functional component.

- 📼 I also published a YouTube short showing [How to add TypeScript to your existing Next.js project](https://www.youtube.com/shorts/rj6_Cm30DgQ) - it's surprisingly easy!

- 🥳 This last bit is indirectly my work, but I wanted to share anyway - we published our [first couple articles](https://craftwork.com/articles/tips-for-hiring-a-residential-painter) online for my new company, Craftwork. If you're interested in home painting, check them out! This also marks the beginning of a new journey into SEO and content marketing - building up a domain's authority and ranking for relevant keywords from scratch. I expect to share some of my learnings in the months to come.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Perception and unexpected tricks of the mind]]></title>
            <link>https://mikebifulco.com/newsletter/unexpected-observations-in-human-cognition</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/unexpected-observations-in-human-cognition</guid>
            <pubDate>Tue, 31 Jan 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Explore the fascinating world of perception and cognition in the Tiny Improvements newsletter. Uncover the unexpected tricks of our minds and learn how to make tiny improvements in our cognitive abilities.]]></description>
            <content:encoded><![CDATA[
I have really enjoyed learning about human cognition - the study of thinking and understanding. It's all about how we gather, process, remember, and use information in order to make sense of the world around us. As you might imagine, _the way people do thinking_ is a broad topic which research has only just begun to explore.

The fascinating thing to me about cognition is that many of the learnings we can derive from research on human thought boil down to simple principles. For me, at least, they always seem to make _so much sense_ once I've heard them said out loud -- but are often things that I've never really thought about before.

We tend to think of our interpretation of the world around us as something that works in a straightforward manner - that the world appears to us in the same way it truly is. The truth is that our perception of the world is often distorted by our own biases and expectations, and can also be manipulated by the way we are presented with information.

For example: research has shown that when people are asked to remember a list of items, they tend to remember items that appear at the beginning and end of the list more easily than those in the middle. So -- if you need to remember something, it's best to put it at the beginning or end of a list.

Similarly, the [Von Restorff Effect](https://mikebifulco.com/posts/product-marketing-defy-expectations#what-is-the-von-restorff-effect) is a psychological phenomenon that describes how people tend to remember things that are different from the rest of a group.

This week I've been captivated by entasis, a technique used in architecture that uses optical illusions to make physical structures seem more visually balanced. It involves slightly bulging the sides of a column or other straight structure in order to create the illusion of a taller, straighter structure. This technique is used to make structures appear more aesthetically pleasing - you've probably seen [entasis](https://en.wikipedia.org/wiki/Entasis) used in buildings that use columns, such as the Parthenon.

<Image
  publicId="newsletters/unexpected-observations-in-human-cognition/entasis"
  alt="A diagram of a column with a slight bulge on the side. The bulge is used to create the illusion of a taller, straighter column."
  caption="Entasis is a technique used in architecture that uses optical illusions to make physical structures seem more visually balanced."
/>

This is an effect that I've seen used in visual design as well, although I never had a name for it. As it works out, Entasis is frequently used in the design of typefaces. [Font designers often use entasis](https://graphicdesign.stackexchange.com/questions/111439/is-there-a-font-that-has-the-same-height-for-every-character) to create a subtle optical illusion that makes the font appear more balanced and symmetrical. Somtimes, a character will _appear_ more visually balanced if it is just slightly taller than the others around it, even though that feels like it shouldn't be the case. It's a subtle effect, but it can make a big difference in the way text appears.

<Image
  publicId="newsletters/unexpected-observations-in-human-cognition/x-height"
  alt="A diagram showing that the characters in a font aren't all the same height, as compared to the height of the 'x' character."
  caption="The 'x' character is often used as a reference point for the height of a font."
/>

From remembering lists to making typefaces look better, cognition plays an important role in product design. By understanding our cognitive biases and how we perceive the world, designers can create products that are more intuitive and aesthetically pleasing. Cognitive science is a powerful tool for product designers, and it can be used in unexpected ways to create remarkable results.

---

## More Tiny Improvements on cognition

If this tickled your curiosity, you might enjoy these:

- 📚 [Predictably Irrational, by Dan Ariely](https://hardcover.app/books/predictably-irrational) is a great book that explores the irrationality of human thought. It's a fascinating read that will make you think about the way you think.
- 🍷 [Why no one talks about the best marketing campaign in history](https://mikebifulco.com/posts/product-marketing-defy-expectations) - my writeup on the Von Restorff Effect, a psychological phenomenon that describes how people tend to remember things that are different from the rest of a group.
- 📅 Last week I gave a talk on _Unlocking the power of OSS
  to launch your startup and career_ at the first ever Open Source Charlotte Meetup. Check out the [slides](https://unlocking-open-source.netlify.app/%20) and event [summary](https://www.allthingsopen.org/charlotte-meetup-1-summary/) - we had a great time!

And one last thing -- you're doing great. Keep it up. I believe in you!
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Learn from me: a Dunning-Kruger expert]]></title>
            <link>https://mikebifulco.com/newsletter/learn-from-a-dunning-kruger-expert</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/learn-from-a-dunning-kruger-expert</guid>
            <pubDate>Tue, 24 Jan 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Drawing on the Dunning-Kruger Effect to propel tech progress is like using a slingshot to travel into space: Leaving our comfort zone to learn from experts gives us the momentum to break through boundaries and break records.]]></description>
            <content:encoded><![CDATA[
You may have heard of the [Dunning-Kruger Effect](https://en.wikipedia.org/wiki/Dunning%E2%80%93Kruger_effect) - people with limited knowledge overestimate their abilities when compared to those with more know-how. We've all experienced it in one form or another.

Passionate people often mistake their newfound passion for expertise, which can lead to some pretty bad decisions.

Recognizing my own ignorance is useful when viewed as a two-way street. There are things in this world that I feel comfortable sharing my expertise for. I am also wrong _all the time_ -- and I'm okay with that, as long as I can learn from people who know better than I do.

So, is it possible to **flip Dunning-Kruger on its head**, and use it to build momentum?

By honing in on the fact that you don't know it all, and making a conscious effort to seek out and listen to experts, you have the opportunity to build on your own knowledge and expertise. By recognizing your own ignorance, you can use the Dunning-Kruger effect to propel your career and business forward.

Here's a concrete example: I've got some background in design, and a little bit of background in engineering (true story: I have an undergrad degree in Mechanical Engineering that has gone largely unused since 2009). For a while, I've been mulling over the idea of designing Open Source, flat-pack furniture that could be cut from a single piece of plywood. Sounds cool, right?

<Image
  publicId="newsletters/learn-from-a-dunning-kruger-expert/flat-pack"
  alt="A render of a flat pack table, and a diagram showing how it was cut from one piece of plywood."
  caption="Flat pack furniture, laser cut from a single piece of plywood. Image from Instructables."
/>

I've got a few ideas, and I've been doing some research, but I'm not an expert in furniture design. I'm not an expert in woodworking. I'm not an expert in small batch manufacturing.

I'm just a dude who is excited about an idea, and I have a lot of questions.

I spent a few hours scouring the web for people smarter than me (spoiler alert: there are _many_ of them). From there I found [/r/hobbycnc](https://www.reddit.com/r/hobbycnc/) and [/r/woodworking](https://www.reddit.com/r/woodworking/), where I can learn from experienced makers and woodworkers. Instructables has an article series on [flat pack furniture](https://www.instructables.com/Flat-Pack-Table-Design/), and there's endless youtube [reviews of home CNC machines on YouTube](https://www.youtube.com/watch?v=_IxPxcvc9Wg).

Now that I've found places where experts are sharing their domain knowledge, I can start to listen, ask questions, take notes, and follow heated conversations. Before long, I may be ready to execute on my idea, or I may decide to pivot and make changes that better suit my expertise and situation.

This is something you can apply to any problem space. The best product builders are those who see the world through their own expertise _and_ the expertise of others, to build something that is greater than the sum of its parts.

It's also important to be prepared for the Dunning-Kruger effect to show up again. As you continue to learn, stay tapped into the community. Be mindful of your perceived level of expertise, and the potential mistakes that come with that knowledge.

Finally, when you do find yourself in the position to share your expertise, do so with humility. It is so powerful to be wrong on the internet, and it's even more powerful to [be wrong and admit it](https://mikebifulco.com/posts/semantic-html-heading-subtitle#-update-i-was-wrong-).

## There are things I think I know

- 💼 **The cat's out of the bag...** at least a little bit. Last week I started listing my new job on my various profiles on line. I'm working on a new company called [Craftwork](https://craftwork.com). I'm working with an outrageously talented team on making it easier for homeowners to get their houses painted... and that's just the tip of the iceberg. If you know any full-stack engineers who love TypeScript and react... I'm [hiring](https://docs.google.com/document/d/1orbRYcbBd2UfSHM5mvgCm_gYSwjOQAeaTh7YqymWAkM/edit?usp=sharing)!

- 🫶 **I'm speaking at the [first ever Charlotte Open Source Meetup](https://www.meetup.com/open-source-charlotte/events/290694423/)** this Thursday (Jan 26) at 6pm. The topic is _Unlocking the Power of Open Source to Launch Your Startup and Career_ - not-at-all hyperbolic. Hope to see you there!

- 🎙️ **A new APIs You Won't Hate podcast** is live! [Funding Open Source, with Dudley Carr from Stack Aid](https://share.transistor.fm/s/9bb11fc4) was a great conversation with a new friend I met at All Things Open last fall in Raleigh. We talked about the importance of funding open source projects, and how Stack Aid is helping to do just that. Check it out!

## ...and the things other people know

- 📚 [**"Thinking, Fast and Slow"**](https://hardcover.app/books/thinking-fast-and-slow) by Daniel Kahneman is a must-read, continuing the pattern of sharing books I love. It explores two modes of thought (fast and intuitive vs slow and reasoned) which appear time and again in decision making and cognitive science.

- 🎥 **[@nolanperk](https://www.tiktok.com/t/ZTRp352dc/) is a skilled designer** and TikTok creator who shares beautifully-made, thoughtful design tips on his account. Ever wonder how to make font sizes feel _just_ right on your app? Look no further.

- 🎙️ [**The Happiness Lab, with Dr. Laurie Santos**](https://www.pushkin.fm/podcasts/the-happiness-lab-with-dr-laurie-santos) is a podcast that explores the science of happiness... that's right, the _science_ of **happiness**. It turns out that personal happiness is something we can study, measure, and quantify. It's an occasional listen for me, and I always learn something.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[These are the books that shaped my career]]></title>
            <link>https://mikebifulco.com/newsletter/books-that-shaped-my-career</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/books-that-shaped-my-career</guid>
            <pubDate>Tue, 17 Jan 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[A sampling of books that have had a fundamental impact on my career as a designer, developer and startup founder.]]></description>
            <content:encoded><![CDATA[
## These are the books that shaped my career

I am a voracious learner. At this point in my life, I listen to a ton of podcasts, watch loads of this-and-that on YouTube, and listen to the occasional audiobook. In my first few years after finishing my undergrad studies, I was traveling for work just about every week, and because of that I spent tons of time in airports. During my downtime in transit, I'd pull out my trusty Nook (and later Kindle), and dive into something I wanted to learn about.

While I do occasionally read fiction books, for the most part I find myself going back to non-fiction. Reading non-fiction books helps me to understand how other people think, and how they approach problems. I can also get a taste of topics that I might not have otherwise been exposed to - and that's a good thing.

I've been thinking about this a lot lately, and I wanted to share a few books that have shaped my career as a designer, developer and startup founder. I'm sure I'll add to this list over time, but for now, here are the books that have had the biggest impact on me:

### Never Eat Alone

[By Keith Farrazi and Tahl Raz](https://hardcover.app/books/never-eat-alone)

I'm a firm believer that your personal network can be one of your most valuable assets. This book helped me affirm that belief. It's a great book for anyone who wants to build a network of people that they can rely on. I'll be the first one to tell you that I think some of the authors' perspective is a bit exaggerated and hyperbolic, but the general themes within are fantastic. If you're looking for strategies to stay in touch with the people in your life, give it a read.

### The Design of Everyday Things

[By Don Norman](https://hardcover.app/books/the-design-of-everyday-things)

This is an absolute must-read for anyone with even a passing interest in design -- whether it's physical objects, software, or the built environment. Don Norman is a design legend, and this book is a great introduction to his thinking. It's a bit dated, but the core concepts are still relevant today. You know that feeling you get when you can't figure out which light switch turns on the lights in a hotel room? That's a design problem. This book will help you understand why.

### Company of One

[By Paul Jarvis](https://hardcover.app/books/company-of-one)

This book's subtitle is "Why Staying Small is the Next Big Thing for Business," which was a revelation for me. The truth is, it is _really_ hard to build a billion dollar company. There's a delusion in the startup world that we all need to be building billion dollar companies, and we often forget that it can be far more practical to _start_ by building products that will serve a small audience. I've been a fan of Paul Jarvis for a long time, and I think he's got a great perspective on building a business. This book is a great read for anyone who's thinking about starting a business for the first time.

## Recommendations for things what can help you learn good

- [Hardcover.app](https://hardcover.app) is an indie-web product is self-described as "Social discovery for book lovers." I've been using it for about a year to keep track of books I read, and to keep a running list of books I want to read. I've also created a few lists of books to recommend on various subjects, like [The Designer's Reading List](https://hardcover.app/@irreverentmike/lists/the-designers-reading-list), which you may want to check out!

- [Snipd](https://www.snipd.com/) is an app for listening to podcasts that uses AI to transcribe the shows you listen to into text. From there, you can save snippets of the show to your notes, or share them online. I've found it to be useful for collecting bits of podcasts to share with friends. It's a fairly new app, so it can be a bit wibbly -- but it's been really cool to see the team building it add features over time.

## What I've been up to

I feel like we've all settled into the new year by now, and my work is back to full tilt. In case you missed it, here's the things I've been up to lately:

- 🎙️ In this year's first episode of the [APIs You Won't Hate podcast](https://apisyouwonthate.com/podcast), I spoke to my pal [Drew White](https://www.linkedin.com/in/drucial/) about how he broke into the tech world, and what he's been up to in his work at [Stashpad](https://stashpad.com/).

- 🫵 If you're local to my home town of Charlotte, NC, I'll be giving a talk at the first ever [Charlotte Open Source Meetup](https://www.meetup.com/open-source-charlotte/events/290694423/). I'd love to see you there!

- 📝 My AI side-hustle [Speechwriter.ai](https://speechwriter.ai) is just about ready to make its way into the real world. The last little step is adding payment features to the thing. If you or someone you know is speaking at a wedding soon and are interested in being a beta tester, reply to this email and I'll drop you a coupon code.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Tools for building a new company]]></title>
            <link>https://mikebifulco.com/newsletter/tools-for-building-a-new-company</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/tools-for-building-a-new-company</guid>
            <pubDate>Tue, 10 Jan 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[I spent the last week spinning up a new company for the first time since 2017. Here are the tools I used.]]></description>
            <content:encoded><![CDATA[
I spent the last week spinning up tools for a new startup I'm working on. Although I've built several products in the past few years, they have all been solo-efforts, so I haven't had to think about setting up collaboration tools. I haven't started from scratch with a new team since somewhere around 2017, and I was surprised at how much has changed.

Here's what I learned:

### The basics - the best got better

The first few tools I set up have been constants in my work life for a while - we're using [Google Workspace](https://workspace.google.com) for email, access to GSuite, and Google Drive, [Slack](https://slack.com) for team communication.

Notably, onboarding for both of these has gotten _much_ better - both for administration _and_ end users. I was able to get both of these set up in a few minutes, and adding new teammates was flawless.

I also set up [GitHub](https://github.com) for code collaboration, [Google Search Console](https://search.google.com/search-console/about) to keep an eye on SEO, and [Cloudflare](https://cloudflare.com) for managing DNS and protecting our web properties from abuse. These are tools I've used for years, and I'm happy to see that they've continued to improve -- and they all have generous free tiers, which is helpful if you're in the early days of bootstrapped products.

### First time tools for me

Believe it or not, I haven't used [Notion](https://notion.so) before. I've been using [RoamResearch](https://roamresearch.com) for personal note-taking years, and GSuite / Google Docs for authoring and collaboration since about 2014. I'm definitely a bit set-in-my-ways when it comes to collaborating - having worked at Google for a couple years, I got to see how the best-in-the-biz use Gmail and Google Docs to get things done.

_With that being said,_ I'm already really impressed by Notion. They've got an incredible set of templates for all sorts of use cases, and the ability to embed all sorts of content makes it easy to get started. To boot, my teammates have used it extensively, so I'm looking forward to learning from them as well.

We're using [Rippling](https://rippling.com) for Workforce Management -- in other words, for things like HR and payroll. Although I didn't set up Rippling, I have been plugging other tools into it - and I've been delighted by the automations they've built in for provisioning and deprovisioning services. This makes it easy to spin up services for new teammates - when they're added to Rippling, they're automatically added to the tools we use (and just as well, when they one day leave the company, Rippling makes revoking access a breeze).

Somewhere in the past few years, I started using [Figma](https://figma.com) as a design tool alongside my longtime staple [Sketch](https://sketch.com/). At this point, Figma is definitely better suited for collaboration, and I'll be using it with my new team to design our product UI and design language. I still use Sketch for design assets for mikebifulco.com, as well as many quick operations -- but I'm looking forward to using Figma for the bulk of my design work.

I'm sure we'll end up adding plenty of other services as time marches on - and I'm really interested in the things you use to get work done. If you've got a favorite tool that I missed, reply to this message and let me know. I'd love to check it out!

---

## Top tip: Browser profiles keep your work and personal lives separate

If you use Chrome (or any Chromium-based browser like Brave or Edge), and you're setting up a Google account that will live alongside your personal one, it's a good idea to set up different [browser profiles](https://support.google.com/chrome/answer/2364824) for each. This means your personal and work browsing histories will be separate, and you'll be able to install different extensions for each profile. I also tend to set up a third profile which I use for testing.

## Resources for fluorishing developers

These are a few of the things that have been occupying my brainmatter lately. I think you might like them, too!

- 🖇️ Growing on LinkedIn - now that I'm no longer using twitter, I've been working on strategies for increasing my area of influence in places like [Mastodon](https://hachyderm.io/@irreverentmike) and [LinkedIn](https://linkedin.com/in/mbifulco). My friends at Taplio (who previously sponsored Tiny Improvements) are currently hosting their [LinkedIn Growth Challenge](https://taplio.com/linkedin-growth-challenge-2023), where they're sharing their best tips for growing your network on LinkedIn. I'm participating, and looking forward to figuring out what catches peoples' attention on LinkedIn.

- 💼 Are you building a portfolio? [Victor Eke (@Evavic44) on GitHub](https://github.com/Evavic44/portfolio-ideas) has a great list of portfolios built developers, which is a great place to start if you're looking for inspiration for your own portfolio. I was flattered to find my site featured in the list alongside many others I admire.

- 🎥 I talk a lot about [Design for Developers](https://mikebifulco.com/newsletter/design-rules-everyone-should-know). I have a strong belief that most developers would benefit from learning just a few design basics. This week I came across [The missing guide to grids](https://www.youtube.com/watch?v=wIabVp0Hh8U) on YouTube. Whether you've used a grid system before or not, this video is a great introduction to the basics of grids, and how they can help you build better layouts.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[The case for continued learning, and getting side projects out the door]]></title>
            <link>https://mikebifulco.com/newsletter/side-project-and-a-fresh-start</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/side-project-and-a-fresh-start</guid>
            <pubDate>Tue, 03 Jan 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[The end of 2022 brought about a ton of change for me, and a major shift in my career. I'm excited to talk a little about what's next, and to show off a side project I'm readying for release soon.]]></description>
            <content:encoded><![CDATA[
It doesn't feel great to admit this, but for me the day _after_ Christmas is one of the most refreshing days of the year. The holidays tend to be a time of stress and anxiety, filled with challenging travel plans, rough weather, and saccharine holiday music. It's a day spent at home, tidying up the house and taking down decorations, and catching up on podcasts.

It's a deep, refreshing breath of oxygen.

That day after -- it's a welcome relief. I'm sure I'm not the only one who feels this way, but I do feel like I may be in the minority of people who talk about it. So if this resonates with you, you're not alone.

This year's exhale was especially welcome. A few weeks back, after sharing that I had gotten [laid off from my job at Stripe](https://mikebifulco.com/newsletter/leaving-stripe-going-viral), I told you that I would be sharing my next career move after the new year. Well, friends, we're here, and... I'm _almost_ ready to spill the beans. What I can say is that my next job is something entirely new - I'm headed back into the startup world, and will be building a new company and a new product with an _insanely_ talented team.

I'm excited to share more about that soon, but for now, let's talk about the new year.

In the coming weeks, I'm expecting to release version 0 of [Speechwriter.ai](https://speechwriter.ai), a generative AI product which uses GPT-3 to write speeches and other documents. It's built with an array of tools that I hadn't used before, including [Next.js](https://nextjs.org/), [Tailwind CSS](https://tailwindcss.com/), [Supabase](https://supabase.io/), and [TypeScript](https://www.typescriptlang.org/). I'm also using [GPT-3](https://openai.com/blog/gpt-3-apps/) for the first time, and I'm excited to see what it can do. I'm excited to share it with you, and I'm excited to see what you think of it. If you happen to be speaking at a wedding sometime soon and you'd like to test it out, drop me a line and I'll send you a coupon code for a free speech.

<Image
  publicId="newsletters/side-project-and-a-fresh-start/speechwriter-redesign"
  caption="A screenshot from the newly redesigned Speechwriter.ai homepage"
  alt="A screenshot from the newly redesigned Speechwriter.ai homepage"
/>

I'm also really interested in hearing what you're thinking about, and what you're working on. If you're diving into a new project or learning this year, reply to this email with what you're working on. I'd love to hear about it, and to help share it with the world when you're ready.

Happy New Year - let's get building!

## The things holding prime real estate in my brain this week

- 🧮 [Knolling](https://www.youtube.com/watch?v=EJuUhegtlOc) is a the practice of organizing physical things in your workspace at 90 degree angles. It's both visually appealing, and a helpful way to make sure everything is in its right place. It was created by Andrew Kromelow, a janitor working at Frank Gehry's furniture company in the 1980s, where it was used to keep tools organized in their workshop. It's since found footing in the photography world - the [#knolling tag on insta](https://www.instagram.com/explore/tags/knolling/) is full of beautiful examples.

- 🐘 Have you moved to Mastodon yet? I have, and you should too. Find me at [@irreverentmike@hachyderm.io](https://hachyderm.io/@irreverentmike). If you're worried about rebuilding your network from twitter, there are tools like [Fedifinder](https://fedifinder.glitch.me/) which can help you find your friends who have already moved. I've also found Mastodon to be super helpful for SEO -- I've seen a surprisingly high engagement rate in links I've shared, and a distinct uptick in traffic to my site since I started sharing my work there.

- 📚 I recently re-listened to Tony Fadell's book [Build: An Unorthodox Guide to Making Things Worth Making](https://hardcover.app/books/build), and even on a second listen I really enjoyed it. Fadell is the co-founder of Nest, and the inventor of the iPod. He's a fascinating guy, and his book is a great read for anyone who's interested in building things. It's been surprisingly prescient lately - I particularly enjoyed hearing his perspective on wny Southwest Airlines was so successful in their early days, and how they've struggled to adapt to the modern world.

## ABC - always be learning

This week I also thought I'd share some of the resources I've been using while I'm learning new things. I'm a big believer in the idea that you should always be learning, and that you should always be building -- and we damn well ought to be sharing the things that help us out. Here's a few of my favorites recently:

- 📼 [James Q. Quick's YouTube Channel](https://www.youtube.com/@JamesQQuick) has been hitting all the marks for me lately. He shares tutorials and examples on bleeding edge JavaScript frameworks and libraries, and does a great job of making it accessible to folks who might not be super experienced

- 👾 Another recommendation from YouTube, creator CodeBullet has been making in-depth, animated tech videos for quite a while. While they're not step-by-step tutorials, his videos are super engaging and very funny, and they do a great job of breaking down the basics of some seriously complex topics. Check out his recent 2-part series on [Teaching AI to walk in 3D space](https://www.youtube.com/watch?v=qvpXpCvkqbc)

- 🎙️ [Conduit](https://www.relay.fm/conduit) is a podcast from [Kathy Campbell](https://hachyderm.io/@mrssoup@mastodon.social) and [Jay Miller](https://hachyderm.io/@kjaymiller@mastodon.social), which explores "the connection between what we should be doing and what ultimately gets done" - I often feel like my ambitions outrun the time I have to get things done, and Conduit does a great job of exploring why that's okay... and why it's probably a good thing in some cases.

Alright fam, that's it for this week - I'm off to smash my hands into my keyboard and hope something good comes out. Don't forget to send me what you're working on, and in the mean time, be excellent to each other 🤜🏼🤛🏻
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Building your brand in the developer community]]></title>
            <link>https://mikebifulco.com/newsletter/be-intentional-about-building-your-brand</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/be-intentional-about-building-your-brand</guid>
            <pubDate>Tue, 13 Dec 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[Learn how to build a personal brand as a developer or product builder to differentiate yourself in the tech industry and gain recognition for your work. Authenticity and consistency are key to attracting the right people and opportunities. Follow these steps to get started.]]></description>
            <content:encoded><![CDATA[
I have spent _quite_ a few hours over the last few years publishing tutorials, podcasts, newsletters, and videos in an effort to share my knowledge and expertise with the world. I've done my best to be intentional about establishing who I am online and in the working world, and I've tried to do it all in a way that feels natural to me. Fundamentally, my goal has been to build a personal brand that reflects who I am and what I care about, and attracts the kind of people I want to work with.

In doing so, I've learned a lot about what it means to build a personal brand, and it turns out I've developed some strong opinions on the subject.

By sharing your working expertise with the world, you can differentiate yourself from others in tech and gain recognition for your work. One of the best things about this strategy is that you don't need anyone's permission - this is especially helpful if you don't have a fancy college on your resume, or you are moving into a technical career path for the first time.

Boiled down to its absolute core, this is my advice for you:

**Figure out what feels most natural to you, and do that.**

Whether you're writing articles or a newsletter, building demos or tutorials, producing videos, making memes -- the medium doesn't matter. What matters is that you are consistent and authentic in your approach. If you're not sure what that looks like for you, consider this approach:

1. Keep a list of people whose voices you value, whether they're in your field or not. What draws you to them, and not someone else? What do they do that you identify with?
1. Start writing down things that interest you day to day - when you find yourself going on a deep dive in wikipedia or google, make a note. That can be a great seed for something to write about.
1. Set a publish date for yourself (when I started, it was every Friday morning). Smash some words onto the page (or whatever makes sense for your medium of choice), and hit publish. It doesn't have to be perfect, it just has to be out there.

You'll get better with time, and you'll find your voice. You'll also find that you'll start to attract the kind of people you want to work with. That's truly one of the best things about putting yourself out there.

## Resources I use to manage my menagerie

As you might imagine, one consequence of me publishing _stuff_ all over the web is that it gets a little complicated to manage it all. I have done my best to be super intentional about keeping my processes minimal and functional - I don't want to spend a lot of time managing the information I share. I want to spend my time creating it.

Here's some of the things I use to keep an eye on what I'm making:

- [Detailed SEO Extension](https://chrome.google.com/webstore/detail/detailed-seo-extension/pfjdepjjfjjahkjfpkcgfmfhmnakjfba) - this is a Chrome extension that I use to do a quick audit of the SEO metadata for web pages. It's super helpful for checking the SEO of new articles on my site before I publish them.
  cop

- [Sketch](https://www.sketch.com/) - I use Sketch to create all of my the images and illustrations I use on my site. It's a great tool for creating vector graphics and it's super easy to use. If you're not a mac user, or work on a team[Figma](https://figma.com/) is a great alternative.

- [Squoosh](https://squoosh.app) is a utility I use all the time for reducing file size for images. It's a drag-and-drop web interface that can help you shrink big images [by as much as 95%](https://www.tiktok.com/@irreverentmike/video/7173745190220336426)!

## Brand-related thingies from me this week

- 👾 Do you have a README set up on your GitHub account? Do you have a personal website? This week I shared a tutorial on how to [sync your GitHub profile page with your next.js site](https://mikebifulco.com/posts/next-js-github-bio-about-page), so that you can have a single source of truth for your `About me` brand.
- 🎙️ My philosophy on creating a personal brand: I spoke with my Pals CJ Avilla and Colin Loretz on their podcast [Build and Learn](https://buildandlearn.dev/) this week. We talked about how I built my brand, and how I think about building a personal brand. You can [listen to the episode here](https://buildandlearn.dev/11) and subscribe in your podcatcher of choice.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Customer experience, quality, and the hype cycle]]></title>
            <link>https://mikebifulco.com/newsletter/quality-and-the-hype-cycle</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/quality-and-the-hype-cycle</guid>
            <pubDate>Tue, 06 Dec 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[The Gartner Hype Cycle, and its relationship with customer experience for new products and companies.]]></description>
            <content:encoded><![CDATA[
## You have _got_ to try this!

Think back to the last time a friend emphatically recommended a product or service to you.

For me, it was shoes.

A friend was raving to me me about Shoe Company™️ - an incredible, new, online-only merchant. My friend was vibrating with excitement as they told me how wonderful it was to buy from them. The website was beautiful and straightforward, the product was well-designed and sustainably made, and the ordering experience was exceptional.

They explained that when their shoes arrived, they looked great, and fit just right. Even so, the packaging that they were shipped in was minimal and thoughtful - made from recyclable materials, the box had a small strip of adhesive tape integrated into its lid so that the box could be easily re-sealed and mailed back thanks to the return label provided inside.

I _really_ love thoughtful experiences -- so this recommendation stuck with me. Around 6 months later, I was looking for a gift for my wife, and recalled the fervency of my friend's recommendation. Just like that, I bought her a pair of shoes that I thought my wife might like.

You might be able to guess where this is going already.

<Image
  publicId="newsletters/quality-and-the-hype-cycle/hype-cycle"
  caption="A modified version of the Gartner Hype Cycle chart, showing my experience"
  alt={`Gartner Hype Cycle chart, with my experience overlaid on top. I was recommended the company when they were in the "Peak of Inflated Expectations" phase, and bought from them when they were in the "Trough of Disillusionment" phase.`}
/>

Perhaps unsurprisingly, my experience was different. The website was still beautiful, but the ordering process was clunky. The product was still well-designed and sustainably made, and the packaging was nice. The shoes arrived, and while they looked great, they didn't fit quite right. The return label was missing from the box, and I found myself driving out of my way to one of a few shops in the city that could process my return.

Woof.

I was disappointed, and I felt like I had been misled by my friend's recommendation. But what was happening here? Why did my purchase differ so much from my friend's? At the risk of oversimplifying, I think it comes down to growth.

The company in question saw rapid growth, and as a result, they had to make some trade offs to keep up with demand. They prioritized growth over quality, and their product and experience suffered for a while.

On the other side of the spectrum are companies who make the decision to grow more slowly, and focus on quality as job #1. These companies may not grow as fast, but they tend to have a much higher chance of success in the long run. I find myself more loyal to these companies and experiences, having never been let down by them.

Growth-first companies _can_ bounce back from a dip in quality, and many have done so. I've been impressed lately with [Airbnb's efforts to improve their product](https://twitter.com/bchesky/status/1589541705921212416), and I'm hopeful that they'll get back to providing the unique alue they once did. But I think that the companies who prioritize quality will have a much easier time sustaining growth, and handling issues as they arise.

<small>

_(Newsletterman's footnote: I'm intentionally **not** naming Shoe Company™️. The point of this musing is not to shame or call anyone out. I'm just using this as an example to illustrate a point. I've noticed this same pattern in all sorts of companies and services, and I think it's worth thinking about.)_

</small>

## Recommendations from all over the hype cycle

Now that I've pointed out that you shouldn't trust recommendations from your friends (lol), here's some things I've found lately that you might enjoy.

- 🐘 [Mastodon (specifically, hachyderm.io)](https://hachyderm.io/@irreverentmike) - You may have seen that I've left Twitter, at least while it's under Elon Musk's control. I've moved to Mastodon, and have an account on Hachyderm.io. If you're on Mastodon, feel free to follow me there! If you're not sure what Mastodon is, check out [joinmastodon.org](https://joinmastodon.org/). If you're still not sure, reply to this email, and I'll find some time put together a quick explainer video.
- 📖 [The Innovation Stack](https://hardcover.app/books/the-innovation-stack) is a book by Jim McKelvey, who co-founded IRL payments company Square (now and its parent company Block). It's hard to imagine how a glass blower became the founder of such an influential company -- his story is fascinating, and the book is a great read.
- 📚 [Hardcover.app](https://hardcover.app/@irreverentmike) (Public beta) is a service for rating, recommending, and discovering books to read. If you've used GoodReads and find its UX lacking for 2022, or you're looking for a service not owned by Amazon, you'll love Hardcover.

## My recent work

- 🏳️ [**Twitter, and the Perils of Obedience**](https://mikebifulco.com/posts/twitter-and-the-perils-of-obedience) I wrote a long-form opinion article on my departure from Twitter, relating it to a famous experiment in behavioral psychology from the 1960s.
- 📹 Quick tech tips on TikTok and YouTube - I've been experimenting with releasing 60s tech tips on TikTok and YouTube. If you're active on either platform, I'd love to hear your feedback! TikTok: [@irreverentmike](https://tiktok.com/@irreverentmike) / YouTube [@mikebifulco](https://youtube.com/@mikebifulco)
- 🎙️ Did you know you can write C++, C#, and Java code that can be used directly on the web? My recent [interview with Matt Butcher from Fermyon](https://softwareengineeringdaily.com/2022/11/25/cloud-native-webassembly/) on the Software Engineering Daily podcast dives into Web Assembly, and was one of my absolute favorite interviews yet.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Put a fork in it - how to know when your work is ready to publish]]></title>
            <link>https://mikebifulco.com/newsletter/how-to-know-when-to-publish-your-work</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/how-to-know-when-to-publish-your-work</guid>
            <pubDate>Tue, 22 Nov 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[Deciding when your work is "done" can be a crippling decision for creators. Let's talk about that.]]></description>
            <content:encoded><![CDATA[
Hey friend,

Earlier this week, I had a discussion on Polywork with [Brian Green](https://www.polywork.com/brian_green), who is the founder of a learning platform called Curricular. He posed a question that I think we can all identify with:

> How do you know when your work is ready to publish?

I feel like this issue is at the heart of _everything_ I create, but it's particularly spicy when it comes to video. I can publish articles all day long, and go back to update them on a whim if the need ever arises.

Video is much more final - at least on YouTube, TikTok, and Instagram, because those platforms don't let you edit your videos after they're published.

After some thought, here's my answer to the question:

**Imperfection is part of the brand.**

Showing some scuffs here and there, and the vulnerability it takes to let those things out into the world helps people connect with you. It also gives you wiggle room to improve over time.

If you're constantly aiming for perfection, you'll never publish anything, and because of that, you'll never get any better.

It's a balance, of course - you don't want to be so imperfect that your work is incoherent or unprofessional. But a few scuffs along the way show that you're a real person, trying your best.

In fact, I think that I grow a much deeper personal attachment with creators who let me see into their process a bit. Things like editing, deciding on a voice, and what to deliver all make the brand feel more real, and more relatable to me.

There's also a subconscious element to it - I feel like I'm getting a peek into the creator's brain.

The secret sauce seems to be leaning into the bumps and bruises, and pointing out from time to time "hey, this isn't perfect, but I see that too".

When things feel _super_ polished all the time, it creates a veneer of false authenticity that just feels like... marketing? I think most people don't want to be sold to; they want to feel like they're a part of something genuine.

So, in short… here's what I think: don't be afraid to put something out there that's not perfect. It'll be more relatable, you'll meet more interesting people, and you'll have more fun with it.

To me, that's something people can get behind.

<SponsoredSection
  imagePublicId="sponsors/twirp.ai/cover"
  sponsorName="Twirp.ai"
  CTAtext="Try it for free"
  href="https://twirp.ai?utm_source=nl_tinyimprov"
>
  This dispatch of Tiny Improvements is sponsored by
  [Twirp.ai](https://twirp.ai?utm_source=nl_tinyimprov), a tool for A/B testing
  your twitter profile. Test different bios, profile pictures, and header images
  to see which ones get you more followers.
</SponsoredSection>

## What I'm reading

I've had a few connections ask me which newsletters I read regularly, so I thought I'd some of my favorites:

- 🗞️ If you're publishing a newsletter, you have to check out the [Growth Currency newsletter](https://www.growthcurrency.net/?utm_source=MikeBifulcoNewsletter). It's a weekly newsletter by Dylan Redekop providing highly-actionable tips, tactics, and resources to help you grow, improve, and monetize your own newsletter.
- 🏙️ For all my Urbanist / NUMTOT pals - my friend Barry Greene has been sharing his thoughts on Urbanization and public transit in his newsletter [Density Dad](https://cutloose.substack.com/?utm_source=nl_tinyimprovements). His perspective on responsible growth and planning for cities is refreshing, and I always learn something new.
- 🖍️ If you're a parent of an elementary-aged youngster, you should check out [Primary Focus](https://newsletter.primaryfocus.tv/), a newsletter by Miss Natalie, a 10-year veteran of the classroom who also happens to be my best friend and partner. She's been sharing her thoughts on education, parenting, and the future of learning in her newsletter for a while now, and it's a great read.

## Oh and BTW - I've been publishing videos, too

Despite publishing Tiny Improvements weekly, I've taken the last few weeks to recharge my cells a bit. It's a funny time for me - I'd love to be outside enjoying the weather even though it's cold out, but a recurring injury means I really need to take it easy. It's probably a good thing, honestly.

I've been making ~60s tutorials for creators and developers, and publishing them both on [YouTube](https://youtube.com/@mikebifulco) and [TikTok](https://tiktok.com/@irreverentmike).

If you're active on either platform, I'd love it if you checked them out and subscribed.

That's it for now - thanks so much for reading, and if you're in the US, enjoy the holiday.

Until next time,

Mike
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Get started: The trick to publishing online]]></title>
            <link>https://mikebifulco.com/newsletter/today-is-your-day-to-start</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/today-is-your-day-to-start</guid>
            <pubDate>Tue, 15 Nov 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[The biggest benefit about telling people online about what you're learning is the network effect.]]></description>
            <content:encoded><![CDATA[
Hi friend,

Today I want to talk about publishing things online.

My writing habit (and my [personal site](https://mikebifulco.com)) started on a lark - I wanted to learn about building websites with [Gatsby](https://www.gatsbyjs.com/). At the time, I was technical director for [Gymnasium](https://thegymnasium.com), and had been building a SaaS product in my spare time. I was learning so many things all at once that it seemed like a good idea to give myself somewhere public to write them down.

Fast forward to today, and I've got a few years of publishing under my belt. I did a quick audit over the weekend to see how far my words have gone, and I gotta tell you - I was not ready for the results.

Between articles written for [mikebifulco.com](https://mikebifulco.com), [apisyouwonthate.com](https://apisyouwonthate.com), and my past employers Google & Stripe, I estimate that **my work has reached about 1.3 million people.**

That is _STAGGERING!_

...and _super_ humbling -- even after all this time, I can't help but think _who wants to hear from little ol' me?_

<SponsoredSection
  imagePublicId="newsletters/today-is-your-day-to-start/taplio"
  sponsorName="Taplio"
  CTAtext="Try it out for free"
  href="https://taplio.com/?utm_source=nl_tinyimprov"
>
  This dispatch of Tiny Improvements is sponsored by
  [Taplio](https://taplio.com/?utm_source=nl_tinyimprov), the first AI-powered
  personal branding tool for LinkedIn. Increase your impact with your network,
  by creating high performing content 10x faster.
</SponsoredSection>

## Getting started as a writer

I hear from lots of people who _want_ to start writing online. Many people get in their own way, and never publish anything because of impostor syndrome, or because they don't have an audience yet. The best thing about being a creator is that you can start with _nothing_, and you don't need anyone's permission to get started. The sooner you create something and share it with the world, the sooner you'll get better at it.

Don't get me wrong - I've seen countless people set up a blog for themselves, publish a ["hello world" article](https://mikebifulco.com/posts/it-was-time), and only come back every 6 months to post something like _sorry it's been so long since I've written something here. I'm back for real this time_.

The biggest challenge for online creators is avoiding that pattern.

If you've been on the fence about starting a blog, or a YouTube channel, or a podcast, **this is your call to action:** publish something (_anything!_) and send it to me on twitter [@irreverentmike](https://twitter.com/irreverentmike) or mastodon [@irreverentmike@mastodon.online](https://mastodon.online/@irreverentmike). I'd love to see what you're building, and be a signal boost for your work.

## 2 guiding principles for publishing online

1. [**There is no bar**](https://chriscoyier.net/2022/06/27/there-is-no-bar/). In my absolute favorite blog post of all time, [Chris Coyier](https://twitter.com/chriscoyier) writes about how there is no minimum bar for publishing online. You can start with anything -- and you shouldn't be the one holding yourself back. The only thing you need to do is start.

2. **Writing triples your impact** - during his recent keynote at All Things Open, [Scott Hanselman](https://twitter.com/shanselman) shared a poignant observation. When you teach someone by sharing your knowledge, you've doubled the reach of your brain. If you write it down and even **just one other person** sees that, you've tripled your impact - and it only goes up from there.

When you have something to share -- write it down, and make it available **anywhere** with a public URL. It doesn't need to be any more complicated than that!

## Tools for publishing online

- 🗒️ [Obsidian](https://obsidian.md/) is note-taking tool, and is perfect for creating a second brain and getting things off your mind. If you're used to writing with [Markdown](https://www.markdownguide.org/basic-syntax/), it will feel very familiar. It's free for personal use.
- 🌁 Ever try to upload an image from your phone to your website, only to find it's 30mb and takes forever to download? Enter [Squoosh](https://squoosh.app/), a tool for compressing images. Pull up the URL, drag-and-drop your image, and hit the download button to grab a compressed version. It's that easy.
- 🖼️ Speaking of images, [Unsplash](https://unsplash.com) is a treasure trove of beautiful, high quality images licensed for use online (with attribution). You'll never want to use clip art or a stock photo again.
- 🧇 Waffle -- city -- ice cream cone -- if you've ever had trouble finding an icon for something, you're going to love [The Noun Project](https://thenounproject.com/). Their mission is to provide a library of icons for every _noun_ in the world. Can you imagine such a person, place, or thing?

Alright friends - now go smash some words on a page, and hit publish. I'll be waiting to see what you do!
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[What it's like to get laid off and go viral on the same day]]></title>
            <link>https://mikebifulco.com/newsletter/leaving-stripe-going-viral</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/leaving-stripe-going-viral</guid>
            <pubDate>Thu, 10 Nov 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[Last week may have been the most complicated week of my life. I got laid off from Stripe, and went viral on Twitter. Here's what happened.]]></description>
            <content:encoded><![CDATA[
## This is how my day went last Thursday:

**08:00am** - hop on a zoom call with a teammate to discuss Twitter's developer conference, Chirp, which had been canceled the night before. We were scheduled to give a tutorial on building SaaS apps at the event.

**08:05am** - While still on the phone, an email landed in my inbox, from Stripe's CEO Patrick, announcing that there would be a round of layoffs that day.

**08:08am** - While _still_ on the phone, another email hit my inbox. Subject line: "Mike, your role at Stripe".

<br />
<br />
That was it. I got laid off.
<br />
<br />

If you're new here, it's likely because you saw my tweet later that same day:

<blockquote class="twitter-tweet" align="center">
  <p lang="en" dir="ltr">
    🚨 I was laid off from my job at Stripe this morning. I will always look
    back on my time at Stripe DevRel fondly. Time to unwind and decompress. If
    you are a newly-former Stripe, DM or email hello@mikebifulco.com. I'll do
    whatever I can to help you find your next job.
  </p>
  &mdash; Mike Bifulco (@irreverentmike){' '}
  <a href="https://twitter.com/irreverentmike/status/1588197009315442688?ref_src=twsrc%5Etfw">
    November 3, 2022
  </a>
</blockquote>
<Script async src="https://platform.twitter.com/widgets.js" charset="utf-8" />

The timeline above outlines a vast simplification - to give you some idea of what happened in my world last week, here's a few high-level events:

- **Monday**: I enjoyed an emergency dentist appointment after a crown come off my tooth during a weekend trip to Philadelphia.
- **Tuesday**: Went to [All Things Open](https://allthingsopen.org/) in Raleigh, NC, and gave a talk about [Markdoc](https://markdoc.dev) to 50 devs.
- **Wednesday**: Drove home to Charlotte, to pack for the next day's trip to the [Caribbean Developer Conference](https://cdc.dev) in Punta Cana, Dominican Republic.
- **Thursday**: Ya boy got fired. lol. In the afternoon, I boarded a jet to Punta Cana with my wife, and shortly after arriving I fired off the tweet above.
- **Friday**: With the help of my incredible better half (Natalie 🫶), and steady stream of Piña Coladas, I responded to a trillion messages from people who had seen my tweet.

My dudes - it was a wild-ass week.

As I write this, it is almost exactly one week later. I've managed to untangle most of my brain by now, and have heard from a _massive_ number of people who reached out to me with love and support. I have probably sent hundreds of replies by now, and I'm extremely grateful for each and every one of you who reached out, RT'd, and subscribed to this newsletter.

Seriously -- Tiny Improvements has _doubled_ in subscriber count since last week!

## On moving on & momentum

You can't control everything in life, but you can control how you react to it. I am extremely grateful for the experience I had - my team at Stripe was truly unique, and indescribably talented. I'd tell my colleagues that working with them was like having lightning in a bottle.

I still feel that way, but it's time to move on.

I was pleasantly surprised to see my tweet getting so much attention. It's the most viral thing I've put on the web to date, and I'm trying to use that attention for good. Since getting laid off, many people have reached out to me who are hiring for super interesting jobs. I've been maintaining a list of these jobs, and will continue to keep it up for as long as I can manage.

**If you're looking for a job**, or know someone who is, check out [@irreverentmike's job list](https://airtable.com/shrbIYV7uOCfQDeGR)

**If you're hiring**, please DM me on twitter [@irreverentmike](https://twitter.com/irreverentmike) or [submit a job directly through this form](https://airtable.com/shraftW1575L6nGED).

## What's next for me

I am endlessly thankful for the great network of people I have in my life. Friends, family, former colleagues, and complete strangers have reached out about job openings. I'm thrilled to say that my next job is lined up already. I'm excited to share more about that soon.

### Now back to your regularly scheduled newsletter...

As you can imagine, this dispatch of Tiny Improvements is fairly atypical. Generally, this newsletter caters to people building great products - I'm a designer and front-end developer at heart, and a serial SaaS builder.

Generally my newsletters include a couple paragraphs diving into a topic like [design for developers](https://mikebifulco.com/newsletter/design-rules-everyone-should-know), or [managing burnout](https://mikebifulco.com/newsletter/burnout-and-stress), a photo or screenshot from my week, and links to a few interesting & helpful tools for getting things done.

If that sounds like something you'd enjoy, I'd love it if you stick around.

If you know anyone else who might benefit from my writing, please forward this to them, or send them off to [mikebifulco.com/newsletter](https://mikebifulco.com/newsletter) to subscribe. Thank you!

Here's hoping this next week is extremely un-interesting. ✌🏾
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[What I learned from using AI in my work]]></title>
            <link>https://mikebifulco.com/newsletter/what-i-learned-from-using-ai</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/what-i-learned-from-using-ai</guid>
            <pubDate>Tue, 25 Oct 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[Machine learning and AI tools have been making waves in the news lately. Let's take a look at some that you might want to consider using]]></description>
            <content:encoded><![CDATA[
It's no secret that I like playing with new tech, and lately there has been no shortage of AI tools making the news. By now, I've spent quite a bit of time testing out AI tools of various descriptions. It is encouraging to see consumer-facing AI products quickly becoming more useful.

Even on my own website ([mikebifulco.com](https://mikebifulco.com)), I've used AI for a pretty broad variety of tasks. This includes writing and publishing articles, and maintaining the code that keeps the site running. Some recent articles have cover art generated by Open AI's DALL-E. I bet you can probably even pick them out if you look closely! Until this moment not a single soul has asked me about where they came from. That's one point to the machines for their good work. 🤖

I also use GitHub's Copilot as a pair programmer when I'm working on personal projects. It's definitely not perfect, and I have my concerns about the way that GitHub/Microsoft are sourcing the code that Copilot uses to generate suggestions, but it's still a really useful tool. I find that it helps me avoid brain fatigue when I'm coding, even if it suggests solutions that are sometimes incomplete or incorrect - it's still a great way to get unstuck.

Of course, alongside good experiences, I've had my fair share of eye-opening and distinctly bad experiences with AI tools. In my favorite article ever, I wrote about a positively jaw-dropping moment I had when attempting to use one product to write blog posts. Sound interesting? I hope so - give it a read here: [Why no one talks about the best marketing campaign in history](https://mikebifulco.com/posts/product-marketing-defy-expectations).

It's important to point out that AI makes many people (myself included) nervous. We're anxious about what implications AI tools have on the future of our work, culture, and politics. Those concerns are valid - right now, I think one of the most important things you can do is get some experience using AI. This will help you understand its strengths and weaknesses in a practical way. It will also help you stay in touch with what's going on in the industry.

<Image
  publicId="newsletters/what-i-learned-from-using-ai/autumn"
  alt="A photo of a vast mountain landscape, showing blue-colored mountain tops extending into the distance"
  caption="A landscape from my recent trip to North Carolina's Blue Ridge Mountains."
/>

## AI tools you should try

These tools all use machine learning and AI to help you get things done. While most of them are not free, they all have some version of a trial or free tier that you can use to get a feel for them. If you haven't tried any of these, I recommend giving at least one a look - AI has come a **very** long way since the days of Goldeneye 64.

### No Code AI tools

📝 [Jasper AI](https://jasper.ai/) is a fantastic aid for people who write - it will help you write better emails, blog posts, and more. It's a great tool for people who want to write better, but get stuck on the details, or suffer from writer's block.

🎙 [Snipd](https://www.snipd.com/) is an incredible tool for people who listen to lots of podcasts. They use AI to automatically create an analyze transcripts of the shows you listen to. You can then use those transcripts to **snip** moments from a podcast, just like you'd bookmark a link to a webpage, or earmark a page in a book. I use it to take notes on podcasts that I listen to, and it's a great way to keep track of the things I want to remember.

🛋 [Interior AI](https://interiorai.com/) is a tool that lets you upload a photo of a room and it will suggest furniture that would fit in the room. It's pretty cool, and has been growing by leaps and bounds. Full disclosure: I happened across the product on twitter recently, and [have been helping its creator](https://twitter.com/irreverentmike/status/1579959127932968960) hone in on their pricing strategy using Stripe's tools. Apart from that, I'm not affiliated with, or paid by them in any way.

### For developers

✍🏼 [Open AI](https://openai.com/) are the creators of GPT-3, a language model that can generate text. It's pretty amazing, and you can try it out for yourself [here](https://beta.openai.com/).

🖼 [Stable Diffusion](https://github.com/CompVis/stable-diffusion) is an AI tool that you can run on your own computer to generate images from text. This one is for my more code savvy friends - it's written in python and not too challenging to use, but it does require some comfort with using a terminal.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Tips for managing burnout and stress]]></title>
            <link>https://mikebifulco.com/newsletter/burnout-and-stress</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/burnout-and-stress</guid>
            <pubDate>Tue, 18 Oct 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[We all experience stress and burnout at some point in our lives. Here are the tools I've found to stay ahead of burnout in my job and my relationships.]]></description>
            <content:encoded><![CDATA[
After I finished undergrad, I was hired by Microsoft to work in their consulting organization. I was hired as a software engineer, and traveled around the US building software for big, impressive Fortune 50 companies. The first project I was placed on was at Dell, in Austin TX -- all because I was the first one to raise my hand when someone asked "has anyone here used jQuery?" (this was early 2009).

Because I was the resident JavaScript expert, I thrust into the deep end immediately, leading front-end development for a complete rebuild of dell dot com. Our team of ten-or-so Microsofties were sent to deliver a from-scratch rebuild of the website, reporting directly to Dell's CTO. The stakes were high: we were expected to deliver a world-class website in a matter of months.

Seriously. If you're thinking _wtf, there's no way that's right_ -- it was truly surreal. Just a few months earlier, I had been loudly proclaiming "Wednesdays are little Saturdays!" while skipping all my classes one day a week, and splitting my weekends between going out drinking with friends and building my 1965 Corvair into a race car.

I was barely an adult, and had been given a huge responsibility. I was not equipped to deal with the stress of the situation. I worked 12-hour days to keep up with the other people on my team, and traveled between Charlotte and Austin every week. After 6 months, I was exhausted, and barreling toward burnout for the first time – and I didn’t see it coming.

One early Texas morning after a long night of coding, I dragged myself out of bed and showered, and... what the _fuck?!_ On the top of my head, directly above my left eyebrow, a small patch of my hair was missing. I had been pulling it out in my sleep. I was so stressed out that I was literally pulling my hair out.

**Burnout hit me like a ton of bricks.**

I called my manager that morning, and calmly told him I would be taking the next week off.

---

Look, we all experience stress and burnout - in different ways and to different degrees, certainly, but everyone feels it. In that moment, I learned a lot about myself. I'm a hard worker and I love my job, but I am not a machine. If I can help it, I'll never let myself get to that point again.

Learning to manage burnout has been a career-long journey for me. Stress ebbs and flows day to day, and week to week, but I've found being proactive about managing the way I work keeps burnout away.

There are many things we can do to manage stress and burnout, and I believe the details will be different for each of us -- but figuring out the right mix of work, rest, and play is where it all starts.

It's not just about you, either. Think about the people around you in your life who will benefit from you being less stressed and more present. Your family, your friends, your coworkers, your boss, your clients... the list goes as far as you can imagine.

You can't be expected to do good work if you're not feeling your best, and you can't get there if you're not actively taking steps to be selfish about what you want and what you need in life.

<Image
  publicId="newsletters/burnout-and-stress/autumn"
  alt="A photo of a beautiful autumn scene. The trees are all shades of red, orange, yellow, and green, and the sky is a pale blue."
  caption="We took a field trip to North Carolina's Blue Ridge parkway over the weekend. It was beautiful, and I'm so glad we got to go."
/>

The [World Health Organization](https://www.who.int/news/item/28-05-2019-burn-out-an-occupational-phenomenon-international-classification-of-diseases) classifies burnout as a syndrome resulting from chronic workplace stress that has not been successfully managed. It is characterized by three dimensions:

1. Feelings of energy depletion or exhaustion
2. Increased mental distance from one's job, or feelings of negativism or cynicism related to one's job
3. Reduced professional efficacy

...sound familiar?

Thankfully, the WHO is also working with scientists to develop guidelines on identifying and managing burnout. Science is looking out for us again, y'all. While I'm definitely not an expert on the subject, I've found that the following tools have helped me stay ahead of burnout in my job and my relationships.

## The tools I use to stay ahead of burnout

- 🛌 **Sleep better**. I'm intentionally putting this at the very top of the list so that you take it seriously. People always underestimate the effect that sleep has on their life. Don't take my word for it, listen to the experts - [**Why We Sleep: Unlocking the Power of Sleep and Dreams**](https://hardcover.app/books/why-we-sleep) by Matthew Walker is an exploration of our scientific understanding of sleep, and why it is critical to living a good life. Still not convinced? Check out this review from [Bill Gates](https://www.gatesnotes.com/Books/Why-We-Sleep).

- 🖼 **Therapy** is something that we all can benefit from. Especially men -- we are often not equipped with the right tools to deal with and express our emotions. Speaking to a professional can help you understand yourself better, and can help you learn to manage your emotions in a healthy way. Whoever you are, wherever you are, give it a shot. Talk to a _real_ professional (I'm looking at you, evangelicals) and invest in yourself. There are many options available, and [**BetterHelp**](https://www.betterhelp.com/) is a great option if you're looking to try therapy online.

- 📝 **Take notes** - No single habit I've adopted has had an impact on me like note taking. Writing down my thoughts helps me offload tasks from my brain, stay organized, and work more efficiently. I'm a big fan Zettelkasten-style note taking, and I use [**Roam Research**](https://roamresearch.com/) for my notes. It is a paid service - if you're on a budget or just dabbling for now, check out [Obsidian](https://obsidian.md/) and [LogSeq](https://logseq.com/).

- 🧘 **Meditate** - I use [**Headspace**](https://www.headspace.com/referral/z6jb3?slug=cebee0&audio=false) for a few minutes of peaceful meditation when I'm feeling overwhelmed.

- 🧠 This [5-minute video on Burnout from Dr. Sahar Yousef](https://www.youtube.com/watch?v=cFjK5WLpSHE) was actually produced by Headspace, and I found it to be pretty enlightening. Your brain's fear and anxiety center is literally activated by the accumulation of small bits of stress building up for days and weeks on end. The researcher from this video, [Dr. Sahar Yousef](https://www.saharyousef.com/), is working to develop frameworks to help us deal with burnout before it happens.

- 🪐 [The third place](https://mikebifulco.com/posts/remote-work-and-the-third-place) is a term that has been making the rounds on the internet lately. The long and short of it is this: we live a more balanced life when we somewhere to go that is not our home or our workplace. It's a place where we can go to relax, to socialize, to be fulfilled. Check out the linked article for my feelings on the importance of [The Third Place for remote workers](https://mikebifulco.com/posts/remote-work-and-the-third-place).

I'll leave you with this: if there's someone in your life who may be going through a tough time right now, drop them a line and tell them you see them, and you care about them. That little gesture can go a very long way.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[5 Design rules everyone should know]]></title>
            <link>https://mikebifulco.com/newsletter/design-rules-everyone-should-know</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/design-rules-everyone-should-know</guid>
            <pubDate>Tue, 11 Oct 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[For most of my life, I would not have described myself as a creative person. As it works out, nobody is inherently creative. It's all about following rules.]]></description>
            <content:encoded><![CDATA[
I never got on well with art when I was a kid. I didn't have a steady hand, which meant that I could never draw or paint well. My handwriting has always been abysmal, and I didn't have it in me to do better.

I was not an artistic person. Or so I thought.

After studying CS in college, I started working as a front-end engineer at Microsoft. Back then, front-end engineering was a blossoming discipline. Very few engineers worked in the land of CSS and Javascript, and almost nobody cared about design.

I got into design as a curiosity. I sure wanted to build better looking apps, but because I'm not an artistic person, I never thought to try...

...until...

one day, at the recommendation of a mentor, I picked up a book on design. I tore through it, gobsmacked by the revelations I was experiencing with each new page.

Friends, I am here to tell you: design is for EVERYONE.

## Heck, grits is just corn

In software, 99% of the things that you might think of as "creative" are careful and deliberate application of basic rules. Sure, there's usually a bit of taste and color sprinkled in, but the basics are all science.

In cognitive science, we study behavior and functions of the mind. It has helped us make sense out of how humans think, and distill that into rules and patterns.

In UX, we use these to take advantage of how people interpret and experience software.

Once you understand some of these rules, you'll find it gets easier to write letters, design graphics, build products, etc.

Whatever it is you're doing, design can help.

## 5 Rules of design to give you superpowers

...no matter what it is you're doing. Seriously. From writing to graphic design to designing products for the web, I promise you'll find something helpful in here.

### 1. **Hierarchy**

<Image
  publicId="newsletters/design-rules-everyone-should-know/hierarchy"
  alt="A screenshot of part of an article layout, showing a large, bold title followed by the familiar shapes of a date and author, and text below"
  height={300}
  width={300}
/>

In western countries, we tend to read from top to bottom, left to right. It is something we've all been subconsciously trained to do since an early age.

When you're designing something, you can use this pattern to help guide your reader's eye. Assume they will go from looking at the biggest, boldest thing on the page, to the next biggest, and so on. You should therefore make sure that the most important things you want someone to see are the biggest and boldest, and step down from there.

This is called hierarchy. It's a way to help your guide your reader's eyes predictably.

### 2. **Similarity**

<Image
  publicId="newsletters/design-rules-everyone-should-know/similarity"
  alt="A grid of buttons that all look the same, except for one that is a different color"
  height={300}
  width={300}
/>

One nice thing about the way humans perceive things is that we use **similarity** to recognize things, and group them together. This comes from basic survival instincts - if you ate a fruit from a bush without getting sick, others that look similar are probably safe, too.

Apples to apples, literally.

Your reader will use similarity to group things together -- and just as well, things that are _dissimilar_ will stand out like a sore thumb. Break similarity when you want to bring attention to something, like the most important action on a page. This is why you'll often see a "sign up" button in a different color than everything else on a given page.

### 3. **Half the words, and then half again**

<Image
  publicId="newsletters/design-rules-everyone-should-know/half-the-words"
  alt="A paragraph of lorem ipsum text, with many words struck out by black lines"
  height={300}
  width={300}
/>

Every one of us has a tendency to write too much. We want to be thorough, and we want to make sure we cover all the bases. The trouble is, our natural disposition to write long-winded descriptions is at odds with our readers' desire to get to the point. Cut down the words on the page to the bare minimum, by following Steve Krug's adage:

> “Get rid of half the words on each page, then get rid of half of what's left.”

Here's how I might rewrite for the paragraph above:

When it comes to writing, less is more. Don't waste users' time by making them read. Get to the point, and be memorable.

### 4. **Colors are math**

<Image
  publicId="newsletters/design-rules-everyone-should-know/colors"
  alt="A grayscale colorwheel, with an equilateral triangle overlayed on top of it, showing the relationship between 3 colors"
  height={300}
  width={300}
/>

For me, this was a big one - colors, and the way they interact with one-another, are predictable. In other words, we can tell whether a set of colors are likely to be in harmony with one another based on where they fall on the color wheel.

There are _many_ tools out there to help with this, too (see below for some examples). If you're working with a brand that has a specific color palette, you can use these tools to select colors that both complement _and_ contrast the brand's colors.

You don't need to have a _feel_ for colors - you can go a long way with the help of a calculator.

### 5. **The Rule of Thirds**

<Image
  publicId="newsletters/design-rules-everyone-should-know/rule-of-thirds"
  alt="A photo of a field of sunflowers in front of a clear sky, with a grid overlay demonstrating the rule of thirds"
  height={300}
  width={300}
/>

The Rule of Thirds comes from photography, where it's used to help guide the eye of the viewer. It's a simple rule: divide your image into thirds, both horizontally and vertically, and place the most important elements of your image on the intersections of those lines.

It's a shortcut to make your image look and _feel_ great every time. You can do this with photos, graphics, and entire page layouts.

## Colors, colors, everywhere

Color is a powerful tool, and a tricky concept to master. There are many tools out there to help you pick colors that work well together, and I've listed a few of my favorites below.

🎨 There are many **color scheme tools** available online to help you pick the right colors for your project. I really like [Coolors](https://coolors.co/) for picking colors, and [Color Hunt](https://colorhunt.co/) for finding inspiration. If you happen to be using Material UI, Google has some incredible docs on [generating Material-friendly color palettes](https://material.io/design/color/the-color-system.html#tools-for-picking-colors).

🧙 I'm a huge fan of **[@color.nerd](https://www.tiktok.com/@color.nerd) on TikTok** - he's a wizard when it comes to color theory, and does a great job of illustrating how colors interact with one another in the real world.

🧰 Did you know that about **1 in 12 men are colorblind**? That's a staggering percentage - and it's why it's so important to make sure your colors are accessible to everyone. [Stark](https://www.getstark.co/) is an accessibility tool that plugs into Figma, Sketch, and your favorite browser. It will help you make sure your designs are accessible to everyone.

📙 If you're ready to dive into more, the **[Color Design Workbook](https://hardcover.app/books/color-design-workbook)**, by Terry Lee Stone, Sean Adams, and Noreen Morioka should be required reading. You'll get some great fundamentals of graphic design and color theory, and learn how to use colors in your designs.

📚 Ready to take a course on design? The squad over at [The Gymnasium](https://thegymnasium.com/ux-design) have a whole suite of **free, online courses on design**. Check out their [UX Design Collection](https://thegymnasium.com/ux-design) to get started.

## Just enough to be dangerous

I hope you found something useful in here - and you can start applying these rules to your own work. If you did, please consider sharing this with your network, or sending it to a friend who might benefit from it.

If you're looking for more, I've got a few resources to keep you busy - check out [my articles on design](https://mikebifulco.com/tags/design), and let me know what you think.

I'd love to hear your feedback, too. Did you learn something new? Are you thirsty for more? Let me know what you think, and I'll keep writing.
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Remember these apps?]]></title>
            <link>https://mikebifulco.com/newsletter/lifecycle-of-a-moonshot-company</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/lifecycle-of-a-moonshot-company</guid>
            <pubDate>Tue, 04 Oct 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[This Dispatch of Tiny Improvements dives into some of †he apps we've forgotten, no code tools, and time off.]]></description>
            <content:encoded><![CDATA[
This week, I'm thinking about the lifecycle of moonshot companies. In particular, ones we may have forgotten about as they lost popularity.

A moonshot company is one that aims to solve a big problem, but is unlikely to be profitable in the short term. They're often started by a small team, and are often funded by venture capital. The idea is that they'll grow quickly, and eventually become a big company that solves a big problem.

The term comes from the old adage, _Shoot for the moon. Even if you miss, you'll land among the stars._

_Most_ moonshot companies don't make it to the moon or the stars. Instead, they become a stepping stone for new use cases, competition, and other product ideas. Every once in a while, though, an interesting thing happens -- an app that was once outrageously popular seems to fade into obscurity. I'm not sure why this happens, but it's worth thinking about.

## A blast from the past

You may remember [**FourSquare**](https://foursquare.com/), the popular app which let you check-in to a location and review it. If you checked-in frequently enough, you could become "mayor" of the spot.

It was a super cool idea that ended up being a direct competitor to Yelp, Google Maps, Trip Advisor and other services like them... and I thought it was _gone gone_ until last week, when a colleague mentioned that he was still using it. Get this: FourSquare has a loyal following! Superusers leave reviews on the app which tend to be more thorough and trustworthy than Yelp.

So, surprisingly enough, I reinstalled the app! It ended up being a great way to find good coffee shops while visiting my team in New York last week.

## Remember these apps?

- **Vine** was a social network that let users share 6 second video clips that would repeat when viewed. It was acquired by twitter in 2012 for $30M, and was eventually shut down because Twitter had other plans for video on their platform... and now the world uses TikTok, whose parent company, ByteDance, is worth an estimated $300B.

- **HQ Trivia** was a live trivia game show app that was wildly popular in 2018. It was acquired by the gaming company, Intermedia Labs, for $100M, and then shut down in 2020. Strangely, it appears to have been rebooted, asit is once again available in the app store.

- **Path** was a photo sharing social network app, which was popular in the early 2010s. It was founded by Shawn Fanning (of Napster fame) and was acquired by a South Korean company called Kakao in 2015. It was shut down in 2018, and the app is no longer available in the app store.

- **Yo** is definitely my favorite among this group. It was an app that let you send a message to your contacts -- and the only message was "Yo", accompanied by a sound effect. It was cofounded by [Or Arbel](https://twitter.com/orarbel), and the company raised $1.5M in funding. It was all over tech news for quite a while, but somehow never found a path to profitability. Even still, I sent my fair share of `Yo` messages to friends. I'm still not sure why, but this app has a special place in my heart.

## Recommendations: No-code for everyone

🤓 Last week, an article that I worked on for a while finally went live. [Devs: It's okay to use no-code tools](https://dev.to/stripe/devs-its-okay-to-use-no-code-tools-1gld) is a treatise I wrote to devs, imploring them to _try_ no-code tools. It's so much easier to automate work today than it was even just a few years ago. Even if you don't consider yourself technical, you can make something impressive with no-code tools.

🧪 Along those lines, [Mike Cardona](https://twitter.com/CSMikeCardona) has been publishing [Busy to Leveraged](https://letters.busytoleveraged.com/), which is all about how to build an automated a business with no-code tools.

🤖 My friend Aron Korenblit has been writing about automation for _years_ on his site [Automate All the Things](https://www.aatt.io/). Did you know you can use an Airtable as the content source for an entire website? Some real magic there.

📸 [Shottr](https://shottr.cc/) for MacOS is one of the best tools I've found for quickly annotating and sharing screenshots. It's optimized for new M1 Macs, too, so it's is super quick, and best of all - it's free!

## Please, make sure you're registered to vote!

(This is for my American friends - sorry international readers, but you'll have to bear with me for this one).

For crying out loud, please make sure you're registered to vote. Next month the US holds Midterm elections, and keeping the Congress in Democratic control is critical to the future of our country. You can check your voting registration status and register to vote over at [vote.org](https://www.vote.org/register-to-vote/).
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[The way we talk about our things]]></title>
            <link>https://mikebifulco.com/newsletter/use-of-language-and-intent</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/use-of-language-and-intent</guid>
            <pubDate>Tue, 20 Sep 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[This we we talk about intentional use of language and how it can affect subconscious behavior.]]></description>
            <content:encoded><![CDATA[
Hi there,
I hope you're well.

A few weeks ago, Apple launched their 2022 lineup of iPhones.

It was a typical event for Apple, with tremendous production values and exciting product announcements from executives. I'm always struck by how much intention and design goes into the production of Apple's live events - every single moment is scripted carefully; every camera angle is calculated and precise.

One thing that always stands out to me is the way that _Apple_ refers to their phones. During launch events, you'll never hear someone from apple talk about "the iPhone", or "an iPhone".

Seriously - go back and listen.

They will say things like "iPhone enables gorgeous photo capture across the entire range of light", or "iPhone 14 is designed to last".

That's a tiny change, but it's so significant. By never saying "the iPhone", Apple creates an air of elevated expectation for their product. The way that language is used is critical in marketing and sales, and Apple is a master at using language to create an emotional connection to their products.

If you're not paying attention, you might not even notice it. But it's something that I think about every time I see Apple use language to manipulate buyers.

What's even more interesting to me is the other side of this -- consumer behavior. Listen to people talking about their devices, and they speak differently still. Most people won't say "yesterday I got an iPhone 14" - instead, you're likely to hear "yesterday, I got **the** iPhone 14".

My friends, they made more than one. I promise.

And yet, it feels more special, exclusive, privileged to call your phone **the** iPhone 14.

Fascinating!

This week's dispatch of Tiny Improvements focuses on language and cognition.

## The way we talk about our things

You don't have to take my word (lol) on language and cognition. These are some of of my favorite resources on the topic, from around the web:

🎙 [**The Allusionist**](https://www.theallusionist.org/): A podcast about language, hosted by Helen Zaltzman. Helen is a fantastic host, and the show is always interesting and entertaining.

📖 [**Cultish: The Language of fanaticism**](https://hardcover.app/books/cultish) is a book by [Amanda Montell](https://twitter.com/AmandaMontell) on the language used to create and control people within cults of all sorts - from religion to fitness, politics and MLMs. It's a fascinating read, and I highly recommend it.

🦤 [**Toucan**](https://jointoucan.com/) is a browser extension that helps you immerse yourself in language learning, by replacing words on web pages you're visiting with vocabulary in another language. I've been using it to bolster my learning of Japanese. Their free tier is generous and super helpful. Give it a shot!

## From me this week

- I published an article on [using the ConvertKit API with Remix](https://mikebifulco.com/posts/publish-your-newsletter-with-convertkit-api-remix) to publish past newsletter issues to the web. It started as a quick experiment, but I'm really happy with how it turned out. I'll be publishing a follow-up article on how to use the same technique to publish your newsletter with Next.js, too.

- A great demonstration of why I love sharing on twitter - what started as a [tweet on my thoughts about figma getting acquired](https://twitter.com/irreverentmike/status/1570393684130103298) turned into a discussion on how to improve UX for signups on my site. You may be here because of it!
- It's officially busy season for work - and I'll be attending a few events in the coming weeks. Most will have livestreams or recordings, so I'll be sure to share them here.

That's all for now - thanks for reading. If you found this useful, I'd love it if you shared Tiny Improvements with a friend. It's the best way to help me grow the newsletter.

Until next time,

-M
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[What I've learned from working in public]]></title>
            <link>https://mikebifulco.com/newsletter/building-in-public</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/building-in-public</guid>
            <pubDate>Mon, 12 Sep 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[I'm a big fan of working in public. It's a great way to get feedback and improve your work... you just have to be ready to deal with The Internet™️]]></description>
            <content:encoded><![CDATA[
Hey - stop keeping your work a secret.

People building new products have a tendency to keep their projects secret until launch. Usually this is chalked up to a fear of a person or company stealing your idea. I'm willing to bet that we all know someone who has hidden their work from the world until it is "ready" or "done".

Here's the thing: When you keep your product journey a secret, you are robbing yourself of the chance to connect with people who might be interested in you and your product. There are countless success stories from people building in public online -- I'll even share a few below -- and very, very few success stories about things that are built in stealth, and only revealed to the world on launch day.

You don't have to trust me on this, but you should - I've made this mistake before.

You have more to gain by sharing your work with the world than you do by keeping it a secret. It's simple: make the process of building your product part of marketing it. Let people see the bumps and bruises, the moments of joy, and the uncertainties you encounter. Use this to build yourself a community of people who are interested in your product and your journey. Their interest will go past just your product - they'll be interested in you, and your story, and you'll see attachment that is difficult to replicate with a traditional marketing campaign _after_ launch.

The #indiehackers community has been doing this for years, and it's a big reason why many have been so successful.

![A chart comparing the kinetic energy of a Tesla Model 3, a Honda Civic Si, and a Hummer EV in a crash](https://res.cloudinary.com/mikebifulco-com/image/upload/v1663072457/newsletters/building-in-public/cover.png)

## Bigger trucks endanger us all

Have you noticed trucks are getting bigger? Next time you see a new truck in a parking lot, stand next to it - the hood on a new Chevy Silverado comes up to my forehead!

Trucks are extremely popular in the United States - there's no getting around that. I saw some friends sharing an article about the New Hummer EV, which weighs in at an absolutely staggering 9,046lbs. I made the chart above to highlight an important point: in an accident, the hummer EV carries _much_ more energy with it, especially at speeds above 40mph. It has the potential to be far deadlier than the other two cars in the chart. For the sake of comparison, I also included two lines for the F150 (the most popular truck in the world) - depending on its configuration, it can weigh between 4,021lbs and 7,050lbs.

Heavier trucks are worse for the road, more dangerous in collisions, and worse for the environment. I'd wager that more than 90% of these trucks are bought for the sake of vanity... and that's a problem.

## What I've been working on

Practice what you preach, right? It's been a busy few weeks over here.

I recently published an article showing how to recreate [The Orton Effect](https://mikebifulco.com/posts/orton-effect-css-react) with CSS and React. A few weeks back, I shared a post about my thoughts on working remotely, and finding happiness. It has started some great discussions, which was exactly the goal. Check out my article on [the third place](https://mikebifulco.com/posts/remote-work-and-the-third-place) and let me know what you think.

I've also been publishing **new episodes of my podcast, Tiny Improvements**, which you can [subscribe to here](https://plnk.to/tiny-improvements?to=page).

## Great products being built in public

**Todo lists for people with ADHD**
[Llama Life](https://llamalife.co/) is a thoughtfully designed web app for keeping track of the things you need to get done. It's a project that I've been watching for a while, particularly because the app's creator, [Marie Ng](https://twitter.com/threehourcoffee) does an amazing job of sharing her story over on twitter. It's a simple product that is changing peoples' lives, and has a serious following.

**Write like a doc, present like a deck**
[Gamma.app](https://gamma.app) puts a new spin on the presentation tool. It allows you to create beautiful presentations with a workflow much closer to authoring a document than something like a traditional PowerPoint. If you like writing, and hate laying out slides, this one's for you. Built by @by [@thatsjonsense](https://twitter.com/thatsjonsense) and [@thisisgrantlee](https://twitter.com/thisisgrantlee)

**Convert your most engaged readers into newsletter subscribers**
[Polite Pop](https://politepop.com) is a website plugin that _politely_ prompts your readers to sign up for your newsletter. I use it on my site (you may be reading this because of it!), and it's been a great way to grow my newsletter. It's built by [@panphora](https://twitter.com/panphora), and you can see updates for the product on twitter at [@polite_pop](https://twitter.com/polite_pop)
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Balance for remote workers]]></title>
            <link>https://mikebifulco.com/newsletter/balance-for-remote-workers</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/balance-for-remote-workers</guid>
            <pubDate>Tue, 06 Sep 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[Show up better on video calls, make your writing better by writing more, friction logging, and conferences are back!]]></description>
            <content:encoded><![CDATA[
Hey there,

I hope you had a great week. I [spoke at a conference](https://twitter.com/fintechdevcon/status/1562477596343816193) called Fintech Devcon last week in Denver, Colorado, about how we use Friction Logs to make our products better at Stripe.

It was the first time I had traveled for work in a while, and I found it extremely refreshing. The recording for my talk should be available soon - I'll be sure to share it once it is live.

I was also able to explore Denver a bit while I was there. The River North Arts District (or Rino) was great fun - I can see why people are moving there in droves.

## Learn with me

📝 Finding balance as a remote worker - I wrote an article on the Third Space and why it is important for remote workers finding balance. It was a super fun project to work on and I'm excited to share it with you. It's called "[The third place - the secret to a happy life for remote workers](https://mikebifulco.com/posts/remote-work-and-the-third-place)".

📹 Supercharge your video call setup - This [twitter thread by @theKevinShen](https://twitter.com/theKevinShen/status/1565791729906745348) shares some helpful tips for improving your video setup for calls. This one is really useful if you're doing a lot of calls with other people for work. Your presentation on video can have a real psychological effect on the people you're meeting with!

🧘‍♂️ Write more, write better - I've been working on developing a daily writing habit. This has helped me become more aware of how I use language which is making me more effective at writing great content for my job, and for Tiny Improvements!

Thanks for reading Tiny Improvements. If you found this helpful, I'd love it if you shared it with a friend. It helps me out a great deal!

Until next time - be excellent to each other!

-Mike
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Has it been four years already?]]></title>
            <link>https://mikebifulco.com/newsletter/four-years-already</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/four-years-already</guid>
            <pubDate>Tue, 19 Jan 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[MLK, presidential inauguration, time illusions, new features in Gatsby, and designing for musicians.]]></description>
            <content:encoded><![CDATA[
Hi there,

I hope you're well.

This week we remember the life of Dr. Martin Luther King, Jr., just days before the inauguration of America's 46th President, Joe Biden. As the inauguration draws nearer, I hope you're able to take some time to sit with the importance of this week in the context of history, of the past four years, the past year, and within the context of your own life.

I'll leave you with a quote from Dr. Martin Luther King, Jr. that a friend shared:

"In the End, we will remember not the words of our enemies, but the silence of our friends."

This is the time to step up and do your part. I'm proud of you for the hard work you put in, and I understand if you feel tattered and exhausted from the past year. Do what you can to stand up for the things you believe in, and use your voice and your actions to amplify the people that are making this world a better place.

✊ We're all in this together.

## This stuff has been living in my brain rent free...

- ⏲️ **Temporal illusions** are like optical illusions... but for time. (Note: Very 2019 metaphor incoming) Ever wonder why a delay at the airport on your way to vacation (I know, I know) feels so damn long? [Check out this video](https://www.youtube.com/watch?v=zHL9GP_B30E) from YouTube channel Vsauce for a stretchy explanation of our trippy perception of time.
- 💃 About a week ago, the **Great Gatsby lost copyright protection in the US** (the life of the author plus 70 years). That means it is now in the public domain, and we may start seeing some interesting works based on Gatsby.. What an appropriate time for it, too! Check out this really cool [Graphic Novel version of The Great Gatsby](https://www.woodmanmaynard.com/the-great-gatsby-graphic-novel), by K. Woodman-Maynard.
- 🤙 If you're an American, [5Calls.org](https://5calls.org/) is a super easy way for you make 5 quick calls to people who represent you in congress. Tell them you're a constituent, what city you live in, and a brief message about what you support. For example: "Hey, this is Mike, a citizen from Charlotte, and I'm calling to voice support for removing president Trump from office." That's all it takes!
- 🎵 Ever wonder what goes into **designing a font for musicians** to use? Did you know that sheet music used to be freaking hand engraved?! Honestly, neither did I! That didn't stop me from going deep on this fantastic [video from Tantacrul](https://www.youtube.com/watch?v=XGo4PJd1lng) about his work on the matter. Get in there and learn a bit - it's fascinating, even if you're not a musician.
- 🏞️ In green-ness news, the city of Paris has approved plans to **turn the iconic Champs-Élysées into a giant city park**. I have fond memories of meandering the Champs with two dear friends during a work trip in 2016. Freeing that area of car traffic will be absolutely transcendent. Check out this [article from The Guardian](https://www.theguardian.com/world/2021/jan/10/paris-approves-plan-to-turn-champs-elysees-into-extraordinary-garden-anne-hidalgo) discussing the project.

If you enjoy my musings, I'd love it if you'd share _Tiny Improvements_ with a friend. Feel free to forward this to them, or shuttle them directly over to [newsletter signup on my website](https://mikebifulco.com/newsletter). Thanks in advance - it means the world.

Do yourself a favor and take an extra moment to be kind to yourself this week. While you're at it, be excellent to each other.

<hr />

Talk soon!

Mike
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[Sip your coffee quietly, act kindly]]></title>
            <link>https://mikebifulco.com/newsletter/sip-coffee-quickly-act-quietly</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/sip-coffee-quickly-act-quietly</guid>
            <pubDate>Tue, 12 Jan 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[Watching history happen before our eyes, the economic study of bitcoin, accessibility, and drinking coffee in a quiet room.]]></description>
            <content:encoded><![CDATA[
Hi there,

I hope you're well.

This week, we saw some particularly disturbing history take place in front of our eyes at the US Capitol building. We're living through a time where facts seem optional, and people are being blinded by what they're told and what they want to see, as opposed to what's actually going on around them.

We're living through a very difficult time, and I think many of us are regularly finding our wits' end. Time and again, I find myself trying to center on kindness and optimism to get through my day. Remember that we all play a part in the bigger picture. It's up to each of us to do our small part to make things better.

Living selfishly pays off in the short term, but will inevitably cause harm to the world around you and the people you care about somewhere down the line.

Today, tomorrow, as you're going about your day, I urge you to be kinder. Be more intentional and more thoughtful with the people around you. The people you're sharing a space with can benefit from a tiny bit of kindness. People you've never met can benefit from a tiny bit of kindness, and certainly you can benefit from a tiny bit of kindness.

The path forward is unclear, but I think that we can get through this together. I'm reluctant to say that we're on the homestretch because I've seen time and again that that isn't the case. But I have my eyes on the hopeful horizon, and I hope you do too.

## What I'm reading this week

I'm making my way through a book called [The Bitcoin Standard](https://amzn.to/3btwyyR). It's more-or-less about the history of money, and the role that Bitcoin has played so far in advancing financial markets around the world, as well as some speculation on what's to come.

I enjoyed the first few chapters, which leaned heavily on history - but have found it harder and harder to get through as the book caught up with modern day. The author has some pretty strong takes on pop-culture that distract from the content of the book... even if they're a bit funny. Imagine being so annoyed by Miley Cyrus that you interrupt an otherwise-informative book to complain about her pop music as it relates to Mozart... what a strange take to put in a book about money.

I'll admit that it's overall the book is bit dense, and leans heavily on a solid basic understanding of some economic and financial terms - but I learned quite a bit by stopping to do so some research in the early chapters of the book. Still I'm 50-50 on recommending this one. If you're really interested in Bitcoin, give it a go - and [tweet at me](https://twitter.com/irreverentmike) if you make it farther than I have 🤣

## Some things you might enjoy

- 🎨 My friends and former colleagues over at Gymnasium are hosting a free webinar on **Accessibility and Inclusive Design** on Jan 21. Make sure to register before the event fills up.
- ☕️ Did you know **coffee tastes better in a quiet environment**?. According to a [study by scientific journal Food Quality and Preference](https://www.eatthis.com/news-how-noise-can-ruin-coffee-flavor/), sipping your cappuccino in your kitchen or a quiet cafe is a measurably better experience than if you're in a noisy room. Fascinating!
- 🌳 If you're in the UK, my friends over at Protect Earth are looking for volunteers to **help plant 500 trees** on the weekend of Jan 23-24. [Register here](https://www.protect.earth/events/planting-at-pantpurlais) if you're available.
- 👩‍⚖️ Current events in the US have been concerning, confusing, and scary for the past few weeks. [Opening Arguments](https://openargs.com/) is self-described as **A legal podcast that helps you make sense of the news.** I've been listening for about 4 years now, and it's helped me make sense of it all, and to understand a bit about what's coming. Give it a listen.

Keep up the kindness, and continue to be excellent to each other. Thanks for reading Tiny Improvements. Talk soon!

Mike
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[The Enthusiast's Hidden Superpower]]></title>
            <link>https://mikebifulco.com/newsletter/enthusiasts-hidden-superpower</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/enthusiasts-hidden-superpower</guid>
            <pubDate>Sun, 03 Jan 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[Optimism and the new year, why being an enthusiast can help you build a better product, espresso drinking and daily writing.]]></description>
            <content:encoded><![CDATA[
Hey there,

I hope you're well.

I love the turnover of the year: a time where people tend to become the most hopeful and optimistic. January can feel both cleansing and refreshing, like we've all just stepped over an invisible barrier that was holding something back. I love the way people share their goals openly and reflect on their past year's progress. Even if you're the type to turn your nose up at New Year's Resolutions™️, by doing so you've acknowledged that some people find them motivating. That right there is what has me transfixed right now.

From motivation grows enthusiasm. In enthusiasm, there is value.

## On Working in Public

In a [recent newsletter](https://mikebifulco.com/newsletter/on-seasonal-change-open-source-carbon-offsets), I mentioned that I had just finished reading a great book on building Open Source Software, called Working in Public. I had a few hiccups get in the way of getting my notes out into the world, but by now they're public! Feel free to [give them a read](https://mikebifulco.com/posts/working-in-public). I'd love to know what you think.

## On Enthusiasm

Lately, I've been describing myself as an _Enthusiast's Enthusiast_ - I truly love the feeling of developing and growing a new passion. I find that I go through regular cycles of passion for this-and-that, growing my expertise quickly and listening to others to glean as much as I can from them. I could make a list a mile long of the things I've done this for, but I thought I'd share a few recent passions that might interest you:

- 🧧 I've been reading about **Bitcoin** lately, as I'm sure you may have been as well. A friend pointed me to a few great primers on the subject, which I tore through as my on-ramp to learning more. I'd recommend getting started with an article called [The Bullish Case for Bitcoin](https://vijayboyapati.medium.com/the-bullish-case-for-bitcoin-6ecc8bdecc1), by Vijay Boyapti.
- ☕ I really, truly love great **Espresso**. To me, there's nothing better than taking in a cup of perfectly brewed beans. Learning about how and why coffee can taste so wildly different has opened my appreciate for the experience that much more. I'd recommend checking out [James Hoffman](https://www.youtube.com/channel/UCMb0O2CdPBNi-QqPk5T3gsQ) on Youtube - he's a former World Barista Champion, and a genuinely wonderful human being. His videos are world-class, relaxing, and supremely informative.
- 📝 I've never really had a habit for **writing** -- but I'm trying to build one. I'd love it to be easier for me to knock out a few paragraphs. I've been told it's simple: just write more, and it gets easier. In an attempt to do so, I've started a small daily writing habit based on [Morning Pages](https://juliacameronlive.com/basic-tools/morning-pages/) -- every day I write stream-of-consciousness thoughts in my notes, to help me to clear my mind, organize my day, and express myself more clearly. I was on the fence at first, but after a couple weeks, I think I'll stick with it for a bit!

## What are you working on?

I'd love to hear about your passions, or what you're looking to learn about in the new year. I'm here to learn and to listen just as much as I am to share. What's your latest muse? Let's [talk about it](mailto:hello@mikebifulco.com)! hello@mikebifulco.com. If you found this interesting or useful, I'd love it if you shared it with a friend.

In the meanwhile, be excellent to each other. Thanks for reading Tiny Improvements - talk soon!

Mike
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[On seasonal change, open source, and carbon offsets]]></title>
            <link>https://mikebifulco.com/newsletter/on-seasonal-change-open-source-carbon-offsets</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/on-seasonal-change-open-source-carbon-offsets</guid>
            <pubDate>Tue, 08 Dec 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Cognitive science and the framing effect, Open Source software and Working in Public, language learning, creating online courses, and reforestation.]]></description>
            <content:encoded><![CDATA[
Hey there,

I hope you're well.

Autumn has flown by at a crawl this year. I'm doing my best to focus on the little glimmers of light shining through for me right now, and I hope you can do the same.

Speaking of which, here it is - a big change for me! I recently started a new job at Google as a Developer Advocate for Google Assistant. You know the one - “hey google, what's the weather?” - I'm thrilled to be given the opportunity to work on such a wildly cool product. The interview process was intimidating, long, and challenging, but I did it! To say I'm standing on the shoulders of giants is an understatement. (I'll also be adding a disclaimer to my newsletters from here in: the things I discuss here are my own thoughts and opinions, and not those of my employer.)

## The brain is a strange place

Cognitive Psychology is the study of attention, perception, creativity, and other mental functions. Great software design takes advantage of cognitive biases to anticipate your behavior. For example, the [framing effect](<https://en.wikipedia.org/wiki/Framing_effect_(psychology)>) is when people are able to draw two distinct conclusions from the same set of data, depending on how it's presented. Forex: I have 200 unread emails in my inbox. Should I panic? Nah, they're marked "To Do" -- I'll get to it later.

## Working in Public (OSS!)

If you're interested in Open Source Software, you should check out the book Working in Public: The Making and Maintenance of Open Source Software, by Nadia Eghbal (link). I just finished reading through it with a book club I was invited to, and I enjoyed the read. I plan on [publishing my book notes to my website soon](https://mikebifulco.com/posts/working-in-public), as well.

## Kicking around in the old domepiece

These are a few of the things I've found on the web lately. I thought you might benefit from them as well:

- 🇪🇸 I've been brushing up on my Spanish. It's a relaxing couple-minute ritual in my day. I enjoy it so much that I've been sprinkling in some Japanese here and there, too! I've been using Duolingo's free plan - my referral link is [here](https://invite.duolingo.com/BDHTZTB5CWWKSRQUQARVC6SFNU) if you want to give it a shot.
- 👨‍🏫 How much do online courses make? Have you ever taken a course online, or thought about making one yourself as a side hustle? [This is a tool](https://revenue.sixfigureinstructor.com/) that lets you peruse the aggregate statistics of various course topics across Udemy. Did you know that on average, courses on Next.js make $40/day? Pretty wild!
- 🌳 Planting trees can make a difference. In the past, I've mentioned my love for [Ecologi](https://ecologi.com/irreverentmike?r=5d386c6667bad5001010ffae) (that's a referral link), which was previously called offset.earth. I'm excited to share that my good friend Phil Sturgeon has embarked on a carbon offsetting project of his own - he's on a mission to plant a forest of trees on farmland near his home in the UK this winter. Check out his work at [protect.earth](https://www.protect.earth/) , and donate if you're able!

Thanks for reading Tiny Improvements. If you've got any feedback, my inbox is always open: [hello@mikebifulco.com](mailto:hello@mikebifulco.com). If you've found this useful, I would love it if you shared it with a friend!

Be excellent to each other - talk soon.

- Mike

_Disclaimer: Tiny Improvements are my own thoughts an opinions, and not necessarily those of my employer._
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
        <item>
            <title><![CDATA[I swear I wrote that down somewhere 🤦‍♂️]]></title>
            <link>https://mikebifulco.com/newsletter/swear-i-wrote-that-down-somewhere</link>
            <guid isPermaLink="false">https://mikebifulco.com/newsletter/swear-i-wrote-that-down-somewhere</guid>
            <pubDate>Mon, 11 May 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Training your brain with networked note-taking, privacy-first analytics for websites, expensive asparagus, speed reading and retention.]]></description>
            <content:encoded><![CDATA[
I hope you're well.

I've been continuing my habit of getting out with the sunrise each day for a walk. I've been covering 4-5mi each morning. By my count, today I'll hit a 62 day streak, so if you're playing along at home, that's about 250mi I've traipsed through my neighborhood since this whole shutdown started. It's given me lots of time to work through my thoughts and feelings on everything going on in the world.​

## Brain training

_Write more!_

I'm trying to write more in general, and I'm starting by taking better notes. Part of that process is writing down things that I think about or come across each day, if they pique my attention in any way.

If you've crossed the same parts of the internet as I have, you may have heard about [Roam Research](https://roamresearch.com/) - a fairly brutalist note-taking tool which helps you see how your thoughts are linked together. I've been using it for a few months now, and while I'm not quite addicted to the thing, I absolutely see the value in continued use. They've had a tremendous amount of adoption lately. Last weekend, they saw 10k users register, which all but shut down their service. That's a hell of a success story!

## If you make things for the web...

- 📈 I put out a new article last week on why I adopted Fathom Analytics for my personal site (and a few other projects). If you haven't had a chance to read it yet, [give it a look here](https://www.mikebifulco.com/posts/why-fathom-analytics).
- 🔨 Have you tried out [Gatsby's incremental builds yet](https://www.gatsbyjs.com/blog/2020-04-22-announcing-incremental-builds/)? I've given it a go on both Netlify and Gatsby Cloud, and I've gotta say, I'm impressed.
- 🎨 Designing software with accessibility in mind is more important every day - and I've really enjoyed watching the growth of a product called [Stark](https://www.getstark.co/), which helps teams meet accessibility standards.

## Never stop learning

- 🥬 Unlike most commodities in the US during the pandemic, asparagus has become harder to source, and so its [price has gone up drastically](https://www.upi.com/Top_News/US/2020/05/07/Asparagus-price-bucks-norm-spikes-during-coronavirus-pandemic/5101588800054/).
- 📚 On any given day, the average person reads 113 thousand words(!). Cognition is the process of acquiring knowledge, and it's been capturing my attention lately. Check out this [great twitter thread from Kyle Harrison](https://twitter.com/kwharrison13/status/1257817073868107776) about how much we read, and some compelling thoughts on
- 🇬🇧 Did you know London is divided into 32 boroughs? I sure didn't. [Jay Foreman's video](https://www.youtube.com/watch?v=_T_0FYHn0I0) explaining what makes them all unique and strange is about as witty and British as one could hope for.

<hr />

Thanks for reading Tiny Improvements. If you've got any feedback, my inbox is always open: [hello@mikebifulco.com​](mailto:hello@mikebifulco.com)

Be excellent to each other -

Mike
]]></content:encoded>
            <author>hello@mikebifulco.com (Mike Bifulco @irreverentmike)</author>
        </item>
    </channel>
</rss>