Skip to content

bambamboole/wordpress-starter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

192 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

WordPress Starter

An opinionated WordPress starter for building modern, testable sites on the Roots stack.

  • 🧱 Bedrock foundation β€” 12-factor WordPress with Composer-managed core, clean config, and a public/ web root.
  • 🌿 Acorn + Sage theme β€” Laravel-style service providers, Blade templates, Vite, Tailwind v4, and Alpine.js.
  • πŸ›’ WooCommerce-ready β€” seeded products, German store settings, Blade template overrides, and an end-to-end checkout test.
  • πŸ§ͺ Pest 4 included β€” Unit, Feature, and Browser suites with a reusable test database baseline and FrankenPHP browser driver.

Inspired by Roots Radicle; the original Roots attribution is preserved in LICENSE.md.

Features

A working theme out of the box, with seeded content so every feature is visible after composer setup.

Classic WordPress mega menu

Built from the standard wp-admin β†’ Appearance β†’ Menus editor β€” no page builder, no extra plugin. Each menu item gains a Mega menu type fieldset (Link / Image / HTML); a top-level item with at least one Image or HTML child renders as a multi-column mega panel, otherwise as a plain dropdown.

Mega menu open on desktop showing the Shop panel with Categories column, featured image, and Free EU shipping highlight

On screens narrower than lg, the nav collapses into a hamburger drawer with the panels rendering inline β€” same Blade partials, no JS branching.

Mega menu drawer open on mobile showing the Shop panel expanded inline

Themed posts, archives, and comments

Single posts, the blog index, search results, and the not-found page all ship with consistent Tailwind styling. The comment form is restyled to match the rest of the theme β€” <button>-based submit, theme-consistent inputs, required-field markers β€” via a custom comment_form() args array.

Single post with styled comment form: label, textarea, name/email/website inputs, and a black Post Comment button

Blog index showing seeded posts with title, date, author, and excerpt Search results page styled like the blog index
404 Not Found page Seeded home page with a centered hero, GitHub and Blog CTA buttons, a wide responsive image, a six-card 'What's included' grid, a tech-stack list, and a closing CTA

WooCommerce shop with Blade templates

A complete WooCommerce vertical wired into the theme: 8 seeded products in 2 categories, German store configuration (EUR / 19 % VAT inclusive / flat-rate shipping), and BACS payment labelled Rechnung (Vorkasse). The shop archive and single product pages render through Blade templates resolved via the wc_get_template_part and wc_get_template filters, with Tailwind styling on the cards, sort toolbar, and category chips. A shopping-bag icon in the header shows a live cart count that updates without a page reload via WooCommerce's add_to_cart_fragments AJAX hook.

Shop archive with header eyebrow, category chips, sort toolbar, four-column product grid, and a cart-count badge in the header

Single product page with two-column layout, product gallery, price, add-to-cart, and tabbed description Shop archive on mobile, single column with the cart icon in the top right

A Pest browser test (tests/Browser/ShopPurchaseTest.php) drives a guest through the full flow β€” shop β†’ product β†’ cart β†’ block checkout β†’ BACS β†’ thank-you β€” and asserts on the seeded IBAN on the order-received page.

What's under the hood

  • Bedrock layout β€” WordPress core vendored at public/wp/, content at public/content/, config via .env. No wp-config.php to edit.
  • Acorn (Laravel-on-WordPress) β€” Blade templates, Eloquent models that map onto wp_posts/wp_postmeta, Acorn mail, service providers in app/Providers/.
  • Sage (theme conventions) β€” Vite + Tailwind v4 + Alpine.js; no tailwind.config.js, CSS-first @theme configuration.
  • Custom Gutenberg blocks β€” PHP class + Blade render template + JSX editor file, scaffolded with wp acorn make:block.
  • REST API scaffold β€” controllers in app/Http/Controllers/Api/. Never admin-ajax.php.
  • WooCommerce integration β€” App\Providers\WooCommerceServiceProvider resolves WC templates to Blade, wraps content in the theme layout, and feeds AJAX cart fragments. Seeders bootstrap a German storefront ready to purchase from.
  • Translations β€” __() everywhere, full .pot / .po / .mo / .json pipeline via composer translate.
  • Pest 4 tests β€” three suites (Unit / Feature / Browser) sharing a dedicated starter_test DB with a generated baseline dump. Browser tests spawn a real FrankenPHP subprocess (multithreaded, so WC Blocks Store API checkout works end-to-end).
  • Automated screenshots β€” composer screenshots regenerates the images in this README from the running site at desktop and mobile viewports. See tests/Browser/ScreenshotsTest.php.

Requirements

  • Laravel Herd
  • PHP β‰₯ 8.4
  • Composer
  • Node.js β‰₯ 22.12 (npm)
  • WP-CLI

Quick start

# 1. Scaffold the project (also installs Composer + npm deps + Playwright browsers)
composer create-project bambamboole/wordpress-starter starter
cd starter

# 2. Configure environment
# Edit .env: fill DB_NAME, DB_USER, DB_PASSWORD; generate fresh salts at https://roots.io/salts.html

# 3. Create the database, install WordPress, run migrations, seed baseline content, build assets
composer setup

# 4. Visit the site
herd open https://starter.test/

# 5. Start the dev server (Vite HMR + Laravel scheduler, side by side)
composer dev

Herd auto-derives the .test hostname from the project directory name. To change the hostname, pass a different name to create-project (e.g., composer create-project bambamboole/wordpress-starter myproject β†’ myproject.test).

composer create-project strips the .git directory by default β€” run git init afterwards to start your own history.

To wipe local data and reseed from scratch, run composer reset β€” drops the DB and re-runs composer setup.

