Latest News

What a Year This Month Has Been

…and what a life this year has been.

My last update was posted on the day that George Floyd’s life was taken by four officers of the Minneapolis Police Department. The week that followed his murder was filled with justifiable anger and protest, and subsequent retributional attacks on the minority-owned businesses all through our communities. Neighborhoods came together to help with clean-up efforts, and though the news coverage has dissipated once the violence has lessened, protesters continue to call for change every day here in the Twin Cities and nationwide.

I cringe looking back on that update, knowing how trivial it all is. I, too, cringe thinking about writing right now, knowing that I’m not yet doing enough myself to contribute back to the broader efforts to enact change in this country.

Change runs through all of us.

Before I switched to a career in software development, I’d worked for 3 1/2 years as a project coordinator at a small healthcare research company in St. Paul. My boss, Cori, was an epidemiologist by training, and her particular focus was on influenza vaccination and why nurses choose not to get them. My first week on that job started just as H1N1 was beginning to surface in Mexico, and I quickly went from knowing next to nothing about epidemiology to sitting on weekly media calls with the Centers for Disease Control (led by Anne Schuchat, even then!), listening to them answer questions and allay fears about the virus and giving practical advice for what we can all do to keep it from spreading.

Naturally, with the Coronavirus rampant in the U.S., I think about that job and all the time, and how those few short years directly affected the trajectory of my own life. Between learning about pandemic preparedness, regularly getting my flu shot (even before I worked there!), and subsequently switching to remote work for the last 4 1/2 years, I’d never felt more “ready” to tackle a situation like we’re all in right now.

I’m not ready, though. As I write this, the U.S. has reached 126,000 deaths caused by COVID-19, with millions more infected. We know next-to-nothing about this disease, and particularly its long-term effects, and so I’m surprised to see how cavalier some of us are about mask usage, calling for businesses to re-open and demanding haircuts as if somehow staying home longer would kill us, when the reality is that the reverse is true.

We don’t talk about fear much, and it’s perceived as an unbecoming quality to have. But I argue that it’s healthy to talk about, and that understanding the things we fear make us better equipped to tackle them. I’m already a homebody, and I fear contracting an illness with unknown long-term effects. I wear masks in public knowing that it does a far better job of protecting others from me than it does protecting me from them, and so I’m thankful to my neighbors who put in the effort, because it shows me they care, and that they’re scared, too. Our collective fear, in a way, is a strength, because it will help keep us safe in this particular instance.

This is a fairly long-winded way of saying that I’m thankful to the people who are out there protesting and continuing to fight for justice that is long overdue in this country. My partner and I attended a clean-up effort on Lake St. in Minneapolis, and it was heartening to see so many people who care about our neighbors in these cities. However, my anxiety ran high being out in public for the first time in months, so potentially exposed to my own undoing.

The week before our world change completely again for the umpteenth time this year, my first paycheck cleared from my new job, and I received my second one as well. It’s a popular saying in open-source that there are many ways to contribute – through time, effort, documentation, etc. At the end of the day, if you don’t want to or are unable to contribute in those ways, the last thing you can do is donate money. I want to play a part in affecting change in this country, and I also recognize that I am scared for my health. So, I opted to donate. It literally is the least someone can do, and I hope that if you’re reading this, and you feel like you want to help out, but you’re scared too, I hope you’ll consider researching BIPOC businesses and movements and making a financial contribution. In the meantime, I want to give you a head-start.

These are the organizations I donated to in May and June:

There are tons more organizations and people that you can give to. Donating (and volunteering, and shopping, etc.) is personal, and that’s why it’s important to do your own research. Here are a few more links that could be potentially helpful for you as you consider ways in which you can contribute to these efforts:

  • PB Resources – resources for activism, learning, and donation.
  • Amplify Black – an online directory of Black-owned businesses and organizations.
  • Black Lives Matter – information about petitions, current protests, resources, and places to donate.

If you choose to donate, recurring donations are always more helpful to organizations than one-time payments. It gives them a sense of their continuing monthly income, and allows for better long-term forecasting and planning.

Unfortunately, all of my donations in the last month-plus have been one-time, as I wasn’t sure yet what my own ongoing income situation would look like. In my last update, I announced that I’d started a new job; in this one, I’m announcing that I’ve left that job, as I came to understand that it just wasn’t what I was looking for. I’m in the process of applying and interviewing at a few different companies, and once I land somewhere new, I intend to set up several recurring monthly payments to some of the organizations above. I hope you’ll consider doing the same.

We’re all in this together. If you’re reading this, stay safe, wear a mask, fight injustice, and hold me and one another accountable to do the right thing.


You know the Potpourri category of Jeopardy, how it’s mostly a hodge-podge of general knowledge questions? That’s this post, because it’s been over a month since my last update, and I just wanted to give everyone a quick update about what I’ve been up to.


