Latest News

2020: The Lost Year

On March 6th of this year, I posted about leaving my role at WebDevStudios is pursuit of new opportunities. It might as well have been a decade ago.

That weekend, I celebrated “funemployment” by hanging out with some of my closest friends at The Lab in St. Paul, a conceptual taproom of sorts where brewers and beverage makers can try out new recipes in small batches that they can sell to those with adventurous palates. I didn’t have a new role lined up just yet, but I was studying and working through online tutorials to teach myself Python. At the time, I was in the middle of an interviewing process with a company where I’d have the opportunity to branch out beyond both WordPress and agency and finally get to experience the world of product development, all while becoming acquainted with a programming language that was both new and yet somehow familiar to me.

Last winter, lots of tech folks in the Twin Cities had started co-working occasionally at BlackStack Brewing, in large part because of 1) the ample taproom space, and 2) BlackStack’s change in business hours and structure; while still a brewery, they’d also begun marketing themselves as a coffeehouse by day. With fast wifi, a low-key environment, and a staff that was friendly to folks settling in and writing code throughout the day, I made plans for it to be the place where I’d spend my first day with some downtime to write some code for fun.

Much to my surprise, when I showed up to BlackStack that following Monday, I ran into some friends and former colleagues alike. The pandemic hadn’t completely settled here in the U.S., but the news was becoming increasingly scary by the day. Folks were showing up throughout the day, some (such as myself) already very mindful about not shaking hands, but of course, in early March, nobody was wearing masks yet, and a group of us went out for lunch together at The Naughty Greek, a fast casual Mediterranean restaurant just up the street.

Those are probably my last tangible, positive memories of The Before Times, though of course they were already tainted with my experience of working with an epidemiologist for almost 4 years earlier in my career and the worry about what was to come.

Later that week, I hosted my last in-person weekly board game night, something I’d organized for a full four years prior. My friends Nick, Bela, Austyn, and I played Great Western Trail, a game about herding cattle from Texas to Kansas City, where you later ship them off by train. Two days later, on Saturday the 14th, my friend Will was the last invited guest to our home for the entirety of this year. He, my partner Abby, and I played the cooperative game Horrified, which I’d purchased in South Dakota just two months prior when Abby and I visited her folks, oblivious to the fact that a global pandemic was looming.

Of course, we all know the rest. And it’s hardly been just the pandemic that’s resulted in this year being, perhaps inarguably, the most terrible of our lifetimes.

Being Thankful


The Python job that I was interviewing for in March became suddenly unavailable as a result of the economic downturn from the pandemic. In May, I was fortunate enough to land a position working at a local startup, but it quickly became evident in the subsequent weeks that the culture and development stack wasn’t a right fit for me. I turned in my resignation at the end of June, and starting fresh in my search. That very day, I heard from Steve Henty about an engineering position on the product team at Rocketgenius. After a couple weeks of interviewing with him and various members of the team, and learning more about the company’s mission and vision, I decided that staying in the WordPress space but making the switch over to product was going to be the right fit for me.

Man, am I ever glad I did.

I think I have a hard time articulating sometimes what it is I’m looking for out of my career, or even what I want from an employer. Every company that I’ve worked for in the WordPress agency space has done something smashingly well. Some have given me the opportunity to learn and grow, either by paying for memberships to online tutorial services, or helping sponsor travel to attend or speak at a conference. Some have recognized the benefits and challenges associated with remote work, and have taken great strides to do what they can to make their culture open and inclusive. Some have recognized holidays as official company holidays where others haven’t. Some have granted autonomy and trust to you, as an employee, to make decisions and take actions in the interest of the company, without the need for a special sign-off – making the pitch is usually enough.

I don’t know how they do it, but I’ve been with Rocketgenius now for 5 1/2 months, and somehow they do it all, and I’ve worked at enough places at this point in my career to know not to take this for granted. Every day, I am astounded by the thoughtfulness of my colleagues and leadership, the kind ways with which we interact, and the hard work and care that everyone puts into our products. We plan and communicate and check in with one another in ways that I’ve only seen glimpses of in past roles, and it’s made going to work each day something to look forward to; a welcome distraction from the madness of everything else.


Since that festive gathering in the beginning of March, I’ve managed to see my friends a handful of times this year, at extremely social-distanced outings in large backyards, city parks, and the front lawn of the Minnesota State Capitol. I’m grateful for those moments of simply reconnecting with one another, of catching up, of celebrating each other’s wins, and of hoping that we can all hug one another again when we finally get a calendar with a new number on it.

