I discovered the technique of using functionality plugins several months ago and was reluctant at first. When building a site with WordPress using my own theme, I usually just dump any custom functionality I want into the functions.php file. But the idea with functionality plugins is that you put non-theme-specific code into a plugin instead. This prevents your code from being overridden when changing themes.

Addressing objections

At first, this might seem like a bunch of hassle for little payoff. You might be thinking:

“I don’t know much about making plugins.”

But a functionality plugin is not a big plugin like you would normally think of. It is simply one file (you can optionally put it into a folder) that works just like your functions.php file, only you must put a special header at the top. For instance, this website uses a plugin I made called “Matt Watson Functionality” that is simply one file I placed in my wp-content/plugins folder and named mattwatson-functionality.php. It starts like this:

   * Plugin Name:       Matt Watson Functionality
   * Plugin URI:        https://www.mattwatson.org/
   * Description:       Matt Watson functionality plugin
   * Version:           1.0.0
   * Author:            Matt Watson
   * Author URI:        https://www.mattwatson.org/
   * License:           GPL-2.0+
   * License URI:       http://www.gnu.org/licenses/gpl-2.0.txt
   * Text Domain:       mattwatson-functionality

From there on, I put whatever PHP code I want, just like I would in the regular functions file.

“I’m using my own theme that I’m never going to change, so what’s the point?”

This is certainly a common use case scenario — where a developer is coding their own or a client’s website and is only using WordPress’s theming feature because that’s what you must do in order to use the CMS. This kind of “theme” is not meant to be used by anyone else, is not going to be distributed in anyway, and is not meant to be switched out. In essence, the theme is the website.

While it is true that such a website is not designed in the first place to allow the user to switch themes, there are still other scenarios where having your functionality code separate from the theme is useful. For instance, in 3-5 years when the website frontend design plans get overhauled, you might want to develop the frontend code from scratch again using a new custom theme. Essentially, you are rebuilding the website… but if you’ve used a custom functionality plugin, you have saved yourself some time. You don’t need to migrate non-frontend-related code to the new theme, because your plugins will just carry over.

Using a functionality plugin with other themes

Most chatter I’ve read on using functionality plugins are directed toward developers who are coding their own theme. But what if you’re a lazy developer like me who is just using a standard theme from the WordPress.org repo? It is rather common, in fact, for developers to have ugly personal websites or use other people’s themes, because they just don’t have time to work on it. When you use a third-party theme, though, you pretty much lose the ability to write anything to the functions.php file, because your changes will be deleted on a theme update. This is annoying if all you need to do is add a few lines of code to, say, the head of your pages, or inject a few style rules for whatever reason. This often results in just downloading a plugin from WordPress.org. A lot of these plugins do super basic things and are largely meant for non-developers.

But if you’re a developer and used to touching the code, you can just add a functionality plugin to do basic things instead of using other people’s plugins, which are usually large and designed to do a lot of things you might not even need.

For instance, I decided to use the Twenty Fifteen theme for this site, and I wanted to track my site’s traffic using my self-hosted Matomo installation. While I could have downloaded a plugin from WordPress.org that would inject Matomo’s JavaScript snippet into my page head, I can just do it myself in my own functionality plugin. And hey, while I’m at it, I’ll go ahead and add anything else I need to the wp_head hook, such as my favicon links.


// [... Plugin header]

