projects

  • Personal Site Gallery

    I’ve put together what I think is currently the most comprehensive directory of personal sites available on the internet today. 31,000+ personal web pages, screenshotted for easy browsing and tagged with visual characteristics so you can search through them very easily.

    Give it a try at zmh.github.io/personal-site-gallery/

  • Dispatch

    A focused inbox for Slack.

    I hate how Slack’s Activity and Catch Up features work, so I built Dispatch, an opinionated and focused inbox for Slack. Sort of like Superhuman for Slack — never miss an important message, and triage your inbox quickly.

    1. Add your Slack cookie so it can connect to your workspace. Everything happens locally.
    2. Choose what messages you want brought into Dispatch. Mentions are included by default. You can additionally specify people or channels. For example, I have people I work most closely with and senior execs listed, along with a few whole-company channels I know might be relevant.
    3. All the messages imported by the above will be categorized into split inboxes or categories, based either on simple keywords (e.g. from:@Matt should be filtered into the Important inbox) or, optionally, with Claude Haiku using a prompt you can configure. If you choose to enable Claude, you’ll effectively have a little assistant categorizing each message into a bucket based on your description.
    4. Go through each inbox. Star, snooze, or mark messages as done with keyboard shortcuts. Hit enter to read more or reply in Slack directly.

    This lets you treat Slack just like email. Messages come in, get filtered into inboxes, and then you can action them quickly.

    The design is inspired by Superhuman Mail, as well as a now-defunct alternative Slack client I used and loved called Ripcord. Dispatch is typography-heavy and very dense, with inspiration and guidance from Matthew Butterick’s Practical Typography, which argues that typography (font size, spacing, and density) are the primary interface of any text-heavy app. Dispatch uses SF Pro at 13px with tight row heights so you can scan dozens of messages without wasted space, and lets you switch to monospace or adjust sizes from 11–18px, because good typography respects the reader’s context. Just enough structure to let you read fast and act.

    There are probably definitely bugs, but I’ve been using it for the past few days and it’s helped cut through a lot of the noise on Slack. Give it a try and let me know what you think!

    Why build a Slack client? For years, I’ve been fed up with how Slack treats channels, messages, and threads. Channels are too noisy, important context gets lost in threads, the Activity view captures a subset of actionable items, and notifications often don’t fire. And seemingly most of the internet agrees with me:

    If someone doesn’t @-mention you or the channel, the only way you’ll see that message is to read every message, in every channel, every day. For orgs with hundreds of channels, it’s a mess.

  • 2025 Side Projects

    I’m finally publishing my side projects for 2025 on Github — 36,408 lines of code, almost entirely vibe coded.

    • Quill, a beautiful, fast, native Mac WordPress blogging editor inspired by IA Writer but with full, bidirectional Gutenberg block support
    • Gymtxt, a lightweight way to log workouts as plaintext
    • Day One Publish, a way to generate static sites from a Day One journal to share with friends and family
    • Shrinksearch, a fast way to search and browse Psychology Today profiles

    Some notes from building this year:

    • I’ve been preferring one-page tools that read/write from a local CSV, JSON file, or sqlite db — the data layer is easy for the models to use, version controlled, and super fast on the frontend for the user.
    • I like UX where the app is a layer on top of plaintext. Gymtxt was my first attempt at this, and I love this travel app with a similar vibe. Treating the text area as the database means the user, LLM, and developer can all easily interact with the same dataset.
    • I highly recommend Coolify or Dokploy for vibecoding projects with Claude Code. They’re essentially a self-hosted Replit or V0 — you get a unique URL per project, and they auto-deploy when you push to Github. Set it up once on a cheap $5 VPS and you can go from a new folder on your computer to a link you can share in ~3 steps (create the repo in Github, push to it, and then tell Coolify about the new repo.)
    • I’m interested in what LLMs can “see” when processing images. Web projects were easier than native apps because Claude Code could snapshot the page and verify its results vs. native apps where I would largely do that (though I imagine giving screen access in the future will fix that.) But even when snapshotting, specific layout tweaks were sometimes hard for it to see in the generated image.
    • Apple should have an App Store submission MCP and an improved notarization experience. The hardest part of Quill was getting it into executable form so people could download it and run directly. Until then, my default stack will skew towards web technologies unless there’s a specific reason to build natively.
    • I find it crazy that, when facing a bug the LLM can’t solve, starting entirely from scratch and referencing the old project code will often result in 100% feature parity with the issue resolved. I wonder if coding agents will adopt this as a way to get around roadblocks.
  • Day One Publish

    Day One Publish is a project I made to generate a static site from a Day One journal.

    For some recent travel, I wanted a way to add photos each day for a small group of family and friends to see. A blog would work, but I wanted a great native editing experience, with particular focus on places we were visiting. Luckily Day One has gorgeous native apps and now allows shared journals, but there was no way to take a journal and publish it as a site. 

    The design is entirely inspired by the Day One app interface itself, so it feels native. View entries as a timeline, calendar, mosaic of photos, or on a map. I have it run nightly locally on my Mac, and it deploys via Coolify.


  • Quill

    Quill is a native macOS WordPress editor, built for those who like to edit their site posts directly.

    I’ve used Ulysses, IA Writer, and MarsEdit, but none of them let me publish a post and then edit it later in the editor. Once a post was published, I’d need to switch to WordPress to edit (or in MarsEdit’s case, I’d get a bunch of HTML comments around each block, which made editing hard.)

    So I made the Mac WordPress post editor I’ve always wanted, mainly for blogging:

    • Native – primarily I wanted this for the writing and editor experience, but it also means things like keyboard shortcuts, drag and drop, etc
    • Well-designed – nice fonts, fits into Mac OS, and feels like a place where I can get cozy and write
    • Blogging-focused – I really wanted to know how much I was writing and set goals
    • Notes-like – I wanted to treat posts as notes so they’re living documents. Easy to open quickly, make a change, and save. Fast and available offline so you can edit on a plane
    • Gutenberg support – I wanted the editor to be bidirectionally compatible with the Gutenberg block editor. Edit on web or in the app, resume editing in the other. No weird save artifacts or unsupported blocks

    The app was almost entirely vibe-coded using Claude Code in a few sessions. Some observations:

    • Claude Code, and Opus, are substantially better at project management and context compacting since I started in June. 
    • Opus is very good at Mac development — the hardest part was notarization. If Apple fixed notarization and App Store submissions for Mac and iOS (perhaps using MCPs), I think you’d see a renaissance of native app development.
    • Building text editors continues to be one of the hardest problems in computer science.

    Check out the project on Github, and download the Mac app here.

  • Gymtxt

    Gymtxt.com is a lightweight way to jot down exercises at the gym, in plaintext. It’s based on how I log workouts in Apple Notes / IA Writer, with a little scaffolding to make it easier to track workouts over time.

    It allows you to write something like

    10/13
    squats 100lbs 5x5 
    bench press 45 each side 5x8

    The date, exercise, set count, rep count, and weight are parsed automatically and tracked over time with graphs.

    Easily remember what you did last time and update your workout as you go. It also includes a basic timer for breaks between sets.

    All data is stored in local storage and importable/exportable as plain .txt files.

  • Shrinksearch

    Shrinksearch lets you quickly search and browse mental health providers from the NYC area, with data from Psychology Today as of April 2025.

    Psychology Today has the best data set for mental health providers, but it doesn’t let you search the text of providers’ descriptions and only shows a few providers per page. 

    View live here, or the code on Github here.

  • 2025-01-27

    I’ve been waiting for a DIY / open source version of Find My, mainly to allow new form factors beyond AirTags and supported third parties.

    Came across OpenHaystack today and it seems like the best so far given their supported device list. Their version cleverly works as an Apple Mail plugin, but biemster/FindMy is another project that works with just your Apple ID.

    I wonder if this would allow for something like remote Find My beacons that you could post around your house to instantly find items instead of wandering around with an iPhone, or help visualize things moving around a space like a marauder’s map.

  • Installing Comma.ai on a 2018 Mazda CX-5

    I recently ordered a Comma.ai kit to add semi-autonomous driving capabilities to my 2018 Mazda CX-5. It took some trial and error (and help from the Comma.ai community on Discord) to get it working properly, but I highly recommend it as I’ll explain later.

    I’m sharing the steps I took in case it’s helpful for others looking to install the Comma 3X on the same or a similar vehicle. It’s a pretty intuitive process, all things considered, but there weren’t a lot of guides with photos on how to do the actual installation process.

    What is Comma.ai?

    Comma is like Tesla Autopilot for your existing car. It plugs into the car’s OBD-II port and uses data from your car’s existing sensors to do some Level 3 automation (ish). That’s partial automation — if the systems fail or there’s a major incident on the road, you still need to be ready to take over. But it works well on highway drives and anywhere you’d normally be using cruise control.

    This might sound sketchy, but Comma was actually ranked #1 by Consumer Reports. After a few months of using it, I can attest it’s not a fly-by-night hardware operation, and the software is quite good.

    What cars support Comma.ai?

    Comma’s official compatibility list is here, but if you don’t see your car listed it doesn’t mean it’s not supported. As I later found out, there’s an “unofficial” list of community-supported vehicles (like this for Mazda) where the sensors exist but capabilities have various limitations.

    In my case, CX-5 models earlier than 2022 have all the sensors needed for the full Comma.ai experience, but the EPS motor (which provides lane departure warnings by rumbling the wheel a bit) isn’t strong enough to move the wheel enough for medium to large turns when automated. That changed in 2022 model years and later, which is why they’re officially supported.

    Earlier models are community-supported, and there are some asterisks around what you get with the out-of-the-box Comma experience. But — if you’re willing to do a 30 minute part swap (that I thought would be scary and warranty-voiding, but is actually easier than you’d think with my guide below) you get the full Comma experience, which is better than most built-in car autopilot features today.

    A false start

    When I initially received the Comma 3X kit and installed it (follow the installation video and Jafar’s post, it’s pretty simple) I thought I’d be up and running quickly. However, the device seemed stuck in dashcam mode and didn’t move the steering wheel at all. After digging into the Discord server and reading more, it appeared to be an issue with fingerprinting my specific Mazda model.

    I reset the device and installed a special fork I found on the Discord server which had more Mazda car fingerprints to help identify how to interface with the car. This worked on a test drive, but the car would beep aggressively every 5 seconds if you weren’t holding the wheel very deliberately, making highway driving difficult. Even without Comma installed the car would complain when you had cruise control enabled and weren’t holding the steering wheel in the right place, but adding the Comma made it complain much more.

    The Discord community recommends trying a wheel cover with weights underneath, which worked somewhat but was quite bulky. Ultimately, I decided to pursue the ultimate solution I had been trying to avoid: swapping out the EPS motor.

    Swapping the EPS motor

    The EPS motor on pre-2022 Mazdas is designed for very lightweight lane departure vibrations. I always thought it felt a bit underpowered, and you could feel the car lightly bouncing between the lane markers. On any serious turn, the car would just continue to depart the lane.

    Newer Mazda EPS motors can apply more torque to the wheel, allowing for real LKAS (lane keep assistance) that can turn the car even through 10+ degree curves. I was initially hesitant to replace the EPS motor because I wasn’t sure exactly where it was located. But after reading the pinned messages on Discord and asking a few questions, the community reassured me it was pretty straightforward.

    The process ended up being easier than I anticipated, although there were a few tricky parts. Here’s a detailed breakdown of how it works:

    1. Order the new EPS motor from eBay — the LKQ store has several options, but you have to make sure the vehicle is model year 2022 or higher. As an example, here’s a search on LKQ’s eBay store, or just look for “2023 Mazda CX-5 Power Steering Pump OEM”. You’ll also need a 10mm and 12mm wrench for later.
    2. You’ll receive a hunk of metal similar to this. The only part needed is the circular gearbox-looking piece on the left of this picture.
    1. Remove the two bolts pictured here, which will detach the shaft from the EPS motor. Use a 12mm wrench for these and be careful not to lose the small plastic gear in the center of the motor once you remove it.
    1. Disconnect your car battery using a 10mm wrench to prevent the airbags from firing.
    2. While not required, I recommend removing the cover to the left of the steering wheel. It pops out easily and improves access to the EPS motor.
    1. Now that you’re in, you’ll see the same motor mounted, as pictured here:
    1. Here’s the trickiest part: you need to remove the same two bolts on the old gearbox, but one bolt is close to a piece of metal, making it hard to fit the wrench in. It’s doable but will take a few attempts. Both bolts are on quite tight, so don’t be afraid to use some force to loosen them.
    1. Once the bolts are out, unhook the 3 cables at the top and detach the old motor.

    One tip: the small gear kept falling out or misaligning as I tried to install the new motor. Rather than fumbling with alignment, I positioned the gear on the other (already mounted) side so it was already lined up correctly. You’ll see what I mean.

    1. Screw the bolts back in, reconnect your battery, and you’re all set! Once the Comma turns on, you’ll go through an installation process. Like this video shows, you’ll want to select “Custom software” but then you’ll enter the URL https://smiskol.com/fork/jafaral/mazda-eps22-swap on the Comma 3X, which tells older Mazdas to use the new EPS motor.

    Review

    After installing the new EPS motor, I’ve been really impressed with its performance. I wouldn’t even bother installing Comma.ai on an older Mazda without it — the experience is just too annoying otherwise.

    The upgraded EPS motor enables stop-and-go adaptive cruise control, which by itself is a fantastic improvement for city traffic. It also provides LKAS that keeps the car smoothly centered in the lane without any warnings to keep your hands on the wheel. These enhancements make long drives much more pleasant.

    With the new motor, I’ve completed a few hundred-mile road trips with only three or four interventions to assist with turning, and just a handful of additional interventions in busy city traffic. It really is quite capable.

    Since I had Comma installed before the EPS motor upgrade, I spent some time observing the Openpilot lane markings as we drove. There was never a point where the green outline indicating the car’s projected path was misdirected or where the detected lane markers deviated from reality. I also drove at night and in the rain, with no issues whatsoever. This gave me a lot of confidence in the system’s capabilities.

    Special thanks to the Comma team for building an incredible hardware product, and to all the maintainers of Openpilot and volunteers in the #Mazda Discord channel.

    Update: 6 months later

    Highly recommend the Comma, and will continue updating this post with observations.

    • After ~500 drives and 10k+ miles, I’ve never had any safety issues, and have even relied on it in rain and snow because it did a better job of observing lane markings than I could.
    • I’ve noticed on some roads it adjusts the wheel back and forth a bit more than it should — this is a known issue called “ping-ponging” and some other branches are supposed to be better at minimizing wheel turn. More info is available on the Discord channel, but it hasn’t been a big enough issue for me to investigate further.
    • I might try some of the other forks like Sunnypilot that offer more customization.
    • I have noticed that the unit doesn’t do well in extreme temperatures, which usually happens when you leave it connected in a hot or cold parked car. Before purchasing, I had read reviews of people whose units broke in extreme heat, and I think it’s a real concern but avoidable in average climates. Either way, I’ve been disconnecting the unit and putting it in the glove box when I know it will be in direct sun or extreme temps. Quite easy to do, and so far no issues there.
    • I do think having the Comma as a dash cam is an underrated benefit. The team discourages its use as such, but it’s good enough and gives me some peace of mind.
  • Daily 140 and Macaw, RIP (2014 – 2023)

    Last month, after almost exactly ten years, my side projects Daily 140 and Macaw stopped sending out emails thanks to Twitter’s API changes.

    Some stats:

    • 14,547 users
    • 21,201 Twitter accounts that Daily 140 users chose to monitor
    • 7,333,659 total Twitter accounts monitored for likes/follows for Macaw
    • 4 million+ emails sent with a 40% daily open rate

    Daily 140 was by far my most successful side project, so I wanted to document its arc and what I learned, particularly for the many people it’s helped connect me with.

    • All credit for the premise and the name goes to my old roommate Ryan, who was manually tracking the likes and follows of a few high profile VCs with interesting results and more generally is a spectacularly creative Twitter user
    • Built over a few weeks in the fall of 2014, and launched on Product Hunt in January 2015
    • I forgot about the project for a few years after starting a new job, but realized after 3 years that I had thousands of users and a bunch of mentions on various blogs
    • The biggest issue with Daily 140 was not knowing which accounts would yield interesting results (in hindsight, I should have published something like @BigTechAlert that was more easily visible and followable). That led me to launch Macaw, which showed you a feed of the tweets all of your followers liked each day, and the new accounts they followed.
    • Tech stack for Daily140 was PHP, MySQL, TwitterOAuth. Macaw used Python and Tweepy instead, for performance reasons.

    Both projects led to a few fun opportunities:

    • I met a number of investors who would use it to get leads on new deals, people leaving companies, and other business intelligence
    • The Twitter Developer team did a one-hour research call with me, as part of their diligence before launching the v2 API and new Developer site
    • I emailed several crypto anons, all of whom used Daily 140 to monitor new protocols and blockchains
    • I got 3 offers to buy the software outright

    And were written up in a few publications:

    All of my time now goes towards building Clay, a home for your people and relationships that leverages a lot of the skills I learned building Daily 140 and Macaw, and we may end up rolling in some of the features those tools provided.

    In both Clay and my side projects, I’m thinking about similar features layered on top of the next wave of social tools that are replacing Twitter, like Mastodon, Bluesky, and Micro.blog. Decentralized architectures and availability of APIs unlock a whole world of possibilities on those platforms, and there’s clearly still a need for tools like Daily 140 for research, discovery, and monitoring.

    Some final thoughts:

    1. If you’d be interested in a replacement for either tool, take my quick survey here.
    2. If you’re interested in learning more in the coming months, sign up for my updates newsletter here.