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.
Core classes
Section titled “Core classes”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 CSSWage\Forms — form registration, validation, spam preventionWage\Styleguide — dashboard (token audit, component library, SEO overview)Wage\FluidGenerator — generates fluid clamp() values for type and spacingDirectory structure
Section titled “Directory structure”Parent theme (core framework)
Section titled “Parent theme (core framework)”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\LightboxChild theme (per client)
Section titled “Child theme (per client)”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 instructionsFile organisation
Section titled “File organisation”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 stylesinc/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 viaWage\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.
Key paths
Section titled “Key paths”| Constant / Function | Points to |
|---|---|
get_template_directory() / WAGE_CORE_DIR | Parent theme (core) |
get_stylesheet_directory() / WAGE_CHILD_DIR | Child theme (project) |
WAGE_IS_CHILD | true when a child theme is active |
Load order
Section titled “Load order”<style id="wage-tokens">— merged token values viaWage\Assets::output_tokens()(priority 0)<link rel="preload">— font preload hints viaWage\Assets::preload_fonts()(priority 1)<style id="wage-fonts">—@font-facedeclarations viaWage\Assets::output_font_faces()(priority 2)<style id="wage-flags">— wireframe/x-ray CSS viaWage\Flags::output_css()(priority 3)wage-core—inc/core/css/core.css(structural framework)<style id="wage-global">— global CSS (surfaces) viaWage\Assets::register_global_css()<style id="wage-components">— component CSS collected byWage\Componentduring renderingwage-site—assets/css/site.css(project visual styling)
JS (footer)
Section titled “JS (footer)”wage-main—assets/js/main.jsif present (enqueued withdeferstrategy)<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:
- Core classes loaded from
inc/core/classes/(WageComponent,Page,Flags,Assets,SEO,Forms,Styleguide) - Classes initialised with
::init()—Flags,Assets,SEO,Forms,Styleguide - WordPress bloat stripped by
App::dequeue_bloat() - Child theme auto-scanned —
inc/core/components/,inc/components/,inc/sections/folders loaded via glob - Core
inc/core/includes.php— auto-scansinc/core/components/via glob (components useclass_exists()guards) - Child forms auto-scanned —
inc/forms/*.phploaded viaApp::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))setscolor: var(--link-color)andtext-decoration: underlinewith 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.phpneeded. - Everything is in the
Wage\namespace. No standalonewage_*functions. - WordPress bloat is stripped by
App::dequeue_bloat()(block library, classic themes, global styles, emoji scripts).
Updating core
Section titled “Updating core”Push changes to the parent theme repo. Pull on each server. Child themes are unaffected — they inherit the updated core.