Something that isn’t changing with my new role are the languages in which I use to do my work, the primary one of which is PHP. Readers of this space know that I’ve been digging into learning Python this year, and I’m going to continue to do so within side projects for the foreseeable future. Yesterday, I purchased a Humble Bundle of 14 Python books, one of which is Automate the Boring Stuff Using Python by Al Sweigart, the book I’d borrowed from the library just before the pandemic began. Of the 14, there are 9 that are pertinent to what I want and need to learn, so there’s plenty of study time ahead of me. If you’re interested, the bundle is live for another 7 days, so you can get your study on with me.


I created a Twitch account several years ago, but never really used it all that much. However, during these uncertain times (is anyone else sick of hearing variations of that phrase?), I decided it was a great time to start streaming my daily runs of The Binding of Isaac, which for some reason has become the only video game I play, more-or-less, over the past seven years. If you’re interested in seeing what it’s all about, give me a follow. I’m also considering live-streaming some personal coding projects, but I haven’t convinced myself that I’m ready for that just quite yet. Baby steps.

Of Mice and Men

To help me celebrate my first pay day in two months, I ordered myself a Logitech MX Master 3 wireless mouse. And, can I just say, I wish I had done this a long time ago. When I picked up a Linux desktop a few months back, I wasn’t sure I’d ever been able to get back down to one keyboard and one mouse to use between it and my laptop, but lo and behold, the MX Master 3 lets you sync with up to three devices. As if that wasn’t enough, it’s got some nice features, such as built-in forward/back buttons for browsers, a horizontal scroll wheel, and the ability to get a few hours of life out of a single minute of charge. Not only am I happy to finally go down to a single mouse between devices, but I finally get to ditch the poorly designed Apple Magic Mouse when using my laptop. Never again will I need to take a break when my mouse runs out of juice!


It wouldn’t be a true potpourri post without a miscellaneous list of links. Here’s some other cool stuff:

And… that’s about all that comes to mind right now on this overcast Memorial Day holiday. I can’t believe it’s almost June.

A Bold Claim Explained

Two days ago, I tweeted:

Vastly oversimplified opinion: all programming languages are the same.

It is, of course, vastly oversimplified, but borne out of the continuous education I’ve dedicated myself these past few weeks, and of conversations I’ve had with recruiters and potential employers alike.

But I Digress…

As I’ve written about in this space, I have been studying Python. Two weeks ago, I created a repository for an app I named py-bgg, and my goal was to use it as a place to commit my experiments with the language, and refamiliarize myself with some general web development concepts such as API development and database schema design, which I wrote a bit about in my last update.

The main foundation of the py-bgg project is built on Flask, a web framework. To get started, I needed to learn a little bit about how Flask’s routing system worked. Since my app was going to connect to BoardGameGeek, that I’d be pulling down information about users and their collections of games, and that I’d like to reference that data locally, I knew I needed to create a database schema as well. I’d need to know how to connect Flask to my data source, and also how to query against it.

This wasn’t much for a small project: a web framework, a database, some custom routes, and then some basic templates using Jinja2. Somewhere along the way, a friend of mine mentioned he liked working with flask-smorest, a Python module that includes SQLAlchemy and Marshmallow, the former an SQL Toolkit and Object Relational Mapper (ORM), and the latter a library for serializing and deserializing object data.

This introduced a few problems for me. First and foremost, I haven’t worked with an ORM before. As soon as I started integrating flask-smorest with my project, I quickly felt a bit over my head. Suddenly, I wasn’t just learning Python and a web framework, but I was also learning about ORMs and how they replace the need to write database queries (a negative for me, in some ways, since part of this project was to reacquaint myself with writing them), and how to incorporate a serialization/deserialization library into all of it.

Thankfully, some peers in my tech community are also teaching themselves Python right now, and one person in particular and I had both come across “The Flask Mega-Tutorial” by Miguel Grinberg. Chapter 4 in the series talked about SQLAlchemy and ORMs. Unfortunately for me, I was working on a custom app with an incomplete understanding of what I was doing, and I needed to understand how to tear apart the work I had done to that point just to get things back up and running again.

I’m here to report that I eventually got there, and about a week ago, I got my app into a basic state that includes some forms with which to interact to connect to the BoardGameGeek API, pull down some user data, and display a user’s list of games at a particular route. It’s neither production-ready nor something I would ship, but it has served its initial purpose, which was to help me gain some familiarity with how things are done.

All Languages Are The Same

Since I created that initial Python app, I started having ideas for other things I can build, and what else I want to learn next.

I started a small project that involves creating a WordPress plugin to publish my content to an external API, with the idea that I might someday convert this very site to a headless implementation.

