Category: Programming

  • Adding Logic Cleanly

    With the WordPress block editor, you get a reasonably good editor for managing the pieces that make up a typical web page. And that can include things like forms and interactive charts and so on.

    For that reason, PeakZebra uses the block editor as the interface for any clients that want to build or customize their own pages. They are otherwise shielded from the potential confusions of the WordPress back end.

    But while the block editor is good for making a page that looks like part of an application, you have to ask the question: what happens when something is supposed to happen.

    Enter logic

    For “normal” form processing, PeakZebra justs handles putting any updated values from forms on the page into their appropriate database records. For use cases where you’re just tracking data (what’s this client’s mailing address?) that’s surprisingly powerful all by itself. If you use address fields in a form that gathers client information, for example, simply submitting that form ensures that the data winds up stored in the right table.

    But what’s needed beyond that is a (relatively) easy way to make more complex interactions happen. I think what you need is some kind of logic block that’s configurable in the editor–you give it a set of instructions through some kind of GUI–and presumably not visible (though present and ready to do its work) in the front end.

    Alternatively, you could simply make it possible to attach actions or code to each element of a form or other block and tie them to specific actions (onclick, for example), in pretty much the same matter that HTML lets you attach JavaScript to element events.

    The lotsa-pulldowns approach

    While Bubble and other no-code platforms use a sort of “assemble instructions by clicking options” approach to attaching procedures to elements, I’m resistant to this, even with a client base that doesn’t really want to code.

    That’s because it quickly becomes nearly impossible to keep track of what’s going on (or what’s going wrong) because you have to go back through all the options you selected in that visual interface, plus you can’t get any coherent overview of your whole application’s logic flow. (Actually, maybe one or another of the no-code options handles this well–I’d love to get a heads up on that.)

    So it’s tempting just to make it easy to insert plain old code snippets into a logic block that essentially just exists as a container to put that code in. This, of course, means people have to code at least a little in order to take advantage of this.

    One ecosystem divided by two languages

    In the WordPress world, this approach gets more complex right out of the gate because, of course, WordPress uses two separate languages: PHP on the server and JavaScript on the client side. So should the logic block handle one or the other, or both. And does this increase the complexity sufficiently that this just can’t be termed “low code” anymore.

    I’m tempted by the idea of creating a highly-simplified language for describing what should be done, like:

    see if zipcode begins with “19”

    if yes, set timezone to “EST”

    And then this would parse back into _either_ JavaScript or PHP, as appropriate. Sounds so easy, right? What’s a programming language but a huge nested if statement, amirite?

    Let’s be real, or else let’s use AI. It’s magic.

    Sure. However. Given that this is almost certainly way harder than it sounds and would be a constant source of annoyance while the kinks were ironed out, I then begin to wonder whether AI is the answer. It’s the answer for everything else, after all.

    And this actually does seem plausible, given how good copilot style programming assistance AI has gotten. You’d just need to train the AI on the specific codebase, something that Cursor does already, though I haven’t tried it yet to see if it actually “gets” a WordPress code base.

    But I don’t think, for the moment at least, that AI is really the answer. And that’s because experienced developers bring some important horse sense into the game.

    Horse sense to the rescue

    It’s pretty easy to design a system that does something that is error prone and non-scalable from the get-go. If you talk to a developer who really understands the code base and what you might be trying to do with it, they can help you see if you’re really tackling the problem in the right way, with the right approach.

    In other words: maybe you could get the count of the number of tasks associated with a project by counting the tasks associated with that project in the task table, but maybe it’s better to keep a running total that the system updates whenever tasks are added or subtracted from the project.

    You want someone at least looking at this from a perspective that has the whole picture in view.

    For the foreseeable future, this is how PeakZebra handles these things: by request. Your request to do X or Y is handled by a real, human programmer who is familiar with the PeakZebra code base as well as the WordPress platform (from a technical perspective).

  • Best WordPress Blocks Plugins to Push Your Gutenberg Imagination

    Gutenberg arrived on the WordPress scene five years ago by now, but plugins that implement more-than-basic blocks were relatively slow in coming. Still, five years: so you might think everyone would have it all figured out by now. But no. And plugins that implement more-than-basic blocks were relatively slow in coming.

    For one thing, there’s a huge percentage of WordPress users who wish that Gutenberg had never happened. Especially among WordPress professionals who feel this way, they have come to the conclusion that Gutenberg blocks are trying to be something like Elementor or Divi–and that they are failing miserably at it. With Divi, they say, they get pinpoint control over positioning, gradients, and animations.

    With blocks you have nothing but the bluntest of tools for positioning, gradient controls (only recently starting to appear) are confusing and inconsistent, where available at all. And just forget about animations–none to be had. That’s the argument.

    There’s something to be said for their arguments: blocks arrived to the world in fairly rough shape. Eventually, they got to be pretty good at handling blog pages and, once you got used to some of the quirks, you could put together page designs fairly quickly, provided you weren’t trying to do anything that relied on pixel-perfect control.

    Just as we arrived at that point, though, the roll-out of “full-site editing” came along. Now all of a sudden we were asking blocks to carry the weight for lots of things in themes that had previously been handled in PHP templates. Now everything including headers, footers, and sidebars were built with blocks.

    Well, FSE was pretty shakey out of the gate, but it’s made steady progress. And there’s been another development as well: blocks have gotten a lot better, a lot more capable, and a lot more interesting. So let’s talk about the best WordPress blocks plugins.

    Block variety

    There are blocks (and groups of blocks) that I think are presently somewhat ahead of the curve. If you take some time to put them through their paces, you’ll see they show where blocks are headed.

    So here’s my short list of the best block plugins that push you to think more broadly about what blocks can do (including things that are well beyond traditional page builders like Divi).

    Greenshift Animation and Page Builder Blocks

    I’m not a big fan of typical on-page animations, but they are a necessary tool in any web-builder’s toolkit and one thing that block skeptics are always lamenting is the lack of simple animations like fly ins. And it’s true that there are no animations for core blocks or any of the blocks in the more widely adopted block libraries like Kadence (no knock on Kadence, to which we’ll return in a bit).

    With Greenshift, you get a bunch of new blocks over to the left of the editor, some of which give you new capabilities, some of which offer spiffier versions of some of the core blocks (from paragraph on up).

    For any given Greenshift block, you’ll have some animation options. The text block (a much-fancier-than-paragraph option) gives you a number of options including looping through alternatives for a key word or phrase in your text.

    The panel to the right gives you eight animation options for the replaceable section, including a nice one called zoom that sort of superimposes the new word over the old word. Additionally, you have control over the color of the replaceable section separately from the rest of the text–and this includes gradients.

    On the advanced tab, you can also animate the entirety of the block, so that all the text can drop down even as the typewriter animation, to pick another option, types in the first word of the replaceable part. The effect here is way too busy, but the point is that you have a lot of options.

    And the larger point is that the Greenshift group of blocks is a lot more of a Divi replacement than most of the Divi loyalists would care to admit.

    Mindspun Payments

    Mindspun is a startup that clearly gets the value of a block-based approach and they work in an area that makes enormous sense to tackle with blocks: the payment space. I say “payments,” but their blocks do a lot more than that, handling pretty much the whole stack of things you need to sell, in particular, digital products (including licensing and managing downloads).

    If you think about it, a checkout page is a group of elements that break down readily into separate chunks (that is, blocks)–and also a place where the blocks need their individual functionality tied together into an overall package.

    I like what I see enough that you’ll be seeing a Mindspun Payments installation right here on PeakZebra.com before long.

    Block Visibility

    This plugin doesn’t add blocks to your site, so you could argue on a technicality that it’s actually not one of the best WordPress blocks plugins. But all the same, it’s a good plugin for blocks–one that takes advantage of the architecture of blocks to add a “Visibility” panel to every block on your site. So if you only want something visible during, say, business hours, you just set it so that this is the only time this block (whatever it is) is visible. And you can place this setting on a group block to take care of whole section of a page.

    I wanted to mention this plugin not just because it’s handy, but also because it’s an example of a block that behaves different ways in different contexts. I suspect we’ll see more and more of these.

    Content Control

    Here’s another plugin that adds a panel to existing blocks on the site. It gives you the sort of controls you’d want for a membership site, and gives them to you on a fairly fine-grained basis.

    Control panel for the Content Control plugin, one of the best WordPress blocks plugins in terms of doing the unexpected.

    You can use it to drop blocks from a page (visually) on mobile devices, for one thing. But you can also restrict views based on user role, as I’ve done here. Mere subscribers will not see the paragraph block in my example page above.

    It’s the kind of thing that’s perfect for a call to action that you want non-subscribers to see, but that people who’ve already subscribed will just see as a nuisance.

    Custom Blocks Creator — LazyBlocks: Make your own best blocks

    I’ve liked this tool since it first emerged. It gives you an interface to create blocks without having to know the full-blown block creation process. Instead, you can build blocks exclusively using some drag and drop controls and the PHP you already know how to code with. And you can do full-speed, heavyweight blocks with this.

    The cool trick to it is that it hides all the JavaScript and React that would normally be associated with creating a block. Rather than code the controls that appear in the inspector panel, you pick them and configure them to name the things you wind up storing from them. To handle the data that the user adds to the block, you write code in PHP (or present it in template format). It’s pretty darned seamless.

    One point about it that might make a difference in some instances: the PHP rendering magic is accomplished by creating dynamically rendered blocks, as opposed to blocks that are pre-rendered and stored as straight-up HTML. The traditional pre-rendered approach is inherently more performant, but that’s only going to matter in certain kinds of instances (high overall volume to the site, or some kind of process that makes rendering slow but could be handled without dynamic rendering).

    For the most part, though, dynamic rendering just doesn’t inflict much of a performance price–not the sort of thing you particularly notice on a typical site and not the sort of thing that’s going to send your Lighthouse scores into the dumpster.

    Code Block Pro

    I discovered this very recently and I freakin’ love it. It displays your code samples as if you were viewing them with syntax highlighting in VSCode. Indeed, it uses the VSCode engine. It handles just about any programming language you can think of and offers a ridiculous number of VSCode themes for different colorways.

    The point here is that it’s a block that brings an enormous bunch of capability to a specialized kind of display and means that no one else has to do all the heavy lifting to get it done for themselves–exactly what blocks are about.

    Kadence Blocks

    If you’re following the world of blocks, you may well already be familiar with Kadence Blocks, because there’s a fairly large group of block-based site developers who have chosen Kadence as their go-to set of blocks.

    The Kadence package is pretty typical of a class of plugins out there that provide a whole set of blocks that more or less replace (or at least significantly augment) the WordPress core blocks.

    I mention Kadence because it was out there early in providing lots of the fine-detail controls that were missing in core blocks. In the Kadence text block, you can alter settings not just for typeface and font weight, but also things like character spacing. Core blocks are, to some extent, catching up, but progress there has been uneven. And I don’t know whether the core blocks, with their emphasis on keeping things simple, will ever have all the controls for drop shadows and so on that Divi users are accustomed to. But the point is, block groups like Kadence (and others such as Greenshift) will fairly soon have all those bases covered.

    Enter the Zebra

    Blocks can do other, perhaps less expected things. In the context of this article, at least, I think they are the best WordPress blocks plugins for this very reason. And I’ve tried to do my part to push things along: the blocks I’m building with PeakZebra, for example, work with tables in the site’s SQL database, for example. And they handle display using React on the front end, so that it’s possible to have a table that interactively lists a table of people, for instance. Personally, I like the idea of bundling up the blocks and their presentation in extended themes or blueprints.

    On the editor side of things, you can choose which columns to show, how many rows to show in the box, and what should happen when a row is selected.

    Meanwhile, on the front end, the end user can shift the column order, sort by column, page through data without a page refresh, and so on. Like a modern web application, you might say…

    The point is not that it’s got to be PeakZebra supplying you with blocks like these, but rather that these kinds of blocks are on the way. Maybe they’ll be custom to your particular needs or maybe they’ll be utility functions with broad application, but they’ll be doing things above and beyond text on the page.

  • Onboarding

    I’m banging away on what I guess you could call the second sprint of PeakZebra blocks (except that it’s just me, so it’s a pretty thin scrum), but it’s hard to work on applications like CRM (built from blocks) without thinking about onboarding.

    Onboarding is an enormous opportunity for WordPress, just because so many (including the core team) do it poorly or, more often, not at all.

    If you are brand new to it and load a fresh install of WordPress on that hosting account you just signed up for, you’re almost certainly about to be royally confused. There have been a couple of slight improvements in the 6.3 release that just came out, but basically you end up looking at the admin back end, perhaps without even knowing that there is such a thing, and if you find your way to a view of the front end, you’ll be wondering how you accidentally loaded a “blog about philosophy” when you were trying to load a blank WordPress site.

    If you survive this onboarding (designed to weed out the folks with no grit), dealing with new plugins can be rough, too. Most of them just load and then wait around for you to find the configuration page and do something. Some of them are clever enough to go ahead and jump to that page, but you may have very little idea what you’re supposed to do at that point and what effect different settings will have on your site.

    Yes, there’s lots of documentation, but the prevalent experience in the computer and internet world these days includes at least a little in situ onboarding. There are surprisingly few tools for this in the WordPress space.

    Now, I’m as big an offender as any, at least so far. But I want to work on making it easy to get rolling with the fairly large set of blocks I’m putting out into the world.

    And it occurred to me, maybe each of the primary blocks should be capable of creating a popup that can be customized to provide an onboarding experience. There are a few key variables in the PZ block system that are essentially persistent (for a session) global variables, so why not have one that tells the block to do the onboarding thing.

    I haven’t built this into blocks or given it a test to see if it really provides anything useful, but I think I’m going to try to sneak at least a small test of the concept into the current, um, sprint. I’m letting all the scrum members know about it right now.

  • Soft Release Minus One

    My original vision fro PZ Blocks was that they would be relatively low cost and that they would require minimal interaction with PeakZebra once you’d downloaded. You know, if you’re not charging a lot, you simply can’t afford to spend a lot of time tweaking things for individual customers.

    My thought was that you’d get your various blocks and then just drop them into your various pages. Only very minimal configuration would be needed.

    I suppose it’s still possible that this vision will eventually be delivered. While I still think the block system is very approachable, it’s become clearer to me that for each client to build what they really want and need, rather than making do with something straight off the shelf, more back and forth, more interaction, is required.

    The clear upside to this is that you get the applications you need–even if they are quite complex–quite quickly. We’re starting from existing components and templates and we’re intimately familiar with how they work, so as you describe your needs, we can realize them fast. You have a whole family of blocks at your disposal, but you don’t have to figure out all the possibilities and combinations that this menagerie of blocks offers.

    The core goal–getting bespoke applications into your hands at a cost that’s a mere fraction of hiring an agency or your own developer. Plus, the more PeakZebra works with the blocks, the more we see how to make them simple and intuitive to interconnect. We move, by degrees, toward that initial vision of just handing you the set of blocks.

    Meanwhile, the communication channels are open and we want to hear what you’re doing and building. Let’s get together and innovate!

  • Wordcamp Phoenix Slides

    Here are the slides from my presentation at WCPHX, Using Blocks to Build Applications. Note that most of the presentation was a live demo. I’ve included the backup slides I made in case the demo went south– a series of screen shots that captures much of what I showed.

  • GutenTour: JetFormBuilder Block Collection by CrocoBlock

    I’ve headed out on a world tour of Gutenberg blocks. Third-party blocks. There are starting to be quite a few of them out there, sometimes singly, sometimes in groups of layout and design-related blocks. Especially for the groups of them, you’ve typically got to pony up a few bucks to license them.

    But one I ran across—JetformBuilder—is both free (though there’s a pro version for $39 (unlimited sites for $79) per year) and a nice example of how blocks let you go about some kinds of page creation in rather different ways. Experimentation ensued.

    The product is made by Crocoblock, which I only recently learned is a Ukrainian company. They have continued to run the company (even make product updates) from the basements where they are taking shelter. I don’t want to shill the product, but on the other hand I can imagine you could do a lot worse in supporting these Ukrainians directly by purchasing a license or two (and I think you’ll get your money’s worth, too, but Sláva Ukrayíni!).

    Forms with blocks

    The easiest way to explain JetFormBuilder, I think, is to just call it a block-native version of more traditional third-party WordPress forms packages like WPForms. You create a form and then you can embed it in your posts by way of a JetFormBuilder block with a dropdown that lets you select the form you want to appear.

    What’s different is that you create the form within the block editor as well. There’s a custom post type for forms, the difference being that when you publish a form post, it’s just saved. Each field is a block. When you want to embed the form in a page, you use a block to place one of your previously created CPT forms.

    What makes JetFormBuilder especially interesting is that it gives you a bunch of options you don’t generally get with the free versions of other forms packages. For one thing, you can store your form entries on the site (WPForms makes you upgrade if you want more than an email of the filled form). You can add multiple actions on form submission without upgrading.

    You can create multiple-page forms. You can create fields that display calculated values. Indeed, that last bit means that you can create calculator-style tools for site users that aren’t possible in a typical WordPress forms package.

    Let’s base a little calculator project on a block that allows you to hide or display fields on a form based on previously entered values.

    Before we do that, let me just say that I’m not going to use this article to dig into what extras you get if you pay for the license. It’s a fairly long list of things and, if there’s interest, we can dig into that on another occasion.

    Dog years

    All right, project time. I want to create a calculator that allows people to determine their dog’s age in human years.

    As you know, no one can ever quite remember how many years you’re supposed to multiply the dog’s age by. Is it 3 years? Is it 7 years?

    If it were, say, 3 years, then you could have a form field for the dog’s age, then a calculated field that multiplied the age field by 3. That’s trivially easy to do in JetFormBuilder.

    Alas, I think the reason no one can ever remember what to multiply by is that, well, that’s not actually how it works, at least according to the American Kennel Club, which uses this chart:

    Table that shows human-year equivalent for a dog’s age.

    Yeah, so people years are harder to come up with than simply multiplying by a number. We have to take the size of the dog into account. Of course it’s easy enough to ask what that is, but the real problem is that this chart doesn’t move in predictable increments. Giant dogs age slower in human years the first couple of years, then age faster than other dogs. The other three sizes age 15 years in year one, then 9 in year 2, then 4 years for each of the next 3 years.

    If this is unclear, spend a couple minutes with the chart trying to derive a rule for how to convert years to human years–you’ll see what I mean.

    Since the human age varies on a cell-by-cell basis, you need a table-driven way to retrieve and spit out the answer. You can imagine loading an array and then using two form fields to determine the right indexes into the array.

    But there are no arrays in block forms. You can’t do this the easy way.

    Thing is, even if it’s not straightforward, it’s at least possible. Color me impressed. Not one line of code gets written, and you wind up with a calculator that follows some wonky, non-mathematical rules.

    Now you see it

    My approach hinged on the conditional container block that JetFormBuilder includes, the one I mentioned above, which is visible (or not) depending on some other field’s value. I include several such containers, each containing a single field: a radio button selection of the dog’s size.

    Which version of the size selection radio button you see is determined by which age you input. There are a bunch of different ones, but you only see the one corresponding to the age you entered and all the rest of them are hidden.

    For the radio button you do see, there’s a value associated with each of the options. In other words, there’s the label or text you see, like “Giant,” but there’s also a value attribute, and I set the value for each option for a given age at the appropriate number for the size of dog.

    In other words, if you say your dog is two years old, you see the two-year-old version of the radio button field. In that version, the value for the Giant dog selection is set to 22 and the other sizes are set to 24 (these come from the American Kennel Club’s chart).

    Elsewhere in the form, I have a calculated form that simply takes the value associated with the selected radio button. So if you said your dog was 2 years old and then selected Giant, the number 22 is displayed in the calculated field. (In other words, in this case it isn’t really calculating anything, it’s just pulling in a value from another field and leaving it be.)

    Effectively, each different version of the radio button field functions as one row of an array of year equivalents. It’s a little clunky, but when you work with it on the page, it’s shockingly clean because you aren’t aware of any of the multiple versions of the radio buttons that you don’t see.

    I suspect you can do this sort of tomfoolery and come up with all sorts of ways to get real-world worksheets and calculators to work, which I find very intriguing. So, just by way of showing that it does in fact work, here’s a rudimentary version of the form that only handles years 1-4 (I got tired of duplicating the conditional radio-button blocks–indeed, it’s a bit of a kludgy hack as far as making a calculator goes, but it does work and, to be sure, something that was actually calculated rather than looked up in a table would be a fair bit more straightforward).

    [jet_fb_form form_id=”223750″ submit_type=”reload” required_mark=”*” fields_layout=”column” enable_progress=”” fields_label_tag=”div” load_nonce=”render”]

    Progressive

    My initial thought was that the conditional field capability could be used to perform another bit of magic: progressive form fills.

    A progressive form fill is a process whereby you only bother a site user for a piece or two of new information per visit, but you ask different questions each time around and eventually you have a fully filled form.

    The first time a user shows up, for instance, you might ask for nothing more than a first name and email. If you were implementing this from scratch, you’d probably tie the process to a cookie on the user’s system, but in this case let’s assume the return user logs in (or, perhaps, stays logged in because of a cookie).

    Let’s say there’s a private page each user is redirected to as they log in. There’s a form embedded in that page and what the user sees is something like “Welcome back – can we just ask two quick questions?” and then the two next questions.

    I was wrong about Jetformbuilder being able to do this, though, and I mention it because the underlying reason is worth thinking about. Like other form packages, here we have form definitions (which happen to be made out of blocks) and then, as a user submits a form, the data is written to a row in a table of entries.

    This is what you’d expect, but it means that, in the normal course of things, each time the form is filled, it’s a brand-new entry. As a nice extra, it actually is possible to prefill some limited information from the user account (like the user’s name) into a form, just to speed up the form filling process for users. But each entry is still filled de novo.

    This is what you’d expect—I’m not knocking the plugin for being set up this way—but it’s interesting to contrast this to the way that data attributes in blocks are natively handled.

    Let’s say I create a custom block that has an HTML form embedded in it (by way of React createElement calls). When you add that block to a page within the back-end editor, you’ll see a form. If you’ve set up the block to save the attributes you’ve associated with your form fields, then when you update the page, the data in the fields will be stored. Next time you come back, the data will be there. Additionally, you can use this saved data as part of what’s displayed on the public-facing page.

    To take an obvious example, you could create a company address block that the page creator could fill in with an address when they added it to a page. When people viewed the page with the block in it, they’d see the address.

    I’m spelling this all out because I want to point out that, should you happen to use this address block on some other page you’ve created, the address you entered before will not be there. The address data within your custom address block is stored with the instance of the block that’s within the individual post you’ve created.

    Block data, unless you do something to make it work differently, works like custom fields within posts. Each post has different data. Indeed, you can build applications by treating each individual post as a record within a database table. (And of course that’s what the core of a post actually is: a row in a SQL database table.)

    I think that blocks that do things and that store things are going to be where the really interesting developments in WordPress will be found in the next couple of years. JetformBuilder is interesting because it lets you build forms, and you get a lot of value even within the free version. But it’s probably just the tip of the iceberg as we move forward.

  • Theft Revisited: What Gatsby JS Should Steal from WordPress in 2022

    A long, long year ago, it seemed prudent to bring up a few things that worked well in WordPress that were missing in Gatsbyjs. For instance, one-click exchangeable Gatsby js themes.

    Some, but not many, of those holes have been filled in various ways, but others remain (and probably will remain). But time has pushed each of these web frameworks down the road a piece, meaning more developers have had more, different experiences with them. A knock-on effect of this is that it’s now clearer what it would be most useful to beg, steal or borrow from WordPress.

    WordPress vs Jamstack

    To be clear, Gatsby and WordPress are trying to solve somewhat different problems.

    Nor is anyone saying there’s something terribly wrong with Gatsby (or Next.js or Remix Run, the new kid on the block). WordPress is monolithic, the Jamstack crowd is looking for the Great Decoupling, plus static pages, plus edge functions, plus GraphQL queries to anything you might once have tackled with a REST API.

    Jamstack is aimed squarely at developers, not people who just want to drum up a website with their contact information and a few brochure pages. At the same time, a lot of the world’s websites are running on WordPress, frequently on fairly straight-out-of-the-box WordPress. That is, these are not people (and marketing departments) who are going to fall into the arms of Gatsby, even with a Gatsby template for a blogsite. They’re not going to be pushed into those arms, either, not by the need for blazing-fast speeds and not by their desire to move to a “friendlier” cloud CMS.

    As far as speed goes, last year’s “theft” essay got at something of a fundamental truth:

    A framework like Gatsby claims to have the upper hand by using static pages, but of course that’s not quite comparing apples to apples. If a JAMstack site needs to personalize pages on a per user basis, it may do so by way of API calls to a third-party services, but make no mistake, this is still just referencing a database on the back end. In the customized-page scenario, there’s no inherent JAMstack speed advantage. And, frankly, this is a fairly common scenario.

    Another thing happened in the course of the past year: Google rolled out the Core Web Vitals algorithm update that had us all worried about whether our web pages were as blindingly fast as they needed to be to rank. And it turned out not to make all that much difference. The WordPress sites of the world did not drop off the face of Google Search Engine Results Pages (SERPs).

    So if you’re running a website on WordPress and wondering whether you need to high-tail it to Jamstack, the pressure is off, by and large. It’s still nice to have a screamingly fast site, of course, and it’s nice, most folks seem to agree, to work strictly in JavaScript, rather than PHP, as is used for the core of WordPress.

    The Headless WordPress CMS Approach

    The Jamstack response is to argue that the point of decoupling the front end from the back end is that the back end can still run a WordPress stack. In Gatsbyjs, you’ve got the rather sweet option of using WPGraphQL (with a hat tip to Jason Bahl (@jasonbahl) for putting that great WordPress plugin in motion).

    That’s good stuff if you’re a developer, but on the flip side, all sorts of very useful things drop out of play if you abandon the WordPress monolith you’ve been running. And they’re mostly gone even if you keep running WordPress, but use it as a headless CMS.

    For one thing, the WordPress theme you’ve been using on the monolithic site is gone, with the design coming from the front-end side of the house.

    You can deal with this by getting a theme that behaves and looks more like WordPress—have a look at GatsbyWPThemes for a run at that (and I plan to dig in, try it out, and write about it before long, following on a great conversation the other day with Alexandra Spalato, one of the company’s founders.

    In short, you can’t just point your Gatsby front-end at your WordPress theme.

    It might seem like this should be doable because, after all, a theme is basically a bunch of CSS in a style.css file.

    But it’s not nearly so simple. For one thing, there are also template files that determine what the various repeating sorts of pages (blog entry lists, the blog entries themselves, and so on) should look like. These are written in PHP and HTML, using conventions that are very closely tied to WordPress.

    I’ve wondered in the back of my head whether it would be very hard to just write a simple (but would it be?) cross compiler to translate from the PHP files to more Gatsby-native templates. It wouldn’t shock me to see something like this get cooked up before too long.

    Jamstack Admin

    But even if we get to that point, where WordPress themes are convertible to Jamstack scenarios, you still won’t be able to jump into an admin console, look at a list of themes currently downloaded for use on your site, pick a different one, and hey presto, have a new and different look instantly online at your site.

    You can’t do that because, duh, there is no admin console for that Gatsby site of yours.

    If you build your site with a CMS and some other, separate services for identity management, database interactions, and localized customization, you have many things to manage and no centralized console.

    If you’re a relatively low-code user of WordPress, what you’re going to be missing most of all is that you can’t jump into the WordPress plugin section of the console.

    Gatsbyjs Plugins

    Now, Gatsby does have plugins. These plugins have some of the same uses as WordPress plugins, but they are designed to be consumed more or less as libraries that the developer has access to. Next.js has plugins, pretty much along the lines of Gatsby, along with some interesting third-party twists. For example, Grouparoo has a system for adding plugins that grab non-static content to add to pages.

    All that said, I’m not aware of any way on the Jamstack side of things for a third-party to program some simple little bit of functionality—to take a trivial example, giving you the ability to create pop-up footnotes within your text content[footnote]Why look, here’s just such a plugin in action.[/footnote]—that you can download and just start using at runtime and without having to work it into the fabric of your own custom application.

    During the static site generation process, extensions that acted on the source code or the generator would be called.

    Anybody who’s worked in WordPress knows that plugins can be an incredibly powerful way to get a lot done without having to do any real work. Books are always mentioning how many tens of thousands of plugins are out there. The huge number thing is nonsense, because there are all sorts of duds and orphans in the pool. But the decent plugins (and there are certainly a few thousand of these) out there make it possible for you to add nice bits of extra functionality because it’s already coded and it’s available with no fuss.

    WordPress plugins are a different animal, and Jamstack needs to steal this version of the plugin thing wholesale.

    Gatsby JS Extensions

    To keep things straight, I’m going to dub the Jamstack version of plugins “extensions.”

    Extensions should snap into a Jamstack framework along the same lines as their WordPress forebears. In other words, they should register callbacks to their functions with named events in the Jamstack process.

    As the user browses the site, other, runtime extensions would be called.

    So, if we imagine that there’s an event in a Jamstack site where a user logs in, that event might be called “user_login”. In the plugin, we’d include a function called greet_user() that did whatever we’d want to do now that the user was authenticated and we knew who it was. In addition to declaring and defining the function, a separate line of code would “hook” the “user_login” event, along these lines:

    register_action( 'user_login', 'greet_user' );

    Thus the user lands on the site, which because this is Jamstack is a bunch of basically static pages, there’s a login routine that does whatever it does, calling back to some remote service for authentication. When the user successfully logs in, the Jamstack page currently loaded “fires” the “user-login” event and calls back any functions that were registered for this event.

    Since we registered for this event, our greet_user() function will be called, we’ll do whatever we need to do, then the function will return to the overall process of showing pages and interacting with the user.

    Jamstack Architecture: Complicating Issues

    A bunch of things add some measure of complication to this, compared to the WordPress version of it.

    1. No admin interface. We don’t have the admin interface for adding and activating (and deactivating, and configuring) these extensions. For now, let’s pretend that this is no big deal. (It’s probably actually a big deal, because you probably want to build it so that non-developer admins can use and tweak extensions. That’s kind of the whole point of them, at the end of the day. But where does this thing live? Static pages on the client? But most clients aren’t admins…)
    2. Adding events to static pages. WordPress goes through its whole process for each and every page it serves, meaning there’s a centralized point (the code on the server) from which to execute events. It doesn’t matter where the user first lands—every page does this. With Jamstack, on the other hand, the user could request any page, so every page will need to know whether and how to fire events (or report back to some process that fires them).
    3. Generation time and runtime. WordPress is a simple process, dynamically building the page from header to footer, calling things along the way. Jamstack, on the other hand, has generation time in addition to client runtime, which of course is running on the edge in a browser. So there needs to be mechanisms for extensions that allow functions that do their work as pages are being generated (changing the text content of certain kinds of pages, for instance, with these changed pages thereafter being static) and functions that are shipped out to the client side, to be invoked at the appropriate moment, for instance, changing the content of a page as a React component switches in new content.
    4. Common variables and functions. This is probably the least of the issues, but it will enable extensions to do more work if there is a common environment in which extensions run (particularly on the client side). A WordPress developer has a huge list of functions and globally retrievable variables that describe the current state of the platform, who the current user is, what the URL of the current page is, what the URL of the folder that holds the templates is, what day it is, and so on. If all this sort of stuff is predefined, everybody knows what’s going on. Otherwise, everyone gets to reinvent the wheel for each outing.

    Getting back to my example of adding support for pop-up footnotes, the extension version of this would perhaps use a simple character sequence to denote footnotes in normal running content text, maybe something like [fn]comment that makes up the footnote[/fn].

    When the content is being rendered at the client, assuming we’re in a Gatsby-like environment where React is going to load in the content for the component on the fly, the content would be retrieved but, just before it was displayed, an event would fire and a callback would be made to the footnote extension.

    The Callback Process

    In WordPress, the content that goes in the middle of the page is accessible through a function call to, catchily enough, get_the_content(). Let’s assume there’s something similar available to the extension, that the content is scanned for the [fn] marker, and that some spiffy extra stuff is injected.

    Now, when the text is rendered onscreen, it includes a numbered footnote that pops up a note when hovered or clicked.

    Whoever developed this hypothetical site was not involved in making this happen. One of the site’s content developers (with appropriate administrative clearance) decided it would be great to have footnotes, found a footnote extension that had the right look and feel, installed the extension, and then added the markup to the content.

    The Upside of Aggressive Borrowing

    I don’t pretend to have worked out all the answers here, but none of the issues I’ve mentioned seems insurmountable.

    And there could be some real upsides to having a bunch of capabilities ready to plug in and go, just by checking the activate box.

    Menus, for example. WordPress menu configuration is something that could be handled by an interface on the generation side. In WordPress, I can write my own menu code if I want to, but if not, I can configure all sorts of things, beginning with the location on the page where the menu appears (and whether it’s sticky, and so on). All that stuff just happens. Building this as an extension in a Jamstack environment would mean faster deployments and more options for who changes the menus and when.

    Other examples: language localization, widgets that display links to related content, vast functionality additions like WooCommerce (a widely used plugin that provides a full range of ecommerce site capabilities), and so on.

    On the one hand, Jamstack seems to be slowly reabsorbing dynamic capabilities because, whaddya know, those dynamic things were nice to have. On the other hand, the flip toward static first, backend decoupled seems like the best approach now that there’s enough tools to make this more sophisticated architecture readily available. It’s an opportunity to borrow from time-tested approaches such as those that were gradually built into WordPress over the years. We should be able to benefit from the experience and rebuild these things cleaner and faster than ever.

  • The WordPress Developer in 2021

    I suspect that being a WordPress developer isn’t especially fashionable these days. You’re not a rat fink or a fool if you’re a WP developer, but you’re not the it kid. At least not in the developer crowd. WordPress has just been around too long to be the thing.

    That said, developing software in the WordPress ecosystem can be just as interesting as being that on-the-edge dev who codes React components that interact on the fly with distributed network microservices. (In fact, these days you can be that guy coding in React right within WP, though it’s too early to say if that’s a good thing or not).

    Toward the end of this piece, I’m going to provide links to resources that a person would need to have under their belt to enter confidently into WordPress development. How to become a WordPress dev? Learn the things on the far end of the links I’ve put into that list.

    The Age-and-Complexity Factor

    Today’s WordPress is the result of a gazillion revisions, and even the first pass of the code, almost twenty years ago, was a fork of an existing blog-creation utility. Lots of rethinking, lots of code changes. It’s complex as a result. People say it’s easy to use but I’m not really so sure about that.

    You can switch back and forth among thousands of pre-created looks and feels (that is, themes), so it’s powerful in that respect, but it’s also true that this works because the underlying presumption remains that we are dealing with something that is or is very like a blog. We’re just switching the colors around on a page that reliably has a bunch of stock components (the text, the header, the footer, a search bar, etc).

    You can’t pick a random website out there and tell immediately whether it’s running on a WordPress installation. But then again, If you looked at the last thousand new WordPress launches, you’d find a high percentage of sites that had a recognizable “WordPress” look.

    The look is a header with a horizontal menu, a hero image, a title, text paragraphs, and a sidebar down the right rail. Like this:

    What used to be a Drupal site is a WordPress site these days.

    So, big hero image. There’s also a very characteristic WordPress effect that zooms out the photo as the page is loaded. (It’s a CSS effect, really, nothing to do with WordPress from a technical view, but way overused in pre-developed themes and page builders for WP.

    What’s below the image, further down that same page? This:

    It looks pretty good.

    Click on a story link and you get a header, a text section, and, well actually, the text pages on the site are considerably simpler and cleaner than one is used to seeing. So, this:

    Clean.

    Rather than something like this:

    I don’t love the design, but I’d never disrespect the Pergola Garden.

    I should emphasize that I’m not knocking Martha’s basic format (can I be honest, though? I can’t believe Martha’s site isn’t better looking than this). When it’s the right approach, center content and sidebars is the way to go. And you can design horrible versions of this or fantastic ones.

    But while I think a perceived frumpiness may being weighing on WordPress (use of WordPress from increasing every year, notwithstanding), design isn’t really the direct purview of the WP developer, and it’s the developer aspect that I want to turn to.

    The Language Problem

    When the internet decided that browsers should be capable of doing more things than displaying text, the language used for adding some programming to web pages was JavaScript, so PHP found no role in client-side, front-end programming. PHP runs on servers. PHP makes you put a frigging dollar sign in front of all your variable names. (Actually, these days, there are usages where you wind up with dollar signs in JavaScript, too. And what’s wrong with dollar signs, anyway?)

    [et_bloom_inline optin_id=”optin_2″]

    WordPress Developers: Three Different Kinds

    WordPress developers, as opposed to theme designers, fall into what I think of as three categories.

    The first is people writing the code for WordPress itself. Anyone can throw their hat into this ring, because WordPress is an open-source project. But when I talk about WP developers in this article, I’m not really talking about WordPress Core developers.

    The second sort of WordPress developer is someone who knows their way around WordPress, knows how web style sheets work, knows good themes from junk themes, has experience with the most widely used plugins that extend WordPress’s capabilities, and knows how to take all these things and craft a solution. This is someone who probably does some coding, can write a plugin in PHP in order to smooth over a bump in the works, and who can absolutely help you avoid those early mistakes that take a lot of time to correct later.

    There’s a huge ecosystem out there for this sort of WordPress developer, and rightfully so. For all its surface calm and order, the internal workings of WordPress are the result of years of tweaking and extension while trying to maintain backward compatibility. There’s a whole universe of craziness and detail lurking there. People who really understand how the parts fit together and can control things without blowing your site up are people who provide extremely valuable services.

    My heart’s with the third group, though. These are the folks who write more complex plugins. They write shopping cart plugins, newsletter plugins, calendar management plugins, and so on. Historically, they have done their programming in PHP. That’s shifting, but most WP custom coding still happens in PHP.

    I started my coding with the C programming language. As I’ve mentioned elsewhere, many languages out there look a whole hell of a lot like C, or its C++ descendant. PHP, for instance, looks like C, just with annoying dollar signs pasted in front of variable names (and a few dozen other annoying changes that I think were thrown in spitefully). JavaScript is C thrown into browsers, with a bunch of stuff stripped out for simplicity’s sake, then gradually added back in over the years.

    C made it trivially easy to screw up memory management and mistake pointers to variables for the variables themselves. The later languages made it very hard to make these basic mistakes, so I’m not sorry to have moved on from C. But my point is that PHP is like C which is like JavaScript.

    JavaScript is on trend

    Now, JavaScript is undeniably trendy. It would have to be, because it’s what’s built into all the browsers in the world. People who didn’t want to code in PHP on the server anymore made a server-side setup for JavaScript, in the form of Node.js. And it’s pretty sweet, I’m not gonna lie.

    Yeah, JavaScript is sweet. On the client side, all sorts of wildly capable libraries and frameworks have been created, of which the one that really grabs me is React. It grabs everybody who dips a toe into it. I’m restraining myself from taking a big detour to talk about why React is cool.

    You know how you can tell JavaScript is absolutely the height of fashion just now? Because people using it are ready to look past all sorts of “extra step” things you have to put into the mix to really play ball with JavaScript. I’m talking about Babel, Webpack, and the way you can’t code for the front end without running Node.js (a backend piece) and its toolset. Oh, probably include React in that list, though React brings more benefit than extra learning curve.

    React

    I’m not the only person out there who thinks that React is the cat’s meow. WordPress used it to build their new Gutenberg editor system as well, and multiple facets of the future of WordPress are written in React.js.

    Yeah, yeah, the server-side core is still written in PHP, but the move to JavaScript within the fortress walls was the death knell for PHP. Even WordPress has given up on it (sort of).

    And you can take a step back and just maybe worry that WordPress itself looks less than brand new and exciting. I mean, you know that company Culture Trip? OK, it’s entirely possible that you don’t because I at least am not aware of them being a household word. But they did get funded to the tune of $80 million (on top of a $20 million Series A round).

    In a Medium blog post about changing tech stacks, note the implicit world-weary sigh in the first sentence:

    Culture Trip’s website used to be a WordPress site. Now it’s a flexible, universal (isomorphic) JavaScript App powered by Next.jsReactMobX and Styled-Components on the front-end that uses WordPress as a semi-headless CMS.

    I mean, holy freaking cow! You want to waste your life in WordPress after you’ve read about what Culture Trip did?  I mean, 2019 was probably not a great year to invest in a travel-related web business, what with the pandemic arriving and all, but this puppy is universal (isomorphic). You heard anyone describing their WordPress site that way lately?

    Yes, do note that they are still running WP on the back end for this ass-kicking site of theirs. This time around, we’ll skip getting sidestepped on WP as a headless CMS, but it’s a huge, interesting topic.

    But here’s my point (and yes, I do have one, though it’s taken me long enough to get to it): WordPress is a fascinating development environment, PHP is basically the same as JavaScript, so who cares if we’re writing PHP, and a tremendous amount of junk that you’d have to go off and find a library for if you were coding in JavaScript are already turned up and running in WordPress, so you only write the code that does something new and different.

    If you wind up as a WP developer it will not have the adverse effect of stunting your growth, either as a developer or as a human being.

    Coding within the WordPress universe can be pretty interesting. There’s a whole world in there, largely driven by callbacks to functions you’ve written (though, in fact, pretty much everything in WordPress itself is implemented as callback functions, so it’s not just you.

    Each time a page is served up by WordPress, there’s a sequence of events that has roughly the complexity of whatever list NASA put together to launch a Saturn V rocket. At each point in the sequence, WordPress checks to see if a some process has registered a callback function for that point, then calls each function in turn (based on a priority ranking that you can manipulate to increase or lower the priority of your own functions).

    You kind of have to stub your toes as you learn the quirks of this process, but it’s incredible how much nuanced control this enables you to have when creating a plugin.

    To take an important instance of this up for a moment, there’s an action (those points in the sequence I mentioned above are referred to as actions and filters—they are slightly different from each other, but they each call back to a registered function that “hooks” the action or filter) that gives you a chance to create new post types.

    Custom Post Types

    Content posts are the primary elements of WordPress as a content management system. WordPress began life with the assumption that it was going to store blog entries, and that each blog entry would be several things (the title, the publication date, the text itself, and so on) stored together. But lots of other things (non-blogpost pages, to take the next post type that WordPress added, but also stored media, site navigation menus, and any behind-the-scenes prior revisions of posts) can be stored as “several things stored together.”

    What makes WordPress more of an application framework than you might think is that you, as developer, can decide that you want other sorts of things to be stored this way, and thus you can create new Custom Post Types (CPTs). You might decide that your web site will have “sections” that you can treat as grouped into multisection publications, along the lines of an ebook.

    In this example, “sections” will be more or less the same thing as regular old blog posts, but they’ll be grouped differently, can be sorted in some other way than the reverse chronological order that blogs generally use, and can have different layout and styling.

    Or if you built a site for selling event tickets, you might have a CPT with entries for each event (event description, date, time, venue, and so on).

    Layout and styling are in the “theme” category rather than the “plugin” category, but when you’re creating applications that organize themselves by using CPTs, the look and behavior of pages within this CPT becomes an important part of overall development. And, indeed, the template for a given type of page is, in fact, a PHP file. It’s a template, yes, with baseline text and HTML tags and so on, but in some situations a great deal of actual code winds up in those template files.

    If you’re a hip cat and you’re working with Gatsby, you are doing largely the same thing when creating React components that will render portions of the various pages on your site. If you like doing it in Gatsby and React, there’s really no reason not to think you won’t like doing the same basic stuff in PHP files inside WordPress.

    It’s real development, rewards your increasing understanding of WordPress internals in that ‘instant-gratification’ reward system that is such an addictive part of learning new things in programming, and lets you build surprisingly complex applications all by yourself, because you’re able to operate at a high level of abstraction in a system that has a huge range of capabilities.

    A huge amount of the world’s online business is for small things and mid-sized audiences. People using highly tailored applications—things that run low-volume ecommerce sites or that manage architect offices or manage bids for roofing contractors—get more than enough performance from WordPress.

    If you’ve got content that needs to slaughter PageSpeed scores, sure, maybe you need a statically generated site (like something done in Gatsby, as per the above). But in point of fact it’s entirely possible to generate static pages from plugins within WordPress (if you’re curious, here’s more about how I do this).

    You can also get better performance from nothing fancier than a well-tuned cache for your static pages and elements.

    Given the modest traffic and transaction rates that most custom-programmed WP sites get and the ability to make static versions of posts and pages, WP is mature, sure, but also still pretty limber. It’s still the popular choice for most business websites and, it’s going to be dominant for years.

    There’s work to do, the programming tasks can be subtle, demanding, and rewarding.

    What to Learn

    As long as we’re here, we should talk about the skill set. It’s straightforward, but not necessarily easy to get everything into your head that you’ll need to be a successful developer in this environment.

    A stack of boxes showing elements needed for WordPress developers: HTML and CSS, WordPress, PHP, and JavaScript.

    First, you need to know your way around setting up and running a WordPress site. I think the best way to get started is to get a cheap web hosting account at a place that offers users the Cpanel interface for loading software on their account. Get into Cpanel and install WP. Figure out how to make a site that looks like Martha’s. Then figure out how to make one that looks even better.

    You want to know how to create new posts, how to create “pages” that aren’t posts and how to manage access to these pages using menus. How to install and swap out WP themes. Then find some basic tweaks that you can handle with one of the tens of thousands of existing plugins out there.

    Everything about everything in WP is described, sometimes quite cryptically, in the WP Codex. For elucidation in bite-sized pieces, there are sites like WPBeginner.com. There’s a good video tutorial from FreeCodeCamp.

    Beyond baseline WP admin mechanics, you should know a reasonable amount about HTML and CSS. There’s really no way to work on the web without understanding these two fundamental pieces. HTML is no big deal (though make sure you’re clear on what the DOM is within a browser, along with the subtle ways in which it represents but isn’t the same thing as the HTML for a page). CSS can be a complex beast, alas. People tend to give it short shrift and then they live in fear of it for the rest of their coding careers.

    A good resource for both HTML and CSS is W3Schools.com. PHP and JavaScript, too.

    I haven’t taken it myself, but Josh W. Comeau is on the cusp of the general release of an online course that covers CSS soup to nuts. I’ve seen bits and pieces and they are interactive and engaging. He’s not giving it away, by any means, but it’s probably worth the ticket price.

    The Actual Development Part

    After that, you’ve got to know how to program. Server-side pieces like plugins continue to be written primarily in PHP. Client-side stuff is JavaScript. If you are comfortable in one you can get coding with the other in relatively short order (add or remove the dollar sign in front of variable names).

    While PHP is the core of WordPress, if I were starting from scratch, I’d learn JavaScript first. You’ll find more resources, and generally better ones, than you’ll find for PHP. And though I’ll annoy some folks by saying this, you’ll find more of the resources pushing you toward a better grade of programming. PHP is capable of all the elegance and cutting-edge techniques you can throw at it, but it has a history of people writing (and sharing) fairly messy hacks. When you look for “how to do this or that” in WordPress, it will help if you can distinguish clean, well-coded examples from solutions that have edge-case bugs and are insecure.

    As you learn to code, you should start looking at how themes and plugins are built in WordPress. Build minimal versions of each, then try tackling increasingly demanding tasks, especially on the plugin side of the equation.

    Ultimately, you should figure out the workings of Gutenberg “blocks,” which are the emerging new paradigm for building things in WordPress. Since new blocks are coded and the whole block thing is still very much in process, there’s going to be a lot of work on this front over the next couple of years. See here for a quick introduction to the development side of Gutenberg. The tutorial at Delicious Brains is more hands on and has some good insights.

    Are you thinking about jumping into WP development? If so, what are you hoping to do with it?

  • Future URL

    One thing I always wished I’d had in my last “real” job (as an editorial director) was a way to link from web content I was currently writing to content I knew we were creating in the near future. A future URL. Of course, I could have just written in the links, but they’d by definition have been broken, at least until the scheduled pieces actually went live.

    TLDR: I wrote a WordPress plugin to do it, which, if it’s of any use to you, can be found on GitHub here.

    Back at the old job, we were, in point of fact, required to find places to link to our new content from existing older content and there were people on the staff tasked with editing the older stuff and putting those links into the older posts. And going to this extra trouble absolutely made sense from an SEO standpoint (and still does, and is routinely ignored by content teams far and wide).

    What I wanted was a way to embed the link, but not have it go live until a certain date. Now that I run my own shop, it occurred to me that there was no reason I couldn’t just build this for the current WordPress-based version of PeakZebra.com.

    Now, part of the point of PeakZebra is to migrate from WordPress to a Jamstack site, something I’ve written about here and here, to take a couple of examples. So I didn’t want to create something that would break on a static site. As we’ll see in a moment, I can actually do a somewhat better job of this forward linking in a hybrid site that’s half statically generated and half dynamic WordPress.

    Plugins and Filters

    To handle the job in WordPress one wants a plugin. From my point of view, there was no reason not to write this in PHP, the core WordPress language. Architecturally, WordPress operates by executing a series of “actions” and “filters” as each page is dynamically created and served to requesting web browsers. The execution of each action and filter is hooked to various functions, and a developer writing a plugin gets most of the work done by hooking custom functions to the appropriate actions and filters.

    As an aside, actions and filters are secretly the same thing, so basically all I’m saying here is that I can pick a moment in the page-creation cycle and tell WordPress I want it to call a custom function I’ve written at that particular moment.

    In this “future url link” scenario, all I really want to do is grab the main bunch of content on the page (what we’d typically call the blog post), search for my special kind of date-sensitive link, and enable or disable it before letting WordPress continue to serve up the page.

    The Future URL Format

    I called the primary function for this processing “handle_future_urls” and then hooked what is arguably the most important of the WordPress filter hooks, namely “the_content”. Setting up the callback looks like this:

    add_filter( ‘the_content’, ‘handle_future_urls’ );

    This statement is the first bit of code in my plugin and it executes as WordPress is getting ready to serve a page. Later in the process, when the page’s primary content has been called up from the database, WordPress will call my function handle_future_urls();

    When that function gets called, it’s with one parameter, $content, a string that contains all the words that make up the center of the page. This can be lots and lots of words—it’s all the stuff on the middle of the page that isn’t the header, footer, or sidebar widgets.

    You’re handed the content, you do whatever you want to it, and then you return the modified string of content from your function. In all honesty, it’s easy peasy and I think it makes it clear why WordPress has proven to be so extensible, versatile, and popular.

    In this case, I decided I’d work with a format that put the future link not in the standard HTML a tag, but in a nonstandard tag that took this format:

    [[http://example.com/theurl|September 1, 2021]]then some anchor text[[end]]

    It’s probably pretty obvious how the future URL format works. If you put a link like that while you’ve got the futureURL plugin loaded and activated, you’ll either get a link in your copy or you won’t, depending on the date when it’s being viewed.

    It’d be nice if the page updated to just an ordinary URL once the date had passed, just to save processing time. So… that’s coming along… And in case you were wondering, yes, there is a [[https://peakzebra.com/futurefixedurl|September 15, 2021]]future link[[end]] embedded in this paragraph, linking forward to the post I’ll write when I’ve made that update

  • Over-And-Under Static WordPress

    Proponents of GraphQL interfaces are quick to point out that this approach allows you to easily use WordPress as a headless Content Management System (CMS) with a static site serving as your front end.

    They’re not wrong. And as a developer, using the WPGraphQL interface is a lovely experience. With this approach, you create something like a Gatsbyjs site and the generator for that site sucks up all your blog entries and pages from the WordPress instance and spews out HTML pages, as all Static Site Generators do. All these blog pages display lightning fast and give you a blazing static WordPress site, but right out of the gate you’ve lost at least two functions from your old WordPress: comments and search.

    In many cases—particularly pages that serve marketing goals—you don’t want the comment system turned on anyway. That said, there still may be situations (actual blog entries, possibly) where comments are a good idea. And while search is less important on, say, a landing page, in general it’s hard to see why you’d willingly give up support for search for a site as a whole.

    The “standard” way to return comment, search, and other dynamic functionality to a static site is to use third-party services that offer APIs. So, maybe Algolia for search or Disqus for comments. There are upsides and downsides to this approach but I won’t belabor them in this piece.

    WordPress Under, Static Over (WuSo?)

    With all this in mind, I set out to create a site that’s static on the front end, but that understands when something is supposed to be dynamic and links back into the WordPress site in order to get the dynamic services WordPress normally handles. During the handling of the request (in real time for the user), a new static version of the page is updated to the static version of the site as needed (if, for instance, a new comment has been added—the static page will now show that new comment).

    Initial Caveats

    When I first started experimenting with this, I was impressed by how simple it seemed. If you have a static page and you leave the standard WordPress comment section on it, but simply change the link that the form sends its GET request to back to the original WordPress site, it’s almost frighteningly seamless (at least it is if the static page looks exactly like the WordPress page—more on this later).

    It wasn’t actually quite as seamless as I initially thought. Or at least not as easy to make really work.

    So, yeah: getting the new static page updated with a new comment requires sorting out a lot more details than you might initially expect. Additionally, while the update of the comment itself isn’t susceptible to race conditions caused by other comments arriving at the same time, some approaches to updating the static page open a small window of chance that one update will get temporarily overwritten by another one (the way I’m currently going about this, though, seems to avoid this problem).

    One more important caveat: a significant security boost can be had by taking your WordPress site offline whenever you’re not updating the content. In this scenario, which is the one that current plugins like WP2Static and SimplyStatic provide, only the static site is available to would-be attackers, and it’s hard (though not entirely impossible) to successfully compromise a static site.

    There are a couple of service providers—Strattic and HardyPress—that run your WordPress instance in a virtual container (I think they both use Docker containers) that is spun up only when administrators log in through the service’s front end. Otherwise, the dynamic WordPress site is spun down and simply isn’t there to attack. It’s ingenious, from a security point of view, and both vendors have added functionality to support search and comments. In other words, these guys already do the basics of what I set out to do, and fairly affordably too.

    I have some further destinations in mind, though, about which more in subsequent posts. So I needed control of the underlying code and the ability to release plugins for some of the functionality.

    WordPress Under

    In an approach where dynamic components are being handled by a live WordPress site, that site obviously has to be up and running somewhere. Exactly where that is can vary, to be sure, and putting it somewhere hard for random scans run by hackers to find could theoretically lower your attack profile, but of course the rewritten links in your static code, pointing back to the WordPress instance, make it readily findable to anyone who understands even basic HTML. (Could this be made more bulletproof? Maybe. Possibly one has an edge handler of the sort that Netlify offers to static site creators and it serves as an intermediary between static user and WordPress instance… Something to think about.)

    All that said, if you’ve been running your site on WordPress up to this point and been basically OK with your security posture, you’re no worse off for having that same site still running behind the static site. And you’re arguably a little better off, because attackers who are using scanners to look at your domain for signs that you are running WordPress may not find them, since your installation is running a bit behind the scenes and doesn’t have quite the directory tree that a WordPress-only site would have.

    The Over/Under Setup

    As I noted, you could put the WordPress installation pretty much anywhere, but to keep myself sane while running a bunch of these setups, I decided to have the static site running at the “top” of a domain (where you’d normally find your WordPress entry point, index.php) and then have the entire WordPress site moved to a subdirectory within that top level. I tend to think of this as having the WordPress site in a directory that’s “under” the static site. At first, I literally called this folder “under,” and inside of it you’d find the usual WordPress directories: wp-admin, wp-contents, and wp-includes. More recently, I’ve changed the “under” directory to names that are randomly generated, password-like strings, things like “df2CvIE9etuVJX4snt7N” so that automated hacking tools would be less likely to stumble into it (though, again, all the links from static to dynamic pages include this subdirectory name and someone expressly looking for it can readily find it).

    Creating the Static Site

    As I’ve already hinted at, there are a couple of easy ways to create a static version of your WordPress site if you don’t want to jump to a full-blown static site generator (SSG) like Gatsby or Next.js. These come in the form of WordPress plugins: SimplyStatic, WP2Static and Export WP Page to Static HTML/CSS.

    I’m going to write in more detail about these in another article, but here are a few salient facts.

    SimplyStatic doesn’t work on Windows platforms right now, which is a problem more for local development than for most production sites, which tend to be running on a Linux variant. It works very cleanly in my experience and you can point the output directly at the “over” root directory, which saves some extra fiddling.

    It’s pretty fast at the task, even though it (as well as WP2Static) only does full builds (almost certainly a deal killer for really large sites).

    It creates a new directory for each file it encounters as it spiders through your site. Inside that folder is an index.html and a subfolder with all the assets required to display the file.

    If you’re looking to display a few pages, this is perfectly fine. For a whole site, you wind up with all sorts of duplicated files, all of which are also sitting in subfolders within the underlying WordPress site. So while I would generally give SimplyStatic high marks, the asset folder-palooza isn’t ideal for our purposes.

    Having a separate folder for each page is the easiest way to have URLs match what you’ve got in your WordPress site, so it makes sense that plugins would go this route and, indeed, it’s what I currently do. This is another thing I’d like to look at further, however, when other more pressing bugs and issues are ironed out.

    Then, there’s WP2Static, brainchild of Leon Stafford, who seems to just live and breathe the open-source approach. I don’t have a lot to say about it, because it does exactly what you think it does. It’s the incumbent option for this sort of plugin.

    There’s also Export WP Page to Static HTML/CSS, by ReCorp, which has a free version that only lets you process a list of files, and there are limits on even this. If you buy a license, you can export as long a list as you like, plus you can instead export the whole site. I tried both versions and both work, even on Windows, but the pro version is licensed via Freemius, which I find a pretty unpalatable approach.

    And there’s a new kid on the block that I just ran across and haven’t looked at yet, called WP2HTML. The static world is a busy place these days, I guess.

    With any of these plugins, you have two problems left unaddressed. First, you have copies of all the image and other assets. This makes sense for their main use case (that is, making a static site that is fully independent of the WordPress site), but is total overkill for us, because we could just as easily bring in our assets from WordPress.

    Second, neither approach saves you from the sometimes breathtaking bloat in CSS and JS files within WordPress themes. The static version will be static, but it will still load in all the junk it loaded in with your big, fancy Divi-based WordPress theme. It’s possible that your Google Pagespeed scores won’t improve a whit (though, for the most part, you’ll still see improvements, especially on your mobile scores).

    It appears to me, from my preliminary soundings of the tangle of code that is Export WP Page to Static HTML/CSS, that it does make some effort to cull out unused CSS code, but honestly it looks like it doesn’t actually cull out much. This is reasonable insofar as it takes a fair bit of logic to figure out, site-wide, what can actually be cut. Nothing I’ve looked at so far looks at the site in toto—they work entirely on a page-by-page basis.

    What one really wants is a plugin that doesn’t change URLs that don’t need to be changed. If you think about it, actually, most URLs could continue to point wherever they already pointed. In fact, they all could, with the exception of links to other static pages.

    And all we really need for the static version of the site is the HTML pages. So what we want is sort of like what SimplyStatic and WP2Static spit out, but just HTML files. For each of the HTML files, the links that are “staying the same” actually need to be adjusted to point down to the “under” directory.

    All right, I concede that what I just described in no way fixes the style and JavaScript file bloat issue. But there are ways to tackle this and I’ll talk about my approach in upcoming posts.

    How to Get a Static Page

    Both WP2Static and SimplyStatic do what you might expect in order to get all the pages in a site: they start at the index page, look through all the links on the page, determine which ones are in the same domain, then recursively look at the pages on the ends of each of those links.

    Both of them then cleverly use Ajax requests to have the pages at URLs returned to them. It’s smart and I may well use the approach in a later iteration of this over/under thing. But for now I went a different way, an inherently incremental one.

    The Output Buffer

    PHP has this wonderful and weird couple of functions that access a built-in buffer construct. It’s exactly the sort of thing you might imagine would get created in a language designed almost exclusively to create web pages on the fly.

    With the output buffer, you can turn it on before WordPress would normally have written anything, then capture everything that WordPress writes into the buffer. Before you let go of the captured page, you can make whatever substitutions you’d like.

    This is where things get interesting. You’re going to return the “native WordPress” version of this file, except that all the links to HTML files within the domain are going to be rewritten to point up to the top level where the static site lives. But we’re also going to write a version of the file up to the static level, overwriting the one that’s already up there with a more current version, and in that version all the links that aren’t links to HTML pages will be pointed “down” into the “under” directory.

    Search requests are handled differently, in that no permanent static page is created. Instead, the regular WordPress page is created, but all links to HTML pages on the site are rerouted up to the static version of the site.

    It probably goes without saying, but every URL that contains “wp-admin” (that is, every page in the admin console) is left to run dynamically on the site.

    Still Clumsy

    It’s a pretty simple setup and, if you choose a “sane” theme for your WordPress site, it’ll be fast, and in fact your Pagespeed scores will probably improve on the static site. I’ve run against three popular free themes as I write this and they all come out blinding fast and kind of “just worked.”

    Crazily enough, with this approach many of the plugins you might be using will still work (though of course plenty of them won’t). Plugins you use to add features like sliders—things that are inserted into the page as it is created—will still be inserted and will wind up in the static versions of the pages. If they rely on JavaScript functions to, say, make the slider work, they’ll include .JS files that will be included (with a rerouted URL) in the static version.

    For the most part, things like form builder plugins still work. You build the forms within the admin console as always, then the forms are inserted into the pages as they are being dished out for conversion to static versions.

    One regrettable thing that does get broken in an important way is user management. You can login through the back end, as per usual, and any pages you access on the dynamic WordPress site will work as always, but if you have front-end controls on what users or non-users can’t see, the static versions of these pages will be flummoxed. The best approach to fixing this is something I’m still looking into, but I suspect it boils down to writing static-page calls into the WordPress REST API.

    The Current State of Play

    I’ve got running code at this point, but there are lots of gotchas that require tweaks and rethinking of algorithms. But all the same I have a site running (well, most of the time) at PeakZebra.link (not .com, which is where you are right now). It gets blown away and reinstalled, functions added and deleted, and themes swapped out pretty frequently, so I’m by no means suggestion you run over and see what you think of it, because it’s entirely possible is that you’ll think it’s broken.

    On the other hand, it wouldn’t surprise me if I got to a point fairly soon where it becomes usably stable. I’ll come back and revise this entry at that point.

    The end game, I should mention, is to produce “better-than-native” static pages, by which I mean pages that look like the WordPress site they come from and that still have WordPress dynamic functions, but that have optimized those pages in various ways.

    Readers of PeakZebra already know that I’m pretty impressed with the way Gatsby uses React such that React components can be swapped in and rerendered within static pages at run time, so it’s probably no surprise to learn that I either want to convert the output either to straight-up Gatsby source code or else output static files that use some of the same React tricks.

    It’ll be interesting, I promise. More to come.