My friends have still managed to make this year special through trivia nights, board game tournaments, scotch nights, meetups, impromptu online gatherings, and the occasional telephone call (hi Josie!).


Above all else, I don’t know what I would have done this year if not for Abby. We celebrated our 12th anniversary at the end of October, and we’ve largely spent the year doing a handful of activities: taking walks around Lake Phalen largely as an excuse to run our car, playing a board game I can talk her into playing, watching a movie she can talk me into watching, finding occasions to use the oven instead of the microwave, and sending each other cute stories we find and as many animal-related pictures and gifs as possible. She supported me by remaining optimstic about my career change, even after it quickly got scarier than I’d expected, and I think what I’ll most cherish about this year is her dedication to getting me out of my comfort zone and encouraging me to take a walk in the neighborhood or go sit in the park for awhile. We started the year playing trivia at our local brewery nearly every Wednesday, and pandemic or not, I’m looking forward to warmer summer nights when we can go hang out in the park some more: the sun for her, the shade for me.

Looking Ahead

There’s a whole lot of stuff that’s going to be the same when we wake up tomorrow morning as it was through most of this year. Still, I think there is reason for optimism and hope, and for the new year, I’m planning on a small set of goals to keep me focused and motivated:

  • First and foremost, giving more than I did last year. I wrote a bit about some of my charitable giving over the summer. I’ve given more since then, both via official and unofficial channels, but I recognize that there’s more that I can do and now that my situation has thankfully stabilized a bit, I’m seeking opportunities to do more of that. One thing I’m considering is a monthly donation to Second Harvest Heartland beginning in January.
  • Reading more. A lot more. I’ve fallen out of the habit, and things were already sufficiently dire before 2020. I only managed to finish three books this year, and two of them I’d started in 2019: We Were Eight Years in Power: An American Tragedy by Ta-Nehisi Coates, Someone Who Will Love You in All Your Damaged Glory by Raphael Bob-Waksberg, and The Answer Is… Reflections on My Life by Alex Trebek. I’m not setting a hard goal, but more non-fiction, non-memoir I think is a good place to start. That said, I’m still trying to get through Exploded View by Sam McPheeters (made all the more difficult since it’s a police story) and The First Bad Man by Miranda July.
  • Writing more. Amazingly, this is my 16th blog post this year! I even got my first-ever reader e-mail the other day, related to my post about Xdebug 3. I’m hoping to write more about technical topics, and in particular, I want to write more about the process of learning. I’ve been less motivated to spend additional time in front of a screen that isn’t something mindless like video games or engaging like playing a board game with my friends, and I feel that my tech exploration has suffered as a result. I’m hopeful that we might start to see things normalize at some point this year, and that I’ll regain that excitement to learn and share what I’m learning more.

That last bullet sorta dovetails into some professional goals I have, too. In a particular, I’m working goals at work to open-source some tools, and a plan for sharing/presenting information about those efforts in some fashion. More on that at another date, I suppose.

To sum things up: so long, 2020. You were terrible, but I’m thankful for the good stuff.

Add Featured Images to Old Posts Using “Set Post Thumbs” for WP-CLI

Hey y’all! While I’ve admittedly been delaying my series about rethinking PHP development in WordPress first because of this global pandemic and all the election nonsense, and now more recently because of sheer procrastination because I’m not entirely sure how to start it, I wanted to take a minute to let you know that I made a thing!

Early this year, I got together with my buddy and former bandmate, Matt Semke, to talk about his website, Cats Will Eat You. For a number of years that I’m sure I should know by now and will surely get wrong (14, I think?), Matt has been publishing new art on his website every single day. But, even though his site was getting a lot of love content-wise, it wasn’t getting much attention from a web development and maintenance standpoint.

Matt and I got together over a couple of beers to talk about updating his website from WordPress 3.4(!) to the latest version, getting him onto a better hosting plan, and brainstorming some ideas about how to improve his site overall and make it better for both him and his visitors. This is one of my favorite (and only, at the moment!) freelance projects for a couple reasons: it means I get to help out a good friend who makes cool art, and it’s a low-impact obligation on my time, because I pretty much check in on it periodically and work on it when I have the interest and energy.

That said, there’s one other cool thing I love about this project: it gives me the opportunity to generalize stuff I work on specifically for Matt, and open-source the reusable bits. This weekend is the first such instance of that.

The Problem

With over 14 years of every-day art, Matt’s got thousands of posts on his site. He’s been using WordPress for a very long time; so long, in fact, that the content on his site predates the existence of features we take for granted today, like custom post types, featured images, the REST API, and so on.