I revisited the PHP web framework, Laravel, and as I examined its architecture, thought about building basic web forum software so I could gain a better understanding of how it functions.

I started teaching myself Node.

Through all of this, I came to the conclusion that, beyond standards and syntax, there isn’t any meaningful difference between languages — particularly in the context of software development for the web.

Most web applications require routing so that it loads an expected set of data when visitors access a given URL. They need one or more data sources to store and access information. They often require a caching layer so routes can load that data quickly. They might need user authentication and role-restricted access to some data. They need templates to present that information, styles to make things look nice and interactions to make the app delightful to use. And they need well-structured information architecture on both sides of the application so it’s logical for users and developers alike.

The languages that power the services we all use — PHP, Python, Go, Node, Java, .NET, Ruby, and so on — each contain modules as part of their standard libraries to achieve common tasks. Every language is going to have a way for importing libraries, for scanning filesystems, for connecting to data sources, and for reading and writing to files. The basics of computer science — expressions, conditional statements, data structures, design patterns, algorithms, and so on — are all transportable between languages, leaving you only the syntax and the standards left to discover on your own. On the web, an app is an app is an app, and at some point, it’s all a matter of defining the right tool for the job.

I’ve been having a lot of fun learning Python in particular. This week, I’m giving Node.js the long-overdue attention it deserves. Next week, I might give Go a try. While the syntax will change, the needs of a given project won’t truly fluctuate much.

Next up, figuring out how I can convey that in interviews so I can land my dream job, even if it happens to require a language I don’t yet know.

Finding Focus Through Personal Projects

It can be challenging for me to stay focused during this time for a myriad of reasons. Not just due to the news of the day and the current situation we’re all in, but because I have so many projects that are either fun or necessary (or both?) to work on. I’m continuing to seek out my next role, and it’s been difficult to know where to focus my learning because I don’t necessarily 100% know what my dream job looks like or even who’s hiring in this economic landscape. I’m also immensely curious, and there is just so much about computer programming that I don’t yet know, and I want to gain at least a basic understanding of as much of it as possible.

Currently, I am dedicating time to the following projects:

These projects are all in varying states and are providing me with different levels of excitement.

Board Game Collector, for instance, is something I’ve worked on here and there for the last few years, usually as a reason to tinker with some other tools or concepts. It’s been a playground for developing OOPS-WP, to try out alternatives to Webpack, to bolster my skills with package management, to gain more experience working with APIs, to better understand how to collaborate on open source projects, and more. This has all come at the expense of getting it done, however, and there’s no better time to ship something than right now, which is why I created the first beta release and set up milestones for version 0.2.0.

My personal site project was the catalyst for last week’s blog post about using the Composer config command to add additional repositories to your project. Working on the infrastructure for the site has been enjoyable, and while I’m eager to get a refreshed theme (and content) out into the world, I’m also less enthusiastic about it simply because it’s necessary due to my job search. WordPress is a known entity to me, so doing a personal project because I have to, at this particular time, is less nourishing for my soul than exploring new languages and skills.

That said, this week has felt like a bit of a breakthrough. On Monday, I decided that I wanted to focus my attention once again on learning Python, but through the lens of developing a custom web app. Working once again with my favorite API, I would start working on a site from the ground up, which, in addition to learning and using Python, would also grant me the following benefits:

  • Re-learning the many basics of database management: creating schemas, writing custom queries, optimizing results
  • Exploring how to develop an API
  • Working with a new-to-me templating language (Jinja2)
  • Learning how to build and structure an app within a web application framework

In two days, my app is to the point where I can stand it up and seed it with some data from BoardGameGeek. I can transform BGG’s XML data into JSON, and render a user’s game collection on their profile page, and as an API query response. None of these concepts are new to me, but having the time to build something from scratch in a language that is new to me has been a rewarding experience. More importantly, I’m excited about the opportunity to share my codebase with potential employers and showcase my dedication to learning.

Will this app have the most beautiful, well-written HTML, MySQL, and Python ever? Well, maybe. It could! Right now, though, I just care about the fundamentals, about having something productive to do with my days, about learning something new, and about having something I can share with others that will perhaps help inspire them in some small way, too.

Managing Composer Repositories via the Command Line

I’m in the process of a top-to-bottom restructure of this site: everything from the design, to the code architecture, to the content, to the deployment strategies. One major piece of this work has been integrating the Composer-based workflow I’m so familiar with using on the large enterprise client sites that I’ve worked on into my personal toolset.

Composer is an amazing tool for PHP, and if you aren’t using it yet for WordPress development, I highly encourage you to stop reading this post right now and go check it out. I’ve given a talk about it at several different WordCamps in the past two years, and there’s lots of great content on the web about what it does and how to integrated it into your workflow.

