I'm Justin Duke — an engineer, writer, and founder. I currently work as the CEO of Buttondown, the best way to start and grow your newsletter, and as a partner at Third South Capital.
Subscribe here, or follow me on Twitter / Bluesky.
to search.
Writing
Slack workflows as duct tape
9/14/26
A workflow we've wanted for a long time at Buttondown: throw a random paper cut or complaint into a Slack channel, and get a nicely formatted Linear issue ou...
Talk Easy
9/11/26
A running joke between me and a few friends is the inevitability of all podcasts — or really, all interview mediums — to curdle into anodyne pablum as they g...
It's just a model
9/10/26
I, like many people, have witnessed and felt the whiplash between the seemingly-orgastic highs of the Astra launch and the experience of using the model. Whe...
Hiring and firing a DBA
9/7/26
Hiring our DBA For the past sixty days, Buttondown ran a scheduled LLM invocation once a day. Every morning it would look at the previous few days of databas...
/shuffle
9/4/26
I'm here to tell you about a hidden feature of sorts that I built for Buttondown. Go to buttondown.com/shuffle and you will be served a completely random arc...
Fable 5.1
9/2/26
Anthropic released Fable 5.1 this week. My initial reaction to the release was this comment I made in the Third South Slack: > More seriously: I'm excited to...
BB, Grok Bot
8/22/26
Another month, another field report from testing some vaguely interesting tools: this time, BB and Grok Bot. --- BB is a tool from the folks who built Terrag...
EPUB is not that scary
8/21/26
In a prior life, I worked on Kindle — specifically on content pipelines and data processing. This either excuses the fact that I had no real idea what EPUB w...
Notes on Cloudflare Access
8/19/26
Cloudflare is now in the AWS zone: it has a long tail of useful but under-examined little services that haven't quite entered the zeitgeist the way the flags...
Tech debt is weird
8/8/26
Jesse wrote this interesting article on technical debt, which resonated with me spiritually but not directionally -- which is a very weird way to say that I...
Patch notes
8/5/26
Earlier this year I mentioned that Slay the Spire 2 had reached the status of needing to be deleted from my computer, on the grounds that it was proving too...
op, mprocs
8/2/26
Two small tooling changes that have been really nice for us at Buttondown: 1Password CLI A long-standing annoyance has been dealing with secrets and coordina...
Snacks are cheaper and tastier than ever
7/31/26
Perhaps the single most consequential essay I've read is Will Larson's Work on what matters. This is ostensibly advice targeted towards staff engineers, but...
Cursed knowledge
7/29/26
Nick pointed me towards Marcin who pointed me towards immich's list of cursed knowledge the other day, and it has already become a running joke in the Slack....
Check the status page
7/20/26
As I've covered somewhat extensively in prior writing (see A month of OpEx quick wins and Self-hosting our GitHub Action runners), this year has been marked...
How the media library works
7/17/26
I've received a number of questions as to how the media library part of this blog works, and I figure it's worth a bit of time to explain — even though there...
Two hundred decisions
7/3/26
This week, after a little under two years of having adopted the practice, Buttondown has minted its 200th decision log. This is a practice very similar to RF...
June, 2026
7/1/26
June, like any month in which I neither write very much nor read very much, feels already cryptographic in retrospect. Part of this was due to significantly...
Denormalization 101
6/23/26
I have had exactly two conversations this week about denormalization, which is a sign that it is time to write a blog post. If you already know what denormal...
Indeterminate / Squash
6/15/26
The hardest part of gardening is not correctly timing the seedling transfer, or deciding when a plant is a goner versus when it just needs one more week. The...
Victory is a lossy compressor
6/9/26
Update, July 2026: Bill Mill kindly pointed out that the Cavs' head coach is Kenny Atkinson, not JB Bickerstaff — who coached Cleveland until 2024 but as of...
Back to Overcast
6/4/26
In what is certainly the least consequential update in this blog's history: I have boomeranged back from Apple Podcasts to Overcast. None of my gripes with O...
May, 2026
6/1/26
There are two mental models about work and fatigue which, like my brief dalliance with Roshe Runs, I have loved and outgrown: 1. The first is the fungibility...
Self-hosting our CI, three months later
6/1/26
A couple of folks have written in over the past month asking how my experiments in self-hosting GitHub Actions runners have held up. And three months seems l...
ccusage
5/27/26
Inspired by a recent Simon Willison post, I just ran ccusage on my laptop and learned that over the past thirty days, on my sole subscription of $200 a month...
What matters
5/20/26
<div class="teleplay"> <p class="character">Toby</p> <p class="dialogue">I turned it on just as they got to the scene when Richard, Geoffrey and John were lo...
Be careful what you make easier
5/19/26
I have found much peace this year going offline to shelter myself from the whiplash of LLM companies jockeying for mindshare by cosplaying as DevRel. Every n...
Screen record more
5/17/26
One of the things I miss most about working in an office is osmosis: the ability to absorb information from coworkers purely by peering over their shoulder f...
Buttondown no longer runs Redis
5/15/26
Buttondown no longer runs Redis! I added it years ago for the same reason almost every Django app has Redis: that's just what you do. Workers wanted a queue,...
Just aim the cannon correctly
5/14/26
James Shore has a post I found myself nodding along to until the very last step, where he loses me. The thesis is clean: > Your AI coding agent, the one you...
LLMs and Buttondown
5/12/26
Buttondown has grown a lot in 2026; some of that growth is uncomfortable. I've talked to enough people about this in real life that it felt worth writing som...
On self-updating screenshots
5/8/26
Nick sent me a great post from one of the engineers at Goodenough, the fine folks behind Jelly, on the topic of self-updating screenshots. It is near and dea...
April, 2026
5/1/26
I had hoped and expected that the chaos which had marked the start of the year — floors, termites, sickness, fires, ACL surgery — was largely behind us, and...
Four years in the maelstrom
4/19/26
> A baby holds your hands, and then suddenly, there's this huge man lifting you off the ground, and then he's gone. Where's that son? > And at one point, I n...
Write as you want to be heard
4/10/26
If you have ever chatted with me in real life, you know that my writing style here closely reflects my speaking manner. My writing, just like my speaking, is...
Software never had a soul
4/2/26
Ryo Lu recently wrote: > The web was the same. Personal sites were genuinely personal. Blogs felt like letters. Forums had regulars. You knew who made what....
March, 2026
4/1/26
The chaos is finally — but not totally — starting to fade. In early March we moved back into our house, replete with new floors and a sense of something once...
A month of OpEx quick wins
3/29/26
I spent the past few weeks chasing quick OpEx wins for sport, having felt a nagging sensation that the orchards of our org were a little too-laden with low-h...
Why I'm a film blogger now
3/27/26
I have written more words about film in 2026 than I have about technology and business. This has not escaped your attention — so much so that real-life and i...
What I would be doing
3/16/26
Tanvir asked me a few days ago what I would build today if Buttondown didn't exist and I was still keen, fully employed elsewhere. This is a fertile question...
Archiving the roadmap
3/13/26
Pour one out for Buttondown's transparent roadmap, which I formally archived yesterday evening after a year or so of informal archival. This felt like the jo...
Self-hosting our GitHub Action runners
3/7/26
The impetus Buttondown's CI runs on Blacksmith, which is a great service that I am still happy to pay for (see also this note). But our January bill was $300...
The road to Pydantic V2
3/4/26
Around 18 months ago, I wrote: > Cursor did both! ...and then it choked on some more complicated feature work that spanned multiple files. Which is fine: a t...
Ascensions
3/2/26
Most procedurally generated roguelikes have a concept of ascending difficulty levels designed to test the mettle of players who have wasted the most time mas...
February, 2026
3/1/26
Last month's Wednesday update, I recorded from a train headed to Middelburg. This month I write closer to home temporally and otherwise. I am en route to the...
Unshipping Keystatic
2/28/26
Two years after initially adopting it, we've formally unshipped Keystatic. Our CMS, such as it is, is now a bunch of Markdoc files and a TypeScript schema or...
Scattered thoughts on LLM tools
2/24/26
1. Claude Desktop is a poor app in bizarre and inexplicable ways — stale table view cells, constant reauthentication requests, a markedly worse harness and r...
Golinks
2/23/26
If you've never encountered golinks before: they're short, memorable URLs that redirect to longer ones. Instead of telling a coworker "the dashboard is at ht...
Improper nouns
2/22/26
Myles wrote a great post about standing up and scaling our nascent recommendation engine. Buried in the middle is an aside which, as you might suspect, is ne...
Changelog mornings
2/21/26
A new addition to my routine has been to start every morning writing out our changelog from the day before. This is mildly surprising to people who assume th...
More weird tests
2/21/26
It has been a while since I wrote about weird tests. This is not due to lack of enthusiasm — if anything, I think my passion for them has redoubled over the...
Maybe use Plain
2/20/26
When I wrote about Help Scout, much of my praise was appositional. They were the one tool I saw that did not aggressively shoehorn you into using them as a C...
Subpaths vs. subdomains
2/18/26
If you want to have user-level namespaces on a single domain — such as company.com/justin — you have two options: namespacing via subpath (company.com/justin...
Outgrowing Django admin
2/17/26
For a bit of dessert work this week, I'm working on a full-fledged attempt at replacing the majority of our stock Django admin usage with something purposefu...
Notes on "Harness Engineering"
2/16/26
I find it useful and revealing to perform very close readings of engineering blog posts from frontier labs. They seem like meaningful artifacts that, despite...
The death of software, the A24 of software
2/14/26
Steven Sinofsky recently published Death of Software. Nah., arguing via historical case studies that AI will not kill software any more than previous technol...
Better tests
2/14/26
What makes for a good test? I feel like there is a dearth of useful literature on this subject, perhaps because a lot of the content which ostensibly aims to...
Notes on "How I'd Grow Buttondown"
2/13/26
A friend sent me Andrea Bosoni's How I'd grow Buttondown, a great and thoughtful piece. It's fun to read someone else do the exact intellectual exercise you'...
One status field per model
2/12/26
Any sufficiently old application starts to succumb to a pernicious form of technical debt known in street parlance as shitty data modeling. Sometimes this ma...
RIP XSLT
2/11/26
If you visit feed.xml in your browser, you will see that I have done the Cool Kid thing and added styling to it via XSLT. This was originally something I've...
Building a data greenhouse
2/7/26
A conviction I've held for a while now — one that has upgraded from idiosyncratic to prescient — is that you should insource your data warehouse. Pull all ex...
In praise of actions
2/5/26
When I first encountered all of the concepts that I'll describe as controllers or actions or services, I would try to adhere to them with the logic of consis...
January, 2026
2/3/26
This is not, if I'm being honest, the simple, structured start to 2026 that I had in mind. Rigor and early workouts have been replaced by pulled floors and s...
Maturing your support function past a single engineer
2/3/26
It feels a little odd to be writing about scaling support as if from a position of authority. But I had two recent conversations around the same topic—going...
LLM as advance team
2/2/26
My first foray into using git worktree-style development — spinning up multiple workspaces and having LLM agents attack different problems in parallel — was...
Brief notes on migrating to Postgres-backed jobs
2/2/26
It seems premature to talk about a migration that is only halfway done, even if it's the hard half that's done — but I think there's something useful in docu...
Recent forays into developer productivity
2/1/26
I've written before about my posture around LLMs being mostly summarizable as design your systems and abstractions to accommodate an infinite number of junio...
Every model should have a notes field
1/20/26
Production data, like real life, is messy. Your database — or at least the projection of the world as expressed by your database — will become riddled with e...
Pure strategy
1/20/26
The goal of a build tool is to take a bunch of disparate inputs and compile them into an output: zsh $ rustc main.rs <pre class="mermaid"> flowchart LR subgr...
Refactoring a product is tricky
1/17/26
It's easy to talk about refactoring at the codebase level because there's a reflexive definition: a refactor is a change to the codebase that preserves all e...
Migrating to PlanetScale
1/16/26
First off, huge amount of credit to Mati for migrating our database to PlanetScale. I highly recommend reading the blog post. He does a good job talking abou...
Uses (January 2026)
1/16/26
A few updates to my Uses page: Software: I switched from Cursor to Zed. Zed is fast, native, and the editing experience is snappier. I've also been using Con...
Obsidian for internal docs
1/12/26
I've grown cautious of my proclivity to prematurely review a tool. The most important quality of any tool meant to be used regularly is the ease with which y...
Terragon, Conductor, PyCharm
1/11/26
I was sad and unsurprised to get an email from Terragon announcing that they were sunsetting the product. I was a happy user for the two or so weeks in which...
10 questions
12/30/25
Inspired (as so many things are) by Behzod: 1. How do I carve out time and energy to be a better friend? 2. What is Buttondown's strongest medium-term source...
Big Brother
12/29/25
 Telemachus has been with my parents (a fifteen minute drive away) for the past week, a fact I was reminded of three minutes ago as...
Bauhaus, by science or magic
12/28/25
!Patrick Collison and Tyler Cowen are funding a new aesthetic --- Patrick Collison and Tyler Cowen are funding a new aesthetic: > We're more than a quarter w...
sitemaptorss
12/28/25
In the waning hours of my Christmas break, I've launched a new project: sitemaptorss. It, like caltorss before it, is hopefully well-described by its name: i...
mise hooks
12/27/25
I've written before about having a standardized set of commands across all my projects. One of the things that helps with that is mise hooks. I've actually b...
Avoid single-use variables
12/27/25
After all these years programming, it's fun to catch myself changing my style preferences in real-time. Here's a change I find myself getting very aggressive...
Dotfiles
12/24/25
Fernando convinced me to publish (and, therefore, clean up) my dotfiles: > I’m interested in people who customize their experience of computing. This is ofte...
How LLMs change my codebase
12/23/25
Fewer dependencies. I've always been suspicious of pulling in a library to accomplish what a few hundred lines of code could also accomplish. Now, that senti...
2025
12/21/25
(You may be interested in 2024 as well, which was last year's annual review.) Family Lucy is now fifteen months old; I think my previous writing (two-weeks-o...
Uses
12/20/25
A living document of the tools and gear I use. See also: Buttondown's stack and my Uses This interview. Hardware | Item | Notes | | -------------------------...
GitHub Actions' pricing changes
12/17/25
GitHub announced pricing changes for Actions: > TLDR - On January 1, 2026, we are lowering the price of hosted runners, and beginning March 1, 2026, we are c...
Site 2026
12/16/25
Welcome to the latest version of my website. Continuing my annual tradition, I've rebuilt the site with a new platform and design—this time by developing my...
October, 2025
11/9/25
How are you doing? Are you doing well? October's been very fun, as evinced by the length of things I am remiss in writing about: EntryThingy 2.0, Long Live T...
Eucharist
11/2/25
Lucy, watching with a curiosity bordering on frenzy as I slowly fry her a single egg in the French style (which is to say drowning in butter); her wary gaze...
Picnic
10/30/25
Picnic is an app that can be described in one sentence: > Every day, you see all of the photos you took on that day in previous years, and you decide which o...
Cheetah II
10/29/25
I wrote about cheetah two weeks ago and appreciated the multiple people who quietly whispered in my ear after publication that it was, in fact, a Cursor mode...
Vercel's abstractions
10/25/25
use workflow is cool. I admire Vercel for many things, but in particular for what I will phrase charitably as a steadfast refusal to shackle themselves to th...
Business as authorship
10/23/25
When Buttondown was a smaller company, the goal was to, quote unquote, stick around. That mostly meant making: 1. enough money; 2. providing enough value; 3....
Someone built it; someone has to build it
10/16/25
This afternoon I stumbled upon this ticket from Tom Forbes about a faster bulk update mechanism in Django. Django's ORM workings can be complex, but the conc...
Cheetah
10/13/25
My usage of LLM tooling has plateaued — a word I use deliberately. I feel like I've developed a pretty solid sense over the past three months of what these m...
Adding imports to the Django shell
10/10/25
I was excited to finally remove django-extensions from my pyproject.toml file when 5.2 dropped because they added support for automatic model import. However...
Fixing CSS variables in Superhuman
10/9/25
Part of running a business like Buttondown is spending more time than you'd like installing esoteric email clients and trying to debug odd rendering behavior...
Hidden coupons
9/29/25
Much of our work at Buttondown revolves around resolving amorphous bits of state and cleaning it up to our ends, particularly state from exogenous sources. T...
September, 2025
9/28/25
The last of summer's grip finally loosened its hold this September, and Richmond began its annual transformation into something gentler and more contemplativ...
Weeknotes 2.0
9/17/25
Once upon a time, I wrote weeknotes for Buttondown. I’ve started them up again—the first edition is linked below. I’ll spare you the navel-gazing about wheth...
Pulumi
9/13/25
I'm spending a lot more time lately using Pulumi. This is for a handful of reasons. The two biggest ones are as follows. 1. First, we're ramping up our inves...
Another reason our pytest suite is slow
9/12/25
I wrote two days ago about how our pytest suite was slow, and how we could speed it up by blessing a suite-wide fixture that was scoped to session. This was...
Why our pytest suite is slow
9/10/25
The speed of Buttondown's pytest suite (which I've written about here, here, and here) is a bit of a scissor for my friends and colleagues: depending on who...
63 postcards
9/7/25
We have wrapped up the formal portion of DjangoCon. DjangoCon is not Buttondown's first conference that we've sponsored, but it is the first one that we've a...
Django forever
9/3/25
Tomorrow, I am taking a very early morning flight to Chicago to attend DjangoCon US. Buttondown is sponsoring, less as an exercise in lead generation and mor...
Onboarding survey, one week in
9/2/25
One extremely compelling form of blogging, both for the reader and the writer, is the admission of defeat. Seriously: whenever you find yourself faced with a...
Goodwill
9/1/25
!Morrowind is made much easier when everyone you talk to has an 80+ Disposition! One of the amazing things about Morrowind is that it's a combat-rich game in...
August, 2025
8/31/25
The summer heat in Richmond clung to everything this August like a second skin, broken only by afternoon thunderstorms that sent Telemachus scurrying to his...
What follows GitHub?
8/29/25
It seems fairly clear that, as far as product lifecycle goes, GitHub is in its “Azure metered billing” stage. I don’t mean this as a negative value judgment...
Ashland, 2025
8/20/25
Trundle is not quite the right word. When I hear trundle, I think of layers, of wool and dampness, of hitting the road before the sun does, wrapped in a blan...
Three apps that will not change your life
8/15/25
After what has felt like a long winter of habitual reliance on my existing tools, I’m finally playing around with some new ones. This is a healthy habit—so l...
July, 2025
7/30/25
Telemachus turned five, two weeks ago. He did not have a great July; Richmond's been roiled by storms (ten nights in the past two weeks have ended with him h...
Have you at least tried asking?
7/17/25
My wife got sick this past weekend, and as a result we had to cancel or at least postpone a trip to Seattle that we had been looking forward to. She's feelin...
Are calendars underrated?
7/15/25
When talking about the power of open formats, discussion generally gravitates to one of two ends of the same spectrum: 1. SMTP, which by all accounts has bee...
Post-Watch
7/6/25
There was a point in my life where I was excited about the Apple Watch. I think in no small part because it represented a new frontier in consumer technology...
The year of mint chimichurri
7/2/25
This is the fifth summer that we've stayed in Richmond since moving back east, and therefore also the fifth soilday of our backyard garden. Our garden is not...
VC-subsidized tokens
7/1/25
Simon Willison writes about the recent Cursor changes: > Firstly, the era of VC-subsidized tokens may be coming to an end, especially for products like Curso...
June, 2025
6/29/25
We are officially in H2, gang. I published fewer posts than I had hoped: | Post | Date | Genre | |------|------|-------| | Black Bag | June 18 | Thriller |Fi...
Nine months in
6/28/25
- Many people have asked me what the biggest surprise has been, now that the dust has settled: I politely inform them that the dust has never been more unset...
Justfiles are great
6/27/25
One of the first things I did when setting up whisperglass was to create a justfile. I have grown older. I've either gotten worse at context switching or bet...
Whisperglass
6/26/25
 I spent a couple hours this weekend resuming work on Whisperglass, born from some of t...
Colocating your pytest fixtures
6/22/25
pytest is, in many ways, the Age of Adz of the broader Python ecosystem: a rewarding idiosyncratic departure from convention whose quirks and foibles are qui...
Replacing screenshots and videos with iframes
6/18/25
Scattered throughout the Buttondown docs site, you'll see the fruits of the latest experiment I'm running: getting rid of outdated screenshots and videos by...
Spring, 2025
6/1/25
Hello! I have so much to catch up with you about. The time has flown. Reading (and watching) As you might have surmised from the radio silence, less to share...
Aqua Voice, text-to-speech, non-determinism
5/15/25
 While I've been impressed with the advancements in software engineering LLMs over the past six months, it's hard for me to say that anythi...
Fatherhood
5/10/25
 I'm emerging from what already feels like, in retrospect, the hardest two months of my career and the hardest I've worked since I wa...
Performance improvements can be obvious and silly in retrospect
3/23/25
One of the most useful and janky internal tools we have in Buttondown’s codebase is a codegen pipeline called “autogen”. There is nothing “auto” about autoge...
Smoke test your Django admin site
3/8/25
<div class="addendum">3/14/2025: Updated the snippet to include imports and remove some unused stuff. Thanks, Andy!</div> Here is a confession: I am a very s...
Recursive filter schema
3/2/25
When we added support for complex filtering in Buttondown, I spent a long time trying to come up with a schema for filters that felt sufficiently ergonomic a...
Does that dependency spark joy?
2/25/25
If there's been one through line in changes to Buttondown's architecture over the past six months or so, it's been the removal and consolidation of dependenc...
HQ1
2/23/25
!A picture of HQ1 during what we will look back fondly as 'the early days.' After many wonderful years of working out of my home office (see workspaces), I'v...
Naughty vs. nice
2/19/25
I love this bit from Paul Graham on pattern-matching founders: > Though the most successful founders are usually good people, they tend to have a piratical g...
YOLO-squashing our Django repository
2/15/25
Buttondown's core application is a Django app, and a fairly long-lived one at that — it was, until recently, sporting around seven hundred migration files (f...
Humane Inc.
2/14/25
Humane Inc. started in 2018; it raised around $250M over five years before coming out of stealth mode with an AI pin that people did not like very much, and...
What Gives
2/10/25
Matthieu asks: > Since you do a lot of things (investor, dad, owner of a "small" business, blog writer) I was wondering what you don't do to keep up with thi...
February, 2025
2/5/25
What a start to the year! January was a bit more flat-packed than I think Haley and I would have otherwise liked, but all with great things. (Highlights incl...
What's in a name
1/27/25
Guillermo posted this recently: > What you name your product matters more than people give it credit. It's your first and most universal UI to the world. Des...
Three Problems
1/25/25
When Lucy was two weeks old, we had our greatest test as new parents. She woke up at 3:30 in the morning—not a time we considered particularly unusual—and we...
Vibe coding your way out of a SaaS contract
1/22/25
There is, I would argue, too much discussion online about the demise of smaller SaaS vendors at the hands of LLMs. A lot of these conversations go roughly al...
Truncating timedeltas in Django
1/9/25
Consider a fan-out-ish model that you want to aggregate a bunch of: likes on a post, for instance. python class Post(models.Model): createdat = models.DateTi...
January, 2025
1/5/25
Hello, 2025! (As always, Death Cab remains the soundtrack by which you should read this.) Headlining this month was my annual review; everything else is flot...
2024
12/17/24
(You may be interested in 2023 as well, which was last year's annual review.) Family Haley and I welcomed our first child, a daughter named lucy, on Septembe...
Order, Tailwind, DRY
12/14/24
(Order in the CSS rule sense, not the metaphysical sense.) The time has come to begin exfiltrating some higher-traffic, higher-leverage parts of Buttondown's...
Linear
12/13/24
I invited nickd to join our Linear instance yesterday, which reminded me that I had a slew of notes I wanted to publish on our own experience of migrating fr...
buttondown.com/alternatives
12/11/24
Some kind words from Chris Krycho on Buttondown's Alternatives page: > This is how I want all my tools to be. There is a ton of room in these markets for hea...
Hypermodern Django
12/10/24
I've been on the hunt for a new way to dogfood Buttondown for the past month or so, and I've finally found it: Hypermodern Django. At this point, all of my/o...
Bluesky is good
12/5/24
Three months ago, I wrote Bluesky et al, in which I walked through the various platforms vying for the dubious title of "Twitter's successor" and landed on B...
November, 2024
12/4/24
Not a lot to share this month; it was a particularly busy time, between a mystery (and now solved, without fanfare or closure) cough and a dearth of time to...
Letters to a Young Bartender
12/3/24
Every straight white male is forced, character-creation-screen-style, to choose one overtly consumptive hobby that in some small part defines their twenties...
Hidden settings are for cowards
12/2/24
At Stripe, we had two abstractions for branching logic in production: flags, which were meant to be explicitly temporal (temporarily split-testing traffic; r...
Fathom
12/1/24
I'd been meaning to jot down some thoughts on Fathom for a while, and did not have a particularly good reason to do so until the news broke that Paul Jarvis...
Klarna: nineteen years, twenty billion kroner
11/23/24
I tend to ignore the entire genre of what we now refer to as BNPL businesses — Affirm, Afterpay (RIP), Klarna, et al — not for any particular sin I feel that...
A good H1
11/22/24
Buttondown was kindly featured in H1 Gallery last week, and Ryan asked me to opine a bit on how we arrived at our current iteration, which is the anodyne yet...
Shipping is capturing value
11/20/24
This great essay from Sean Goedecke went viral two weeks ago, drawing fury and fervor alike for a Moral Mazes-esque analysis of how engineers at large compan...
VC does not guarantee PMF
10/30/24
Two companies that I started following (with no small amount of envy) back in 2021: - Hype (fka Pico) sold to an MMA-themed holdco earlier this year. Raised...
October, 2024
10/29/24
Hello! Lots of writing in October (what early parenthood takes away in terms of deep flow, it gives back in terms of twenty-minute pockets of time and though...
Bozos
10/28/24
Kevin Twohy has a list of heuristics for new projects/clients, and my favorite is simple: > No Bozos. Simple policy. No exceptions. You know it when you see...
Meta's two assets
10/26/24
(Epistemic disclaimer: there are few Extremely Big Tech Companies to whom I feel apathy more vividly than Meta. I had a Facebook account in high school and c...
Projects are things with steps
10/24/24
Lots of kind words poured in as a response to My approach to GTD and PKM, and one question was asked so frequently that I decided to write about it. > Why is...
Notebook as marketing primitive
10/19/24
Earlier this week, I stumbled upon this brilliant marketing-slash-documentation idea from SingleStore — notebooks as a first-party page! There are a handful...
My approach to GTD and PKM
10/18/24
One pernicious thing with writing about productivity and knowledge systems: you only change systems that aren’t working, and you tend to write about things d...
Consider the data product
10/17/24
The advice might seem dated these days, but I think the stair step approach to bootstrapping is evergreen: > It’s much easier to sell an add-on to an existin...
You should build this:
10/15/24
A prior iteration of this site had a page called "Project ideas" that listed a bunch of things that I'd like to build. This was a good idea and useful in its...
Migrating to Django 5
10/13/24
The total LOC delta to migrate Buttondown from Django 4 to Django 5 was +143, -150. (I was incentivized to do so because our search right now is quite slow,...
Talking to customers
10/9/24
> You say that these numbers mean dial it down. I say they mean dial it up. You haven't gotten through. There are people you haven't persuaded yet. These num...
Notes on Zed, revisited
10/7/24
A little over six months ago, I wrote Notes on Zed. My conclusion at that time was that Zed made a lot of great choices and felt really good to use, but lack...
Two weeks of parenthood
10/6/24
We've had lucy for two weeks, which qualifies us as experts, which means it is time to write about parenthood. (In all seriousness, consider the below descri...
September, 2024
9/29/24
In descending order of importance: - I had a daughter, Lucy, the light of my life. - I launched a tiny side project, handbook.directory. - I cautioned agains...
Vendor outages
9/12/24
Postmark had an eight-hour outage due to an SSL certificate expiry. Buttondown was not affected; we send a lot of our custom domain traffic through Postmark,...
Bluesky et al
9/11/24
The state of play Much of the discussion about Twitter’s slow death — or, if not death, metamorphosis into a place where I prefer not to spend my time and en...
Always use an enum for your status field
9/10/24
When I was first starting my career at Amazon — even more bright-eyed and rosy-cheeked than I am now — I was thrilled by the concept of an "architecture revi...
Why your marketing site should be separate
9/8/24
In Notes on buttondown.com and How Buttondown uses HAProxy, I outlined the slightly kludgy way we serve buttondown.com both as a marketing site (public-facin...
MD5-based uniqueness constraints in Django
9/1/24
Yesterday, I was trying to set a unique constraint for comments in Buttondown to prevent accidental double-commenting, and I ran into a problem that I hadn't...
RSS in Next 14
9/1/24
We finished Buttondown’s migration from MDX to Markdoc last week. It went swimmingly, except for one little hitch: our RSS feeds, which sat on top of getServ...
Notes on 'Founder Mode' / Lieutenancy
8/28/24
In Paul Graham’s latest essay, he writes: > The theme of Brian's talk was that the conventional wisdom about how to run larger companies is mistaken. As Airb...
Keeping a technical edge
8/25/24
Someone emailed me in response to two-years, in which I wrote: > I miss of being at a large company, which is dealing with deeply cutting-edge technical prob...
How Buttondown uses HAProxy
8/23/24
There are few technical decisions I regret more with Buttondown than the decision to combine the author-facing app, the subscriber-facing app, and the market...
Notes on buttondown.com
8/22/24
We spent $85,000 for buttondown.com in April; this was the biggest capital expenditure I've ever made, and though it was coming from cash flow generated by B...
Using Cursor to port Django tests to pytest
8/21/24
When it comes to AI tooling, I am equal parts optimist and cynic. I have no moral qualm with using these tools (Supermaven is a pretty heavy part of my day-t...
Improving Django's default pagination performance
8/6/24
Buttondown's API calls are very fast, and one of the reasons why is that we've removed every single possible database query that we can. The most recent was...
Peak Newsletter
7/11/24
A handful of folks sent me this quip from Nate Silver a few days ago: > Slightly against interest to admit this (I don't want more competition lol) but I thi...
Incumbency
7/6/24
Andrew Rea with an interesting and increasingly familiar take about how AI will disrupt software-focused private equity: > Distribution and brand moats can p...
Content debt
7/4/24
There’s a nascent trend of releasing ostensibly-private material (changelogs, public wikis, handbooks, etc.) to the public as a bit of a marketing push. This...
Against Against Innovation Tokens
6/30/24
Glyph (whose writing and contributions to the Python ecosystem I am deeply grateful for) wrote Against Innovation Tokens yesterday: > In 2015, Dan McKinley l...
Pytest: test for print statements
6/23/24
Inspired by Adam Johnson's test for pending migrations, and of course in conversation with my own love of weird tests, I offer a similar concept: a test for...
Typesafe routes in Vue
6/15/24
I watched Gary Bernhardt's talk on static routing back a few years ago and — I'm not sure if I would call it formative, but it stuck in my craw as a platonic...
Notes from May
5/29/24
Lots of writing this month: - Why you should use Rails - A reminder that things take time - How shadcn/ui's previews work - Why I hate that 1.01% meme - A lo...
The taste of beer
5/27/24
> Unlike stories, real life, when it has passed, inclines toward obscurity, not clarity. --- There’s a relatively famous line from Bezos, circulated first at...
Git one-liner: get the earliest commit from X hours ago
5/19/24
I wanted to get a commit that was temporally some distance back as part of my experimentation with git cliff. This took some time to do, but here's what I en...
Why can't you just...?
5/19/24
Buried in a snarky thread about why Google Calendar doesn’t support calendar syncing is a long, detailed explanation of why shipping this sort of thing is ha...
Notes on ActivityPub
5/18/24
- By far the single most-fruitful tactic has been "just look at raw GET responses from Mastodon and see what things are shaped like." I know that "ActivityPu...
Auth.js + Square
5/16/24
Internal tools and small, well-scoped projects are a great avenue to tinker with technologies on the periphery of your understanding, and a Third South proje...
Au revoir, Invoke
5/14/24
It's not quite interesting or noteworthy enough to warrant a full-on essay, but yesterday we unshipped the last remaining Invoke commands and ported them ove...
Grace notes
5/10/24
I'm not loving Unreasonable Hospitality, but it did supply me with a phrase that I've been looking for: > Eventually, that gesture became one of our steps of...
How shadcn/ui examples work
5/7/24
I’m increasingly convinced that for developer-first tools, a really good docs experience is a durable, non-trivial advantage. Part of this thesis is that Rea...
Things take time
5/4/24
Things take time. - Nintendo fairly famously was born in 1889, and the modern incarnation — Yamamuchi Nintendo & Co., LTD — was established nearly fifty year...
Use Rails
5/2/24
I have a good number of people ask me what software stack they should use. I always have a two-part answer: 1. Use what you're familiar with. If there's some...
Notes from April
5/1/24
Welcome to spring, bona fide and humid. Lots of writing this month: - I wrote about spending the past two years as an independent technologist. - On the medi...
Finding null JSON values in Postgres
4/26/24
Postgres' JSONB functionality is fast and useful but when I find myself dropping down from the Django ORM into SQL to do weird things, the syntax strikes me...
You need to be frictionlog-maxxing
4/25/24
Lots of people have spent the past few days discussing the perceived increase in difficulty in getting an entry-level programming job relative to the halcyon...
You gotta be able to taste the kool-aid
4/21/24
Cognition, a six-month-old startup in the AI coding space just raised $175m at a $2b valuation: > Despite the skepticism surrounding Devin’s launch, the AI c...
Stripe Sessions 2024
4/20/24
Stripe held the keynote for Sessions, their annual WWDC/re:invent-esque conference, this morning. I wanted to jot down some thoughts while they’re still fres...
Two years as an independent technologist
4/16/24
This week marks two full years since I left Stripe and started what in retrospect is a new (and likely) final phase of my career as an independent technologi...
Weird test: internal link checking
4/16/24
I wrote last month about using weird tests. Here's another example: checking for broken internal links in our upcoming docsite redesign! js const extractInte...
New words
4/14/24
When I was in high school and even more insufferable than I am now, a friend and I started a tumblr called "sun words". The concept of this was to collect wo...
Why Buttondown isn't OSS
4/11/24
A number of people have asked me in the past week why Buttondown isn't open-source, given: 1. the love and overt financial commitment we have to open source...
defineModel is dope
4/7/24
I find myself spending very little time enjoying Vue. Which is not to say I hate it, but that I don't have a lot of fun with it — I've reached a sort of inte...
Tailwind black magic: swallowing all pointer events
3/27/24
I wrote two days ago about a real and useful application of Tailwind black magic; here's another. Buttondown has a dropzone component lets folks drag-and-dro...
Tailwind black magic: styling paragraphs within tables
3/25/24
The new version of the Buttondown docs site is all in on Keystatic, Markdoc, and Tailwind's typography plugin — which makes it really easy to author beautifu...
Why should a company?
3/23/24
For a long time, my goal with Buttondown was largely around failure avoidance: "I want to get my first paying customer so I know it's not a fake product"; "I...
Are monopolies bad, actually?
3/22/24
One of the more interesting theses advanced by Zero to One is that monopolies are good to the extent that they afford companies the agency and comfort to eng...
Is cool enough?
3/17/24
Via HN I ran into not one but two extremely neat and pleasant-looking libraries for URL manipulation. They look like great libraries, and a prior version of...
PSA: mess around with Keystatic
3/16/24
We've been using Keystatic in Buttondown for around six months now: we migrated most of the content on the marketing site (which is backed by Next) from MDX...
On techno-optimism
3/15/24
I consider myself, in a literal sense: a techno-optimist; while technology in of itself is an amoral force, I think it’s pretty hard to disagree with the not...
Globals in Histoire
3/13/24
Histoire, like so many other tools in the Vue ecosystem, is a bit of a neglected younger sibling to Storybook — a little bit uglier, with worse documentation...
Notes on Zed
3/6/24
I was late to the VS Code zeitgeist, and as penitence I try to go out of my way to try new editors whenever I see them — which is why this morning I installe...
Use weird tests to capture tacit knowledge
2/29/24
Working on Buttondown — or any mature, complex codebase — effectively and quickly requires a lot of tacit knowledge that I've done a hitherto-poor job of doc...
PSA: mess around with Kolo
2/28/24
I had bookmarked Kolo many months ago to try out and finally got a chance to integrate it with Buttondown — a process that I expected to take a couple hours...
Years are magic wands
2/23/24
A couple folks wrote in responding to Vibes and Years asking how I did annual planning. I start with a question: "if I had a magic wand, what things would I...
Vibes and years
2/20/24
XH asks: > How do indie developers/small teams keep track of and prioritize long-term roadmaps? > > I've been basically work off my gut + Feeling of the Day...
11ty
2/14/24
- .njk as the default templating language is an odd choice, and I find myself stubbing my toe on it a good amount. Maybe that's a me thing! - It is extremely...
You should use Helpscout
2/14/24
Was digging through old issues of the personal site and found this draft snippet: > I was evaluating HelpScout as a potential first step in a series of many,...
Great essays
2/10/24
Programming - Parse, don't validate (2017) - Pipeline-oriented programming (2019) - APIs as ladders (2022) - Scaling Sidekiq at Gusto (2022) - Heroku HTTP AP...
Buttondown Analytics 3.0
2/7/24
Working on a new analytics engine — a scant eleven months after the previous 'new analytics engine'. Calling this 3.0 is a bit of a misnomer: most of the cod...
Gosling’s Old Rum
2/3/24
Virginia has draconian liquor laws, which means I have to get interesting bottles shipped from [REDACTED], a site on which I am very prone to judging a book...
Migrating someone who's on Stripe Connect Express
1/9/24
Most Stripe accounts on Substack are “Standard Connect”, which essentially means that: 1. the author has full agency over their account and is the merchant o...
Mass renaming files in fish on macOS
12/13/23
One of many two-liners to come as I migrate things from the old site onto Obsidian: brew install rename rename "s/.mdx/.md/" .md
Postgres batch enqueuing in ten lines of Django
12/11/23
It hasn't failed me yet: python BATCHSIZE = 100 def batchproess(queryset) -> None: count = queryset.count() if count == 0: time.sleep(10) return with transac...
Befriending the Goon Squad
7/8/23
TL;DR 1. The single biggest asset that side projects and "nights and weekends" businesses have on their side is near-infinite runway. 2. If you have near-inf...
Spoonbill (2016—2023)
6/7/23
The start I would be lying to you if I told you I remember exactly what was going on when I came up with the idea for Spoonbill. I know I was still in what I...
Bottles of Veuve
1/19/23
I struggle with commemorating accomplishments. The hedonic treadmill of modernity makes it difficult for me to sit back, look at my current state of affairs,...
2022
12/25/22
2022 in review Hello! My name's Justin. This is my annual review for 2022. You may also be interested in last year's. Health I am, as I write this, in the be...
2021
12/25/21
Personal <div class="my-4 lg:my-8"><div class="border-subtler rounded-t-lg bg-subtler border-solid border border-b-0 uppercase font-bold text-sm py-2 px-4">C...
2019
12/25/19
2019 was pretty great. here are the highlights: 1. found someone i loved 2. we moved in together 3. into a house that i bought 4. got promoted 5. at a job th...
Customer Support for Side Projects
4/13/18
I have been running a bunch of reasonably successful 1 side projects for a couple years now. Here is a (unfortunately, very much truncated) list of support e...
Generators are dope
3/7/18
(This is also readable as a gist, if you prefer.) I love generators. They’re one of my favorite features in Python, and criminally underrated. (Or underused?...
Enthusiasm
3/3/18
Here’s a sentiment with which I strongly agree: > I say this occasionally to normalize it: > > I’ve never put code on GitHub > I’ve never done coding in my s...
A month with the AirPods
9/30/17
Tags: technology I bought them, you see, despite my better instincts. I already had BlueTooth earphones that worked (albeit not well). I already had a pair o...
How I cut my Webpack bundle size in half
9/16/17
> In the fall, a young man’s fancy lightly turns to thoughts of front-end performance. When I initially built out Buttondown, I was focused on two aspects ab...
Not The Keynote You're Looking For
9/11/17
I hate to be in the position of defending Apple evangelists, but there have been a lot of weird takes about the Apple leaks the past few days. Here’s one: >...
Turning 25
9/3/17
This week, I turned 25. I spent my birthday doing the thing I want to spend every birthday doing: I reverse seared a filet, bought a nice scotch, and watched...
Creating a password validator component in Vue
8/13/17
Sometimes you procrastinate one feature by writing another. Even if that other feature is pretty small and inconsequential. 1 For me, that other feature — if...
Side Projects: July 2017
8/8/17
Revenues Source USD Advertising $70 App Revenue $680 Consulting $4,000 Total $4,750 Expenses Source USD Advertising $0 AWS $0 App Store $200 Apple Developer’...
There are still dragons everywhere
8/2/17
I’ve been programming for the better part of a decade, and I’ve been programming in Python for the better part of that better part. As loathe as I am to assu...
App sizes are under control, they just aren't under scrutiny
8/1/17
I wrote at the first of last month about bloat in apps, in response to a thoughtful piece by Ben Sandofsky about how he minimized bloat in Halide. I had some...
The best podcasts
8/1/17
First, some background and context, because I’m a super persnickety podcast listener: 1. I think podcasts, like anything else, need to be interesting and tim...
A nice little list of valid and invalid email addresses
7/21/17
I’ve been spending a lot of time working on Buttondown lately and, as you might expect for a newsletter app, lots of this work revolves around dealing with e...
So good it makes you angry
7/18/17
Sometimes there are things that are so good it actively makes me angry, because it presents a version of the form that seems unimpeachable. Money Things is l...
Response Times
7/15/17
Jakob Nielsen wrote in 1993 about the three important demarcations in response time. This is a terrific article that I come back to every year or so and see...
Simply put
7/14/17
Chris Eidhof tweeted a good thing: > The word 'simply' can often create a huge distance between the author and the reader (when the reader doesn't understand...
Code Reviews
7/13/17
I’ve seen three different iterations of “code review culture”, and all of them have been positive with minor tweaks and changes. What follows is a general li...
In praise of bloat
7/1/17
Ben Sandofsky, the creator of Halide (and erstwhile lead of Twitter’s iOS/Mac apps) wrote a worthwhile piece about getting his new app’s size to a mere 11MB....
What Vue needs next
7/1/17
I’ve been using Vue a lot recently on a few test projects, and most notably on Buttondown. Buttondown’s frontend is 100% Vue: around twenty screens (which ar...
namedtuple
5/1/17
Namedtuple programming Fri, Dec 20, 2013 We’ve all been there - working on a one-off script or personal project where you deal with lots of tuples: maybe poi...
Forcing functions in everything
4/29/17
Tags: development Kelly Sutton wrote a great article about how TDD impacts software design: > Design Pressure is the little voice in the back of your head ma...
Be a better employee, not a better programmer
4/17/17
Tags: productivity career André Staltz wrote an article making the rounds, entitled The single tip that made me a better programmer: > As a programmer, you m...
Developer experience is the ball game
4/15/17
Tags: development I’ve read two bad takes recently on how “faux native” technologies are considered harmful. The first is alarmingly titled Electron is flash...
Shooting the Messenger
4/6/17
Tags: design When Facebook launched Messenger for iOS in 2011, I was a little skeptical – this was before the brief and mighty wave of unbundling – but grew...
A bigger pan
3/9/17
Here’s an old joke (or story, or fable, or whatever you want to call it) that I’ve heard some variation of a dozen times. > The new Jewish bride is making he...
Time is money, friend
2/23/17
Tags: personal Cushion, a SaaS for freelancers, has a transparent log of its running costs and expenses that recently got posted to HN and spun up a lot of p...
Waking up early
2/15/17
Tags: personal Ever since I got back to Seattle after Christmas, I’ve been waking up early. Not, like, super early, but 6-6.30 am. This is a big deal for me;...
Burnin
2/11/17
Tags: personal productivity Of all the talk of burnout in the technology industry, sometimes I feel like the opposite is a more apt descriptor: > With phosph...
Skyrim
2/1/17
Tags: personal media So I finally beat Skyrim. Well, I’m using a flimsy definition of the word beat. Skyrim, if you’re unfamiliar, is an open world RPG with...
How liberal arts matters
1/17/17
Tags: personal The idea that a liberal arts education is better for a software developer than a traditional engineering education is increasingly in vogue. T...
My favorite things of 2016
12/30/16
Tags: personal Here are the ten best things I discovered this year. It covers art and content. You should take my word for it – these are very good things an...
A month with the new MacBook
12/21/16
Tags: technology I have been using the new MacBook Pro (fifteen inches, in what I guess is space gray?) for about a month. It’s my primary laptop now. Below...
Floradora
12/19/16
Tags: personal projects development Last week I released Floradora! It’s a tiny little Mac menu bar app. This gif explains it easier than words:  from Innisha...
ambience
6/1/16
Ambience creations Mon, Mar 9, 2015 I have just launched my second app, Ambience. It’s free. You should download it. Ambience is a simple app – a very simple...
A month with the iPad Pro
5/20/16
Tags: technology I thought about writing this blog post on my iPad Pro. I’m not — I’m writing it on the same place I write everything else, my MacBook Pro. B...
Listening to Chance
5/14/16
Tags: personal The summer before I went to Seattle, I probably had my peak mix CD of all time (an artifact which, sadly, has been lost, victim to a shitty De...
Rome
5/2/16
Tags: travel There are ten things you will know about Rome: 1. You will look up the weather in Rome before you pack, you will note that it is projected to be...
Notes for a younger programmer
4/17/16
(A living document.) If you are faced with a question to which you don’t know the answer, spend fifteen minutes looking for the answer yourself. Then ask som...
Subscription pricing is for valuable products
4/13/16
Tags: marketing Jakob Egger, who created a number of great apps that I use daily (like Postgres.app and Postico wrote a post entitled Subscription Pricing is...
Voice interaction and muscle memory
4/7/16
Tags: design Little by little, I’ve been letting voice interaction (Echo and Siri) into my life. What started as a trinket and novelty (“\Hey Siri, where do...
Only compare you to you
3/8/16
Tags: personal I’ve spent a lot of time feeling like an imposter: I look at brilliant developers at work who started coding in middle school and think I’ll n...
Having written
3/2/16
Tags: personal I remember the first time I wrote for pleasure. It was the second grade – we had a bunch of vocab words and could choose between writing out a...
UX Slang
2/17/16
Tags: design > slang (n.) — a type of language that consists of words and phrases that are regarded as very informal, are more common in speech than writing,...
Books of 2015
12/28/15
Tags: data I read around thirty books this year. I was shooting for one a week, but fell a little short: still, this is the most I’ve read since I was in mid...
Packing as premature optimization
12/23/15
Tags: personal development You are getting ready for a trip to Florida. It’s your first vacation in forever, and you couldn’t be more excited; no work, no st...
Snippets from Virginia
11/30/15
Tags: personal I spent the week in Virginia with my family. I’m writing this as I fly back, which has become something of an informal tradition for my trips...
Your legacy code matters
11/23/15
Tags: development Craig Hockenberry tweeted about some stuff a couple nights ago: > That site was built with using 1997’s state-of-the-art HTML and CSS. Eigh...
Why podcasts feel good
11/15/15
Tags: technology > I think they are part of a constructive and fascinating conversation that has, by and large, a relentless positivity, a sense of wonder, t...
What I miss about video games
9/20/15
Tags: personal Like most of you, I used to be into video games as a kid. There was the requisite Warcraft and Starcraft in high school, often squirreled away...
On a plane
9/12/15
Tags: personal Planes used to seem so mystical to me. When I was a kid, I would fantasize them constantly: cross-country, international, just across state li...
22
8/31/15
I turned 23 yesterday. It was cool. I wanted to think about all the stuff I learned and did when I was 22. Looking through what I said I learned last year, I...
What lies under the bandaid
8/12/15
Tags: personal > “It’s like ripping off a band-aid.” ~ people who are bad at metaphors I’m really bad at confronting things. My second internship ever: I was...
In defense of keys
8/1/15
Tags: design I’ve been going through The Design of Everyday Things by Donald Norman over the past couple days, which has been an absolute revelation and tran...
Two weeks with the Amazon Echo
7/11/15
Tags: technology (Obvious disclaimer goes here: I work at Amazon but not on the Echo team or any team that remotely touches this product. I’m writing this as...
porting-barback-to-swift
6/1/15
Porting Barback to Swift programming Mon, Sep 22, 2014 On Saturday, I finished a project that I started this summer – as you might guess, it was porting my c...
Two weeks with the Apple Watch
5/23/15
Tags: technology > Guy walks into a doctor’s office. > > “Doc,” he says, “I’ve got an issue. I used to urinate two or three times a day and that was it. Now,...
Moving
5/17/15
Tags: personal First, the all-too-common apology: sorry for not writing more. There’s been a lot going on in 2015, and some new habits have displaced old one...
Vine Street Market
2/27/15
Tags: personal I have an awful confession: I don’t really care about buying local. Like, I think buying local is great in an abstract sense – objectively, th...
Tumblr
2/10/15
Tags: technology I’ve been using Tumblr a lot lately – or, at least, more than I have have before. 1 It’s been pleasant, and kind of weird, and as solipsist...
Coalesce
1/28/15
Tags: projects I made a theme for Tumblr! It is called Coalesce and I’m fairly proud of it. It’s running live on my own thing and open source on GitHub. I’m...
An average day
1/24/15
Tags: personal (Originally prompted by this HN thread. I didn’t get enough magical internet points to sate my positive feedback mechanisms, so I decided to e...
Dieter Rams’ 15 questions
1/11/15
Tags: design  Disciples of the Rams I am not a designer. There was a time whe...
barback-v23
1/1/15
Barback v2.3 creations Fri, Dec 5, 2014 As I write this post, Barback v2.3 has been marked as Waiting for Review in the App Store. This means that it’s gonna...
2014
12/31/14
Tags: personal The year of Murakami I read a lot of Murakami this year. I read Kafka on the Shore, then I read The Wind Up Bird Chronicle, then I read Colorl...
Crawling Tumblr with multiprocessing
12/20/14
Let’s say you want to crawl Tumblr. I’m choosing Tumblr here because it’s a relatively interesting example: unlike Twitter, which is super transparent about...
Coach marks and onboarding
11/2/14
According to my iTunes history, I’ve downloaded 312 apps. 44 of those have been purchases, with an average purchase price of just under two dollars. 27 of th...
Simple empty states for UITableViews
10/21/14
Even if you’re not familiar with the term, you’ve probably run into empty states before in apps you’ve used:  This is a quick blog post about sending emails through Python’s builtin SMTP library, using...
Analysing Pitchfork using Pandas
12/24/13
I spend a likely-unhealthy amount of time on Pitchfork, its where I get my music news and I can usually rely on their reviews to decide whether or not an alb...
How to make $800/mo with three lines of code
12/12/13
Tags: marketing Even if you’re not a frontend developer, you can probably guess what the following line of code does, right?: .feature { background-color: ff...
the-state-of-tech-recruiting-in-2013
12/1/13
The state of tech recruiting in 2013 data Fri, Nov 15, 2013 !Tech demand for riffs and ninjutsu is nearing an all-time low. But will it last? Recruiting is a...
A gentle introduction to itertools
11/29/13
itertools is pretty much the coolest thing ever. Despite a vaguely technical name and a decreased emphasis in most introductory Python materials, it’s the ki...
2003 and things
10/28/13
Tags: personal It’s hard to believe that 2003 was a decade ago, right? That the difference between 2003 and now is the same as the difference between 1985 an...
Depth and whitespace
10/20/13
Tags: development I got to write the following unit test this week at work: @Test public void testIsWhitespace() { Word weirdWhitespace = new Word(" "); asse...
A mindset of abundance
10/11/13
Tags: personal I woke up early this morning thinking about a great piece by Jack Cheng. He describes his reading of The Miracle of Mindfulness: > The letter...
The John Byrd EP
1/10/13
Tags: personal My favorite record is The John Byrd EP, by Death Cab For Cutie. It’s a live album — snippets and recordings from their tour in the spring of 2...
Bookmarks
Programming26
Parse, don't validate (2017) lexi-lambda.github.io Pipeline-oriented programming (2019) fsharpforfunandprofit.com APIs as ladders (2022) blog.sbensu.com Scaling Sidekiq at Gusto (2022) engineering.gusto.com Heroku HTTP API Design (2015) github.com How Complex Systems Fail (1998) how.complexsystems.fail Choose Boring Technology (2015) mcfunley.com Do-Nothing Scripts (2019) blog.danslimmon.com Practical Railway-Oriented Programming in Ruby (2023) ismaelcelis.com Cruddy by Design (2017) youtube.com Hypermodern Python (2020) medium.com Pure UI (2015) rauchg.com Things You Should Never Do (2000) joelonsoftware.com Load Balancing (2023) samwho.dev The Twelve-Factor Apps (2012) 12factor.net No Haunted Forests (2018) john-millikin.com Is this true? notes.jordanscales.com Turbopuffer's architecture (2024) turbopuffer.com The Configuration Complexity Clock (2012) mikehadlow.blogspot.com JSX Over The Wire (2025) overreacted.io The Clean Screen Habit (2016) inessential.com Behind the scenes of bun install (2025) bun.com A Practitioner's Guide to Wide Events (2025) jeremymorrell.dev Performance is not a technical problem shud.in Ratchets qntm.org Observability first (2026) natemeyvis.comProductivity11
Work on what matters (2020) lethain.com When everything is important but nothing is getting done (2020) sharedphysics.com Agile as trauma (2018) doriantaylor.com Coordination Headwind (2020) komoroske.com Fire and Motion (2002) joelonsoftware.com Mandate Levels (2021) cutlefish.substack.com So You Messed Up! Now What? (2021) jacobian.org Two Big Things (2014) longform.asmartbear.com The Basics (2024) registerspill.thorstenball.com Work is Work (2020) codahale.com When and how to say no at work (2022) amy.devDesign6
The Princess Rescuing Application (2008) lostgarden.home.blog Safe rules (2023) anthonyhobday.com Family Values (2024) benji.org Sanding UI (2024) blog.jim-nielsen.com Guideliens (2025) vercel.com Details that make interfaces feel better (2025) jakub.krMarketing1
Double Shipping (2018) zachholman.comThe Internet1
Deep-Fried Data (2016) idlewords.comBusiness11
The long, slow, SaaS ramp of death (2012) businessofsoftware.org Becoming Data Driven, From First Principles (2024) commoncog.com Sales Advice for Founders (2023) tracy.posthaven.com Muse retrospective (2024) adamwiggins.com The STARS Framework (2023) starsframework.org Statistical Process Control: A Practitioner's Guide (2022) two-wrongs.com Avoid Blundering (2024) longform.asmartbear.com The Secret Heart Of Continuous Improvement (2024) commoncog.com Extreme Questions (2022) longform.asmartbear.com Schlep Blindness (2012) paulgraham.com Big Blue (2024) buildingslack.comMiscellany15
Drink seltzer, live forever (2017) eater.com What Nothing Means: The Peculiar Pathos of Seinfeld Reruns (2013) vqronline.org What is code? (2015) bloomberg.com Pleasure needs no politics (2021) web.archive.org How to Develop Good Taste (2022) dieworkwear.com How is Felix today? (2020) howisfelix.today An App Can Be A Home-Cooked Meal (2020) robinsloan.com In Praise of Passivity (2012) studiahumana.com Obituary for a Quiet Life (2023) bittersoutherner.com The animal is tired (2021) robinhobb.com Goodbye Microsoft, Hello Facebook (2010) medium.com Trust the Process (2016) espn.com Coming Home (2024) aworkinglibrary.com The Communal Mind (2019) lrb.co.uk Practice Discomfort (2017) mythicalstrength.blogspot.com
Media
A
B
C
D
E
F
G
J
K
L
M
N
P
R
S
T
V
W
Z