|
| 1 | +# Architecture |
| 2 | + |
| 3 | +**Analysis Date:** 2026-04-11 |
| 4 | + |
| 5 | +## Pattern Overview |
| 6 | + |
| 7 | +**Overall:** pnpm monorepo with independently versioned packages, following a WordPress block-based theme architecture built on Roots Bedrock + Sage/Acorn patterns. |
| 8 | + |
| 9 | +**Key Characteristics:** |
| 10 | +- Four publishable packages plus a VitePress docs site, all managed in a single pnpm workspace |
| 11 | +- Dual-language runtime: PHP (WordPress backend, Blade templating, block registration) + TypeScript/React (Gutenberg editor, block edit components, responsive settings system) |
| 12 | +- Split-mirror release model: `webentor-core`, `webentor-setup`, and `webentor-starter` are mirrored to standalone Git repos via GitHub Actions for consumption as Composer/npm packages |
| 13 | +- Registry-based extensibility: both JS and PHP sides use a SettingsRegistry pattern for responsive block settings |
| 14 | + |
| 15 | +## Layers |
| 16 | + |
| 17 | +**Configuration Layer (`webentor-configs`):** |
| 18 | +- Purpose: Shared ESLint, Stylelint, Prettier, PHPCS, and editorconfig presets consumed by all packages and consumer projects |
| 19 | +- Location: `packages/webentor-configs/` |
| 20 | +- Contains: `eslint.config.js`, `stylelint.config.js`, `prettier.config.js`, `phpcs.xml`, `.bladeformatterrc`, `.editorconfig` |
| 21 | +- Depends on: ESLint, Stylelint, Prettier peer dependencies |
| 22 | +- Used by: `webentor-core`, `webentor-starter` theme (via `@webikon/webentor-configs` npm package) |
| 23 | + |
| 24 | +**Core Runtime Layer (`webentor-core`):** |
| 25 | +- Purpose: Shared PHP + JS runtime for all Webentor projects. Provides block registration, responsive settings, utility functions, editor filters, and reusable Gutenberg blocks |
| 26 | +- Location: `packages/webentor-core/` |
| 27 | +- Contains: PHP initialization (`init.php`, `app/`), TypeScript/React block editor code (`core-js/`), block definitions with Blade templates (`resources/blocks/`), shared Blade components (`resources/core-components/`, `resources/views/`), CSS styles (`resources/styles/`) |
| 28 | +- Depends on: `kucrut/vite-for-wp` (PHP), `@wordpress/*` packages, React, TailwindCSS, Alpine.js, Swiper |
| 29 | +- Used by: `webentor-starter` theme (via Composer `webikon/webentor-core` and npm `@webikon/webentor-core`) |
| 30 | + |
| 31 | +**Setup Layer (`webentor-setup`):** |
| 32 | +- Purpose: CLI tool and shell scripts for local development environment setup, project scaffolding, and upgrade management |
| 33 | +- Location: `packages/webentor-setup/` |
| 34 | +- Contains: PHP CLI (`src/webentor-setup.php`, `bin/webentor-setup`), shell scripts (`setup.sh`, `common.sh`, `env-check.sh`), platform-specific scripts (`mac/`, `win/`), hook examples (`hooks.example/`), upgrade manifests (`upgrades/`) |
| 35 | +- Depends on: PHP >=8.2, bash |
| 36 | +- Used by: Consumer projects via `git subtree add` into `scripts/setup-core/` |
| 37 | + |
| 38 | +**Starter Layer (`webentor-starter`):** |
| 39 | +- Purpose: Complete WordPress project skeleton (Bedrock-based) with a pre-configured Sage/Acorn theme |
| 40 | +- Location: `packages/webentor-starter/` |
| 41 | +- Contains: Bedrock root (`config/`, `web/`), WordPress theme (`web/app/themes/webentor-theme-v2/`), mu-plugins (`web/app/mu-plugins/`) |
| 42 | +- Depends on: `webentor-core` (Composer + npm), `webentor-configs` (npm), Roots Acorn/Sage, ACF Pro, many WP plugins |
| 43 | +- Used by: New consumer projects clone or fork this skeleton |
| 44 | + |
| 45 | +**Documentation Layer (`docs`):** |
| 46 | +- Purpose: VitePress-powered documentation site for the entire Webentor stack |
| 47 | +- Location: `docs/` |
| 48 | +- Contains: Markdown content (`docs/src/`), VitePress config (`docs/src/.vitepress/`) |
| 49 | +- Depends on: VitePress |
| 50 | +- Used by: Developers and AI agents |
| 51 | + |
| 52 | +## Data Flow |
| 53 | + |
| 54 | +**Block Registration (PHP side):** |
| 55 | + |
| 56 | +1. Theme `functions.php` (`packages/webentor-starter/web/app/themes/webentor-theme-v2/functions.php`) loads Acorn, bootstraps theme files, then requires `webentor-core/init.php` |
| 57 | +2. `init.php` (`packages/webentor-core/init.php`) defines path constants and requires all `app/*.php` files |
| 58 | +3. `blocks-init.php` (`packages/webentor-core/app/blocks-init.php`) on `init` hook: globs for `block.json` files in both theme (`resources/blocks/`) and core (`WEBENTOR_CORE_RESOURCES_PATH/blocks/`), registers each via `register_block_type_from_metadata()` with a Blade render callback |
| 59 | +4. Theme blocks registered first; core blocks skip duplicates (child theme override mechanism) |
| 60 | +5. `register_frontend_blocks_assets()` also registers per-block `script.ts` and `style.css` via Vite manifest |
| 61 | + |
| 62 | +**Block Rendering (PHP side):** |
| 63 | + |
| 64 | +1. WordPress invokes `render_callback` for each `webentor/*` block |
| 65 | +2. `render_block_blade()` (`packages/webentor-core/app/blocks-init.php`) recursively renders inner blocks |
| 66 | +3. `prepareBlockClassesFromSettings()` (`packages/webentor-core/app/blocks-settings.php`) iterates the PHP `SettingsRegistry` to generate Tailwind utility classes from responsive attributes |
| 67 | +4. Blade views (`resources/blocks/{slug}/view.blade.php`) receive `$attributes`, `$block_classes`, `$innerBlocksContent`, `$custom_classes`, etc. |
| 68 | +5. `data.php` files (optional, loaded by `ThemeServiceProvider`) act as View Composers, enriching block data before rendering |
| 69 | + |
| 70 | +**Block Editor (JS side):** |
| 71 | + |
| 72 | +1. Core editor entry: `packages/webentor-core/resources/scripts/editor.ts` imports all core block `.block.tsx` files explicitly |
| 73 | +2. Theme editor entry: `packages/webentor-starter/web/app/themes/webentor-theme-v2/resources/scripts/editor.ts` uses `import.meta.glob('../blocks/**/*.block.{ts,tsx}', { eager: true })` for dynamic theme block discovery, plus imports core init and icon registration |
| 74 | +3. Each `.block.tsx` calls `registerBlockType(block, { edit, save })` with block.json metadata |
| 75 | +4. Responsive settings inject into block inspector via WordPress filters (BlockEdit filter), reading `supports.webentor.*` from block.json to determine which panels to show |
| 76 | +5. JS `SettingsRegistry` (`packages/webentor-core/core-js/blocks-filters/responsive-settings/registry.ts`) mirrors PHP registry: each setting module (spacing, layout, flexbox, etc.) self-registers and provides both a UI component and class generation logic |
| 77 | + |
| 78 | +**Asset Pipeline:** |
| 79 | + |
| 80 | +1. Vite is the build tool for both core and theme, configured via `@kucrut/vite-for-wp` |
| 81 | +2. Core Vite config: `packages/webentor-core/vite.config.js` - builds editor JS/CSS, app CSS, core components, and per-block assets |
| 82 | +3. Theme Vite config: `packages/webentor-starter/web/app/themes/webentor-theme-v2/vite.config.js` - builds theme editor/app JS/CSS, core-component overrides, and per-block assets |
| 83 | +4. TailwindCSS v4 with `@tailwindcss/vite` plugin; responsive settings generate a safelist JSON file at build time for dynamic Tailwind classes |
| 84 | +5. `@roots/vite-plugin` `wordpressThemeJson` generates `theme.json` from Tailwind config in the theme build |
| 85 | + |
| 86 | +**State Management:** |
| 87 | +- Block state is stored in WordPress block attributes (serialized in post content) |
| 88 | +- Responsive settings are stored as nested objects in block attributes, keyed by breakpoint (e.g. `{ "basic": "pt-10", "lg": "pt-20" }`) |
| 89 | +- No client-side state management library; Alpine.js handles frontend interactivity |
| 90 | +- `webentor-config.ts` defines the design token system (colors, spacing, breakpoints) shared between JS config and CSS |
| 91 | + |
| 92 | +## Key Abstractions |
| 93 | + |
| 94 | +**Block Definition (block triad):** |
| 95 | +- Purpose: Each Gutenberg block is defined by three co-located files |
| 96 | +- Pattern: `block.json` (metadata/attributes/supports), `{slug}.block.tsx` (editor React component), `view.blade.php` (frontend Blade template) |
| 97 | +- Optional: `data.php` (server-side data enrichment), `script.ts` (frontend JS), `style.css` (block-specific CSS) |
| 98 | +- Core examples: `packages/webentor-core/resources/blocks/e-button/`, `packages/webentor-core/resources/blocks/l-section/` |
| 99 | +- Theme examples: `packages/webentor-starter/web/app/themes/webentor-theme-v2/resources/blocks/b-hero-banner/` |
| 100 | + |
| 101 | +**Block Naming Convention:** |
| 102 | +- `e-*` = Element blocks (atomic: button, image, accordion, svg, etc.) |
| 103 | +- `l-*` = Layout blocks (structural: section, header, footer, flexible-container, etc.) |
| 104 | +- `b-*` = Business/project blocks (project-specific: hero-banner, etc., defined in theme) |
| 105 | + |
| 106 | +**SettingsRegistry (JS):** |
| 107 | +- Purpose: Extensible registry for responsive Gutenberg inspector settings (spacing, layout, sizing, flexbox, grid, border, etc.) |
| 108 | +- Location: `packages/webentor-core/core-js/blocks-filters/responsive-settings/registry.ts` |
| 109 | +- Pattern: Each setting module has `index.ts`, `registration.ts` (side-effect self-register), `settings.tsx` (UI component), `properties.ts` (class generation). Settings are grouped by `panelGroup` for panel rendering. |
| 110 | + |
| 111 | +**SettingsRegistry (PHP):** |
| 112 | +- Purpose: PHP mirror of JS registry for server-side class generation from responsive attributes |
| 113 | +- Location: `packages/webentor-core/app/blocks-settings.php` (class `Webentor\Core\SettingsRegistry`) |
| 114 | +- Pattern: Same `register()` / `generateClasses()` API but generates CSS class strings from stored attributes during render |
| 115 | + |
| 116 | +**WebentorConfig:** |
| 117 | +- Purpose: Centralized design token configuration (colors, spacing, breakpoints, typography, border, grid, etc.) |
| 118 | +- Core default: `packages/webentor-core/core-js/config/webentor-config.ts` |
| 119 | +- Theme override: `packages/webentor-starter/web/app/themes/webentor-theme-v2/webentor-config.ts` |
| 120 | +- Pattern: Theme imports `webentorDefaultConfig` and extends it; `buildSafelist()` generates TailwindCSS safelist for dynamic responsive classes |
| 121 | + |
| 122 | +**Blade Components:** |
| 123 | +- Purpose: Reusable UI components rendered server-side via Laravel Blade (through Acorn) |
| 124 | +- Core: `packages/webentor-core/resources/views/components/` (accordion, breadcrumbs, card, post-card, etc.) |
| 125 | +- Core components: `packages/webentor-core/resources/core-components/` (button, slider - with Blade template + optional script + style) |
| 126 | +- Theme overrides: `packages/webentor-starter/web/app/themes/webentor-theme-v2/resources/core-components/` and `app/View/Components/` |
| 127 | +- View resolution order defined in `config/view.php`: theme first, then core (allows override) |
| 128 | + |
| 129 | +## Entry Points |
| 130 | + |
| 131 | +**PHP Entry (`functions.php`):** |
| 132 | +- Location: `packages/webentor-starter/web/app/themes/webentor-theme-v2/functions.php` |
| 133 | +- Triggers: WordPress theme activation |
| 134 | +- Responsibilities: Defines `WEBENTOR_CORE_PHP_PATH`, loads Composer autoloader, boots Acorn application with `ThemeServiceProvider`, loads theme app files (`acf.php`, `blocks.php`, `cpts-tax.php`, `custom.php`, `forms.php`, `setup.php`, `wp-menu.php`), requires `webentor-core/init.php` |
| 135 | + |
| 136 | +**Core PHP Init:** |
| 137 | +- Location: `packages/webentor-core/init.php` |
| 138 | +- Triggers: Required from theme `functions.php` |
| 139 | +- Responsibilities: Defines core path constants, loads Composer autoload if present, requires all `app/*.php` files |
| 140 | + |
| 141 | +**Theme Editor JS:** |
| 142 | +- Location: `packages/webentor-starter/web/app/themes/webentor-theme-v2/resources/scripts/editor.ts` |
| 143 | +- Triggers: Enqueued on `enqueue_block_editor_assets` hook |
| 144 | +- Responsibilities: Imports theme block-filter init, icon registration, and auto-discovers theme blocks via `import.meta.glob` |
| 145 | + |
| 146 | +**Core Editor JS:** |
| 147 | +- Location: `packages/webentor-core/resources/scripts/editor.ts` |
| 148 | +- Triggers: Enqueued on `enqueue_block_editor_assets` hook (priority 5) |
| 149 | +- Responsibilities: Imports core block-editor filters (`_wrap-with-container`), explicitly imports all core block `.block.tsx` files |
| 150 | + |
| 151 | +**Theme Frontend JS:** |
| 152 | +- Location: `packages/webentor-starter/web/app/themes/webentor-theme-v2/resources/scripts/app.ts` |
| 153 | +- Triggers: Enqueued on `wp_enqueue_scripts` hook |
| 154 | +- Responsibilities: Frontend Alpine.js setup, header behavior, lightbox initialization |
| 155 | + |
| 156 | +**Setup CLI:** |
| 157 | +- Location: `packages/webentor-setup/bin/webentor-setup` (symlink to `src/webentor-setup.php`) |
| 158 | +- Triggers: Manual invocation from consumer project |
| 159 | +- Responsibilities: Project scaffolding (`init`), starter upgrades (`upgrade-starter`), environment diagnostics (`doctor`) |
| 160 | + |
| 161 | +## Error Handling |
| 162 | + |
| 163 | +**Strategy:** Minimal explicit error handling; relies on WordPress and PHP error mechanisms |
| 164 | + |
| 165 | +**Patterns:** |
| 166 | +- Block rendering: `render_block_blade()` falls back to `$block->render()` if no Blade view exists, providing graceful degradation |
| 167 | +- Block registration: `register_block_from_filename()` checks `WP_Block_Type_Registry` to skip already-registered blocks (prevents duplicate registration crashes) |
| 168 | +- Template loading: `functions.php` calls `wp_die()` if required app files are missing |
| 169 | +- Setup CLI: Uses `fwrite(STDERR, ...)` and `exit(1)` for error conditions; shell scripts use `set -eE` with trap for error handling |
| 170 | + |
| 171 | +## Cross-Cutting Concerns |
| 172 | + |
| 173 | +**Logging:** Console/browser dev tools for JS; PHP relies on WordPress `WP_DEBUG` and `WP_DEBUG_LOG`. Tracy debugger available in development (starter dev dependency). |
| 174 | + |
| 175 | +**Validation:** Block attributes validated by WordPress block API via `block.json` schema. PHP side uses type hints. No runtime validation library. |
| 176 | + |
| 177 | +**Authentication:** Not applicable at the framework level; authentication is handled by WordPress core and plugins in consumer projects. |
| 178 | + |
| 179 | +**Internationalization:** `wp_i18n` for JS, `load_theme_textdomain()` for PHP. Text domain: `webentor`. Translation files in `resources/languages/`. WP-CLI `i18n` commands for POT/PO/MO/JSON generation. |
| 180 | + |
| 181 | +**CSS Architecture:** TailwindCSS v4 utility-first approach with `wbtr:` prefix used in Blade templates for core classes. Design tokens defined in `webentor-config.ts` and mapped to CSS custom properties. Responsive settings generate breakpoint-prefixed Tailwind classes dynamically. |
| 182 | + |
| 183 | +--- |
| 184 | + |
| 185 | +*Architecture analysis: 2026-04-11* |
0 commit comments