Pantheon Community

WebOps Wednesday AMA: Kevin Fodness of Alley

Hi, I’m Kevin.

I am the Director of Software Development at Alley. I lead Alley’s JavaScript practice, developing everything from front-end data visualizations to full-stack JavaScript applications written in React and Node. I have delivered JavaScript customizations to the front-end and editorial experience for the Kaiser Family Foundation and The Brookings Institution, as well as a full-stack data visualization tool for the National Science Foundation. Additionally, I frequently develop custom Gutenberg solutions for WordPress sites.

I earned my PhD in Science and Technology Studies from Rensselaer Polytechnic Institute in 2016, with a focus on web accessibility.

In my free time, I enjoy cooking and spending time with my wife and four children. I work from home on the banks of the Hudson River in the Lake George area of upstate New York.

Ask me anything!

Conversation notes:

  • Have worked with WordPress since the early days
  • Authored a doctoral dissertation on web accessibility
  • Been building React apps for 4 years
  • Early adopter of Gutenberg editor in WordPress, building custom Gutenberg integrations for clients, and new sites Gutenberg-first
  • Work at Alley, fully remote for past 4 years
  • Has 4 kids, all of whom were homeschooled before COVID-19, and works from home
  • Loves to cook—makes, eats, and cleans up from 3 meals/day with my wife and kids, knows how to cook for a crowd, meal plan, buy food in bulk, etc

Hi, Kevin! Welcome to the Pantheon community & thank you so much for hosting an AMA today! :woman_cartwheeling:t2: I saw your webinar with @carolyn and learned so much–thanks for sharing your knowledge.

I am building a Gutenberg-first site now and am curious: What tips & tricks do you recommend for getting started? What are common mistakes you see?

AND (Do I get two questions? I don’t know!)

Can you talk a little bit about inclusive design? I’d love to hear how you & your team think about it.

Hi Kevin, having spent so many years with WordPress has it has grown and matured, what do you see as the biggest movement forward within the project as far as accessibility?

1 Like

Thank you! I’m glad to help.

Of course you do!

The biggest change for us was moving away from using the save method to save the rendered HTML for a custom block and instead just saving attributes and rendering the output in PHP using a render_callback. We’re still rendering the edit view in React, but offloading the front-end render to PHP. The reason for this is that if you need to change some aspect of your output, like making something an <h2> instead of an <h3>, or adding a class to an element, it results in a rather nasty error message for an editor unless you code a rather complicated deprecation pathway, and if you want to update the output of custom blocks that have already been saved to post content, you have to re-save all of the affected posts or use a script to go back and update them. Making PHP responsible for the front-end output solves all of those problems, and by leaving the edit view in React, you still get the snappy instant-preview of Gutenberg that makes it such an attractive choice for an editor. I realize that’s a rather complicated answer to a “getting started” question, but I think it’s an important architectural decision when building custom blocks that needs to be addressed at the beginning of a project.

Another answer for tips and tricks for getting started is to learn how InnerBlocks work. We use InnerBlocks a lot, particularly when you want the ability to add one or more items to an area, re-order them, remove them, etc. A good use case for that is building a block that lets you curate a list of posts - if you make individual blocks for the featured posts, and make a container block that includes the individual posts as InnerBlocks, you get all of the Gutenberg controls for adding/removing/re-ordering for “free” and you can focus less on building the admin interface and more on the behavior of the components themselves.

We design interfaces that don’t require special accommodation to make them accessible. Our approach to inclusive design and accessibility is similar to our approach to responsive design - it’s one set of markup that serves multiple audiences. This is especially important when building controls like navigation - it needs to be accessible to people who can use a mouse and people who use a keyboard, people who can see the menu and those that rely on assistive technology, people who are colorblind or low vision, people with motor impairments, etc. So we really think holistically when building components like that into a site.

We also work with our clients to ensure the editorial experience of adding accessible metadata is as easy as possible, so that those features actually get used. The most accessible theme in the world isn’t going to be very usable by users with disabilities if the metadata fields aren’t used, or aren’t filled out properly (e.g., image alt tags, video transcripts or captions, hierarchical headings).

We test our interfaces using assistive technology - most notably, our keyboards and VoiceOver for Mac. During the design phase, we see how our designs will look for users with colorblindness using colorblindness emulation tools. And, whenever possible, we test our interfaces with users that have disabilities, because the best insights are gleaned from actual users. Standards can only go so far.

Let me know if you have any other questions, and thanks for participating!


WordPress has always been a leader in making an accessible CMS. Having a dedicated working group to accessibility has helped WordPress remain accessible over time. However, the Gutenberg project had a rough start with respect to accessibility, to put it mildly. The biggest movement forward in the project today is ensuring that Gutenberg is fully accessible, especially as WordPress is moving further into JavaScript development for the admin interface. Making JavaScript apps, particularly React, accessible is a different challenge than making PHP-generated views accessible. However, I’m optimistic that solving those problems in WordPress core packages that can be reused in front-end React apps that consume the WordPress REST API could end up moving the entire project in a more accessible direction.

1 Like

Hey Kevin!

Thanks so much for jumping in to share your experience :slight_smile:

I am curious, what drove you to pursuing a PHD in accessibility? Was it something you were always so passionate about or something you grew to understand the value in?

Also love to cook! :woman_cook: Although right now I don’t get out as often as I like so I find myself constantly forgetting something at the store. Top Ramen anyone? :woman_shrugging:


That’s interesting. Could you share an example, breaking it down for a beginner? Doesn’t have to be today, of course. I know a lot of people struggle with the depreciation path for blocks.