In reviewing his theme over the weekend, I realized that I wanted to move some of his data around, get rid of some of the cruft, and, most importantly, set a featured image on each of his posts. So, I spent some time working on a solution, and then as I realized, “hey, some other folks might like this, too”, I started extracting out the parts that weren’t specific to his site, but to anyone’s. And then I made a repo. And then I connected that repo to Packagist. And then I learned how to make it installable using WP-CLI, because even after all this time, I’ve still never done that.

The Solution: Set Post Thumbs

In short, you can now do these two things:

  1. Run wp package install jmichaelward/set-post-thumbs from the command line of your WordPress project.
  2. Run wp thumbnail set --all, and WordPress will query all of the posts on your site that do not have a featured image, and then check whether there are images in your post. If there are, it’ll attach the first one.

The utility comes with a couple of additional commands to report back on which posts had more than one images, and which posts couldn’t set a featured image because it didn’t have any. And then you can run a cleanup command at the end to clear out all the excess meta.

It’s a little thing. It does a fairly specific task, and not everyone might need it. Additionally, I’ve tried to set it up so that it’s extensible, so that you can make modifications to the default way the tool works, in case your featured image lookup requirements differ.

What I really enjoyed about working on this is that I could take something I was building for a friend and open-source it to the broader community. Drop me a line if you wind up trying it and if you have any questions or run into any issues. I recommend using it only on a development environment where you have the opportunity to review the changes you’ve made. But, if you’ve got a site that has lots of posts without featured images, and you need a way to attach something to those posts, this should do the job for you.

Xdebug 3 is out, and you’ll need to update your settings

As a PHP developer (and particularly as a user of PhpStorm), I’m a huge fan of using Xdebug for step debugging my applications. If you’ve worked with me for any length of time, I’ve already evangelized to you about these tools, most likely ad nauseum. For the rest of you, perhaps that’s a tale for another time: the short answer is, Xdebug makes it easy to work with PHP applications and understand data state during runtime, and PhpStorm itself makes it easy to connect to Xdebug.

For newer developers, or developers who use a different IDE, or developers (like me) who sometimes struggle a bit to read the docs, configuration can be a challenge. And sometimes, troubleshooting a configuration even more so.

All that said, there are loads of examples on the web for a basic step debugging configuration for Xdebug. They typically look something like this:



# For configurations that require a different default port

Configuration for Xdebug 3

Almost every line in the above configuration has changed with Xdebug 3. As such, when you upgrade, you’ll also need to update your php.ini file (or xdebug.ini, or wherever it is that you store your PHP module configurations). The equivalent to the previous example is:

# Configuration for Xdebug 3


# For configurations that require a different default port

# Note: Xdebug 3's default port is now 9003 instead of 9000,
# so even if you don't use this setting, you'll still 
# need to update your IDE settings to get it to connect.

Derick Rethans has published a guide to upgrading from Xdebug 2 to 3 that details the many changes between versions. Importantly, it simplifies a lot of the configuration, and some of the options are now grouped into a single value. For instance, if you want to enable step debugging, but you also want to continue seeing stack traces, you can pass in a comma-separated set of values to xdebug.mode:


As usual, there are many different options that I’m not going to cover in this very short post. Importantly, however, there are enormous performance benefits to this new release, and it’s backward-compatible to PHP 7.2. If that meets your needs and you’re already a user of Xdebug, I highly encourage you to upgrade today, and to consider donating to the continued development of the project.

Update: November 30th

I’ve discovered at least one item of interested since publishing this post last Thursday:

Setting xdebug.start_with_request to yes is the equivalent to always having Xdebug running. With Xdebug 3, this will also generate a PHP warning in your logs with every request you make that doesn’t have a client listening on your debug port. This might be less-than-ideal for development scenarios when you only want to trigger Xdebug when you’re actually debugging. In this case, you should set the value to trigger instead.

The trigger setting for xdebug.start_with_request changes the behavior slightly: it requires that you pass a value to your $_GET or $_POST request in the browser to get Xdebug to listen (or to activate a browser extension such as Xdebug Helper for Firefox) in addition to triggering debugging in your client, such as PhpStorm.

On the WordPress development side, I’m still tinkering with Xdebug 3 to understand how to correctly trigger the debugger from the CLI. The upgrade guide documentation seems clear about what needs to happen (e.g., setting an environment variable before running a PHP script), but it doesn’t seem to be triggering for me. I’ll possibly update this post again and or create a new post with additional findings once I get that sorted.

