For AI agents: a documentation index is available at /llms.txt — markdown versions of all pages are available by appending index.md to any URL path.
202 Posts

Microblog

Short posts that don't need a full article. Most of these started life on LinkedIn (each one links to the original); from here on they get written here first and syndicated there. Subscribe to the microblog RSS feed if you'd rather not follow along on LinkedIn. The main feed still only carries full articles.

DocumentationCoding

This week, I'm helping a team of technical writers deliver a new sample app showing how to use our products with three popular frameworks. I'm slinging around:

  • Bash
  • Java
  • Python
  • TypeScript
  • Markdown
  • YAML

While working on READMEs, repo licenses, .gitignores, GitHub workflows, repo configuration, and a utility/process for copying our sample app from a source monorepo to framework-specific artifact repos to simplify developer usage.

My fellow technical writers have written the app; I'm just out here adding Swagger docs, unit tests, integration tests, doing PR reviews, and setting up infrastructure.

I see posts all the time where technical writers lament seeing so many job postings that require tech writers to have some level of development skill. But the reality is that when we do, we can contribute much deeper and richer learning experiences to help people succeed with our products.

And isn't that the goal?

AICoding

In personal project news, this weekend my household hit two key milestones in our project to liberate our smart home from private clouds whose terms of data sharing are no longer acceptable to us:

  • We removed the Philips Hue bridge from our house while retaining our smart lights
  • We deleted our home from Apple Home while retaining all of our smart functionality

We have also disabled/removed all listening devices provided by Big Corp; no Siri, Alexa, or Google in our house.

We have lost 0 functionality.

We’re now running everything through Home Assistant. It runs in a Raspberry Pi that’s sitting with our networking equipment in our basement. It’s isolated to its own network, along with the smart hardware, so none of it ever has access to the same network as our computers and phones.

We’ve bought antennas to use our smart light bulbs and thermostats through the Zigbee and ZWave protocols without ever calling out to a server outside of our house. We’ve replaced a couple of smart plugs, two very old Hue bulbs that weren’t Zigbee compatible, and the radio module for our smart door lock with alternate hardware that’s compatible with Home Assistant.

The big question for us was how we get voice functionality. We have gotten spoiled by the ability to talk to the air and set timers or have our smart home respond to voice commands. We bought the Home Assistant Voice Preview Edition to replace Home Pod and Siri on our devices. It does listen, but gives us a lot more control about when it listens. And it is developed solely to serve the privacy-conscious Home Assistant audience. We are the consumers of a product, versus being a product whose data is being monetized in the Big Corp ecosystems.

With the new setup, we get all the same functionality (better, actually) as the old one without giving companies we don’t trust access to our data.

Documentation

Woohoo, it's live! For all my documentarian pals who manually maintain OpenAPI specs, here's a tool you might find useful: OASprey, a package that lets you use the Jest testing framework to validate that real API calls match your API spec.

In this screenshot, we're looking at a Jest test file where we load an OpenAPI spec from our docs, call various endpoints, and assert that the status is 200 and the response we get satisfies the API spec. You can either load the published spec from a URL or the pre-published spec from a local file, depending on your needs.

Each test fails if we get fields or types in the actual response that do not match the fields and types in the API spec. By running the tests regularly, we can validate that the underlying API we've documented still matches the spec. If new fields are added, types are changed, or other breaking changes happen, failing tests will alert us that we need to update the API spec.

This isn't net new - it's a hard fork and modernization of an abandoned utility - but now it's available via npm. Links in comments. Happy testing!

Links from the comments:

I’ve been using my new iOS app this weekend while playing my new-to-me game.

I wanted a few small improvements - custom searchable implementations for Characters to find people who like certain gifts (whatever I happen to have on me) and Recipes to see what recipes I can make with certain ingredients (whatever I happen to have on me).

Pushed the new build to TestFlight and have been using it today while playing and boy oh boy is this a nice feature 😁

I really do love building apps that do exactly what I want them to do in the way I want them to do it. 💖

Sharing: my earlier post introducing the app, with screenshots

DocumentationCoding

