Skip to content

Architecture

WAGE is an OOP WordPress theme framework. All framework code lives in the Wage\ namespace as PHP classes. Each client project is a child theme that extends the core.

All classes live in inc/core/classes/:

Wage\App — framework bootstrap (single entry point)
Wage\Page — page lifecycle (set_seo, render, CSS/JS collection)
Wage\Component — base class for all components (classes, root_classes, css, js)
Wage\SEO — SEO engine (title, meta, Open Graph, schema)
Wage\Flags — feature flags (wireframe, x-ray, dark-mode, cookies)
Wage\Assets — SVGs, fonts, tokens, global CSS
Wage\Forms — form registration, validation, spam prevention
Wage\Styleguide — dashboard (token audit, component library, SEO overview)
Wage\FluidGenerator — generates fluid clamp() values for type and spacing
wage/
├── functions.php # require App.php → Wage\App::boot()
├── style.css # Theme header
├── CLAUDE.md # Framework instructions
└── inc/core/
├── classes/
│ ├── App.php # Wage\App — bootstrap, constants, hooks
│ ├── WageComponent.php # Wage\Component base class (classes, root_classes)
│ ├── Page.php # Wage\Page class
│ ├── Flags.php # Wage\Flags class (wireframe, xray, dark-mode)
│ ├── Assets.php # Wage\Assets class
│ ├── SEO.php # Wage\SEO class
│ ├── Forms.php # Wage\Forms class
│ ├── Styleguide.php # Wage\Styleguide class
│ └── FluidGenerator.php # Wage\FluidGenerator — clamp() value generator
├── includes.php # Loads all core component classes
├── tokens.php # Design tokens (raw + fluid scales + semantic)
├── fluid-type.php # Fluid type scale config (child overridable)
├── fluid-spacing.php # Fluid spacing scale config (child overridable)
├── svgs.php # SVG library — icons + decorative graphics (PHP array)
├── css/core.css # Reset, structural layout, surface--dark utility
└── components/
├── badge/ # Wage\Badge
├── button/ # Wage\Button
├── button-group/ # Wage\ButtonGroup
├── eyebrow/ # Wage\Eyebrow
├── section-intro/ # Wage\SectionIntro
├── accordion/ # Wage\Accordion
├── carousel/ # Wage\Carousel
├── tabs/ # Wage\Tabs
├── gallery/ # Wage\Gallery
├── modal/ # Wage\Modal
├── rating/ # Wage\Rating
├── image-placeholder/ # Wage\ImagePlaceholder
├── video-placeholder/ # Wage\VideoPlaceholder
├── trust-strip/ # Wage\TrustStrip
├── section-background/# Wage\SectionBackground
├── form-field/ # Wage\FormField
├── form/ # Wage\Form
└── lightbox/ # Wage\Lightbox
wage-{client}/
├── style.css # Theme header with Template: wage
├── functions.php # Project setup (API keys, shared factories)
├── header.php # Document shell (DOCTYPE, <head>, <body>)
├── footer.php # Document shell (</body>, </html>)
├── front-page.php # Homepage template
├── page-*.php # Page templates
├── assets/
│ ├── css/site.css # Project-specific visual styling
│ ├── fonts/ # Self-hosted .woff2 font files (auto-loaded)
│ ├── images/ # Logo, hero, project images
│ └── js/main.js # Project JS
├── inc/
│ ├── tokens.php # Brand token overrides (PHP array)
│ ├── fluid-type.php # Fluid type scale override (optional, replaces core)
│ ├── fluid-spacing.php # Fluid spacing scale override (optional, replaces core)
│ ├── seo.php # SEO data (PHP array)
│ ├── svgs.php # Project-specific SVGs (optional, merged with core)
│ ├── surfaces/ # surfaces.php + surfaces.css
│ ├── forms/ # Auto-scanned form registrations (one file per form)
│ ├── core/components/ # Core component CSS overrides (mirrors core path)
│ ├── components/ # Building blocks ({name}/{name}.php + {name}.css)
│ └── sections/ # Page sections ({name}/{name}.php + {name}.css)
├── data/ # Protected file storage
└── CLAUDE.md # Project instructions

