Building for writers

A designer, a developer, and a product manager walk into a bar to celebrate a launch at their startup. They sit silently for several moments. Finally, the product manager says: “Now that we’ve launched our big idea, what should we do next?”

The designer thinks for a second and says: “We should do a complete redesign using Storybook, so we can organize all our UI components and update them in one place.”

The developer shakes his head. “No. We need to totally refactor our codebase from the ground up, entirely on Rust.” He starts chopping the air with his hands: “I know you guys think I’m crazy, but Rust solves memory errors and concurrent programming problems better than any other language.”

The product manager looks down at his beer, which is already getting warm, and says: “I think we should get everyone a thermos.”

The designer asks: “What’s so special about a thermos?”

The product manager says: “Think about it: a thermos keeps hot things hot and cold things cold.” He stares back at them, wide-eyed. Then he asks, “How do it know?”

Your site should be like a thermos

When you hand someone a thermos, they take a drink. They don’t think about how pretty it is, or even how it works. More important: the guy filling the thermos doesn’t spend a lot of time troubleshooting the damn thing. He just pours cold or warm liquid into it and gets the same result every time.

If you’re reading this, you’re probably a techie, so let’s be honest: when we techies start to talk about the “right way” to build something, the next thing out of our mouths is probably some obfuscation of technology. I’ll be the first to admit it: I’ve argued the value of MVC frameworks (where you keep your styling completely separate from your data) and, in the same breath, found myself misty-eyed at the elegance of React’s component model (where data and style are combined in a single module). These lectures have not marked me as a genius among my colleagues.

The true right way to design something is to create something that your successor can understand in seconds. If you did it right, even a non-technical person should be able to see roughly what’s going on and understand how the code “fits” together.

Design your front end for the whole organization.

So let’s start by designing the piece of your codebase that is going to get the most wear-and-tear. These days, most editors know enough CSS to be dangerous, so they’re going to ask you to tinker with it all the time. The problem is that it’s all tightly interrelated and, if you’re not careful, you’ll end up with a squirrelly mess of really !important styles.

In the past, I’ve put all my CSS in the style.css file in the theme and left my custom css window fairly empty so I can use it to focus on just the code I’m working on at the moment. This approach has its benefits: it’s clean and allows you to keep your styles in version control.

Keeping all your custom CSS in the theme customizer will drastically simplify design tweaks.

More recently, though, I’ve started just dumping it all in the customizer and being brutal about pruning conflicting CSS. This gives me more control over the code in the moment and minimizes switching between versions, which can be a pain in the butt if you have a caching layer. Added bonus of this approach: you can edit the site on the fly right in front of the client, which usually impresses the hell out of people.

Have a system for custom code.

All websites need some small degree of customization, and you can usually guess what you’re going to have to build by taking a quick inventory of the unusual assets of the organization. One of my clients, a podcasting company, had audio and transcripts that it wanted to display on its site. That meant that I needed to build back-end code to capture audio links with every story, play them through an audio player (and allow others to embed them on their websites), subscribe to the podcast feed, and read transcripts. Taken all together, this is a large chunk of code that could very quickly become unweildy.

Enter my new favorite plugin, Code Snippets. With code snippets, I’m able to drop code I would normally put in my functions.php file (or my own custom plugin) into an organized, documented space, like so:

Keeping all your custom code partitioned and documented in Snippets will help future developers understand your entire codebase in seconds.

If you follow a React-like component philosophy and maintain strict independence between each snippet, this plugin will allow you to turn each component on or off, and even specify whether it runs on the front-end, back-end, or both.

A huge benefit of Code Snippets is that it makes it much easier to share components across multiple sites, so long as you don’t use theme-specific action hooks. If you’re not sure what these are, check out Astra’s list of action hooks. As appealing as these are, though, I’ve found that there are mostly cross-theme methods for getting into every nook and cranny of the layout (such as the content filter hook).

There are drawbacks to Code Snippets. My biggest beef is debugging. If you code directly in Code Snippets, a bug in your code simply shuts down the service and reverts your code to the last save. So you’re definitely better-off doing the initial coding in your local environment in fuctions.php and then transferring the finished modules into code snippets once you’ve got them working. Another big drawback is the lack of version control. My work-around is to check all the boxes and select the Bulk Action to export the code. I then save that file in my theme folder on git.

Create editorially accessible microservice integrations.

Of course, not all code is small enough to be a snippet, and there are some very real needs for interdependent code out there. In these cases, I recommend coding these in a real codebase (php is not a real codebase) and importing them through shortcodes so that editors and designers can adjust the layout without risking the underlying code.

I go into much deeper detail in my article on microservices, but the image below will give you the gist of how these integrations appear in the CMS:

Shortcodes allow editors and designers to understand your custom code and manipulate the layout, without messing with the underlying structure.

The left side of the above image shows what the rendered site looks like to the end-user. On the right is what the editor sees, with titles, custom spacers and short codes all easily manipulated and rearranged.

By building flexible parameters into my shortcodes, I’ve even made it possible for a non-technical person to alter the content from the microservice. In the above case, from my site, an editor could simply change “washington-dc” to “boston-ma” to showcase events from other cities on the page.


Although this approach eschews many of the benefits of managing all code in version-control, it also creates a far more accessible code-base that simplifies participation from other developers. If I were no longer able to help one of my clients, another developer would be able to fix issues on the site almost instantly, without even needing to create a local build environment. So long as you are disciplined about periodically exporting and saving the code elsewhere (and I am), you can create a site that is just as secure and performant as the larger site, but with the simplicity that you expect from a thermos.

If, like me, you believe that your most important user is not the fly-by end-user, but the people in your organization that have to live with your shitty code every day, this could be a truly revolutionary approach to your site design philosophy.