bedrock Documentation

WordPress boilerplate with Composer and Git, easier configuration, and an improved folder structure

RAW Doc

File: README.md

Support us

Roots is an independent open source org, supported only by developers like you. Your sponsorship funds WP Packages and the entire Roots ecosystem, and keeps them independent. Support us by purchasing Radicle or sponsoring us on GitHub โ€” sponsors get access to our private Discord.

Sponsors

Overview

Bedrock is a WordPress boilerplate for developers that want to manage their projects with Git and Composer. Much of the philosophy behind Bedrock is inspired by the Twelve-Factor App methodology, including the WordPress specific version.

  • Better folder structure
  • Dependency management with Composer
  • Easy WordPress configuration with environment specific files
  • Environment variables with Dotenv
  • Autoloader for mu-plugins (use regular plugins as mu-plugins)

Getting Started

See the Bedrock installation documentation.

Community

Keep track of development and community news.


File: 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/",
"authors": [
{
"name": "Scott Walkinshaw",
"email": "[email protected]",
"homepage": "https://github.com/swalkinshaw"
},
{
"name": "Ben Word",
"email": "[email protected]",
"homepage": "https://github.com/retlehs"
}
],
"keywords": [
"bedrock", "composer", "roots", "wordpress-composer", "wordpress", "wp-composer", "wp-config", "wp"
],
"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.3",
"composer/installers": "^2.0",
"oscarotero/env": "^2.0",
"roots/bedrock-autoloader": "^1.0",
"roots/bedrock-disallow-indexing": "^2.0",
"roots/wordpress": "7.1.3",
"roots/wp-config": "^1.0",
"vlucas/phpdotenv": "^5.0",
"wp-theme/twentytwentyfive": "^1.0"
},
"require-dev": {
"laravel/pint": "^1.0",
"pestphp/pest": "^4.0"
},
"config": {
"optimize-autoloader": true,
"preferred-install": "dist",
"allow-plugins": {
"composer/installers": true,
"roots/wordpress-core-installer": true,
"pestphp/pest-plugin": true
},
"sort-packages": 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",
"test": "pest"
}
}


File: LICENSE.md

Copyright (c) Roots Software LLC

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


File: pint.json

{
"preset": "per",
"exclude": [
"web/wp",
"web/app/mu-plugins/bedrock-disallow-indexing",
"web/app/plugins",
"web/app/themes/twentytwentyfive"
]
}


File: wp-cli.yml

path: web/wp
server:
docroot: web


File: .devcontainer/devcontainer.json

{
"name": "Bedrock Development",
"dockerComposeFile": ["docker-compose.yml"],
"service": "app",
"workspaceFolder": "/roots/app",
"forwardPorts": [8080],
"remoteEnv": {
"WP_ENV": "development"
},
"postCreateCommand": "cp -n /roots/app/.devcontainer/.env.example /roots/app/.env"
}


File: .devcontainer/docker-compose.yml

services:
app:
build:
context: .
dockerfile: Dockerfile
volumes:
- ..:/roots/app
- ./config/php.ini:/usr/local/etc/php/conf.d/bedrock.ini
networks:
- bedrock
depends_on:
database:
condition: service_healthy
environment:
WP_CLI_ALLOW_ROOT: 1

web:
image: nginx:alpine
ports:
- '8080:80'
volumes:
- ..:/roots/app:ro
- ./config/nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- app
networks:
- bedrock

database:
image: mariadb:12
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: password
MYSQL_ROOT_PASSWORD: password
networks:
- bedrock
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
timeout: 20s
retries: 10

networks:
bedrock:
driver: bridge


File: .github/renovate.json

{
"baseBranchPatterns": [
"master"
],
"commitMessageAction": "โฌ†๏ธ Bump",
"commitMessageTopic": "{{depName}}",
"extends": [
"config:recommended",
"schedule:weekly",
":semanticCommitsDisabled"
],
"ignoreDeps": ["php"],
"packageRules": [
{
"groupName": "GitHub Actions",
"matchManagers": ["github-actions"]
},
{
"groupName": "roots/wordpress",
"schedule": [
"at any time"
],
"matchPackageNames": [
"roots/wordpress{/,}**"
]
}
],
"timezone": "America/Chicago"
}


File: .github/workflows/ci.yml

name: CI

on: [push, pull_request]

jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
php-version: ['8.3', '8.4', '8.5']

text
steps:
- uses: actions/checkout@v7

- name: Setup PHP
  uses: shivammathur/setup-php@v2
  with:
    php-version: ${{ matrix.php-version }}

- name: Cache Composer dependencies
  id: composer-cache
  run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT

- uses: actions/cache@v6
  with:
    path: ${{ steps.composer-cache.outputs.dir }}
    key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
    restore-keys: ${{ runner.os }}-composer-

- name: Check Composer lock file is up to date
  run: composer validate --no-check-all

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

- name: Run Pint
  run: composer lint

- name: Run tests
  run: composer test

File: .github/workflows/discourse.yml

name: Post release topic on Discourse

on:
release:
types: [published]

jobs:
post:
runs-on: ubuntu-latest
steps:
- uses: roots/discourse-topic-github-release-action@main
with:
discourse-api-key: ${{ secrets.DISCOURSE_RELEASES_API_KEY }}
discourse-base-url: ${{ secrets.DISCOURSE_BASE_URL }}
github-token: ${{ github.token }}
discourse-category: 7
discourse-tags:
releases


File: .github/workflows/integration.yml

name: Integration

on: [push, pull_request, workflow_dispatch]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7

text
- name: Copy .env file
    working-directory: .devcontainer
    run: cp .env.example ../.env

  - name: Start dev container and test
    uses: devcontainers/[email protected]
    with:
      configFile: .devcontainer/devcontainer.json
      runCmd: |
        composer install --no-interaction --no-progress --prefer-dist
        wp core install --url=http://localhost:8080 --title=Bedrock --admin_user=admin --admin_password=admin [email protected] --skip-email --allow-root

  - name: Verify installation
    run: |
      curl -s http://localhost:8080 | grep "<title>Bedrock"