Right out of college, I got a job working for a government contractor in DC, and I was on-site at the U.S. Department of Labor for 3 years in charge of web and database server operations. Among other things, I was responsible for the server that powered I started as an IT major at RPI, and eded up dropping that to a minor by the time I graduated, but still took a large courseload in IT & computer science. When I arrived at Labor, we were subject to Section 508 accessibility requirements, being a federal agency, and that was the first time I’d encountered accessibility requirements for IT systems. Never in my undergraduate coursework had I heard anything about the need to make software accessible, particularly websites. Accessibility also wasn’t a topic in most technical documentation / tutorials / books / etc at the time. This was the mid-aughts - a lot has changed since then. After my three year stint at Labor, I moved back to upstate New York and started my PhD program at RPI with the goal of studying why accessibility wasn’t taught in schools or included as part of what was considered professional practice in web development. Nowadays, it’s included in a lot of training materials, although I think the academic situation is still lagging a bit from those I’ve spoken to about it.

Even pre-pandemic, we were doing monthly shopping and meal planning, so it hasn’t been much of a change for us. When we first started, though, we were constantly forgetting things! The biggest problem right now is that stores are out of so much that you have to get what you can, and substitute things. We’re also limiting our trips out, so we use our fresh fruits and veggies early in the month, then switch to frozen and canned things until our big shop at the end of the month. People give my wife the side-eye when she rolls up with two carts, but she’s buying enough food for three meals a day for a family of six for a month!

1 Like

Of course! The specific bit of functionality is called a “dynamic block” and the docs on it are actually fairly decent:

The important points are:

  1. When calling registerBlockType in JavaScript, omit the save property altogether, and do not include the code in the attributes registration for extracting values from HTML. In the simplest example, an attribute is just a key and a type, although you can also specify a default value.
  2. Make sure you are registering your block in PHP. You should be doing this anyway, to make WordPress aware of the registered blocks, and to allow plugins and themes to filter which blocks are available in what contexts, for example. When you register your block in PHP, specify a function callback in the render_callback property that will handle generating the HTML. You would specify the function callback in the same way that you would for an action or filter hook, so something like 'my_cool_function' for a function, or [ $this, 'my_cool_function' ] for an instantiated class, or [ self::class, 'my_cool_function' ] for a static method in a class.
  3. Code the callback function to return the HTML for the block. It will receive up to two function arguments - $attributes and $content. The attributes variable is an array containing key/value pairs for the attributes you defined for the block, and the content variable is rendered content for any inner blocks. What we do here is call a PHP template part, because it’s a lot more familiar to code template parts than to include output in a PHP function. The important thing here is that the render callback needs to return the HTML for the block, so you need to use output buffering to capture the result of your require or get_template_part call and return it.

We go a step further and have developed a reusable system for loading template parts for dynamic blocks, so most of that code is boilerplate, rather than requiring us to write a bunch of custom code for every block.


That’s very helpful. Thank you so much, @kevinfodness


Hey Kev – happy to see you doing this. Thank you.

Version control and database migrations are still pain-points for WordPress. What are your best practices for moving code and content changes from an internal staging environment to production for a live, active website?


  • O’Malley
1 Like

Wow, thank you for such in-depth answers. Definitely helpful to hear about the save vs. render_callback at this point in my project!

1 Like

Hey, O’Malley, thanks for stopping by.

Yeah, that has continued to be a pain point, and the answer is “it depends.” If you’re in a position where you can stage the content and replace the database wholesale, then that’s a good approach, particularly if there is a large volume of database-level changes involved. We use wp-cli heavily to perform operations on databases when we move them between environments, such as doing a find and replace on domain names to map it from a staging URL to a production URL, for instance.

If the changes are small, we have found that it’s easier to develop a list of things that need to be updated and run the updates manually, rather than developing a scripted solution or replacing an entire database.

I’ve heard good things about the RAMP plugin, but haven’t used it to deploy code to production sites myself.

We run a lot of content migrations when we replatform sites, and the database export with wp-cli’s search-replace is our go-to method there after preparing all of the data using automated scripts. You can then handle delta migrations of articles published after the initial export/import using a WXR export and import into WordPress.

Code-wise, we use git for everything, and deployments happen automatically, along with asset builds, when we merge to the production branch. For larger features, where we can’t continually deliver code, we will park the changes in a dedicated feature branch until we’re ready to go live, then merge all of those changes at once. However, whenever possible, we will prefer to actively deploy to the production environment, except when doing so would break the site in some way.

1 Like

I was out sick and missed this yesterday. On the off chance you are still checking, I’d love to know your thoughts on the future of headless WordPress and what roll Gutenberg should play in that future.


That’s what I expected you’d say. :wink:

For as much as the WordPress platform has grown over the last 10 years, the content management aspects of the system still seem very much geared at smaller sites that make all changes in production. The idea of publishing schedules and progression through staged environments is still very rudimentary and hampered by the database layout selected in the early days as a blogging platform.

The RAMP plugin is an interesting suggestion. On paper it sounds like it addresses many of our needs. I’ll certainly have the team investigate.

Good to hear from you – thanks for running the AMA!

  • O’Malley
1 Like

Sure, happy to weigh in here!

Headless WordPress is becoming an attractive option for a lot of organizations, because it can deliver a faster site (the front-end only needs to fetch updated data, rather than reloading the entire page, repeated markup and all) and because it can enable certain types of functionality that aren’t possible to accommodate on a traditional site, such as a persistent audio or video player that follows you around the site, uninterrupted. At Alley, we’ve built several headless sites for our clients over the past few years.

Gutenberg can make developing headless sites easier, as the same component that renders the preview of a custom block in the admin can be used to generate the component in a React-powered headless front-end. There are some separation of concerns issues if you want to do something like that, certainly, but done right, it can make development of a headless site with live preview of custom blocks in the editor fairly seamless.

1 Like