Deprecated: Function get_magic_quotes_gpc() is deprecated in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 99

Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 619

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1169

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176
Bedrock | Modern WordPress Boilerplate | Roots
Nothing Special   »   [go: up one dir, main page]

Skip to content
Bedrock
v1.28.3

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
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)

Josh Koenig Josh Koenig

Bedrock is like the bridge between WordPress and the rest of PHP

Carl Alexander Carl Alexander

In my opinion, the roots.io toolkit is the most sane way to do WordPress in 2023

Andrew Halliwell 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 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 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 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 Michael Snook

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?

One last step! Check your email for a verification link.