In the short-term, setting xdebug.start_with_request to yes does in fact make it easy to trigger breakpoints easily in either the browser or the CLI, but until I find a way to disable the warnings to my PHP error logs, it’s not my preferred approach.

Series: Rethinking PHP Development in WordPress

My web development career began in earnest in January 2013 when I took on an internship at a small agency in the Twin Cities during the last semester of my degree program at my local community college. There, I was first introduced to WordPress, Shopify, and CakePHP, the framework that the owner of the company used to create a custom CMS that many of his clients used.

Because I was brand new to development and the agency world, the ins-and-outs of a custom application framework didn’t really resonate with me right away. And, since I was the only employee, my boss didn’t really have time to teach me how to support it. Instead, I took on many of the theme build projects that came through the door where we chose WordPress as the platform. It was at that agency job where I first familiarized myself with everything WordPress had to offer, from hooks and taxonomies and custom post types to the theme and plugin APIs, and everything in between.

The current version of WordPress in January 2013 was version 3.5. Just two-and-a-half years prior, version 3 was released with an updated dashboard, improved custom post types and taxonomies, custom menu management, multisite(!), and more. I wasn’t in anywhere near the beginning, but by the time version 3.5 was released, it was slowly becoming evident of just how much I could achieve as a developer atop this platform.

Change is Slow to Come

Naturally, as with all things tech, a lot has changed in the subsequent years. Useful parts of the WordPress ecosystem like WP-CLI, the REST API, the Customizer, and the Gutenberg editor didn’t exist when I started. Many of these features had been hugely controversial at the time they were released; some, perhaps, haven’t lived up to their promise. But, over time, we generally come to accept the quirks that are there and make our best effort to improve upon the parts we don’t like.

The features of WordPress that have thrived have been a result of passionate developers contributing their time and effort to propose new ideas, advocate for their necessity, and work through a somewhat bureaucratic process that requires lots of coding, discussion, testing, documentation, and – with a little luck – ultimate approval and inclusion in core.

This is the double-edged sword that comes with contributing to a legacy platform that powers such a significant part of the web. “Democratize publishing” has long been the mission of the WordPress project, and what that means is having a platform that’s not only easy to set up and start using quickly, but it also means having one that is intuitive to extend and modify as one sees fit, regardless of their skill set. It’s the latter part that causes some friction within the development community, because there are those (like me) who wish to be able to include the latest and greatest language features into their projects, but when contributing to parts of the platform that can affect a lot of people, we have to be mindful about how much we push the envelope.

Then Along Came Gutenberg

In many ways, the Gutenberg editor project has turned the WordPress mission on its head. This is due to a number of reasons, not least of which I think are enthusiasm around advancements in the JavaScript community in the past 7 years, and with the rise of burgeoning competitors like Squarespace, Medium, and Wix, which were providing more intuitive interfaces with which to build websites than WordPress had been offering in recent years.

In my view, the changes on the JavaScript side of the WordPress sphere have been a great advancement, though they come at a cost. Developers who aren’t as familiar with JavaScript may find it more difficult to build on top of the platform. And, as my friend Michelle Schulp astutely put it, compiled JavaScript makes it more difficult to discover readable code, something many new and aspiring developers use to learn and grow.

As a community, I think we can do better. And, as an engineer, I think we can and should take the learnings from advancements on the JavaScript side and apply them to PHP. What that means to me is that we should be more willing to revisit how PHP code is structured in the WordPress environment, but that we should do so in a way to help educate and elevate developers to learn how to write cleaner, more organized, and more reusable code.

Doing My Part

Since those early days of cutting my teeth at my first agency job, I’ve tried to stay current with developments in the broader web language communities. Like JavaScript, PHP has advanced a lot in the time since WordPress was first written, but the community hasn’t necessarily been able to take advantage of these advancements due to the intense dedication to backward compatibility. Gutenberg, in many ways, has shown us that we can start to take risks, that we can iterate, try new things, and occasionally make a few mistakes with the goal of coming out with a stronger product in the long term.

I’ve started jotting down notes about the various things I’ve learned and observed from working on personal projects, large agency clients, and most recently in my role on the product team at Rocketgenius. My aim over the next several months is to start writing more about these various topics, with the goal of sharing what I know (or think I know) about software development. Additionally, I hope to get us thinking about how we might apply some of these concepts within the WordPress ecosystem, with the longer-term goal of helping level up other engineers build more robust, scalable, easier-to-understand systems.


