Like most WordPress developers, I used MAMP for local development environments. MAMP works well for some people, but it doesn’t really allow you to create reproducible development environments. Your environment is really at the will of both MAMP itself (i.e. your settings), as well as which operating system you’re developing on; and that’s really not a good thing.
After awhile, the MAMP workflow isn’t all that it’s cracked up to be, especially once you begin needing to share environments between team members. Suffice it to say, we left the MAMP workflow behind once we were introduced to the ubiquitous Vagrant. I won’t get into the details of that affair, because there’s already a great article written on that happening to somebody else. But how do you ease yourself into Vagrant, when you’re so used to your beloved MAMP workflow?
Enter, Theme Juice (or
tj), a command line utility for modern WordPress development. It takes the pain out of local development by taking advantage of Vagrant and an Apache fork of VVV called VVV-Apache as the virtual machine. It allows you to generate an unlimited number of local development projects, manage their dependencies, and even handles deploying them, all from the command line.
tj is written entirely in Ruby and requires at least version 1.9.3., but I recommend one of the latest versions of Ruby MRI (2.2, 2.1, 2.0). If you’re curious if yours is supported, check out the Travis CI build, where I test against an array of different Ruby interpreters.
Lastly, it’s recommend that you set up SSH-keys for GitHub. Internally,
git clone with SSH URLs, so things might break if you don’t have your keys set up properly.
If you’re using Windows, rest assured that you are supported! Just be sure to check out the documentation, because you might need to do a couple extra things to make sure it plays nicely with your operating system.
It’s as simple as running the command below inside of your terminal:
gem install theme-juice
Depending on how your Ruby environment is set up, you may have to run that with
There has a been a great amount of work put into VVV by the community, but if there’s one thing that isn’t that great, it would be the process of creating a new project. After a few weeks of using VVV, I found myself doing the same steps over and over and over and over again:
- Create a new project folder in the
- Create a new conf file in
.devdomain (which could be using Nginx or Apache, depending on your VVV flavor)
- Create a new entry in
database/init-custom.sqlto set up a new database as well as a new user
- Create a new entry in a
Customfileto sync the local project folders to the VM folder (I don’t like having my actual project within the VM, because then removing the site actually requires you to remove your project folders)
- Create a new entry in a
Customfileto automate adding your new domain to your
/etc/hosts(in our case, setting up a local DNS server with Landrush)
- Create a new entry in a
Customfileto allow me to access my local project from another device (i.e. my phone and tablet), using xip.io
- Set up a local
wp-cli.local.ymlfile to allow me to quickly execute WP-CLI commands on the project (without actually having to SSH into the VM, change to the project directory, and then execute the commands from there)
I would literally do that multiple times a week. Talk about repetitive! The good news is that
tj sits on top of VVV, automating all of that repetition; allowing you to quickly scaffold out (and manage) new development projects in just a few seconds.
We’ll get into the nitty gritty details in a bit, but first let me quickly lay out all of the features
- New local development project generation (by executing the steps above)
- Management of existing projects, including project removal
- Build tool and dependency management (more on this later)
- Multi-stage single-command deployment, including database migration
But, isn’t there already a few tools that do most of that work? At the time (i.e. mid last year), there was only VVV Site Wizard, which didn’t really satisfy all of the requirements put in place by the above steps; not to mention, we install WordPress inside of a subdirectory, which that script doesn’t support in the way we needed.
One of the things about
tj that differs itself from projects like VVV Site Wizard and Variable VVV is that
tj sits on top of proven open source technologies, such as Capistrano for deployment, and Composer for management of plugins and the actual WordPress installation. There’s a huge eco-system around WPackigist, so we believe utilizing such great efforts is a no-brainer.
What that means is that
tj doesn’t provide you with options for selecting your WordPress version or which plugins you want to install, as all of that can (and should) be managed outside of
tj via a starter theme. If you have an array of plugins that you prefer to use on every project, great! Just create a repository for your starter theme and voilà! You can use it within
tj by either requesting it to be added to the CLI itself, or just passing it in via the prompts (discussed below).
One thing worth noting: when I talk about a “starter theme”, I’m not referring to something like Underscores; rather, I’m talking about an entire WordPress-installation-starter, like WP-Skeleton, Bedrock or our starter theme. So, if you’re looking to use a custom starter theme, make sure it’s a full WordPress installation, and not simply a theme. In a future version, this might be changed to something like ‘kit’; it has remained this way so that we can ‘just ship it!’ i.e. to get this project out into the hands of the community as soon as we could.
Creating Your First Project
Now that we’ve discussed the steps that need automation, let’s see how we take advantage of what
tj has to offer. To get started, we simply have to run the following command:
There’s a ton of flags available to this command, but we won’t get into them today.
This will lead us through a series of prompts to set up our project, including name and path for the project (remember, the path can be anywhere on your system!), the starter theme you would like to use, the database information, etc. Using all of that information,
tj will create the necessary files needed to get you up and running as quickly as possible. After the series of prompts, you’ll be asked to confirm:
On your first
create, it’ll go ahead and install VVV into the
~/vagrant directory (unless another path is specified via global flags, or VVV is already installed) and then it’ll provision the VM, which might take a few minutes if you’ve never done it before.
After that’s all finished up,
tj will do its thing and in a few minutes (basically, the time it takes to provision the VM with the new changes), you’ll have a brand new development project to work with. Did I mention that you can automatically access this new project from any device on your network?
Setting up an Existing Project
Working on an existing project? To make life easy, you can run the command below to set up existing projects into the VM:
The prompts will pretty much be identical to a
create (internally, it’s actually the same command), with a few prompts omitted such as asking for a starter theme. Like
create, this command also has a ton of flags available for it.
Removing a Project
One thing that I wanted to make sure was possible with
tj is having the freedom to delete a project from the VM, without actually deleting all of my files. Why? Because I don’t need 20 projects running inside of my VM, when I’m only actively working on 2-3 of them. This allows you to create, remove, and recreate projects with ease.
Now that I’ve mentioned how
tj handles removals, to remove a project from the VM, simply run the command below and follow the prompts:
By default, your database is not dropped when removing a project (to allow easier restoration later on), but just in case you want to drop it, you can use the
--drop-db flag. Check out the documentation to see the full list of flags.
Juicefile is a YAML configuration file that can be used to store commonly-used build scripts and deployment configuration. Each command list can be mapped to an individual project’s build tool, allowing a streamlined set of commands to be used across multiple projects that utilize different tools. To better understand this, check out our starter theme’s
Juicefile; it contains command mappings for all of our build tools and dependency managers:
commands: install: # Run application install scripts - composer install - bundle install - npm install - bower install - grunt build watch: # Manage build tools - grunt %args% assets: # Manage front-end dependencies - bower %args% vendor: # Manage back-end dependencies - composer %args% wp: # Manage WP installation - wp ssh --host=vagrant %args% backup: # Create a backup of the local database - mkdir -p backup - wp ssh --host=vagrant db export backup/$(date +'%Y-%m-%d-%H-%M-%S').local.sql
As you can tell by looking at the configuration above, we’re able to do some minor scripting with arguments. This isn’t huge, but does allow you to better utilize your aliases. For example, by running
tj install we’re able to quickly run our entire build process in the correct order; or another example, we can run
tj vendor update to update all our our Composer dependencies.
This feature obviously isn’t for everybody, especially when you don’t use many dependency managers or build tools. That being said, it works well for us, especially since our build stack is full of pre-compiled languages like Haml, Sass and CoffeeScript.
Interested in learning more about how to set up and utilize a
Juicefile? Check out the documentation for all of the available options.
Deploying a Project
There’s not a lot of things that I dislike more than FTP deployments. By utilizing the popular tool Capistrano, plus an awesome rsync extension,
tj is able to create one-command deployments for all of your projects that are both quick and reliable, without the need for having all of your build tools installed on your remote servers. Setting up a deployment stage is as simple as this:
stages: production: # Stage name server: 192.168.50.4 # Server IP or domain path: /var/www/production # Path to the web root user: deploy # User to deploy as url: example.com # URL for stage uploads: app/uploads # Path to uploads directory from project root tmp: tmp # Path to temp directory shared: # Files to share between deployments - .env.production ignore: # Files to ignore on deployments - robots.txt roles: # Stage roles (for Capistrano) - :web - :app - :db
Once you set up your deployment configuration within your project’s
Juicefile (check out our configuration for inspiration), you simply need to run:
tj deploy <stage>
Aaaaannd you’re off!
tj can also handle database migration with a single command via
tj remote <stage> db:pull and
tj remote <stage> db:push.
In pretty much the same way, you can migrate the
uploads/ folder and
.env file between stages. Want to get started with your first deploy? Head over here and follow the quick setup guide to easily get up and running.
I hope you’ve enjoyed this article. We’ve looked into how
tj can help you leave your dated MAMP workflow behind, while also allowing you to take advantage of its many features. Interested in learning more? Let us know! If the demand is there, I’d love to do a screencast for creating a new project, or setting up and deploying your first project.
If you have any questions regarding what we discussed today, let me know in the comments below or hit me up on Twitter and I’ll help you out wherever I can.
The Principles of Beautiful Web Design, 4th Edition
Learn PHP in One Day and Learn It Well
Learn SQL (using MySQL) in One Day and Learn It Well