Deploying a Composer-Based WordPress Site (Including Bedrock) to WP Engine

Iain Poulson Avatar

·

Modern WordPress development has increasingly embraced Composer as a way to manage dependencies and improve workflow consistency. Whether you’re using a custom Composer setup or a framework like Bedrock, WP Engine supports deploying these projects—with a few adjustments.

This guide covers how to structure and deploy a Composer-based site to WP Engine using GitHub Actions, including Bedrock-specific notes.

Benefits of Using Composer for WordPress

Composer is a dependency management tool in PHP that offers several advantages for WordPress development:

  • Dependency Management: Easily manage WordPress core, plugins, themes, and PHP packages.
  • Version Control: Keep track of exact versions of all dependencies, ensuring consistency across environments.
  • Automation: Automate updates and deployments, reducing manual errors.
  • Cleaner Repositories: Avoid committing vendor files or plugin code, keeping your repository clean and focused on custom code.

By leveraging Composer, you can create a more maintainable and scalable WordPress project.

Managing Plugins and Themes with WPackagist

WPackagist mirrors the WordPress.org plugin and theme directories as Composer packages, allowing you to manage them as dependencies.

To use WPackagist:

1. Add WPackagist as a repository in your composer.json:

{
  "repositories": [
    {
      "type": "composer",
      "url": "https://wpackagist.org"
    }
  ]
}
Code language: JSON / JSON with Comments (json)

2. Require plugins or themes using the wpackagist-plugin or wpackagist-theme prefixes:

{
  "require": {
    "wpackagist-plugin/advanced-custom-fields": "^6.0",
    "wpackagist-theme/twentytwentysix": "*"
  }
}
Code language: JSON / JSON with Comments (json)

3. Run composer install to install the specified plugins and themes.

This approach ensures that your plugins and themes are version-controlled and can be easily updated or rolled back as needed.

Project Structure Considerations

Typical Composer-based sites move the WordPress core files to a different directory, for example /web or /public and with that the wp-content directory housing the plugins and themes will move there too. However, this is a different structure expected by WP Engine as a managed hosting platform. Bedrock also organizes WordPress files differently than the traditional structure expected by WP Engine.

Bedrock Structure:

├── composer.json
├── composer.lock
├── config/
├── web/
│   ├── app/            # wp-content equivalent
│   ├── wp/             # WordPress core
│   ├── index.php
│   └── wp-config.php
└── .env
Code language: PHP (php)

WP Engine Expected Structure:

├── wp-content/
├── wp-includes/
├── wp-admin/
├── index.php
├── wp-config.php
...

To deploy a Composer or Bedrock-based site to WP Engine, you’ll need to restructure your project during the deployment process to match WP Engine’s expectations.

Deployment with GitHub Actions

Use WP Engine’s official GitHub Action to automate deployments. This approach syncs your wp-content/ directory and runs Composer during the build step.

Standard Composer Setup

For sites using Composer with a standard WordPress structure:

name: Deploy to WP Engine

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.2'
          tools: composer:v2

      - name: Install Composer dependencies
        run: composer install --no-dev --optimize-autoloader --prefer-dist

      - name: Deploy to WP Engine
        uses: wpengine/github-action-wpe-site-deploy@v3
        with:
          WPE_SSHG_KEY_PRIVATE: ${{ secrets.WPE_SSHG_KEY_PRIVATE }}
          WPE_ENV: your-environment-name
          SRC_PATH: wp-content/
          REMOTE_PATH: wp-content/
          FLAGS: -azvr --inplace --delete --exclude='uploads'
Code language: JavaScript (javascript)

Including Composer Dependencies (Optional)

If your plugins or themes require PHP packages from vendor/, you’ll need to include it in the deployment. Since only wp-content/ is synced to WP Engine, copy vendor into wp-content/ and add a mu-plugin to load the autoloader:

      - name: Install Composer dependencies
        run: composer install --no-dev --optimize-autoloader --prefer-dist

      - name: Prepare vendor for deployment
        run: |
          mkdir -p wp-content/mu-plugins

          # Create autoloader mu-plugin
          cat > wp-content/mu-plugins/00-autoloader.php << 'EOF'
          <?php
          /**
           * Plugin Name: Composer Autoloader
           * Description: Loads the Composer autoloader.
           */
          if (file_exists($autoloader = dirname(__DIR__) . '/vendor/autoload.php')) {
              require_once $autoloader;
          }
          EOF

          # Copy vendor into wp-content for deployment
          cp -r vendor wp-content/

      - name: Deploy to WP Engine
        ...
Code language: PHP (php)

Composer’s autoloader uses relative paths, so it works correctly from wp-content/vendor/.

Bedrock Setup

For Bedrock projects, you’ll need to restructure from web/app/ to wp-content/ during the build.

Bedrock normally loads the Composer autoloader via its wp-config.php. Since WP Engine manages wp-config.php, the workflow below creates a mu-plugin to load it instead. The 00- prefix ensures it loads before other mu-plugins.

name: Deploy Bedrock to WP Engine

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.2'
          tools: composer:v2

      - name: Install Composer dependencies
        run: composer install --no-dev --optimize-autoloader --prefer-dist

      - name: Restructure for WP Engine
        run: |
          mkdir -p deploy/wp-content/mu-plugins

          # Create autoloader mu-plugin (WP Engine manages wp-config.php, so we load it here)
          cat > deploy/wp-content/mu-plugins/00-autoloader.php << 'EOF'
          <?php
          /**
           * Plugin Name: Composer Autoloader
           * Description: Loads the Composer autoloader for WP Engine deployments.
           */
          if (file_exists($autoloader = dirname(__DIR__) . '/vendor/autoload.php')) {
              require_once $autoloader;
          }
          EOF

          # Move app (wp-content equivalent) contents
          cp -r web/app/plugins deploy/wp-content/
          cp -r web/app/themes deploy/wp-content/
          cp -r web/app/mu-plugins/* deploy/wp-content/mu-plugins/ 2>/dev/null || true
          cp -r web/app/languages deploy/wp-content/ 2>/dev/null || true

          # Move vendor for Composer autoloading
          cp -r vendor deploy/wp-content/

      - name: Deploy to WP Engine
        uses: wpengine/github-action-wpe-site-deploy@v3
        with:
          WPE_SSHG_KEY_PRIVATE: ${{ secrets.WPE_SSHG_KEY_PRIVATE }}
          WPE_ENV: your-environment-name
          SRC_PATH: deploy/wp-content/
          REMOTE_PATH: wp-content/
          FLAGS: -azvr --inplace --delete --exclude='uploads'
Code language: PHP (php)

Setup Requirements

  1. SSH Key: Add your WP Engine SSH private key as a repository secret named WPE_SSHG_KEY_PRIVATE. Generate via WP Engine User Portal > SSH Keys.
  1. Environment Name: Replace your-environment-name with your WP Engine environment name.
  1. Branch Triggers: Adjust the branches trigger as needed (e.g., main for production, staging for staging).

Important Notes

  • WordPress core: WP Engine manages core files. Only deploy your wp-content/ or equivalent.
  • Uploads: Media uploads are not included in deployments. Use SFTP or WP Engine’s backup/restore tools.
  • Vendor directory: Required for Bedrock to enable the mu-plugin directory loader and any Composer dependencies. Include the 00-autoloader.php mu-plugin to load it.
  • Environment variables: Bedrock uses .env files. Ensure environment-specific config is handled appropriately for WP Engine.
  • First deploy: After your first deployment, log in to WordPress and activate your theme. The deploy uses --delete which removes the default theme, so you’ll need to activate the theme you deployed.

Further Reading