-
GitHub stars
-
Projects created
-
roots/wordpress
WordPress boilerplate with Composer, easier configuration, and an improved folder structure
Modern WordPress development starts here — Professional project structure with Composer
Bedrock organizes WordPress with better security, dependency management, and environment-specific configuration for professional development teams.
~/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 wpackagist-theme/twentytwentyfive (1.3): Extracting archive
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 15,691,689 times.
Install plugins with Composer
/srv/www/my-site
$ composer require wpackagist-plugin/woocommerce
./composer.json has been updated
- Downloading wpackagist-plugin/woocommerce (9.5.2)
- Installing wpackagist-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": [
{
"type": "composer",
"url": "https://wpackagist.org",
"only": ["wpackagist-plugin/*", "wpackagist-theme/*"]
}
],
"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",
"wpackagist-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",
"wpackagist-plugin/akismet",
"wpackagist-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",
"wpackagist-plugin/akismet": "^5.3",
"wpackagist-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 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 |
Sponsors
Help support our open-source development efforts
Built with Bedrock
Recommendations
I'm a big fan of Bedrock (and all of Roots in general)
Bedrock is like the bridge between WordPress and the rest of PHP
In my opinion, the roots.io toolkit is the most sane way to do WordPress in 2023
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.
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.
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.
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.
Subscribe for updates
Join over 8,000 subscribers on our newsletter to get the latest Roots updates and tips on building better WordPress sites
Looking for WordPress plugin recommendations, the newest modern WordPress projects, and general web development tips and articles?