Ahoy, since I finally completed the migration to bud
and a bunch of other stuff I thought I’d share the bedrock + sage fork we use at our agency. For various reasons we don’t really follow all roots conventions nor do we have access to radicle so this is closer to the older setup.
First of all thanks to all of you for your great work, if it wasn’t for Roots I personally wouldn’t have agreed to doing WP development in the first place. Recently I was skeptical to Bud but it turned out to be super flexible and a joy to work with–Thanks Kelly! I hope others find something useful or inspirational in our implementations.
Repo: GitHub - generoi/bedrock
Live: https://gdsbedrock.kinsta.cloud/
Repo has been public for a long time but it used to be private so it lost it’s fork status unfortunately.
I tried to summarize what we do differently to bring inspiration to others.
Bedrock additions:
- DDEV for development environment (previously Drupal VM, and sticking with the Drupal origins)
- Deployer for deploying (previously Capistrano)
- Github Actions for CI (we work in master and trigger deploys manually through the interface)
- Setup for Kinsta hosting and some host sniffing in
config/application.php
to setWP_ENVIRONMENT_TYPE
andWP_HOME
etc automatically based on prod/staging so that restoring their backups between environments work. - Robo as a task runner for pulling database and some other stuff.
- Some MU Plugins to prevent user enumeration, disabling emails, wp version sniffing etc.
- Lots of opinionated plugins we use for our client. We use satispress for premium plugins.
- generoi/genero-cmp for cookie consent
- generoi/wp-image-resizers badly named plugin for optimizing image/video/iframe loading + support various image resize proxies.
- We define custom post types in a mu-plugin with jjgrainger/PostTypes. Looking to change this but not a fan of poet, we might just go with core functions.
- Playwright for e2e tests (no defaults in this repo yet)
- We use cweagans/composer-patches for fixing bugs with plugins. Example to fix
get_block_wrapper_attributes()
in acf preview but had like 10+ patches going when PHP 8.2 came out… - WP-CLI hook to use composer versioned wp-cli on remote environments (actually slight memory this might have broken).
Sage differences:
- Pint and prettier merged just now
- Bud merged just now but we stick closer to laravel mix setup due how we enqueue assets.
- We enqueue core block styles but with
should_load_separate_core_block_assets
and then we add our own block stylesheets compiled as individual stylesheets. - Blocks are built using core functions + react + blade for views and we use
block.json
asset loading so individual scripts/styles here too. Wrote aBudBlock
extension for reading the block.json assets. - We use Sage SVG for including FontAwesome Pro icons (so repo wont work unless you have a key). Extended Sage SVG with better a11y support, I’ll open a PR at some point. Wrote a BudCopyWithoutManifest extension to copy all icons into dist folder but skipping the manfest since there’s thousands of them.
- We use Navi for navigation. Eventually I’d like this to use the navigation block instead but not a fan of it yet.
- Our goal is “everything is a block” but without FSE, so eg
content-single-product.blade.php
uses@blocks
and@block
directives. For clients (and for easier overview) we usually have a blocks demo page where all variations are presented and tested. Here’s the current demo. - Recently added a pretty untested setup with spatie/laravel-csp to set up CSP headers + add nonces to all WP scripts.
- Set Cache-Control headers for frontend content since we have some customer sites behind Fastly. Our ideal fastly setup is a super long stale-while-revalidate so users get cached results even if out of date. We also serve cached content to anyone who’s not seeing the admin toolbar.
- For purging proxy caches such as Fastly (or just kinsta) we use a custom generoi/sage-cachetags package where we add suppogate/cache-tags HTTP headers based on content rendered on a page.
- Mostly our JS components are written as web components. I just find them easy to avoid FOUC and encapsulate a11y quirks
- Oh, it should pass WCAG 2.2 AA-level but with so many recent changes it needs another audit
- Pagespeed score is ~99/100 on basic product pages with GTM + CMP + Meta Pixel but without custom events setup. Reality for us is this often drops to 80 once growth hackers get in there. As long as we pass core web vitals we’re happy…
- Just added built-in WooCommerce support since we needed a boilerplate for our customers.
Some blocks that might be useful:
- Accordion
- Carousel which supports arbitrary content + multiple slides per row. CSS Snap based but to make it accessible turned out it needed quite a bit of JS.
- Gallery carousel to replace WooCommerce gallery, it wraps two before mentioned carousels, one for main image and one for thumbnail pager.
- Media card basis for content cards.
- Page title just prints the page title regardless of what page it’s on, plan once block bindings has better support is start using template parts for default archives, 404 page etc. Currently we cant because all our clients need multilingual support and it’s a mess with FSE.
- Post teaser renders a blade view of composed blocks so template remains in code.
- Share widget
Block hooks
- Query block variations are removed and instead we add our own using the Post teaser block mentioned before. Eg we have a Article grid query block variation which when inserted renders Post teasers without granular control but still allows editor to filter the query.
- Product collection block variations are filtered to remove inline styles + use Post teaser, we keep the variations though since they’re useful.
- Handpicked posts filter added to query block
TODO eventually
- REST API support to sage-cachetags
- Template parts once block bindings is supported across more core blocks
- Tabs block but I still haven’t figured out a good web component structure for it that makes it avoid FOUC
- sizes=“auto” is finally getting browser support and need to add it
- publish our varnish configurations for fastly but kinda want a terraform recipe to deploy them
- Time from designers to fix some less opinionated defaults
- Remove SASS and just use CSS but we use a fair amount of mixins and without there being a WIP spec for it I dont want to add a PostCSS plugin. Maybe we dont need mixins
- Audit WCAG 2.2 AA-level again, WooCommerce components are not audited.
- If we get the navigation to be a block + template parts going, we might drop Blade so it’s easier for other agencies to take over if client drops us.