Projects
-
A Handy Shell Script to Publish Jekyll Drafts
The quest to remove friction from posting to this blog continues. In an earlier post, I shared how I used rake to automatically generate a blog template for me and place it in Jekyll’s drafts folder. Now, I realized I’d also like to handle publishing that post with approximately 10% fewer keystrokes.
I’ll share the script first, then explain my motivations and how it works.
#!/bin/bash PS3="Choose a draft to publish: " select FILENAME in _drafts/*; do today=$(date -I) shortfile=$(basename $FILENAME) mv $FILENAME _posts/$today-$shortfile && echo "Successfully moved" || echo "Had a problem" break done exitThat’s it, that’s literally it, but I’m so excited about it.
Jekyll considers a post to be a draft if it is a markdown file in its
_draftsfolder. It considers it to be published if it is in its_postsfolder. I believe the filename in_postsalso needs to contain the date (e.g.2025-11-19-this-is-a-post.md) but I’m not sure if that’s a hard requirement or just a requirement for my setup.So what I have to do when I publish a new post is
mv _drafts/mydraft.md _posts/yyyy-mm-dd-mycoolpost.mdand that is clearly too many keystrokes, right? Now I just have to writerake publish(I created a rake task that just runs this script), choose my file from a list of files, and I’m done.To write this I had to learn about two new-to-me bash concepts, the
selectconstruct andbasename.The
selectconstructselectcan be used to create (super basic) menus. The man page forselect…..is for the wrong thing! But a good writeup on the select construct can be found here. In short,select thing in listwill pop up a menu that you can interact with by choosing the item number, and assign the value to the variable$thing.You can do:
select option in "BLT" "cheesesteak" "pb&j"and you’ll get the following output:1) BLT 2) cheesesteak 3) pb&j $>In the case of my script, the “in” is the contents of the directory
_drafts/*.(Notice the syntax is not
in ls _drafts/*, implying that we’re not just executing a command and passing the results to the select construct. Which is a mystery for another time.)The upshot, however, is that I get a list like:
1) _drafts/ai-is-hard.md 3) _drafts/microblogging.md 5) _drafts/recipe-buddy-part1.md 2) _drafts/efficient-linux-ch-4.md 4) _drafts/rake-publish.md(oooh, a peek behind the curtain!)
selectwill then allow you to choose one of the numbers, and store the value in the variable we defined (here,$FILENAME.)It will continue to loop until it reaches a
breakcommand, so the break is important in this script. But then all we need to do is get today’s date and rename/move the file to its new home.basenameThis is a lil one, but a handy one. Again, let’s go to the man page for this util:
BASENAME - strip directory and suffix from filenamesDoes what it says on the tin. If you have
/home/user/long/path/to/file.mdand you wantfile.md,basename /home/user/long/path/to/file.mdwill get that for you. Note that it removes the extension if and only if the extension is provided as a second argument, and if the provided extension matches that of the file, which is a little quirky. In my case I want to keep the extension, so this works well for my use case.And there you have it, 10 lines of code that took longer to write about than to write, and which will surely save me
hoursminutesseconds of precious time. Huzzah! -
Are There Any Good AI Documentation Apps Out There?

One of the places that I had hoped “AI” could be truly a time-saver is in the realm of creating documentation. There are a number of services out there, including Guidde, Scribe, and Tango, that claim that using their browser extension, you can simply perform a task while the extension records you, and then their software will describe what you did, magically creating a how-to document or video to share with your team.
The promise is amazing, but the reality is .. not so much.
The first limitation of many of these services is that you are limited to actions taken in the browser. If your task requires doing anything outside the browser, you may be out of luck. (I believe Scribe now offers a desktop app, this may be true of others as well.)
Unfortunately, the second limitation of these services is that they are all stupid.
-
From Idea to Acceptance: Crafting a Standout Conference Proposal
Honored to have been a part of this panel on how to get started speaking at tech conferences and meetups – with an emphasis on writing a good proposal – with some very talented and prolific folks. And a big thank you to Joy Hopkins for organizing the panel and having me on.
-
Six Things I Bet You Didn't Know You Could Do With Chrome's Devtools, Part 2
This is the second of two posts about devtools tricks; these are sourced from a conference talk I attended in early November as well as from other things I’ve picked up across the years.
In the first post we covered:
- Time functions with
console.time()andconsole.timeEnd() - Watch any DOM element for changes
- Monitor any function in the browser’s context
In this post, we’ll cover:
- Edit any website WYSIWYG style
- Record and replay any user actions
- Throttle only specific network requests
So without further ado, let’s dive in.
-
Edit any website WYSIWYG style
I love messing around with the DOM on the Elements tab. What would it look like if I removed this class from this element? What happens if the text overflows its container on this page? These are all things you can do by manually editing the node you care about on the Elements tab, but it can be a little fussy. I recently learned that you can make the entire page editable. By running
document.body.contentEditable = truein the console…well, look at this nonsense:I imagine this would be slightly useful for testing UI edge cases, and very useful for entertaining middle schoolers.
Source: Mindi Weik, who showed me a preview of a talk that included this tip – her talk is not online anywhere as far as I’m aware.
Support: All browsers
-
Record and replay any series of actions.
I’ve truly always just ignored this tab, but if you jump into the Recorder tab, hit record, take any series of actions on a site (clicking buttons, navigating, entering text in forms), and then stop recording, you can then replay those actions, share them with another person, and even generate code for many popular testing frameworks.
During Mike’s session, some attendees were really excited about the possibility of catching an “unreproducible” bug by recording the steps to generate the bug and simply replaying the actions repeatedly until the bug appeared; I was excited about getting React Testing Library code that would finally convince my colleagues that writing FE tests are worth the effort :) To my disappointment (and complete lack of surprise), however, the code output by the recorder isn’t up to my standards; it tends toward hyper-specific selectors (ex:
#story > section > div:nth-child(3) > div > div:nth-child(3)) rather than how I prefer to write tests, using more semantic selectors.I still think the generated code could be useful as a starting point, but even if I never use that, I can definitely imagine a scenario where I send a colleague a bug report that says “Run this recording and see if you see the same bug I do…”
Source: Mike Rapa
Support: Chrome for sure; Firefox doesn’t seem to have a record-and-replay function (it does allow you to record for performance analysis, which is different).
-
Throttle specific URLs.
Instead of throttling the browser’s connection speed overall, to simulate your end user being on a slow network, you can now tell Chrome to throttle or block only certain resources, to simulate what happens if a third-party API goes down or is overwhelmed.
This is only available in the Chrome Canary release, but will hopefully make its way into a general release in the next few months. DebugBear has some useful examples on how to get started now, if you can’t wait. There is an example of how to throttle an individual request as well as how to do wildcard throttling.
Source: DebugBear and Javascript Weekly
Support: Chrome only
- Time functions with
-
My 4 Testing Commandments
Bug huntingThis week I was a guest instructor at the Black Venture Capital Consortium’s Software Engineering Career Track. This is was my second year volunteering with BVCC on the SWE track, and it’s super rewarding, although I’m still learning how to deal with the “Gen Z stare” on Zoom. (Teachers who do a lot of online instruction, my hearts go out to you.)
This year, my topic was testing – both manual and automated. The students are pretty new to software engineering, so manual tests were more their speed, for the most part, and we had fun trying to break a demo application.
But automated tests are the thing software developers will spend more of their time on than manual, so I tried to give them a little taste of automated testing principles.
This is, more or less, what I said:
Tests are your contract. When you write tests, you’re forced to decide how a method should behave. This is where you can decide that a method will throw an error when given bad data vs printing a message in the console. This is where you decide that no, you’re not going to allow this edge case. Tests help you think through what you want to code, and six months later, they help you remember what you meant to code.
Always test your tests. You can use a mutation testing framework or just manually, temporarily, modify your code or test assertions. (Sometimes I just change all
assertTrues toassertFalses.) But without knowing that your tests are doing what you think they’re doing, you can’t have confidence in them.Don’t put too much stock in unit test examples when you’re learning. Many, many “how to write unit tests” blog posts use math as their example. This makes sense, because if you know that 2+2=4, it’s easier to focus on the syntax of the test code, and you don’t need to waste brainpower on understanding what the method-under-test is doing. But if you’re new to unit testing, you might be asking yourself, “why on earth would I need to test that 2+2=4”? You don’t. You’ll never write a unit test testing an “add” method in production, because you will never write an “add” method. Don’t focus on the method-under-test, just pay attention to the syntax and trust that it gets more interesting.
Tests and accessibility go hand in hand. Okay, this is more about integration tests for a web app than unit tests, but most good testing libraries, such as React Testing Library, use the same affordances to run tests on rendered elements as a screen reader user would use to interact with a page. If it’s hard to test, it’s probably hard for a screen-reader user to use. (I don’t feel confident saying that if it’s easy to test, the site is accessible–but it can’t hurt.)
What would you add to these four?


