# WordPress with Composer & Git

## Professional project structure and dependency management

### Enhanced security with environment-specific configuration

`~/Code/`

```
$ composer create-project roots/bedrock my-site

Creating a "roots/bedrock" project at "./my-site"
Installing roots/bedrock (1.28.3)
  - Downloading roots/bedrock (1.28.3)
  - Installing roots/bedrock (1.28.3): Extracting archive
  - Installing roots/wordpress (6.8.3)
  - Installing wp-theme/twentytwentyfive (1.3): Extracting archive
```

[Read the docs](/bedrock/docs/installation/) [View the repo](https://github.com/roots/bedrock)

## Manage WordPress with Composer

Treat WordPress core, plugins, and themes as dependencies. Composer makes development more reliable, improves team collaboration, and maintains a cleaner Git repository. Our `roots/wordpress` package has been installed [17,239,750](/composer-wordpress-resources/) times.

### Install plugins with Composer

`/srv/www/my-site`

```
$ composer require wp-plugin/woocommerce
./composer.json has been updated
  - Downloading wp-plugin/woocommerce (9.5.2)
  - Installing wp-plugin/woocommerce (9.5.2): Extracting archive
Generating optimized autoload files
```

### Dependencies in composer.json

`composer.json`

```
{
  "name": "roots/bedrock",
  "type": "project",
  "license": "MIT",
  "description": "WordPress boilerplate with Composer, easier configuration, and an improved folder structure",
  "homepage": "https://roots.io/bedrock/",
  "keywords": ["bedrock", "composer", "roots", "wordpress", "wp", "wp-config"],
  "support": {
    "issues": "https://github.com/roots/bedrock/issues",
    "forum": "https://discourse.roots.io/category/bedrock"
  },
  "repositories": [{
      "name": "wp-packages",
      "type": "composer",
      "url": "https://repo.wp-packages.org"
    }],
  "require": {
    "php": ">=8.1",
    "composer/installers": "^2.2",
    "vlucas/phpdotenv": "^5.5",
    "oscarotero/env": "^2.1",
    "roots/bedrock-autoloader": "^1.0",
    "roots/bedrock-disallow-indexing": "^2.0",
    "roots/wordpress": "6.8.3",
    "roots/wp-config": "1.0.0",
    "wp-theme/twentytwentyfive": "^1.0"
  },
  "require-dev": {
    "roave/security-advisories": "dev-latest",
    "laravel/pint": "^1.18"
  },
  "config": {
    "optimize-autoloader": true,
    "preferred-install": "dist",
    "allow-plugins": {
      "composer/installers": true,
      "roots/wordpress-core-installer": true
    }
  },
  "minimum-stability": "dev",
  "prefer-stable": true,
  "extra": {
    "installer-paths": {
      "web/app/mu-plugins/{$name}/": ["type:wordpress-muplugin"],
      "web/app/plugins/{$name}/": ["type:wordpress-plugin"],
      "web/app/themes/{$name}/": ["type:wordpress-theme"]
    },
    "wordpress-install-dir": "web/wp"
  },
  "scripts": {
    "lint": "pint --test",
    "lint:fix": "pint"
  }
}

```

## Environment-specific configuration

Use .env files and environment-specific configs to manage different settings for development, staging, and production. Keep sensitive data out of your repository with secure environment variables.

### Environment variables

`.env`

```
DB_NAME='database_name'
DB_USER='database_user'
DB_PASSWORD='database_password'

WP_ENV='development'
WP_HOME='http://example.com'
WP_SITEURL="${WP_HOME}/wp"

```

### Main configuration

`config/application.php`

```
<?php

/**
 * URLs
 */
Config::define('WP_HOME', env('WP_HOME'));
Config::define('WP_SITEURL', env('WP_SITEURL'));

/**
 * Custom Content Directory
 */
Config::define('CONTENT_DIR', '/app');
Config::define('WP_CONTENT_DIR', $webroot_dir . Config::get('CONTENT_DIR'));
Config::define('WP_CONTENT_URL', Config::get('WP_HOME') . Config::get('CONTENT_DIR'));

/**
 * DB settings
 */
Config::define('DB_NAME', env('DB_NAME'));
Config::define('DB_USER', env('DB_USER'));
Config::define('DB_PASSWORD', env('DB_PASSWORD'));
Config::define('DB_HOST', env('DB_HOST') ?: 'localhost');
Config::define('DB_CHARSET', 'utf8mb4');
Config::define('DB_COLLATE', '');
$table_prefix = env('DB_PREFIX') ?: 'wp_';

/**
 * Authentication Unique Keys and Salts
 */
Config::define('AUTH_KEY', env('AUTH_KEY'));
Config::define('SECURE_AUTH_KEY', env('SECURE_AUTH_KEY'));
Config::define('LOGGED_IN_KEY', env('LOGGED_IN_KEY'));
Config::define('NONCE_KEY', env('NONCE_KEY'));
Config::define('AUTH_SALT', env('AUTH_SALT'));
Config::define('SECURE_AUTH_SALT', env('SECURE_AUTH_SALT'));
Config::define('LOGGED_IN_SALT', env('LOGGED_IN_SALT'));
Config::define('NONCE_SALT', env('NONCE_SALT'));

/**
 * Custom Settings
 */
Config::define('AUTOMATIC_UPDATER_DISABLED', true);
Config::define('DISABLE_WP_CRON', env('DISABLE_WP_CRON') ?: false);

// Disable the plugin and theme file editor in the admin
Config::define('DISALLOW_FILE_EDIT', true);

// Disable plugin and theme updates and installation from the admin
Config::define('DISALLOW_FILE_MODS', true);

// Limit the number of post revisions
Config::define('WP_POST_REVISIONS', env('WP_POST_REVISIONS') ?? true);

// Disable script concatenation
Config::define('CONCATENATE_SCRIPTS', false);

/**
 * Debugging Settings
 */
Config::define('WP_DEBUG_DISPLAY', false);
Config::define('WP_DEBUG_LOG', false);
Config::define('SCRIPT_DEBUG', false);
ini_set('display_errors', '0');

Config::apply();

/**
 * Bootstrap WordPress
 */
if (!defined('ABSPATH')) {
    define('ABSPATH', $webroot_dir . '/wp/');
}

```

## Must use plugin autoloader & automated updates

Force regular plugins to work as must-use plugins with Bedrock's autoloader. Set up automated WordPress and plugin updates using tools like Renovate for worry-free maintenance.

### Configure mu-plugins in composer.json

`composer.json`

```
{
  "name": "roots/bedrock",
  "extra": {
    "installer-paths": {
      "web/app/mu-plugins/{$name}/": ["type:wordpress-muplugin",
        "wp-plugin/akismet",
        "wp-plugin/disable-comments"],
      "web/app/plugins/{$name}/": ["type:wordpress-plugin"],
      "web/app/themes/{$name}/": ["type:wordpress-theme"]
    },
    "wordpress-install-dir": "web/wp"
  },
  "require": {
    "roots/bedrock-autoloader": "^1.0",
    "wp-plugin/akismet": "^5.3",
    "wp-plugin/disable-comments": "^2.4"
  }
}

```

### Automated updates with Renovate

`renovate.json`

```
{
  "baseBranches": ["master"],
  "commitMessageAction": "⬆️ Bump",
  "commitMessageTopic": "{{depName}}",
  "extends": ["config:base", "schedule:weekly"],
  "packageRules": [{
      "matchUpdateTypes": ["minor", "patch", "pin"]
    },
    {
      "groupName": "roots/wordpress",
      "matchPackagePrefixes": ["roots/wordpress"],
      "schedule": ["at any time"]
    }],
  "timezone": "America/Chicago"
}

```

## Enhanced security & production-ready

Bedrock's structure keeps sensitive files out of the web root and provides production-safe defaults. WordPress core and plugins can't be modified in non-development environments.

## Better Git repository management

Keep WordPress core and plugins out of version control. Your repository contains only your custom code, configuration, and dependencies list—not hundreds of WordPress files.

### Bedrock structure

```
├── composer.json
├── config
│   ├── application.php     # Primary wp-config
│   └── environments
│       ├── development.php
│       ├── staging.php
│       └── production.php
├── vendor                  # Composer dependencies
└── web                     # Public document root
    ├── app                 # WordPress content dir
    │   ├── mu-plugins
    │   ├── plugins
    │   ├── themes
    │   └── uploads
    ├── wp-config.php
    ├── index.php
    └── wp                  # WordPress core

```

### Standard WordPress structure

```
├── index.php
├── license.txt
├── readme.html
├── wp-activate.php
├── wp-admin
├── wp-blog-header.php
├── wp-comments-post.php
├── wp-config-sample.php
├── wp-content
│   ├── index.php
│   ├── plugins
│   └── themes
├── wp-cron.php
├── wp-includes
├── wp-links-opml.php
├── wp-load.php
├── wp-login.php
├── wp-mail.php
├── wp-settings.php
├── wp-signup.php
├── wp-trackback.php
└── xmlrpc.php

```

|  | Bedrock | WordPress WordPress |
|---|---|---|
| WordPress coding standards1 | ❌ | ✅ |
| Traditional WordPress structure2 | ❌ | ✅ |
| Separate configs per environment | ✅ | ❌ |
| Environment variables | ✅ | ❌ |
| Custom wp-content directory | ✅ | ❌ |
| Composer for managing WordPress installation | ✅ | ❌ |
| Composer for managing WordPress plugins and themes | ✅ | ❌ |
| mu-plugins autoloader | ✅ | ❌ |
| 1. WordPress coding standards are not enforced by default, but can added if that is your preference |
| 2. Bedrock leverages functionality that WordPress Core provides and is [compatible with most plugins](/bedrock/docs/compatibility/) |

[Read the docs](/bedrock/docs/installation/) [View the repo](https://github.com/roots/bedrock)

## Sponsors

- [![Carrot](https://roots.io/build/assets/carrot-U-3tnBjH.svg)](https://carrot.com/)
- [![WordPress.com](https://roots.io/build/assets/wordpress-com-COwyg-kV.svg)](https://wordpress.com/)
- [![Itineris](https://roots.io/build/assets/itineris-B1enfPfI.svg)](https://www.itineris.co.uk/)
- [![Kinsta](https://roots.io/build/assets/kinsta-wOzVJCcU.svg)](https://kinsta.com/?kaid=OFDHAJIXUDIV)

Roots is an independent open source org, supported only by developers like you. [Become a sponsor](/sponsors/).

## Built with Bedrock

[![Screenshot of https://www.spin.com/](https://roots.io/build/assets/spin-com-Ds-3zJ3j.png)https://www.spin.com/](https://www.spin.com/) [![Screenshot of https://gizmodo.com/](https://roots.io/build/assets/gizmodo-com-nV3rWMGh.png)https://gizmodo.com/](https://gizmodo.com/) [![Screenshot of https://darksky.org/](https://roots.io/build/assets/darksky-org-BokLmw_C.png)https://darksky.org/](https://darksky.org/) [![Screenshot of https://unfoundation.org/](https://roots.io/build/assets/unfoundation-org-CDM7gGMY.png)https://unfoundation.org/](https://unfoundation.org/) [![Screenshot of https://www.popsci.com/](https://roots.io/build/assets/popsci-com-BkLiIogu.png)https://www.popsci.com/](https://www.popsci.com/) [![Screenshot of https://elprograms.org/](https://roots.io/build/assets/elprograms-org-80le71Uy.png)https://elprograms.org/](https://elprograms.org/) [![Screenshot of https://www.crediful.com/](https://roots.io/build/assets/crediful-com-C9igKt4g.png)https://www.crediful.com/](https://www.crediful.com/) [![Screenshot of https://nutritionfacts.org/](https://roots.io/build/assets/nutritionfacts-org-DywgPglO.png)https://nutritionfacts.org/](https://nutritionfacts.org/) [![Screenshot of https://www.sapiens.org/all-articles/](https://roots.io/build/assets/sapiens-org-t8FDNHrA.png)https://www.sapiens.org/all-articles/](https://www.sapiens.org/all-articles/) [![Screenshot of https://movementgyms.com/](https://roots.io/build/assets/movementgyms-com-heqa5pKL.png)https://movementgyms.com/](https://movementgyms.com/) [![Screenshot of https://foxsoul.tv/](https://roots.io/build/assets/foxsoul-tv-DFJOVaHa.png)https://foxsoul.tv/](https://foxsoul.tv/) [![Screenshot of https://www.nytimes.com/athletic/](https://roots.io/build/assets/nytimes-com-yhl8SAYd.png)https://www.nytimes.com/athletic/](https://www.nytimes.com/athletic/) [![Screenshot of https://www.docker.com/](https://roots.io/build/assets/docker-com-A36wb8ts.png)https://www.docker.com/](https://www.docker.com/) [![Screenshot of https://www.theschooloflife.com/](https://roots.io/build/assets/theschooloflife-com-DUMepGDF.png)https://www.theschooloflife.com/](https://www.theschooloflife.com/) [![Screenshot of https://www.mercedes-benz.io/](https://roots.io/build/assets/mercedes-benz-io-Dh_lKpXV.png)https://www.mercedes-benz.io/](https://www.mercedes-benz.io/) [![Screenshot of https://thewaltdisneycompany.com/](https://roots.io/build/assets/thewaltdisneycompany-com-BJA7e6dW.png)https://thewaltdisneycompany.com/](https://thewaltdisneycompany.com/) [![Screenshot of https://disneyrewards.com/](https://roots.io/build/assets/disneyrewards-com-BruR2ysx.png)https://disneyrewards.com/](https://disneyrewards.com/) [![Screenshot of https://www.quiktrip.com/](https://roots.io/build/assets/quiktrip-com-8CulKn5F.png)https://www.quiktrip.com/](https://www.quiktrip.com/) [![Screenshot of https://www.raspberrypi.org/](https://roots.io/build/assets/raspberrypi-org-DvY_usHo.png)https://www.raspberrypi.org/](https://www.raspberrypi.org/) [![Screenshot of https://yoast.com/](https://roots.io/build/assets/yoast-com-Mn3FrHxG.png)https://yoast.com/](https://yoast.com/) [![Screenshot of https://www.sandia.gov/](https://roots.io/build/assets/sandia-gov-Dlh_3bxK.png)https://www.sandia.gov/](https://www.sandia.gov/) [![Screenshot of https://www.usafa.edu/](https://roots.io/build/assets/usafa-edu-C7W0mJb4.png)https://www.usafa.edu/](https://www.usafa.edu/) [![Screenshot of https://www.banquepopulaire.fr/](https://roots.io/build/assets/banquepopulaire-fr-CfW-NnMz.png)https://www.banquepopulaire.fr/](https://www.banquepopulaire.fr/) [![Screenshot of https://www.tours.fr/](https://roots.io/build/assets/tours-fr-DoXD3Rl0.png)https://www.tours.fr/](https://www.tours.fr/) [![Screenshot of https://www.enac.gov.it/](https://roots.io/build/assets/enac-gov-it-BnGQ6Ne5.png)https://www.enac.gov.it/](https://www.enac.gov.it/) [![Screenshot of https://www.uwa.edu/](https://roots.io/build/assets/uwa-edu-GB7fjG0I.png)https://www.uwa.edu/](https://www.uwa.edu/) [![Screenshot of https://washu.edu/](https://roots.io/build/assets/washu-edu-O2l20bXJ.png)https://washu.edu/](https://washu.edu/) [![Screenshot of https://www.seussville.com/](https://roots.io/build/assets/seussville-com-DVEpUH2Z.png)https://www.seussville.com/](https://www.seussville.com/) [![Screenshot of https://highrollerlobster.com/](https://roots.io/build/assets/highrollerlobster-com-DLBbtOlO.png)https://highrollerlobster.com/](https://highrollerlobster.com/) [![Screenshot of https://faircompanies.com/](https://roots.io/build/assets/faircompanies-com-DHntiCxf.png)https://faircompanies.com/](https://faircompanies.com/)

## Recommendations

> I'm a big fan of Bedrock (and all of Roots in general)
> 
> ![Josh Koenig](https://roots.io/build/assets/josh-koenig-UZlxThhu.jpg) Josh Koenig

> Bedrock is like the bridge between WordPress and the rest of PHP
> 
> ![Carl Alexander](https://roots.io/build/assets/carl-alexander-Dt_iLlr2.jpg) Carl Alexander

> In my opinion, the roots.io toolkit is the most sane way to do WordPress in 2023
> 
> ![Andrew Halliwell](https://roots.io/build/assets/andrew-halliwell-Cg7WRrLV.jpg) Andrew Halliwell

> Roots' distros have been essential to jumping back into WordPress devel after a decade out. Until WP quits being an antiquated, monetized pit of code, this is all that’s holding my sanity in check.
> 
> ![Ross J Kuhn](https://roots.io/build/assets/ross-j-kuhn-BUo8GxT0.jpg) Ross J Kuhn

> Bedrock is doing a huge service to the WordPress community, and I can see it being adopted as the standard for WordPress development. Hopefully as more people adopt it, the developer community at large will view WordPress sites on similar footing as more “professional” platforms.
> 
> ![Daniel Strunk](https://roots.io/build/assets/daniel-strunk-CbrBRn_R.jpg) Daniel Strunk

> If you have to use WordPress, use Bedrock for your web app and Sage to develop your custom theme. Any Laravel developer will feel at home in these tools.
> 
> ![Rory McDaniel](https://roots.io/build/assets/rory-mcdaniel-CTlkgQxJ.jpg) Rory McDaniel

> I think 2 years ago I tweeted to y'all to say I love Sage -- now I'm getting started with Bedrock and loving it! thank you for making me feel like WordPress can be sane, secure, and modern.
> 
> ![Michael Snook](https://roots.io/build/assets/michael-snook-C2siJAXm.jpg) Michael Snook

- Version [v1.30.1](https://github.com/roots/bedrock/releases)

- [Documentation](/bedrock/docs/installation/)
- [GitHub](https://github.com/roots/bedrock)