• 2020

  • New site, who dis

  • I haven’t developed a new WordPress theme for this website (that I really loved) in a long time. So naturally, it was time to re-examine my personal tech stack. If you personally know me, you know I’m a WordPress advocate. Big fan of ol trusty.

    There’s a few problems with WordPress I’ve been hung up on for a while now. It can be a bit slow (sometimes). Media managing can be painful on the front-end. Deployment processes are… all over the place. Historically, I’ve been a huge fan of Trellis from Roots. While we’re at it, I was a big fan of Bedrock too. Finally, I work with React and JavaScript all day long — why can’y my personal website run on a modern tech stack too?

    Well, I came across this post from Chris Coyier, and I was pretty much sold on the JAMStack concept immediately. At work, and at other organizations like Twitter, server-rendered pages are stupid fastest. Heck, they’re typically standard these days for most web apps. Enter the Gatsby + WordPress stack. Why abandon years of publishing paradigms when you can keep them?

    There’s no shortage of tutorials on the Gatsby + WordPress setup. Initially I played around with some starter projects, like this one. I personally started (and later forked) with egghead.io’s starter. It’s pretty spectacular out-of-the-box, and if you enjoy love @emotion theming or styled-components, I think you’ll dig too. But, really Gatsby itself has a lot to love. For example, Gatsby has drop-in support for server-rendering. Super cool stuff. I really enjoyed Juliano Rafael’s (@frontendwizard) notes on this subject:

    Progressive image loading? Inlining of critical CSS? Painless PWA configuration? You name it, Gatsby got you. It is really impressive. Don’t believe me? I encourage you to try it out.

    The solution for images is so good, that is constantly referred as a strong point of Gatsby, even thought it actually is a plugin. All you gotta do is add a couple of plugins into your Gatsby config file and you’re good to go. Your images will be available on the GraphQL API at build time and the image component will handle all the resize, picking the best file format and everything else. You even get a blur up effect to improve the user experience for free.

    That’s just the tip of the iceberg. Seriously. These web apps freakin purr. I’m overdue for writing a full tutorial on this subject, so stay tuned. But, for now I want to share a high-level overview of the technical lift I undertook for my site migration.

    My order of operations (yours might be slightly different):

    Now that we have our API-site prepped for deploy-hooks, exposed the frontpage and menus endpoints — we’re ready to consume the API with our server-rendered React app powered by Gatsby. Here’s a sample of my gatsby-config.js file:

    resolve: `gatsby-source-wordpress`,
    options: {
      // Your API WordPress source goes here.
      baseUrl: `example-api.stephen.news`,
      protocol: `https`,
      // Fetches posts, tags, categories, etc from the baseUrl.
      includedRoutes: [
      useACF: false,

    I absolutely love this setup.

    All of the un-fun configuration stuff is already handled by the WordPress/WP REST API side, and all of the actually fun conventional interface building is done on the… well, the interface side. A complete separation of church and state, if you will. It’s a thing of beauty. Absolute zen.

  • 2017

  • Remote Server Setup with Trellis

  • We’re going to setup a remote server (say hosted on DigitalOcean), with Trellis’ automated deployments. It’s magical. Oddly enough, as of 2018, this guide is still pretty much up date and relatively unchanged.

    We started by getting our local environment setup but now we need to get our production environment setup so we can get deploys going from our local machine. With Trellis, provisioning and deploying occurs from the trellis directory.

    Remember our structure?

    example.com/      # → Root folder for your project
    ├── trellis/      # → You'ver clone of Trellis
    └── site/         # → A Bedrock-based WordPress site
        └── web/
            ├── app/  # → WordPress content directory (themes, plugins, etc.)
            └── wp/   # → WordPress core (don't touch!)

    1. Copy group_vars

    Copy your wordpress_sites from your working development site in group_vars/development/wordpress_sites.yml to the production environment group_vars/production/wordpress_sites.yml.

    Modify your site and add the necessary settings for remote servers:

    • repo – URL of the Git repo of your Bedrock project (required)
    • repo_subtree_path – relative path to your Bedrock/WP directory in your repo (above) if its not the root (like site/ in roots-example-project)
    • branch – the branch name, tag name, or commit SHA1 you want to deploy (default: master)
    • env – environment variables (very important)
      • auth_key – Generate (required in vault.yml)
      • secure_auth_key – Generate (required in vault.yml)
      • logged_in_key – Generate (required in vault.yml)
      • nonce_key – Generate (required in vault.yml)
      • auth_salt – Generate (required in vault.yml)
      • secure_auth_salt – Generate (required in vault.yml)
      • logged_in_salt – Generate (required in vault.yml)
      • nonce_salt – Generate (required in vault.yml)

    You’ve’ll want to make sure that you change all instances of example.local (in your production vars) and switch it to example.com Otherwise you may get some errors.

    2. Setup Hosts and Users

    Create a Digitalocean droplet configured for Ubuntu 16.04.1 in whatever size you may need.


    Once you get your droplet setup, you’ll need to SSH into the server to change the default password DigitalOcean emails you.

    Next, add your server IP (from the droplet) to your hosts/<environment>. Specify public SSH keys for users in group_vars/all/users.yml so Trellis can access your droplet. See the Trellis’ SSH Keys docs for more information.

    3. Provision

    Run ansible-playbook server.yml -e env=<environment>. and Hopefully you get a green light and no errors. If you do get errors, troubleshoot and try again. Trellis has verbose warnings and errors so they don’t leave you high and dry.

    4. Deploying

    To deploy, ensure that your site folder is in a public repository on Github.

    Next, run ssh-add -K, this will add you SSH key to your shh-agent (if you’ve created one, also it’s good practice to add your keys to your Github account). Then, from the Trellis directory, run ./bin/deploy.sh production example.com and watch as your terminal deploys your most recent commit.

    Previous: The WordPress Roots Stack
  • Working with WordPress Locally with the Roots Stack

  • Okay, so it’s been a while since last time I wrote about Roots (shoutout to Rob for pointing it out). The last time I wrote about the Roots Stack, things were more or less the same. But I felt compelled to write this guide ever since Sage got a version bump.

    Secondly, no one enjoys spending precious hours configuring their local setup using a MAMP GUI or fucking up your machine’s hosts file or deliberating on how to fix the dreaded error establishing a database connection. What I love most about Roots is the priority on convention over configuration. 

    It’s literally a playbook taken from Rails. The net gain of this philosophy is twofold:

    1. Lowered barrier to entry for beginners
    2. Productivity bonus, spend more time hacking and less time crying

    The Roots framework has huge benefits for beginners, and even bigger returns for WordPress veterans. Mainly because you’ll no longer have to FTP your deployments like a goddamn barbarian. But I’ll go into more detail on remote server setup in my next post.

    Before I get side-tracked, let’s just dive right in shall we?


    Let’s talk about requirements and assumptions. I’m assuming you’re using Sublime Text 3 (all other versions make sure you have this enabled) and you understand how to use your terminal. Follow the links below and install the following software.


    Below is what we want our project too roughly look like:

    example.com/      # → Root folder for the project
    ├── trellis/      # → You'ver clone of Trellis
    └── site/         # → A Bedrock-based WordPress site (cloned as well)
        └── web/
            ├── app/  # → WordPress content directory (themes, plugins, etc.)
            └── wp/   # → WordPress core (don't touch!)

    Create a Sites folder if you haven’t already. I typically put all of my web projects in a Sites folder in my home directory on my Mac. To get started, we’re going to make a directory called example.com — you can name yours whatever project name you’d like:

    cd ~/Sites && mkdir example.com && cd example.com

    You should be inside the example.com directory at this point. Next we’re going to clone Trellis:

    git clone --depth=1 git@github.com:roots/trellis.git && rm -rf trellis/.git

    Then we’re going to clone Bedrock (which contains WP Core and our web app, etc.):

    git clone --depth=1 git@github.com:roots/bedrock.git site && rm -rf site/.git

    At this point, our example.com directory should look like this:

    example.com/      # → Root folder for the project
    ├── trellis/      # → You'ver clone of Trellis
    └── site/         # → A Bedrock-based WordPress site (cloned as well)

    You’ve’re doing great!

    Trellis vars

    Now let’s get into something a bit more challenging. We’re going into the Trellis directory and need to edit some variables to bring this local WordPress installation to life. I’m assuming you have Sublime Text 3 installed and you’re still in the root of example.com

    Edit the wordpress_sites.yml file first:

    subl trellis/group_vars/development/wordpress_sites.yml

    Then just make sure it looks like this. Replace example.com with the name of the project you have chosen. This is pretty important at this point, as we start getting into the nitty-gritty.

    # Make sure your file looks like this
          - canonical: example.test
              - www.example.test
        local_path: ../site # path targeting local Bedrock site directory (relative to Ansible root)
        admin_email: admin@example.test
          enabled: false
          enabled: false
          provider: self-signed
          enabled: false

    Now go ahead and edit the vault.yml file as well:

    subl trellis/group_vars/development/vault.yml
    # Make sure the site name (`example.com`) must match up with the site name
    # in the file we previously edited: `group_vars/development/wordpress_sites.yml`
    # By default Trellis will provision a user `admin` too, below you can set a different
    # password if you'd like
        admin_password: admin
          db_password: example_dbpassword

    Don’t worry about the other .yml files in the development folder for now.


    Vagrant is our savior. It sits between us and the VirtualBox, and does most of the talking. To get our machine running our new local setup we configured (in the wordpress_sites.yml and vault.yml files), we have to go down into our trellis directory and get vagrant running:

    cd trellis && vagrant up

    By now you should see this a few commands trickling in. At some point vagrant will ask for your sudo password because it needs root permissions.

    Enter your password and vagrant will begin installing, provisioning and start running tasks your virtual-machine.

    At this point, take a break and chill. The total installation/provision time varies from machine to machine, but it takes around 10-15 minutes on a mid-2015 13″ MacBook Pro. Once the provisioner is done (provided that no errors stopped the installation), you can open your browser and navigate to example.test and you should see this:

    Getting started with theme development with Sage

    Now that we have a local development environment setup and running, we can move onto creating our first theme! The Roots team put together an awesome starter-theme to speed up development.

    Remember our project structure? We’re going to cd our way into the themes directory:

    example.com/      # → Root folder for the project
    ├── trellis/      # → Trellis
    └── site/         # → A Bedrock-based WordPress site
        └── web/
            ├── app/  # → WordPress content directory (themes, plugins, etc.)
            |   ├── mu-plugins/  # Must-use plugins live here
            |   ├── plugins/     # Plugins live here, managed by composer.json in the `site` folder
            |   ├── themes/      # We're going to create our theme HERE.
            |   └── uploads/     # WordPress will put uploads here (I wouldn't mess with these)
            └── wp/   # → WordPress core (don't touch! Like ever!)

    Once we’re in the themes directory, we’re going to run a composer command:

    composer create-project roots/sage example-theme 8.5.3

    Basically, the previous command says:

    1. create a composer project with the the roots/sage package
    2. name the theme, “example-theme”
    3. choose the 8.5.3 version of the roots/sage package

    As of October 17, 2017 the LTS Sage version is at 8.5.3 which is why I chose that version. You should see composer downloading the packages (be patient, sometimes composer can be slow)

    Sage requires Node.js to function. Make sure you are up-to-date.

    npm install -g npm@latest

    We’re going to use Gulp to build assets (styles, scripts, etc) and Bower will handle any front-end packages such as Bootstrap or Flickity. To get started, cd inside our new theme example-theme. We’re going to install Gulp and Bower globally (if you haven’t already)

    npm install -g gulp bower

    Now, were’ going to install all the dependencies listed in the package.json

    npm install && bower install

    Next, let’s open our manifest.json in Sublime Text and configure BrowserSync to proxy our dev URL

    subl assets/manifest.json

    Make sure the devURL reflects the canonical hostname we wrote in wordpress_sites.yml earlier since our vagrant machine will be listening for traffic at that URL.

      "config": {
        "devUrl": "http://example.test"

    At this point, we can go to example.test/wp-admin, and login. From the dashboard, choose Appearance > Themes. Pick your Sage Theme and Visit Site. Everything will look broken now, as no styles exist 🙁

    But don’t fret! Next, we go back to the terminal (make sure you’re still in the new theme directory), and run gulp watch. A new tab should open on your browser. That’s BrowserSync loading style changes in real-time (no more ⌘R in Chrome). Save any of the SCSS files in the assets/styles directory and your webpage should reload with the changes. Also watch your terminal 👀

    Gulp literally watches all PHP, SCSS and JS files changes. And BrowserSync will reload your browser window. Pretty nifty. Assuming you didn’t get any errors, your homepage should load with basic styles thanks to Normalizer and Bootstrap.

    From here on out, the world is your oyster!

    Sage doesn’t give you everything you need for WordPress development but it’s speedy, it’s git-friendly, and it’s modern. I’m not kidding when I say this… the Roots Stack is literally my favorite way to interface with WordPress. Any other way just feels primitive and old.

    It gets even better with deployments and remote provisioning which I will cover in my next post. 

    Further Reading:

    Next: Remote Server Setup with Trellis
  • 2016

  • WordPress Local Development on OS X with Trellis and Bedrock

  • I wrote a new tutorial since this one is a bit out of date.



    Okay so a few things have changed since my April post. I figured I’d write an update on how to get started with Trellis and Bedrock. There has been a ton of commits since then.

    Again, I’m assuming you’re on a Mac and have node, npm, bower and homebrew installed. If not start here. Things are a little different if you’re a Windows user.

    1. Install Git, Ansible and Composer

    brew install git ansible composer

    2. Install VirtualBox

    Install your VirtualBox software and follow the prompts.

    3. Install Vagrant

    Download and install the latest Vagrant.

    4. Starting a Trellis Project, Installing Bedrock and Sage

    By the time we’re done here, you should have a folder structure that looks like the following (taken from the Trellis Repo):

    example.com/      # → Root folder for your project
    ├── trellis/      # → You'ver clone of Trellis
    └── site/         # → A Bedrock-based WordPress site
        └── web/
            ├── app/  # → WordPress content directory (themes, plugins, etc.)
            └── wp/   # → WordPress core (don't touch!)


    1. Creat a Sites directory if you haven’t already and cd ~/SitesFirst, create a new project directory and cd to that directory: mkdir example.com && cd example.comClone Trellis and remove the gitfiles: git clone --depth=1 git@github.com:roots/trellis.git && rm -rf trellis/.gitClone Bedrock and remove gitfiles: git clone --depth=1 git@github.com:roots/bedrock.git site && rm -rf site/.gitInstall the Ansible Galaxy roles: cd trellis && ansible-galaxy install -r requirements.ymlInstall Sage in your themes directory, and install npm dependencies: cd ../site/web/app/themes composer create-project roots/sage example-theme dev-master && cd example-theme && npm install
      Now, we head back up the tree to Trellis. Here’s the current folder structure there. We need to configure the WordPress sites in group_vars/development/wordpress_sites.yml and in group_vars/development/vault.yml
    ├── trellis/ # → You'ver clone of Trellis
        └── deploy-hooks
        └── group_vars
        └── hosts
        └── lib/trellis
        └── roles

    Here’s an example configuration for group_vars/development/wordpress_sites.yml

          - canonical: example.dev
              - www.example.dev # optional redirect
        local_path: ../site # path targeting local Bedrock site directory (relative to Ansible root)
        admin_email: admin@example.dev
          enabled: false
          enabled: false
          provider: self-signed
          enabled: false

    Here’s an example configuration for group_vars/development/vault.yml

    # Generate a secure root password
    vault_mysql_root_password: B3LkKUpcZVx4bpLXKXpiez%R
    # Variables to accompany `group_vars/development/wordpress_sites.yml`
    # Note: the site name (`example.com`) must match up with the site name in the above file.
        admin_password: admin
          db_password: example_dbpassword


    5. Let’s Take a Break

    Now that the configuration is done, we can begin the real magic. From the trellis directory, we run: vagrant up. Vagrant will ask for your password, and upon pressing enter it will provision a server and get you all setup. It should take about 10–15 minutes to install. So take a breather if you can.

    Luckily Trellis has some pretty verbose error messages and make sure to double check your group_vars if you have any issues. When the dust settles, head to example.dev and you should see this:


    Now that we got local development out of the way we can move onto your production setup. It’s all about dev/prod parity nowadays and honestly, it rocks.

    [button type=”success” size=”lg” link=”/blog/remote-server-setup-with-trellis”] Next: Remote Server Setup [/button]

  • Intro to Modern WordPress with Trellis, Sage and Bedrock

  • UPDATE: I updated this post here 👀

    WordPress is a beast. Setting up your local machine, mysql, keeping track of users, managing dependancies and plugins, setting up your vhosts—jeez, all of that can be a daunting task. Let’s automate some things.

    I’m making a few assumptions here. Such as you probably have Node, npm and Bower installed on your Mac. We’ll begin with Homebrew. Full disclosure, I forked Dave Kiss’ take on his champion WordPress workflow with some of my own tweaks. Feel free to check out his setup too, it’s really great.

    The whole walkthrough should take about 15-20 minutes of your time on a modern machine. Let’s get started.


    Curl Homebrew:

    ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
    Make sure to run brew doctor afterward to make sure you have everything installed all nice and neat.

    Git, Ansible and Composer

    Now that we have Homebrew installed, let’s go ahead and install some goodies for our workflow and get started. Composer will manage our plugins. It’s awesome.

    brew install git ansible composer

    Install VirtualBox

    Go ahead and install your VirtualBox software and follow the prompts.

    Install Vagrant

    Next, download and install Vagrant. Pretty painless.

    Beginning a Project with Trellis

    Next, mkdir -p ~/Sites/example.com where example.com is the name of the project.

    Then, go ahead and cd ~/Sites/example.comWe should be inside the example.com directory. Now we’re going to clone Trellis into a new directory called ansible with this command:

    git clone git@github.com:roots/trellis.git ansible

    Provision the Ansible roles and packages.

    cd ~/Sites/example.com/ansible && ansible-galaxy install -r requirements.yml


    Finally onto Bedrock. A simple WordPress boilerplate and configuration and improved folder structure for your project. Clone it into a new folder called site

    cd ~/Sites/example.com && git clone git@github.com:roots/bedrock.git site

    Installing the WordPress Core and any Other Composer Dependancies

    cd into the new folder called site and let’s get this party started.

    cd ~/Sites/example.com/site && composer install

    More Ansible Stuff

    If you’re like me, you probably have Sublime Text aliased. But click here if you haven’t aliased Sublime. Or if you’re into Vim and all that, that’s cool too.


    Go ahead and configure your db_namedb_user and db_password and everything else to your liking.

    Now the real fun stuff begins. We’re going to cd to the ansible sub-directory we previously created and start up vagrant and the virtual machine voodoo. It will prompt you for your system password because it’s going to add example.com to your /etc/hosts file. No biggie, but you should know.

    Also, this will take a while. Probably 10+ minutes or so.

    cd ~/Sites/example.com/ansible && vagrant up

    If you got any errors, don’t worry. Vagrant might ask you to install a few additional pieces of software for Vagrant. Go ahead and heed Vagrant’s advice. If it appears that your install falls into a timeout loop, run vagrant reload and hopefully that should resolve any timeout errors in the setup.

    You should be able to navigate to http://example.dev in your browser and see the fruits of your labor!


    Now that we have WordPress installed, let’s get a starter theme going with Sage. Let’s cd to the theme-root and clone the Sage repo over:

    cd ~/Sites/example.com/site/web/app/themes && git clone https://github.com/roots/sage.git

    Now let’s rename the Sage directory to our new-theme-name:

    mv sage new-theme-namecd to the new-theme-name and npm install && bower installNow you can run gulp in that directory and build your theme! http://example.dev should now have some styles. Sage comes with Bootstrap by default, but you can swap it out for whatever framework you want. Or no framework at all! Whew—that was a lot of steps but way less painful than it could’ve been! More about Sage here.