Retiring Pinafore

Five years ago, I started a journey to build a better Mastodon client – one focused on performance and simplicity. And I did! Pinafore is the main Mastodon client I’ve used myself since I first released it.

After five years, though, my relationship with social media has changed, and it’s time for me to put Pinafore out to pasture. The pinafore.social website will still work, but I’ve marked the repo as unmaintained.

Why retire Pinafore?

I don’t have the energy to do this anymore. Pinafore has gone from being a fun side project to being a source of dread for me. There is a constant stream of bug reports, feature requests, and pull requests to manage, and I just don’t want to spend my free time doing this anymore.

By the way, this is not my first rodeo. Read this post on my breakup with another open-source project.

Why not pass it off to a new maintainer?

Running a fediverse client requires trust. People who use Pinafore are trusting me to handle their data securely. As such, I’ve been meticulous about using good security headers and making pro-privacy decisions. A new maintainer (through malice or ignorance) could add new functionality that compromises on security or privacy, essentially trading on my good name while harming users.

Over the years, I have had lots of feature requests that would inadvertently cause a privacy or security leak, and I’ve pushed back on every single one. (E.g. “Why not contact third-party servers to show the full favorite/boost count?” Well, because users may trust their home server, but that doesn’t mean they trust random third-party servers.)

Rather than trust that a new maintainer will keep these high standards in place, I’d rather put Pinafore in a frozen state.

Why not shut it down entirely?

Thanks to Vercel’s generous free tier, Pinafore costs me $0 per month to run. It’s just static HTML/CSS/JS files, after all.

Why are you the sole maintainer?

I’m not – there have been tons of contributions through the years. But for the most part, these have been “drive-by” in nature (nothing wrong with that!), rather than someone deeply learning the codebase end-to-end.

I suspect one of the reasons for this is that Pinafore is written in Svelte v2 and Sapper – both of which are deprecated in favor of Svelte v3 and SvelteKit. Not only is there no migration path from Svelte v2 to v3, but there isn’t one from Sapper to SvelteKit either. (And on top of that, I had to fork Sapper pretty heavily.) Anyone making a bet on learning Pinafore’s tech stack is investing in a dead framework, so it’s not very attractive for new maintainers.

So why didn’t I bother updating it? Well, it’s a lot of work to manually migrate 200+ components to what is essentially a new framework. And plus, as far as I could tell, it would be a pure DX (Developer Experience) improvement, not a UX (User Experience) improvement. (I just wouldn’t be using any of SvelteKit’s new features, and Svelte v3 doesn’t seem to have massive UX improvements over Svelte v2.)

What did you learn while writing Pinafore?

Now here’s an interesting question! And one that may be useful for those building their own Mastodon (or fediverse) clients. It is my sincerest wish that Pinafore inspires other developers to build their own (and better!) clients.

API and offline

First off, ActivityPub does have a client-to-server API, but as far as I can tell, it’s not really worth implementing. Mastodon is the 800-pound gorilla in the fediverse, it doesn’t implement this API, and other servers (such as Pleroma and Misskey) implement their own flavor of Mastodon’s API. And plus, Mastodon’s REST API is pretty sensible and doesn’t change too frequently. (And when it does, they add a /v2 endpoint while still maintaining the /v1 version.)

However, the fact that Mastodon has a fairly bog-standard REST API makes it pretty difficult to implement offline support, as I did in Pinafore. Essentially, I implemented a full mirror of Mastodon’s PostgreSQL database structure, but on top of IndexedDB. On top of that, I had to implement a variety of strategies to synchronize data between the client and server:

  • As new statuses stream in, how do you backfill ones you may have missed if the user went offline? Well, you have to just keep fetching statuses to fill the gap.
  • How do you deal with deleted statuses? Well, you have to remove them from the in-memory store, and the database, and then also go ahead and delete any statuses that boosted them or notifications that reference them… It’s a lot. (And don’t get me started on editing statuses! I didn’t even get around to that.)
  • How to deal with slow servers? Well, you can implement an optimistic UI that shows (for instance) a “favorited” animation while still waiting for the server to respond. (And also cancels if the server responds with an error or times out.)

From my years working on PouchDB, I know that it’s a fool’s errand to try to implement proper client-server synchronization without a holistic plan for managing revisions, conflicts, and offline states… and yet, I did it. The end result is pretty impressive in my opinion, even if arguably it doesn’t add a lot to the user experience. (There’s not much you can do in a social media app when you’re offline, and I’m sure people still frequently have to refresh when stuff gets out-of-date.)

Performance

Speaking of which, refreshes should be fast! And I believe Pinafore is pretty good at this. (I can’t find the link, but someone did a recent analysis showing that Pinafore uses less CPU and memory than the default Mastodon frontend.)

In short, I’d say it’s entirely possible to build a performant SPA (despite some of my misgivings about SPAs). But it helps if:

  • You have a browser perf background (like me).
  • You’re only one developer. (Much harder to implement tricky perf optimizations if you have to explain it to your colleagues!)
  • You use a perf-focused framework like Svelte.
  • You don’t do much! Pinafore has a fraction of the features of the main Mastodon frontend.
  • You’re merciless about removing dependencies, or writing your own dependencies when the existing ones are too slow or bloated.
  • You’re meticulous about little micro-optimizations (e.g. debouncing, event delegation, or page splitting) that improve the user experience, especially on low-end devices, but make the developer experience a lot worse.

Not all of this is necessary to make a fast, fluid API, but it certainly helps. And the fact that I ended up building something that can run on feature phones gives me a lot of satisfaction.

Accessibility

I didn’t set out to write “the accessible Mastodon client,” but I’ve heard from a lot of folks that Pinafore is one of the better ones out there, especially for blind users.

For this, I mostly have to thank Marco Zehe and James Teh (among others), who provided tons of feedback and really helped with the polish of the screen reader experience. Accessibility isn’t always black-and-white – like anything in design, sometimes there are tradeoffs and differing opinions on what the best option is. Leaning on the expertise of actual blind users gave me insights that I couldn’t have had otherwise.

Another thing that helps is just giving a damn. When I started on Pinafore, I didn’t really know much about accessibility, but I decided it was time to finally learn. I started off with a basic intro to screen readers from Rob Dodson, played around with VoiceOver and NVDA, and tried to read and understand as much as I could. I wouldn’t call myself an accessibility expert, but I’ve made a lot of progress in the past five years, and now I wince when I look back at some of the code I wrote in the past.

In the end, I found accessibility to be quite rewarding. Rather than feeling like a chore or a box-ticking exercise, it feels like a fun challenge. In some cases it’s just about leaning on existing web standards, but in other cases it feels like you’re building a parallel semantic UI to the visual one. Sometimes I found that this even influenced the overall architecture of my code – which goes to show that it’s better to consider accessibility upfront rather than as an afterthought.

That said, I definitely messed up some stuff when it comes to accessibility – color contrast in particular is something I did a poor job on. (Luckily Nick Colley has put a bunch of work into Pinafore to improve this!)

Conclusion

Pinafore was a fun project. I learned a lot about web development while working on it. Often, when a new feature landed in browsers – e.g. color-scheme, maskable icons, or various Intl APIs – I would eagerly integrate it into Pinafore, which helped me learn more about how browsers work.

In another case, I went a bit overboard on building my own emoji picker for Pinafore, and in the process learned way more than I ever wanted to know about fonts and emoji rendering.

I also think that Pinafore accomplished many of the goals I had in mind when I originally wrote it. At the time, Mastodon only had a multi-column UI, which many users found overwhelming and confusing. Pinafore demonstrated that a single-column layout could be a viable alternative, and since then, Mastodon has defaulted to a single-column layout.

Back then, there was also only one web-based Mastodon client (Halcyon), and it didn’t support logging in to more than one instance at a time. Pinafore proved it was possible for a web-based client to do this (not obvious given CORS constraints!), and nowadays there are lots of web-based clients, such as Sengi, Cuckoo+, and Elk, and many of them support multi-instance logins.

Pinafore isn’t going anywhere – like I mentioned, the site is still up and running. I also think it could serve as an interesting point of comparison for other Mastodon clients. (Try to beat Pinafore on performance and accessibility! I think that would be a great outcome.)

I also want to thank everyone who followed along with me on this journey over the years, and who either used Pinafore, filed a bug, or contributed to it. Thank you for giving me one of my career-defining projects over the last half-decade. It wouldn’t have been possible without your help.

12 responses to this post.

  1. Loved your work -sorry to see it go.

    Reply

  2. This is a wonderfully thorough, thoughtful, kind signoff for the project. Thank you.

    Reply

  3. Posted by Nina Schouten on January 9, 2023 at 2:22 PM

    I am a new Mastodon user, and an layman in this field. But thanks for all your efforts!
    And it was nice to read more about your journey!

    One of my accounts is https://mindly.social/@AltTextFeatures, where I try to help other laymans. 😅

    Succes, I wish you nice leisure time. Which will probably inspire your creativity.

    Nina Schouten

    Reply

  4. Posted by marco on January 9, 2023 at 4:10 PM

    Any chance you would consider releasing it under a more liberal license like MIT or BSD3? AGPL is a nonstarter in a lot of software shops.

    Reply

    • I prefer to use AGPL for a project like this, because anyone who hosts their own fork of Pinafore must also make their fork open-source. FWIW Mastodon itself uses the same license.

      Reply

      • Posted by marco on January 19, 2023 at 11:19 PM

        Understood. I do wish there were more permissively-licensed products in the ActivityPub ecosystem. Many companies simply will not utilize copyleft products; the net result is that derivative works simply never get made, or the same products are re-built again and again.

        I use Pinafore every day and think it strikes an excellent balance between usability and minimalism. Thanks so much for your work and dedication on this product.

  5. End of an era. Thanks for the experience, Nolan!

    Originally posted at https://jacky.wtf/2023/1/Cyod

    Reply

  6. Nolan you built a beast. Your client sips through a straw of resources and benchpresses performance. I am in awe of your work and completely understand your desire to step away. Just let it be known you have nothing but admiration for what you’ve built.

    Reply

  7. Posted by pax121 on January 11, 2023 at 4:31 AM

    now we need to use horrible web ui to get latest stuff

    Reply

  8. Absolutely incredible work! I still know folks who (I’m pretty sure) have continued to use Pinafore as their primary client in mobile browsers for the whole duration. Thank you for taking the time to cohesively review the work! I think it’s important.

    Reply

  9. […] Mastodon APIのWebクライアントのPinaforeに開発終了の告知があったので紹介します。2023-01-09 Monの「Retiring Pinafore | Read the Tea Leaves」で告知されていました。 […]

    Reply

  10. Posted by Ben on January 23, 2023 at 10:47 AM

    Thanks for building Pinafore! It’s been my default interface to the fediverse since you first released it. And an example of PWAs should be that I share with folks. All the best in whatever you build next.

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.