Latest News

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.

And What a Week It Was

Boy, what a week.

With everything going on nationally and globally, I suspect I’m not alone when I say it’s been really challenging to stay focused. I would expect that to be the case for the next several weeks as more of us stay home and learn how to adapt to a remote lifestyle. In hindsight, my decision to seek new opportunities couldn’t possibly have come at a worse time, but I am extremely thankful that I was able to move at a slower pace and work on my own personal growth during what was undoubtedly one of the most uncertain weeks in recent U.S. history.

With all of that said, I wanted to take a moment to discuss some of the things I worked on this past week, and document additional areas of focus for this week, as well.

Learning Python

Between keeping up with the news and taking some well-needed time off, most of my attention has been focused on learning Python. During the weekend of March 7th & 8th, I visited my local library, and examined their computer programming collection. Sadly, the amount books they have on hand are few, and most of them are 5+ years old, but one book that I thought would be useful to help solidify the basics was Automate the Boring Stuff With Python by Al Sweigart. Thankfully, I was right! Sweigart’s book covers all of the basic data structures in Python – strings, lists, tuples, dictionaries, and objects, then spends the bulk of the rest of the book showing the reader how to write some basic scripts to accomplish a series of tasks, such as parsing and modifying spreadsheets, scraping web content, scheduling tasks and opening programs, and more. He very clearly indicates that the examples are intentionally not the cleanest, least complex way to structure one’s code to accomplish the task, which works fine for me, because that’s where my past programming experience comes into play.

While reading Sweigart’s book, I started a repository for studying Python, but quickly came to realize that simply copying some of the examples wasn’t going to be sufficient for me. More on that later.

The finest benefit offered by my local library, which I also just learned about that same weekend, is that one’s library card grants them free access to all of the instructional videos on (now LinkedIn Learning)! I highly recommend checking to see if your own library offers this benefit, as it has quickly become my go-to resource for learning Python basics. Thus far, I have completed two tutorials: Python Essential Training by Bill Weinman and Python: Design Patterns by Jungwoo Ryoo. These two courses, along with the aforementioned Sweigart book, and my college textbook, Python Programming: An Introduction to Computer Science, Second Edition by John Zelle, have given me enough foundational knowledge to begin tinkering.

Toward that end, one project I started last week and will continue to explore this week is a custom Slack bot written in Python that will integrate with the BoardGameGeek API. If you’re interested, you can follow along with this project on GitHub.


While I’m aiming to learn as much as possible while I seek out my next gig, it wouldn’t be a proper break if I didn’t take a little time for myself, too. In addition to learning a new language, I also played the role of homemaker, which also served as a nice diversion from the news. I went shopping for supplies. I cleaned the whole house, and checked off some seasonal cleaning tasks of the list. On Friday, I baked a lasagna, which we got to enjoy for the remainder of the weekend. And I dug back into a couple of games on the Switch that I hadn’t played in awhile: Celeste, which is absolutely breath-takingly amazing, and Stardew Valley, which I think I’m finally ready for given the slower pace we’ll all be living at in the coming months.

At the library, I also digitally rented Bob Odenkirk’s book of short stories, A Load of Hooey. My partner and I took a nice walk around Lake Phalen. We invited a friend over to play board games on Saturday, and though it was just the three of us, I realized it should be the last time we have anyone over for a bit.

What’s In Store For This Week?

This week, I’m going to continue familiarizing myself with Python via the aforementioned Slack bot project. I’m also looking to do some work on this website, and am planning on exploring some front-end technologies that have come out in the past few years, particularly CSS grid. Also, because much of the U.S. is starting to work remotely for the first time, and/or they’re already remote and are dealing with our new isolated social contract, I’ll be publishing a Zoom link on my Twitter account at 6pm CDT each weekday in the forseeable future so my friends and acquaintances can have a place to connect and socialize.

It’s a strange time, but I’m making the most of it, and I hope anyone who is reading this is, too.

To New Adventures

Today marks my final day as a Senior Backend Engineer at WebDevStudios.

The motivators for change sometimes come in a rush. More often, as in my case, they drip in slowly, their positive or negative impacts affecting the balance, until one’s cup is full with a bittersweet drink — a meaningful goal accomplished, a lifelong friendship forged, a valued colleague departed, a role ever-evolving.

I have so much to be proud of from my time working at WDS. The last year alone has been particularly full of rewarding opportunities, including:

  • Open-sourcing my first library to promote object-oriented programming in WordPress.
  • Speaking at three different WordCamps.
  • Curating, hosting, and occasionally presenting at internal “Lunch & Learns”, our monthly continuous education program.
  • Giving in-depth code reviews and helping mentor junior engineers.
  • Developing my first set of editor blocks, as part of a completely headless publishing workflow.
  • Being entrusted to build relationships and lead the engineering team for one of our largest clients.

I’m proud of the work my colleagues and I have accomplished in the past three years, and the last year in particular has been one of incredible growth. It’s been so rewarding to see the leaps and bounds we’ve all taken to make ourselves better engineers, better project managers, and better co-workers.

The flip side of all of this, of course, is that as I’ve taken these additional opportunities onto my plate, I’ve in many ways been getting further and further from the thing that’s gotten me here: my love of computer programming. And, in particular, as the WordPress programming landscape continues to evolve — WordPress as the client, custom editor blocks written in React, static sites — I’m left with two distinct feelings. First, and most importantly, that there is a broader world of software development that I’ve been missing out on by staying exclusively within the WordPress ecosphere. And second, that my time spent away from my IDE is also time spent away from my absolute favorite part of my career.

With that realization, I’ve come to the difficult decision that it’s time to try something new, to grow once more, and to potentially submerse myself in completely unfamiliar territory: a new language, a new environment, a new community. I don’t know what this means just yet, by my desire is clear:

  • I want to spend the majority of my day writing software.
  • I want the opportunity to learn more languages.
  • I want to work in a physical office again, at least some of the time.
  • I want to continue to grow in every possible way that I can.

In my last entry, I wrote about intentions. Leaving one’s job without having something else lined up is one of the scariest things one could possibly do, but sometimes it’s absolutely necessary in order to enact positive change for one’s self. I have applications in at a few local companies with roles that sound fun and challenging, and in some cases their development stack is something completely outside of my past experience. That’s not surprising, either, given that my past experience to date has been enterprise WordPress development in an agency setting.

My intention for the coming weeks is to rediscover my love of computer programming; to study, and tinker, and create during the day, and also spend time researching, applying for, and interviewing with companies that align with my values and career aspirations. I’m planning on reflecting a bit more about what I’m looking for and sharing updates about what I’m working on during this transition, so keep your eyes peeled for updates to this space.

It’s an exciting time. It’s a scary one, too. But, I enter this transition feeling optimistic and knowing that I’ll become a better engineer as a result of it. And, above all, I’m thankful for my colleagues and the leadership at WebDevStudios for the opportunities they’ve given me. I’m hopeful that I’ve left things in a better place than when I got there, and that we all prosper in our next adventures. I can’t wait to see what’s next.