add_action('wp_head', 'mw_wp_head');
function mw_wp_head() {
	<!-- MW Custom Plugin -->
	<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
	<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
	<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
	<link rel="manifest" href="/site.webmanifest">
	<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5">
	<meta name="msapplication-TileColor" content="#da532c">
	<meta name="theme-color" content="#ffffff">

	<?php if( !is_user_logged_in() ): ?>
		<!-- Matomo -->
		<script type="text/javascript">
		  var _paq = _paq || [];
		  /* tracker methods like "setCustomDimension" should be called before "trackPageView" */
		  (function() {
		    var u="//piwik.mattwatson.org/";
		    _paq.push(['setTrackerUrl', u+'piwik.php']);
		    _paq.push(['setSiteId', '1']);
		    var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
		    g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
		<!-- End Matomo Code -->
	<?php endif; ?>
	<!-- /MW Custom Plugin -->

When you need to push code but can’t FTP

Usually, to update your custom theme’s functions.php file, you would just FTP it (or use a deployment service that does the equivalent). But there might be times where you need to update someone’s website but don’t have access to FTP. For example, the website might have an IP address whitelist, and you’re working remotely today. Or maybe your FTP program is not working for some reason. Not an ideal situation to be in, but it happens.

The more functionality code you have extracted out to plugins, the easier it will be for you to make updates in a pinch. You can just change the plugin and re-upload it in the WordPress admin area. Of course, you could do the same for the theme, but that involves re-uploading all theme files from a zip. Easier just to upload your-plugin-name.php on the plugins screen.

Final thoughts

Going from dumping all your functions in the theme to dumping them in a functionality plugin might not magically make your code that much more organized. You can always be more organized by doing things like applying object-oriented programming with classes to using namespaces, etc., but this is at least a good start with concrete payoffs.

Matt's hand holding a close-up bottle of Spinraza (nusinersen).. Matt's hand holding a close-up bottle of Spinraza (nusinersen)..

It’s been a long time waiting for a lot of red tape to clear up and a surgery to undergo (one year and four months, to be exact), but today my brother and I finally got our first dose of Spinraza (nusinersen), the first drug approved to treat spinal muscular atrophy.

I prayed for this day often as a kid but never seriously thought it would come. It is not a cure, but it is a treatment that has been shown to prevent much of the progression of SMA and to improve strength in many cases. It has mainly been tested on children, and by the chatter I hear, it has been slow going for adults trying to get access to the drug. This is largely because of insurance companies resisting to pay for it, as was our case. After three denials, we got funding through Biogen’s free drug program.

Another reason for the delay in some adults, including us, is that the spinal fusion we received as kids to prevent spinal curvature blocks all entrances for lumbar punctures, the method through which Spinraza is administered. Various strategies have been used to circumvent the spinal fusion and deliver the medicine. I can only comment intelligently about the strategy my doctor and surgeon used, and I’m led to believe Blake and I are the only ones who have had Spinraza delivered this way. So I offer an explanation here for the curious, as well as adults with SMA out there who also have a fully fused spine.

Delivery method

Matt holding a bottle of Spinraza.

About a month ago, a surgeon drilled a hole in our lower fused spine to make an entryway. But instead of injecting the drug there, he placed an Ommaya reservoir, which usually goes in one’s head, on our lower rib cage, right under the skin. A catheter, usually used to go from the reservoir into the brain, wraps, instead, around to the lower portion of our spine, where it enters and goes all the way up the spine until it reaches the top, close to the neck (thorax?, thoracic cavity?… something like that). This is supposed to make the treatment even more effective than if injected into the lower part of the spine, as happens with a regular lumbar puncture. The primary benefit, however, of the Ommaya reservoir is that is makes getting the multiple doses of Spinraza a simple, in-office procedure. No need to do a lumbar puncture for every dose. The doctor simply sticks the Ommaya reservoir on the rib cage with a butterfly needle, withdraws 5mL of spinal fluid, replaces it with 5mL of Spinraza, and puts back a couple of mL of your own spinal fluid in order to push all the medicine in the catheter out into the spine. Gotta be sure and get all of it!

There are four loading doses in the first two months, and then a maintenance dose every four months thereafter. So having the Ommaya reservoir right there under the skin is extremely convenient. I will say, though, that the surgery to initially place the reservoir and catheter wasn’t as easy as it was supposed to be, but with SMA, we expected there might be difficulties.

It’s been almost 12 hours since my first dose. Not feeling any different yet, but hopefully it won’t be long :-). I’ll be writing an update on this in a few months, I imagine.

Note: I wrote this several months ago but am just now posting, fwiw.

Cover Leaf

In this riveting biography of Dennis Rodman, Wolf Blitzer details the quest of the NBA star of ‘90s fame to save the future, a future where all Americans speak Korean and worship the God of Olympia (Rodman himself), second only to the Eternal Leader, Kim Jong-un.

Based on 90 hours of face-to-face interviews of the future Dennis Rodman (who has now come back to the present and married the only person worthy of himself — the current Dennis Rodman), Blitzer chronicles Rodmans’ journey, which begins on a crisp Saturday in October. A black van screeches to a halt not three feet away from Rodman, on an allegedly empty street in LA. When the van’s sliding door opens, Rodman is pleasantly surprised to see his second-best-only-to-Kim North Korean friend, an old-guard lieutenant of the DPRK and esteemed Korean intellectual, Richard.

When Richard debriefs Rodman on Kim’s plan to cryonize Korea’s Black Hope, a riveting tale of friendship and betrayal spirals out of control… eventually, when Rodman is decryonized 500 years later.

Nominated for the 2018 Nobel Prize in Literature, Dennis Rodman: A Biography will keep you on the edge of your seat and awestruck by how one Chicago Bull from Trenton will have saved the world in the would-otherwise-be-coming Kimpocalypse.


Five stars

Blitzer’s masterful retelling of the not-so-distant almost future is bound to make readers stop to think about how far we’ve come in what some commentators have called a post-political world.

Although President Donald Trump is not mentioned on the cover leaf, his multiple colossal failures play a prominent role in the would-be coming global nuclear destabilization. We have already seen dozens of escalating speeches by Trump in regard to North Korea. Perhaps it should not surprise us that the Mentally Deranged U.S. Dotard, as Trump would have officially been referred to in the future North Korean world order, would have launched a nuclear bomb at North Korea in a fit of rage after Arnold Schwarzenegger’s The Apprentice finally would have surpassed its old ratings under Trump.

But this biography is not about Trump or Schwarzenegger or Kim Jong-un. It is about one man and his will to save the future of Planet Earth as we know it. It will cause the sports world to reimagine Rodman’s career in light of the darkest historical timeline, which he singularly prevented through a mixture of basketball skills and worldwide fame.

This biography starts where it matters. Not in Trenton where Rodman was born nor during his back-to-back winning seasons for the Chicago Bulls — but rather in the year 2019, the year Rodman is frozen alive inside the Glorious Sanitarium of the Eternal Revolution.

The friendship between Rodman and Jong-un is notoriously well known, but Rodman’s biography puts to rest any speculation on the extent of the two world leaders’ friendship. In one of the most emotionally intense chapters of the book, a scene of love and rage is on full display as we are taken to Rodman and Jong-un’s reunion of 2019. Without giving away too many spoilers, Rodman did not want to be cryonized but eventually obeyed the Eternal Leader, all while scheming the dictator’s eventual fall.

We are taken into the future and back again, through picturesque Korean jungles in search of a mad scientist’s 5000-year-old time machine invention, to high-octane chases atop self-driving Uber cars. (Yes, Uber still would have existed in the darkest timeline.)

Dennis Rodman: A Biography is the most important book of our time. You will be held captive from page 1 to 843 by a narrative that’s not only wildly entertaining, but also sure to reshape our sociological wisdom for years to come.

One of the first things I had to do as a newly minted web developer was make elements on the page reactive beyond what I could do with my months of study of JavaScript and jQuery. I was introduced to Knockout and Vue at around that time, and I’ve tinkered a little with React.

Vue has been by far easier for me than React, mainly because the setup for Vue is much like other JS libraries (Slick, for instance) that I’m used to including on a project. That is, you download a file or folder and include it in a script tag on your web page, before your main script. Vue even looks a little bit like Slick with how it requires calling a function that just takes an object with properties to define your configuration. No ES6 classes, no npm or Webpack build processes to figure out, if you don’t want to mess with all that. Vue also can be easily used with the HTML you already have; no need to learn JSX.

The part about not having to compile code is the part I really like. I have been working on an app idea recently that requires a lot of compiling, and I’m just kind of sick and tired of it. Whenever I can, I try to go back to the good old days of my first web design training, when I could just write some files and be done, like magic.

For this reason, for the past week and a half, I’ve wondered away from my side project to do a funner side side project. That’s what reactive libraries were made for anyway, right?

The side side project is titled simply “Matt Watson’s Games,” and my idea was to push Vue components with string templates as far as I could without resorting to an npm build situation. I decided to give up .vue component files or any kind of URL routing or store state management, apart from whatever I might be able to write without using an npm package. (Not even any scss, so the new CSS variables ended up being super handy.) There’s just something I like about being able to code static files with plain old css, js and html, upload those few files to a server, and call it a day.

There is a live version running at mattwatson.org/games, and the repo is here. I’m in the middle of coding Mancala right now. All the games are purely frontend and meant to be played by two people on the same device. Data-persisting multiplayer games are completely another kind of project I won’t be doing any time soon, although I did just get a copy of the 447-page book HTML5 Games: Novice to Ninja by Earle Castledine. We’ll see…

I plan to come back to this project occasionally and keep adding games… until I don’t anymore. For every game, I make a new file containing the necessary Vue string template components. Not a very pretty system, but not bad considering there is no build system. And it’s a lot of fun to work on.

I haven’t been updating this blog much for the last two years, partly because it’s a blog and that’s what you do with blogs, and partly because I’ve spent the last two years doing a lot of things and making a lot of changes to my life, personal and professional.

As many of you know, I’m getting married in July to the love of my life, Dr. (!) Anna Wan.

Engagement photo.

We’ve been dating for I suppose long enough now and will be living our life together in the Hub City, of which, if you’ve landed on this web page from some random Google search, you might think to be New York or New Orleans or New England or some other very non-new city. In fact, the Hub City is right here in our neck of the woods — Hattiesburg, Mississippi!

Another big change has been in my career. In the summer of 2016, I was getting along with pursuing a PhD degree in Spanish literature in the great state of Alabama… where there are lots of BBQ…

Dreamland in Tuscaloosa
Dreamland in Tuscaloosa

While I learned a lot there and became a better Spanish teacher and reader, I decided to leave the program early and pursue a job I was offered at Mad Genius in Ridgeland, Miss., as a web developer. It was something quite new for me, but I have fallen in love with coding and am thrilled to have been given this opportunity. My brother also works there and has been teaching me his Jedi ways.

So, from here on out I’ll be posting more informal chatter than I have before (trying to get away from Facebook as much as possible anyway). The switch to coding/programming has been a two-year transition, and there have been a lot of tidbits I’ve been thinking would be fun to blog about. I’m sure I won’t update as often as I want to in this moment, as I sit here writing at 11:10pm on a Thursday, all psyched up about blogzz. But hopefully, I can keep it in a consistently barely revived state. I’ll try tagging or categorizing my boring coding posts so that you’re forewarned if that’s not your thing.