Project layout

Path Description
app/Blocks/ Block render callbacks (Blade templates for blocks)
app/Http/Controllers/Api/ REST API controllers
app/Models/ Eloquent models for WordPress posts/CPTs
app/Providers/ Acorn service providers
app/View/Composers/ Blade view composers
config/post-types.php Custom post types config
config/theme.php Theme menus, sidebars, supports
database/seeders/ Eloquent seeders (e.g. WordPressBaselineSeeder)
public/content/ wp-content directory (themes, plugins, mu-plugins)
resources/views/ Blade templates (theme + components)
resources/js/editor/ Block editor JSX
routes/web.php Acorn web routes
storage/logs/laravel.log Application log
theme.json WordPress block-editor theme config
tests/Feature/ Pest PHP feature tests (REST, models)
tests/Browser/ Pest browser tests via pest-plugin-browser

Common tasks

# Run all tests (unit + feature + browser, in that order)
composer test

# Run only unit tests (no framework boot, fastest)
composer test:unit

# Run only feature tests (boots WP+Acorn+Eloquent)
composer test:feature

# Run only browser tests (spawns FrankenPHP subprocess on :8080)
composer test:browser

# Regenerate the README screenshots in docs/screenshots/
composer screenshots

# Dev mode: Vite + Laravel scheduler daemon, side by side
composer dev

# Front-end dev server only (HMR, no scheduler)
npm run dev

# Front-end production build
npm run build

# Production build (compiles translations + Vite production bundle)
composer build

# Translation workflow
composer translate          # regenerate .pot + sync .po files
composer translate:compile  # compile .po -> .mo + .json (also runs as part of `composer build`)

# Format / lint
composer format       # check
composer format:fix   # apply
composer lint
npm run format
npm run lint

# Scaffold a new block (creates PHP class, Blade view, JSX, registers it)
wp acorn make:block MyBlock

Testing

PHP tests use Pest 4 and bootstrap WordPress + Acorn in-process via tests/FeatureTestCase.php. Browser tests use pest-plugin-browser with a custom FrankenPhpDriver that spawns FrankenPHP (Caddy + libphp, multithreaded) as a subprocess. The binary is pinned to v1.11.2 (PHP 8.4.18) and auto-downloads into the project root on the first browser-test run if missing (gitignored, CI-cached). wp acorn frankenphp:install [--force] is available as a manual pre-warm / re-download.

Both targets share a dedicated database, starter_test, configured via .env.testing. The first feature or browser test run on a machine bootstraps the test database automatically: drop+create starter_test, wp core install, activate all plugins, run Acorn migrations, run WordPressBaselineSeeder, then export to database/dumps/testing.sql. Subsequent test runs reuse the dump.

Every test re-imports the dump in setUp, giving each test a fresh baseline DB.

To force a rebuild (after adding a plugin, changing migrations, or changing the baseline seeder), delete the dump:

rm database/dumps/testing.sql

The next test run rebuilds it.

Detailed testing notes (custom driver, Pest setup, debugging tips) live in the pest-testing skill at .ai/skills/pest-testing/SKILL.md.

Primary navigation

The primary nav is a classic WordPress menu assigned to the primary_navigation location. The WordPressBaselineSeeder ships a default named Primary with Home, Blog, Products (with a mega panel), and Company (with a plain dropdown) so the feature is visible out of the box.

Edit it via Appearance β†’ Menus in wp-admin. Each menu item has an extra Mega menu type fieldset (Link / Image / HTML):

  • Link (default) β€” renders as a normal <a> or, with children, as a column header with sub-links underneath it.
  • Image β€” pick an image from the media library; the menu item's URL is reused as the click target.
  • HTML β€” write rich HTML (TinyMCE editor); the content is wp_kses_post-sanitized on save.

A top-level item with at least one Image or HTML child renders as a multi-column mega panel; otherwise its children render as a plain dropdown. Depth-2 link items beneath a depth-1 link become sub-links under that column header. Click outside, Escape, or the trigger again to close. On screens narrower than lg, the whole nav collapses into a hamburger drawer that expands the panels inline.

The frontend lives in resources/views/partials/nav/ (one Blade partial per concern), the runtime tree-builder in app/Support/MegaMenu/MenuBuilder.php, and the admin/save plumbing in App\Providers\MegaMenuServiceProvider. The footer nav is also a classic menu, on location footer_navigation.

Deeper documentation

Domain knowledge and conventions live in two AI-discoverable locations so Claude (via Laravel Boost) gets the right context automatically:

  • Always-loaded style rules in .ai/guidelines/ β€” concatenated into CLAUDE.md on every wp acorn boost:update. Includes PHP conventions (style/php.md), frontend conventions (style/frontend.md), Bedrock (wordpress/bedrock.md), Acorn (acorn/core.md), project structure, and the canonical command reference.
  • On-demand domain skills in .claude/skills/ β€” Claude activates these by description match when you work in a given area. Skills cover REST API (wordpress-rest-api), Gutenberg blocks (wordpress-blocks), Eloquent models (wordpress-eloquent-models), custom post types (wordpress-post-types), Blade components (blade-components), Tailwind (tailwindcss-development), translations (wordpress-i18n), and Pest testing (pest-testing). Service providers, theme configuration, and Acorn mail are covered by the always-loaded acorn/core guideline.

CLAUDE.md itself is auto-generated by wp acorn boost:update (which runs after every composer update) and is gitignored.

License

MIT β€” see LICENSE.md. Originally derived from Roots Radicle; the original Roots copyright notice is preserved.

About

wordpress starter based on the roots ecosystem

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors