PHPackages                             pressgang-wp/pressgang - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Templating &amp; Views](/categories/templating)
4. /
5. pressgang-wp/pressgang

ActiveWordpress-theme[Templating &amp; Views](/categories/templating)

pressgang-wp/pressgang
======================

Package for the WordPress PressGang parent theme framework

v2.0.0(6mo ago)12.1kMITPHPPHP ^8.0CI passing

Since Feb 6Pushed 5d agoCompare

[ Source](https://github.com/pressgang-wp/pressgang)[ Packagist](https://packagist.org/packages/pressgang-wp/pressgang)[ RSS](/packages/pressgang-wp-pressgang/feed)WikiDiscussions master Synced today

READMEChangelog (1)Dependencies (4)Versions (2)Used By (0)

[![PressGang](https://github.com/pressgang-wp/pressgang/raw/master/img/pressgang-banner.png)](https://github.com/pressgang-wp/pressgang/blob/master/img/pressgang-banner.png)

Hijacking Your WordPress Development Workflow
=============================================

[](#hijacking-your-wordpress-development-workflow)

[![Latest Stable Version](https://camo.githubusercontent.com/135230439404d8e16e80d2bf0a4bf763662439fe1c6582427876513ef37e17d8/68747470733a2f2f706f7365722e707567782e6f72672f707265737367616e672d77702f707265737367616e672f762f737461626c65)](https://packagist.org/packages/pressgang-wp/pressgang)[![Build Status](https://github.com/pressgang-wp/pressgang/actions/workflows/php-compatibility.yml/badge.svg)](https://github.com/pressgang-wp/pressgang/actions/workflows/php-compatibility.yml)[![Total Downloads](https://camo.githubusercontent.com/c20f2a52e69c6100fb498786b15753d5137f0cd7f864b4ba670e70c4a9451a01/68747470733a2f2f706f7365722e707567782e6f72672f707265737367616e672d77702f707265737367616e672f646f776e6c6f616473)](https://packagist.org/packages/pressgang-wp/pressgang)[![License](https://camo.githubusercontent.com/419ff61b74d20df8c906cb407f760f1469379548221996ab82f48182037b7581/68747470733a2f2f706f7365722e707567782e6f72672f707265737367616e672d77702f707265737367616e672f6c6963656e7365)](https://packagist.org/packages/pressgang-wp/pressgang)

**Ahoy there! Modernize your WordPress development and ship your WordPress themes faster than ever. PressGang anchors your workflow in modern development practices. Build cleaner, faster, smarter themes and navigate your development course to calmer seas.**

📖 **[Read the full documentation at docs.pressgang.dev](https://docs.pressgang.dev/)**

Overview
--------

[](#overview)

PressGang is a WordPress parent theme framework that brings Timber and Twig templating, MVC-inspired controllers that act as view models, and Laravel-inspired, config-driven bootstrapping (convention over configuration) to WordPress — all on a modern Composer and PSR-4 foundation. Build child themes on a clean, opinionated architecture with a clear separation of concerns, and spend your time on features, not plumbing.

✨ Key Features
--------------

[](#-key-features)

- 🚀 **Rapid Development** — A solid foundation and conventions that accelerate theme development with clean, modern PHP.
- 🌲 **Timber + Twig** — Built on [Timber](https://timber.github.io/docs/v2/) to separate template markup from PHP logic through the [Twig](https://twig.symfony.com/) templating engine.
- 🎮 **Controller Architecture** — MVC-inspired controllers act as view models, preparing context for templates with a clear separation of concerns.
- ⚓ **Convention over Configuration** — Inspired by frameworks like Laravel, repetitive WordPress tasks are bootstrapped via declarative config files — less boilerplate, more building.
- 📦 **Composer &amp; PSR-4** — Dependency management via [Composer](https://getcomposer.org/) and PSR-4 autoloading for a consistent, modern codebase.
- 🔧 **Flexible by Design** — Keeps the core WordPress structure intact. Leverage everything you already know while gaining powerful tools and conventions.

🧭 Core Concepts
---------------

[](#-core-concepts)

### ⚙️ Config-Driven Bootstrapping

[](#️-config-driven-bootstrapping)

Everything in PressGang starts with a config file. Arrays in `config/` declare what gets registered — post types, taxonomies, sidebars, blocks, scripts, styles, and more. Each config file maps to a class in `src/Configuration/` by convention (e.g. `config/sidebars.php` → `Sidebars`). No queries, no side effects — just declarative registration.

### 🎮 Controllers

[](#-controllers)

Controllers live in `src/Controllers/` and are **view models**, not request handlers. Each controller extends `AbstractController`, gathers data via Timber, builds a context array, and selects a template. They must be side-effect free — no writes, no remote requests, no direct rendering.

Context wiring is declarative: list the template contract in `protected array $context_getters = [ 'news', 'events' ]` and each key is populated from its `get_{key}()` getter — no `get_context()` boilerplate.

### 🗺️ Template Routing (No Stub Files)

[](#️-template-routing-no-stub-files)

Opt-in via `config/service-providers.php` (add `TemplateRoutingServiceProvider` alongside the defaults) — existing themes built on explicit template stubs are untouched by framework upgrades. Once enabled, requests route to controllers by convention — most themes need **no template PHP files at all**. WordPress's template hierarchy candidates are recorded per request, kebab-case twins are added for underscored post type/taxonomy names (`taxonomy-event_type` also matches `taxonomy-event-type`), and when a request falls through to a parent-theme template the dispatcher resolves a child controller:

- `search` → `SearchController`, `front-page` → `FrontPageController` (StudlyCase)
- `archive-event` → `EventsController` (plural for archives)
- `single-event` → `EventController`, `taxonomy-event-type` → `EventTypeController` (singular subjects)

The matching `{candidate}.twig` renders when the child theme has one. `config/controllers.php` maps any name that defies convention, and a physical template file in the child theme always wins — keep one only for genuine logic (e.g. conditional controller selection).

Page templates are file-less too: `config/page-templates.php` registers them (`'page-templates/contact-page.php' => 'Contact Page'` — legacy file-shaped ids keep existing page assignments working), and each resolves to `{Slug}Controller` or falls back to `PageController` with `{slug}.twig`.

**Explicit routing still works** — and always takes precedence. A template stub in the child theme renders exactly what it says, which is how existing PressGang themes are built and how a theme adopts convention routing incrementally (delete stubs one at a time):

```
