WordPress Development Workflow: From Local to Production
A robust WordPress development workflow is the backbone of any successful project. Whether you're a solo developer or part of a larger team, having a well-defined process for moving code from local development to production can save you countless hours and prevent costly mistakes.
In this comprehensive guide, we'll walk through setting up an efficient WordPress development workflow that scales with your projects and keeps your sanity intact. We'll cover everything from local development environments to automated deployment strategies, with practical examples you can implement today.
Setting Up Your Local Development Environment
Your local development environment is where the magic happens. It needs to be reliable, fast, and as close to your production environment as possible to avoid the dreaded "it works on my machine" syndrome.
Choosing the Right Local Environment
There are several excellent options for local WordPress development:
- Local by Flywheel: User-friendly with one-click SSL and easy site sharing
- XAMPP/MAMP: Traditional Apache/MySQL/PHP stacks
- Docker: Containerized environments for ultimate flexibility
- Valet/Herd: Lightweight solutions for macOS developers
For most developers, I recommend starting with Local by Flywheel for its simplicity, then graduating to Docker as your needs become more complex.
Here's a basic Docker Compose setup for WordPress development:
version: '3.8'
services:
wordpress:
image: wordpress:latest
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_NAME: wordpress
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: password
volumes:
- ./wp-content:/var/www/html/wp-content
db:
image: mysql:5.7
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: password
MYSQL_ROOT_PASSWORD: rootpassword
volumes:
- db_data:/var/lib/mysql
volumes:
db_data:
Version Control Best Practices
Your WordPress project should live in Git from day one. Here's a .gitignore file that covers the essentials:
# WordPress core
/wp-admin/
/wp-includes/
/wp-content/index.php
/wp-content/languages
/wp-content/plugins/index.php
/wp-content/themes/index.php
# WordPress config
wp-config.php
wp-config-local.php
# Uploads
/wp-content/uploads/
# Plugins (unless custom)
/wp-content/plugins/
# Cache and logs
/wp-content/cache/
*.log
# Environment files
.env
.env.local
The key principle here is to only version control what you've built. WordPress core, third-party plugins, and uploads shouldn't be in your repository. Instead, use dependency management tools like Composer to manage these components.
Development Workflow Strategies
Feature Branch Workflow
The feature branch workflow is perfect for WordPress development. Here's how it works:
- Main branch contains production-ready code
- Develop branch contains the latest development changes
- Feature branches are created for each new feature or bug fix
# Create a new feature branch
git checkout -b feature/new-homepage-design
# Work on your feature
git add .
git commit -m "Add hero section to homepage template"
# Push and create pull request
git push origin feature/new-homepage-design
This approach works particularly well when combined with WapuuLink's WordPress Developer API for automated testing and deployment workflows.
Database Management
One of the biggest challenges in WordPress development is managing database changes across environments. Here are several strategies:
1. Migration Scripts Create custom WP-CLI commands for database changes:
<?php
class Update_User_Meta_Command extends WP_CLI_Command {
/**
* Updates user meta structure for v2.0
*/
public function update_user_meta() {
$users = get_users();
foreach ($users as $user) {
// Migrate old meta structure
$old_preference = get_user_meta($user->ID, 'old_pref', true);
if ($old_preference) {
update_user_meta($user->ID, 'new_preference_structure', $old_preference);
delete_user_meta($user->ID, 'old_pref');
}
}
WP_CLI::success('User meta migration completed.');
}
}
WP_CLI::add_command('migrate user-meta', 'Update_User_Meta_Command');
2. Configuration Management Use tools like WordPress CLI to export and import configuration:
# Export current site options
wp option list --format=json > site-config.json
# Import on another environment
wp option import site-config.json
Staging Environment Setup
Your staging environment should mirror production as closely as possible. This is where you test everything before it goes live.
Automated Staging Deployments
Set up automated deployments to staging whenever you push to your develop branch. Here's a GitHub Actions workflow example:
name: Deploy to Staging
on:
push:
branches: [ develop ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
- name: Install dependencies
run: composer install --no-dev --optimize-autoloader
- name: Deploy to staging
uses: easingthemes/ssh-deploy@v2.1.5
env:
SSH_PRIVATE_KEY: ${{ secrets.STAGING_SSH_KEY }}
REMOTE_HOST: ${{ secrets.STAGING_HOST }}
REMOTE_USER: ${{ secrets.STAGING_USER }}
SOURCE: "."
TARGET: "/var/www/staging"
Testing on Staging
Your staging environment is perfect for automated testing. Consider implementing:
- Visual regression testing with tools covered in our WordPress Visual QA Testing guide
- Performance testing using the strategies from our WordPress Performance Optimization checklist
- Accessibility testing following our WordPress Accessibility guidelines
Production Deployment Strategies
When it comes to production deployments, reliability and speed are paramount. Here are the most effective strategies for WordPress sites.
Blue-Green Deployments
Blue-green deployments minimize downtime by maintaining two identical production environments. While one serves live traffic (blue), you deploy to the other (green), then switch traffic over.
#!/bin/bash
# Simple blue-green deployment script
CURRENT=$(readlink /var/www/current)
if [[ $CURRENT == *"blue"* ]]; then
DEPLOY_TO="green"
LIVE="blue"
else
DEPLOY_TO="blue"
LIVE="green"
fi
echo "Deploying to $DEPLOY_TO environment..."
# Deploy code to the inactive environment
rsync -av --delete /tmp/deploy/ /var/www/$DEPLOY_TO/
# Run any necessary updates
cd /var/www/$DEPLOY_TO
wp core update-db --allow-root
# Switch traffic
ln -sfn /var/www/$DEPLOY_TO /var/www/current
# Restart services
systemctl reload nginx
systemctl reload php8.1-fpm
echo "Deployment complete. Traffic switched to $DEPLOY_TO"
Zero-Downtime Deployments
For high-traffic sites, even a few seconds of downtime isn't acceptable. Here's a deployment strategy that achieves true zero-downtime:
- Deploy code to a new directory with a timestamp
- Run database migrations (design them to be backward-compatible)
- Update the symlink to point to the new directory
- Reload services (PHP-FPM, opcache, etc.)
- Clean up old deployments
This approach works exceptionally well when combined with API-driven workflows. You can use WapuuLink's API to trigger deployments, run health checks, and manage the entire process programmatically.
Automation and CI/CD
Automation is what transforms a good workflow into a great one. Let's explore how to automate the repetitive parts of your deployment process.
Continuous Integration Setup
A robust CI pipeline for WordPress should include:
- Code quality checks (PHP_CodeSniffer, ESLint)
- Security scanning (WPScan, composer audit)
- Unit testing (PHPUnit)
- Integration testing
Here's a comprehensive GitHub Actions workflow:
name: WordPress CI/CD Pipeline
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
services:
mysql:
image: mysql:5.7
env:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: wordpress_test
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
steps:
- uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
extensions: mysql
- name: Install WordPress Test Suite
run: |
bash bin/install-wp-tests.sh wordpress_test root password 127.0.0.1 latest
- name: Run PHPUnit tests
run: vendor/bin/phpunit
- name: Run PHP_CodeSniffer
run: vendor/bin/phpcs --standard=WordPress .
- name: Security scan
run: composer audit
deploy:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Deploy to production
run: |
# Your deployment script here
echo "Deploying to production..."
Database Synchronization
One of the trickiest aspects of WordPress workflows is keeping databases synchronized between environments. Here are some strategies that work well:
Content Staging: Use plugins like WP Staging or custom scripts to copy production data to staging periodically, while preserving development-specific settings.
Selective Sync: Create scripts that sync specific content types or date ranges:
<?php
// Sync recent posts for content testing
function sync_recent_content() {
$recent_posts = get_posts([
'numberposts' => 50,
'post_status' => 'publish',
'date_query' => [
'after' => '30 days ago'
]
]);
// Export and transfer logic here
foreach ($recent_posts as $post) {
// Process each post for staging environment
}
}
For complex synchronization needs, consider using WapuuLink's API documentation to build custom sync workflows that maintain data integrity across environments.
Monitoring and Maintenance
Your workflow doesn't end at deployment. Ongoing monitoring and maintenance are crucial for long-term success.
Automated Monitoring
Set up monitoring for:
- Site uptime and response times
- Error rates in PHP and WordPress logs
- Performance metrics like Time to First Byte (TTFB)
- Security issues and plugin vulnerabilities
Tools like New Relic, Query Monitor, or custom solutions can provide the visibility you need.
Automated Updates
Create a strategy for handling WordPress core, plugin, and theme updates:
#!/bin/bash
# Automated update script with rollback capability
# Create backup
wp db export backup-$(date +%Y%m%d-%H%M%S).sql
# Update WordPress core
wp core update
# Update plugins (exclude problematic ones)
wp plugin update --all --exclude=problematic-plugin
# Run health check
HEALTH_CHECK=$(wp eval 'echo is_admin() ? "OK" : "FAIL";')
if [ "$HEALTH_CHECK" != "OK" ]; then
echo "Health check failed, rolling back..."
# Rollback logic here
exit 1
fi
echo "Updates completed successfully"
The power of a well-designed workflow becomes even more apparent when you can integrate it with modern tools. For instance, our guide on how AI is changing WordPress agency workflows shows how artificial intelligence can automate many of the manual steps we've discussed.
Advanced Workflow Techniques
Environment Configuration Management
Use environment-specific configuration files to manage settings across different stages:
<?php
// wp-config.php
$environment = $_ENV['WP_ENVIRONMENT'] ?? 'production';
switch ($environment) {
case 'local':
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('SCRIPT_DEBUG', true);
break;
case 'staging':
define('WP_DEBUG', false);
define('WP_DEBUG_LOG', true);
// Prevent search engines from indexing
define('BLOG_PUBLIC', 0);
break;
case 'production':
define('WP_DEBUG', false);
define('WP_DEBUG_LOG', false);
define('SCRIPT_DEBUG', false);
break;
}
Automated Testing Integration
Integrate automated testing into your workflow using tools like Codeception or WordPress's own testing framework:
<?php
class HomepageCest
{
public function _before(AcceptanceTester $I)
{
$I->amOnPage('/');
}
public function seeHomepageElements(AcceptanceTester $I)
{
$I->see('Welcome to Our Site', 'h1');
$I->seeElement('.hero-section');
$I->seeElement('.navigation-menu');
}
public function checkPageLoadTime(AcceptanceTester $I)
{
$start = microtime(true);
$I->amOnPage('/');
$loadTime = microtime(true) - $start;
$I->assertLessThan(2.0, $loadTime, 'Page should load in under 2 seconds');
}
}
API-Driven Workflows
Modern WordPress development increasingly relies on API-driven approaches. Whether you're using the WordPress REST API, WapuuLink API, or GraphQL, APIs can streamline your workflow significantly.
For example, you might use WP-CLI with API calls to automate complex deployment tasks:
#!/bin/bash
# API-driven deployment script
# Trigger pre-deployment checks via API
curl -X POST "https://api.yoursite.com/deploy/pre-check" \
-H "Authorization: Bearer $API_TOKEN"
# Deploy code
git pull origin main
composer install --no-dev
# Notify completion via API
curl -X POST "https://api.yoursite.com/deploy/complete" \
-H "Authorization: Bearer $API_TOKEN" \
-d '{"version": "'$(git rev-parse HEAD)'", "environment": "production"}'
This API-first approach makes it easy to integrate with external tools and create custom dashboards for monitoring your deployments.
Troubleshooting Common Workflow Issues
Even with the best workflows, issues arise. Here are solutions to common problems:
Database Sync Conflicts
When database changes conflict between environments, use WordPress's built-in update system:
<?php
// In your plugin or theme's functions.php
function my_database_update_check() {
$current_version = get_option('my_db_version', '0');
if (version_compare($current_version, '1.2.0', '<')) {
my_database_update_1_2_0();
update_option('my_db_version', '1.2.0');
}
}
add_action('init', 'my_database_update_check');
Plugin Conflicts in Production
Use a staged rollout approach:
# Enable new plugin for admin users only
wp plugin activate