Each component and section lives in its own folder with a paired CSS file:

inc/components/info-card/
├── info-card.php # Wage\InfoCard class
└── info-card.css # Component styles
inc/sections/hero/
├── hero.php # Wage\HeroSection class
└── hero.css # Section styles
  • inc/components/ — reusable building blocks (step indicator, info card, product card, etc.). These appear in the Wage Dashboard styleguide. Auto-scanned.
  • inc/sections/ — full page sections (hero, how-it-works, testimonials, etc.). Use X-Ray mode to inspect them on the actual page. Auto-scanned.
  • inc/surfaces/ — decorative section backgrounds. Registered as global CSS via Wage\Assets::register_global_css().
  • inc/forms/ — form registrations (one file per form). Auto-scanned.
  • inc/core/components/ — core component CSS overrides (mirrors core path). Auto-scanned.
Constant / FunctionPoints to
get_template_directory() / WAGE_CORE_DIRParent theme (core)
get_stylesheet_directory() / WAGE_CHILD_DIRChild theme (project)
WAGE_IS_CHILDtrue when a child theme is active
  1. <style id="wage-tokens"> — merged token values via Wage\Assets::output_tokens() (priority 0)
  2. <link rel="preload"> — font preload hints via Wage\Assets::preload_fonts() (priority 1)
  3. <style id="wage-fonts">@font-face declarations via Wage\Assets::output_font_faces() (priority 2)
  4. <style id="wage-flags"> — wireframe/x-ray CSS via Wage\Flags::output_css() (priority 3)
  5. wage-coreinc/core/css/core.css (structural framework)
  6. <style id="wage-global"> — global CSS (surfaces) via Wage\Assets::register_global_css()
  7. <style id="wage-components"> — component CSS collected by Wage\Component during rendering
  8. wage-siteassets/css/site.css (project visual styling)
  1. wage-mainassets/js/main.js if present (enqueued with defer strategy)
  2. <script id="wage-js-{name}"> — per-component inline JS, one tag per component (e.g. wage-js-header, wage-js-carousel, wage-js-modal). Deduped by content hash.

Each component’s JS gets its own <script> tag with a meaningful ID, allowing performance plugins (e.g. PerfMatters) to delay individual scripts.

Wage\App::boot() loads the framework in this order:

  1. Core classes loaded from inc/core/classes/ (WageComponent, Page, Flags, Assets, SEO, Forms, Styleguide)
  2. Classes initialised with ::init()Flags, Assets, SEO, Forms, Styleguide
  3. WordPress bloat stripped by App::dequeue_bloat()
  4. Child theme auto-scannedinc/core/components/, inc/components/, inc/sections/ folders loaded via glob
  5. Core inc/core/includes.php — auto-scans inc/core/components/ via glob (components use class_exists() guards)
  6. Child forms auto-scannedinc/forms/*.php loaded via App::load_forms()

The child loads before core. Since all components use class_exists() guards, the child’s version of any component class wins automatically. All folders are auto-scanned — just drop a component folder in and it loads.

  • Never put project-specific code in the parent theme. It gets shared across all sites.
  • Core CSS (core.css) is structural only. All visual styling lives in the child theme. The one exception is global link styling: a:where(:not(.btn)) sets color: var(--link-color) and text-decoration: underline with zero specificity, so components can override without fighting it.
  • All component classes use class_exists() guards so child themes can override them.
  • Child folders are auto-scanned before core so overrides work automatically. No manual includes.php needed.
  • Everything is in the Wage\ namespace. No standalone wage_* functions.
  • WordPress bloat is stripped by App::dequeue_bloat() (block library, classic themes, global styles, emoji scripts).

Push changes to the parent theme repo. Pull on each server. Child themes are unaffected — they inherit the updated core.