I’ve seen a lot of love recently for local first apps, and a lot of really exciting tools to build out local first apps. One thing I don’t see discussed enough is that when your app is local first, you have to work without an internet connection, and keep working sensibly once the connection is back online. This means you have to think about:
Data migrations and rolling them out. Migrations become slow to roll out and necessary to get right since people could have data stored for a long time after you ship a change.
Client versions and version upgrades. Shipping a bad client has a huge cost.
As part of my most recent reading strategy I’ve been reading a lot of biographies. I finished the Power Broker in early April, and started reading Isaacson’s biography about Elon Musk more recently. I’d heard excellent reviews about the latter, but halfway through it, I’m sorely disappointed.
What strikes you when reading the Power Broker is the depth of research, the coherence of story and the intensity of feeling that Robert Caro has managed to put into words. None of these exist with the Musk biography. Chapters are short, out of chronological order and feel woefully under written and under researched. For example:
(Chapter 35: Marrying Talulah)
… It’s actually funnier than I made it sound …
Why not just make it sound.. funnier? I’m not saying it’s easy, but its definitely something I’d have expected of Isaacson.
(Chapter 6: Canada: 1989)
… most jobs paid $5 an hour. But there was one that paid $18 an hour, (… describes job).
Did he take the job? We never find out. Presumably yes, based on the description, but it was ambiguous enough while reading it that it stood out to me.
Setting aside individual nits, the biggest disappointment is how uninteresting the story feels (despite how interesting the story actually is). When I read Jobs, I was much more motivated to find out what happens next. Here, it’s as though I’m reading through an extended Wikipedia entry.
Admittedly, I am only halfway through the book, but I am skeptical that the style of writing changes significantly in the latter half of the book. Perhaps this is too harsh of a review, and my biography fatigue might be partly to blame for it, but there’s definitely something missing in this book.
This is an incoherent rant. Read at your own risk.
You show up for your Schengen visa appointment on a Tuesday morning - you’ve taken two hours off work. Your roommate learned about the Schengen agreement for the first time today, it’s been seared into your brain since you were 10. The security guard refuses to let someone else in - they don’t have an appointment but were told to come back by an employee. They slow the queue down, but you can’t help but empathize with them. Travel, after all, frees the mind.
You, the black and brown sheep, are herded into a room with your brethren. The workers - your people, now working for the colonizers - cheerful. The room is understaffed, slow and filled with anxiety. Wait two hours for your turn - the token number is CRAP-71, which matches your mood. Get called up front, spend 20 minutes going through documents, to be told, finally, that you are missing 1 piece of paper - an employment verification letter. Never mind the pay stubs you do have, and immigration proof that you still work at this company.
You leave, and come back 3 days later. Go through the same process, now with all documents in hand. Two hours later, you’re free (or so you think).
Two weeks later - you get a call. “We messed up taking your fingerprints, so can you, please, come back, again?” It’s a Friday morning, so you actually can go right away. You fill out a new application on a website that can best be described as retro, print it out at a nearby Fedex, and make your way over.
You’re supposed to meet C and get the process expedited, but as you enter you see him busy with something. C is spending his time pinning 8 individual QR codes, carefully, onto a board. It’s a Finnish visa board. C cannot do this job alone - so two people stand behind him and watch. A third person (who was originally assigned this job), sees this from a distance, and her insecurities about not doing her job well come out in her words.
Anyway, 20 minutes later, the QR codes are put up on the board, and you can get your fingerprints taken. Your token today is CRAP-85. You get the white glove treatment (only 30 minutes, instead of 2 hours) much to the chagrin of every other person there. This is a zero-sum game though, in this room, so you take your advantage. You submit your fingerprints for the second time, and the clock starts, once again, waiting for a response from the embassy. Will they let you into their country?
I haven’t published anything for about 6 weeks. There are a numer of reasons for this: In March I went on a trip across the US and was “one with nature” as my brother-in-law put it. Zion was incredibly beautiful, but the days of driving and hiking didn’t lend themselves well to writing.
Once I was back, I was laser-focused on finishing the Power Broker. I had to return the book by April 11th to the library, and I finished a week ahead of schedule! It is one of the greatest books I’ve ever read, and has changed the way I view a number of things: government, agency, power and people.
The following two weeks I was really trying to get Tailor out. My weekly goals for the last 6 weeks have inevitably included “Get Tailor Out!!” in no uncertain terms, but while I’ve been making consistent progress, finishing a project with complex UI is so hard.
I realized I hadn’t written in 6 weeks, and so this is just a recap of why. When I asked Tom Macwright what kept him writing for so long, he said his recap posts helped a lot with consistency. This is my attempt at taking good advice.
I like reading a lot of physical books, but I also would like to remember important details from said books. My default strategy for remembering things is to pipe them into Readwise and then Anki where I can make sure interesting pieces of information stay in my head. Unfortunately this is hard for physical books, and sometimes I want to put these pictures into Obsidian when writing recaps about what I learnt from a book. Google Photos makes this unreasonably hard (perhaps because they want to keep all your data). Every downloaded file is 10MiB which is way beyond what I need for an image with a bunch of text in it.
Here’s a tiny bash script to take the zip file Google gives you and output a bunch of tiny images:
The focus of this reading strategy is “How Big Things Get Done” - both on an individual and an organizational level. Like with my previous reading strategy, the first rule was to come up with a simple list of questions to answer:
How hard vs. smart did people who got big things done work?
Were most of them innately smart, or was there something else? What subsets of traits did a lot of them share?
How did they interact with other people?
Did they go wide or deep?
What were values they had? What values did they share?
What were key organizational principles to getting people to work together on large projects?
How large/ unrealistic were the visions of big projects when they started? Did they have to tone it down, or did they just achieve it?
What were key reasons large projects failed?
This is a fairly broad category and I don’t expect to get definitive answers to everything here. Again, as before, I have a curriculum of books. This being a fairly wide topic, the books are also fairly wide (and a bit random), but the benefit of that is I’ve already read quite a few of them (marked with ✓)
When working in Typescript I miss the exhaustive match statements I’ve gotten used to in Rust. They’re super useful when dealing with Enums and expansive types that you want to make sure you cover all cases for. When working on Cannon I have an enum defined for a language. Along the way I discovered a couple of nifty tricks for exhaustive case matching in Typescript. The simple way is to have an exhaustive object:
It’s always been easy for me to “get through” reading. You simply skim through the page, absorb a part of the material, and fumble your way around deep understanding, instead substituting it with words that sound like intelligence.
This is obviously a terrible strategy for deeply understanding anything, and many things have recently taught me that. One example was going through Reflections on Trusting Trust recently. Ken Thompson talks about quines early on, saying:
If you have never done this, I urge you to try it on your own.
Past me would have skimmed through for an answer, but now I opened up a terminal. The best I could come up with myself after 20 minutes was
with open('main.py') as f: print(''.join(f.readlines()))
On researching quines after this, I discovered that I had “cheated” by reading the file. When going through this I finally understood how one could produce a quine in Python: the key was understanding that repr prints the string with quotes. Writing partially from memory now:
Anytime you do something off the beaten path in the world of software, you have one of two choices:
reverse engineer the base concept from a couple of RFCs and a reference implementation
find a couple of libraries that do exactly what you want, but are poorly documented
As a concrete example, I was trying to figure out how you connect to the Astro LSP locally. I started off by reading the LSP specification, but quickly got bogged down by details around how to give requests. I learn best with experimentation, so I moved on to finding a library I could use to connect to LSPs locally. I found ts-lsp-client and pylspclient, both of which are sparsely documented. The VSCode reference implementation looked way too complex. And then I realized both those libraries had tests, and the tests had a working way to connect to those LSPs!
My original goal was to connect to the Astro LSP, so sticking to the pattern above, it’s time to take a deep dive into the Astro LSP test suite.
If you’re an Obsidian power user, you’ve likely hit a wall pretty quickly with what raw Dataview queries can give you. Or you’re just annoyed with how much new syntax you have to learn just to get your data out in anything but the simplest manner. If that resonates with you, and you already know javascript, I’d strongly recommend only using DataViewJS for all your queries. It’s no harder than writing the queries in their custom DSL, and you can massage both the query and the view output however you like.
Some tips when working with DataView JS in Obsidian:
dv.current() gives you the current page as represented by DataView.
console.logs go to the Obsidian dev console (accessible with Cmd + Option + I on a Mac).
You can access lists or tasks on the page using pageData.file.lists or pageData.file.tasks
Inline Dataview fields show up on the list element as properties. For example, if you have a list like this - This is a log #~"some tag" [property::value], you can access property using pageData.file.lists[0].property.
I wanted to write a full review of a lot of books I read this year, but I ran out of time. So instead, here’s a quick little rating scale out of 5 🥔s. It’s also in the rough order I read them this year. If anything is below 3 🥔s, definitely just read a summary. 3/4 is up to your judgement, please read every 5 🥔.
A year ago I started tracking my TODOs much more systematically using the Getting Things Done system in Obsidian. It only clicked for me when I hand rolled my own version on top of Obsidian, using default tools or Notion never felt low effort and easy.
I’ve been relatively consistent with keeping track of my tasks and working on dashboards, but now that a year has finished, I have a much better sense of what works and doesn’t work for me within the system.
Be ruthless in pruning your dashboard to exactly what you can do in a week (hint: it’s not as much as you think).
It’s more important for me to track things I don’t want to do but have to (not always, but as a rough heuristic). My default mode is to execute on things I want to do, so I don’t need a dashboard of tasks motivating me here. I’m going to take this a step further in 2024 by really trying to make my dashboard very sparse so I can focus only on the big rocks I’m excited about.
Have many ways to record and reflect. I have a handwritten journal, random notes I scrawl on project pages and a per day notes section. Variety makes me record more.
Really try to do some version of a weekly review. Even if you lack the mental energy to clean up the dashboard that week, write down the vibes of the week in your weekly review. The stuff unrecorded in your notes but that lives in your memory is really powerful, and you can’t really remember those when looking back at a week months later.
Make it easy to add new projects and be liberal with creating them (even if a lot of them are marked “someday”).
I’ve been working on a new DevTools experience I’m calling Tailor. I was inspired by Tailscan and wanted to understand how I’d build a clone of it as a starting point.
The most annoying interaction problem I faced was when/ how to activate and deactivate DevTools. Tailscan does this super well, you have a button to activate/ deactivate DevTools. When you click on an element the toolbar remains but the hover behaviour is disabled. When you click anywhere outside the toolbar again you reactivate the hover behavior.
Make the toolbar follow the cursor for a more natural feeling placement instead of making it relative to the element you place.
When you add and remove mouseover listeners for document inside a React component, make sure you wrap the callback function you pass in inside a useCallback. Otherwise React creates new functions each time the component re-renders and you won’t properly remove the event listeners.
pointer-events: none is your best friend for the overlay/ toolbar UI you build.
css-box-model is a great package to do math for you.
My friend gave me really great feedback on my review for Atlas Shrugged which made it go from unreadable to ok.
Guzey gave me some feedback on my blog after I emailed asking for it.
I’m not used to asking for feedback generally, and I didn’t know how uncomfortable it made me feel until I started doing it more - but the outcome is (maybe obviously) positive!
I need a place where I just want to dump tiny logs with low pressure to edit things - tiny DevLogs for different things I’m working on. Then I saw Tom Macwright’s Micro section and I was inspired to start my own.
I wanted to call it “DumpTrucks” and format it as a truck, but that felt like a worse and worse idea as I tried to bring it to life. “DevLogs” doesn’t capture everything I want these to be, this is more for just dev stuff. So I settled on the vanilla “logs” - lmk if you have better ideas!