What I want to write about today, though, is a very small part of Composer: the config command. Or, more specifically, the config command as it pertains to non-Packagist based repositories, and how you might consider structuring your composer.json file going forward.

Manually Adding Repositories

Let’s imagine for a minute that you started reading this blog post, didn’t know a thing about Composer, and that you went and studied up on it before coming back to this blog post. First, thank you for your dedication! Second, you probably learned the following bits of information:

  • The composer require command, by default, visits to find an instance of repositories that match the name you provided. So, if you ran composer require wp-cli/wp-cli-bundle --dev, you’d get a copy of the full WP-CLI tool and all of its bundled commands, because it has a reference on Packagist.
  • All packages require a valid composer.json file with, at a minimum, a name entry in order to be installable (well, sort of, but I’ll talk about that later).
  • You are required to give your local Composer project more information if you need to install packages which are not referenced on Packagist.

Assuredly, you learned a ton more information than this. But, in terms of installing a package, those are the key details you need to know: if it’s not on Packagist, you need to tell Composer where to find it.


Here’s an example

Let’s say you wanted to install anything that’s in the plugins repository. This is the bare minimum you will need in your composer.json file:

  "repositories": [
      "type": "composer",
      "url": ""

This block of JSON says to Composer, “Hey, the dependencies for my project are located both on and on, which is a Composer-based mirror of the WordPress plugins repository. Once that’s in your composer.json file, you’re free to install any plugin in the WordPress repository by using the custom prefixes that WPackagist uses. For instance, if I wanted to install Jetpack, I’d run the following command:

composer require wpackagist-plugin/jetpack

I’d automatically get the latest version. Note, though, that this example is a little contrived, because Automattic wisely contributes Jetpack to Packagist, so the additional repository is not needed, but not every company or developer does this. You could run composer require automattic/jetpack instead and get the same result.

Another Example

Let’s say you’re like me, and you’re working on a full rebuild of your site. Maybe you’re making a new theme, or a new plugin, or both, and are not yet ready to put your repository on Packagist (or, you’d argue that you don’t need to). You can add the URL to your Git repository right in your composer.json file:

  "repositories": [
      "type": "composer",
      "url": ""
      "type": "git",
      "url": ""

In this case, if I run composer require jmichaelward/board-game-collector:[email protected], I’ll get the latest version of my Board Game Collector plugin’s develop branch. You might start to see why this is useful.

Automatically Adding Repositories

A Small Problem

There’s something that the Composer documentation and online content that I’ve seen which talks about it doesn’t necessarily cover.

First, there’s no requirement which states that a package’s name needs to be the same as its repository. In the previous example, my repository is at jmichaelward/board-game-collector, but my Composer package’s name could just as easily be jmw/bgc. I can’t reliable use the repositories list to cross-reference the packages in my require object.

Second, there’s a Composer command that lets you add repositories. Consider this example:

composer config repositories.0 git

This command automatically updates the repositories array in my composer.json file! No more need to open my composer.json anymore, I can just achieve this update directly from the command line, right?

Well, not exactly. Note this section of the command: repositories.0. That says, “set the 0 index of my array to this value”, where “git” is the type of repository, and “” is the URL. If I already had a zero index, such as the WPackagist repository in the earlier examples, it would get overwritten.

A Solution, and a Proposal

The composer config command will let you create a key-value object instead. Consider this alternative:

composer config repositories.jmichaelward/board-game-collector git

This converts the repositories array in your composer.json to an object, where each key is the name you provided in the command (in this case, jmichaelward/board-game-collector), and the values are the type and URL for that repository.

If we use the command line to add all of our repositories, we wind up with something that looks more like this:

  "repositories": {
    "wpackagist": {
      "type": "composer",
      "url": ""
    "jmichaelward/board-game-collector": {
      "type": "git",
      "url": ""

The benefit here is two-fold: first, we gain access to the repositories we need to install the packages our project requires. But second, and more importantly, we get a direct map between the package names in our require block and the repositories they’re linked to.

This second benefit could not be overstated. By setting your repositories up as a key-value object instead of an array, you help other engineers who want to quickly look at the repositories for your project’s dependencies. They can easily see which packages map to which URLs, then access those URLs directly. It’s a small documentation touch, and something that I’m looking to do more and more of in my future projects.


Composer is an amazing tool for managing PHP project dependencies, but sometimes the documentation isn’t the greatest, or best practices aren’t well-defined. Documentation is one of the most important parts of building any projects, as it can help others who are looking at your code in the future, or it can even help your future self as you question what you did many weeks or months ago.

Composer’s config command provides a lot of flexibility for setting up your composer.json file. I highly recommend giving it a look and learning other ways it can help you streamline your workflow when managing dependencies.