As of right now, my list of topics in this series will include the following:

  • Using objects instead of arrays for data structures
  • PHP namespaces
  • Type-hinting method parameters and return values
  • Reducing the number of different return types within methods
  • Reducing conditional code complexity
  • Creating more (and more descriptive) methods in place of clarifying comments
  • The first five principles of S.O.L.I.D., with an emphasis on single-responsibility
  • Class file organizational hierarchies
  • How to spot code smells
  • Abstracting shared and repeated behavior

It’s likely that going through the process of distilling my thoughts in these areas and how they specifically apply to the way things are frequently done in the WordPress ecosystem will lead to even more thoughts worth exploring. I hope you’ll join me on this journey, and that it will spark some additional online discussion. I’m looking forward to it.

WP-CLI for multi-language development

This week at Rocketgenius, I was working on some visual refinements in one of our Gravity Forms add-ons. Because our suite of plugins supports multiple languages, part of my ongoing education is learning all about the tools and processes required to build our products for international support.

I’m just getting back into the swing of things again with full-stack development, and this week was the first time in my career where I’ve styled front-end components with internationalization in mind. It’s been an eye-opener for me just how limiting the web can be without this extra attention to detail, and I’m eager to start looking at my personal projects with fresh eyes, figuring out how I can make them accessible to an even broader audience.

One major aspect of internationalization is to style your user interfaces so that they can be read both left-to-right, such as for Latin-based languages, as well as right-to-left, for languages such as Arabic, Hebrew, Pashto, and so on.

Naturally, WordPress has multi-language support, but if you don’t know other languages (and perhaps don’t have every aspect of the user interface memorized), it can be challenging to find your way to the language switcher, then to the part of the admin you want to test (and then back again!). Thankfully, WP-CLI has some helpful commands that can ease this transition for you. Let’s review them.

Installing Languages

First, you’ll need to make sure whichever language you want to use is installed in your site, plugin, or theme. WP-CLI has a top level command called wp language which, when you run it, will reveal sub-commands for core, plugin, and theme! Running wp language core --help will show you all the commands you can run on core. The --help flag, of course, will show you available subcommands for the other commands, too.

Initially, these commands are going to be most useful:

  • wp language core list shows you the list of available languages, their english name, native name, installation status, the last update date, and whether an update is available.
  • wp language core install <language> will install one of the languages for you, where language is the identifier for a particular language. For instance, if I wanted to install Arabic, I would run wp language core install ar.

I encourage you to give these commands a try, and also explore the rest of the CLI commands available to you to see how you can work with languages you have already installed.

Switching Languages

Once you have a language installed, you can easily switch between them using a different CLI command: wp site switch-language <language>, where language is once again the identifier from the list command I mentioned previously.

Thus, if you installed Arabic in the previous step, you can run wp site switch-language ar, and WP-CLI will set the language of your WordPress site to load in Arabic instead. Simply refresh your browser page!

Styling Components

If your admin screen contains components with your own custom markup, and you haven’t considered right-to-left languages for your styles before, you might be surprised at the appearance of those components on the screen. In particular, directional margins and padding will be waaay off, because your properties were written with a left-to-right presentation in mind.

Thankfully, WordPress knows at the time you’ve activated a right-to-left language that it needs to provide you with the tools you need to style these components according. The html element includes a dir attribute when languages are read from right-to-left. Thus, any adjustments you need to make can be done by nested your element selectors in an html[dir="rtl"] selector.

To avoid needing to write lots of additional overwrite rules for the right-to-left counterparts, I prefer wrapping directional-specific properties in an html:not([dir="rtl"]) property. Here’s an example:

html:not([dir="rtl"]) .sidebar {
    margin-left: 1rem;

html[dir="rtl"] .sidebar {
    margin-right: 1rem;

Were I not to include the the wrapper for the left-to-right rule, I’d need to override the value of margin-left in the right-to-left selector. If you have lots of directional values, that can quickly add up.

Bash Aliases

Once you have a single right-to-left language installed, you can make it even easier to switch between your preferred left-to-right and right-to-left languages. Create a couple of Bash aliases, and reload your terminal!

alias ltr="wp site switch-language en_US"
alias rtl="wp site switch-language ar"

Then, when you need to switch between directional language types, it’s as easy as typing ltr or rtl in the command line. Nice!


Multi-language development opens up a whole realm of possibilities for your website. Paying attention to the UX presentation, in addition to providing text translation (naturally, not covered by this article), makes your content available to a much wider audience. Hopefully this small collection of commands will give you the extra encouragement you need to keep internationalization in mind when you work on your next project.