I set out to write a script today to figure out how many instances of a given thing we have on a certain docs page.

I paused before I started, thought a minute, and made it a CLI instead.

Now it has 3 commands with various flags that are going to be super useful for evaluating the impact of changes or scoping maintenance work across our docs. And I’m able to reuse some core logic in different ways across the different commands.

Scripts are nice for one-off tasks, but a lot of the problems we solve in docs aren’t one-off tasks.

The next time you’re considering writing a script, maybe make it a CLI instead.

Links from the comments:

AIPersonal

Well, crud.

Mere weeks after raving about Augment Code and signing up for a personal subscription because I was so happy with using it at work, they are changing their pricing model.

Under the plan I signed up for, I get “600 user messages” per month. I used about 200 of those during 3 days of my vacation. As a personal user, I could just about get away with 600 if I’m only using it on some nights and the occasional weekend day.

For their new plan, they are switching to a “credits” billing model. I’ve been informed that my messages over the last 7 days have used about 1.5 times the number of credits of the average user on my plan. With the new model, my same monthly sub would translate to about 81 messages.

Down from 600 that I was paying for when I signed up.

81, when I used ~200 in 3 days.

So basically a little over a day of usage will burn through my monthly subscription allotment.

I guess I’m in the market for a new agentic coding assistant for my personal projects!

CodingPersonal

As the sun sets on my last day of staycation, I am happy to have this little thing running on my phone. It’s my latest iOS app, designed as a companion app for the cozy video games I like to play. The one shown here is reference info for the game “Story of Seasons: A Wonderful Life.”

Not pictured: the three different Go CLI tools I wrote to help me crawl, explore, and parse data from video game wiki websites to populate the app data. Or the generic, extensible architecture that lets me write plugins for each game, so I can add as many games as I want to this little guy. Or the theme system that lets me style each game’s data uniquely, so the app reflects a given game’s look and feel when you’re viewing the data for that game.

Or the thing I am stupid proud of - the fact that one of the CLI tools writes Swift codable strucs, customized SwiftUI views, and JSON data representing the info I’ve parsed from the wiki.

I’ve made a reference app factory for my cozy game wiki websites. 😁😂🎉

Documentation

I’ve been working on infrastructure to test the code examples we show in our documentation.

Rolling it out to a working group of early adopters has taught me so much about assumptions, both mine and the folks who are onboarding.

Much like any product, good enablement materials are priceless. Actual docs for this tooling + other learning modalities are essential.

I guess technical writing still has a role to play in today’s world 😁

CodingPersonalBusiness

I have been working at MongoDB for nearly 5 years now. That’s also roughly how long I’ve been doing my dev side projects. It’s no coincidence that MongoDB and non-relational databases in general are the default tool I reach for when I need a database for a personal project. I have written and shipped multiple apps that use non-relational databases.

My wife has been a software developer for a lot longer than that. She also uses MongoDB in some of her personal projects, but she comes from a long relational DB background. Her default brain reaches for relational. She keeps trying to convince me to use SQL for things that I am convinced don’t need SQL.

At the same time, I keep catching her ranting about complicated joins and groupings in some of her projects that still use SQL. They’re typically problems I just don’t have in my non-relational world.

My takeaways:

  • Old habits are hard to break. She can’t quit her SQL even though it’s bad for her 😉
  • If I can go the rest of my career without ever having to use a relational DB, I will be a happy human 😂

I filed a support ticket with JetBrains recently about a regression. Something that used to work in an older build no longer worked in the most recent build.

They were unable to reproduce my issue. I spent some time putting together a minimum reproducible test case, and in doing so, discovered a setting that solved the issue.

I don’t know whether this was a new setting, or the upgrade process to the latest build somehow lost a setting I had selected in the past. In either event, this setting caused a change in behavior that looked to me, the user, like a bug. A JetBrains support engineer lost time trying to reproduce my issue, and I lost time setting up the test case and also changing my workflows to work around this change in behavior.

Setting defaults matter! If it causes a change in behavior, it probably should have defaulted to the case that preserved the existing behavior. If the setting changed during upgrade, that’s a miss in the upgrade process.