Skip to content

Commit 3a619c8

Browse files
committed
docs: map existing codebase
1 parent 101ab02 commit 3a619c8

7 files changed

Lines changed: 1291 additions & 0 deletions

File tree

.planning/codebase/ARCHITECTURE.md

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
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*

.planning/codebase/CONCERNS.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# Concerns
2+
3+
> Auto-generated by gsd-codebase-mapper (concerns focus)
4+
5+
## Technical Debt
6+
7+
### TODO Items in Source Code
8+
9+
There are ~17 TODO/FIXME comments scattered across the codebase:
10+
11+
**Core blocks:**
12+
- `packages/webentor-core/resources/blocks/l-nav-menu/l-nav-menu.block.tsx:43` — "check if works with Polylang"
13+
- `packages/webentor-core/resources/blocks/e-table-row/e-table-row.block.tsx:103` — "extract icon to icon set"
14+
- `packages/webentor-core/resources/blocks/e-table-cell/e-table-cell.block.tsx:168` — "extract icon to icon set" (duplicate pattern)
15+
- `packages/webentor-core/resources/blocks/e-slider/e-slider.block.tsx:26` — "extend with slider/responsive settings"
16+
- `packages/webentor-core/resources/blocks/l-site-logo/l-site-logo.block.tsx:6` — "Add logo image?"
17+
- `packages/webentor-core/resources/blocks/e-picker-query-loop/e-picker-query-loop.block.tsx:103` — "Maybe rework to nicer UI"
18+
- `packages/webentor-core/resources/blocks/e-query-loop/e-query-loop.block.tsx:99` — "add settings for these"
19+
- `packages/webentor-core/resources/blocks/e-image/e-image.block.tsx:179` — "maybe move to BlockControls toolbar"
20+
- `packages/webentor-core/resources/blocks/l-nav-menu/style.css:1` — "maybe adjust nested CSS to be compatible with native nesting"
21+
22+
**Core infrastructure:**
23+
- `packages/webentor-core/resources/scripts/editor.ts:4` — "maybe add filter to customize this list"
24+
- `packages/webentor-core/resources/styles/components/_table.css:2` — "adjust variables"
25+
- `packages/webentor-core/resources/views/partials/footer.blade.php:1` — "add basic footer"
26+
- `packages/webentor-core/resources/views/partials/header.blade.php:1` — "add basic header"
27+
28+
**Starter:**
29+
- `packages/webentor-starter/LocalValetDriver.php:13` — "Get from .env file?"
30+
- `packages/webentor-starter/web/app/mu-plugins/webikon-wp-cleanup.php:15` — "add some hooks to enable/disable this"
31+
- `packages/webentor-starter/web/app/themes/webentor-theme-v2/resources/views/ui-kit/ui-kit-core-components.blade.php:8` — "add slider"
32+
33+
### Incomplete Core Components
34+
35+
- **Header and Footer partials** (`packages/webentor-core/resources/views/partials/`) are essentially empty — they contain only TODO comments. These are core framework views that consumer themes are expected to build upon, but the defaults provide no fallback.
36+
- **Site logo block** (`l-site-logo`) has a TODO about missing logo image functionality.
37+
38+
### Icon Extraction Pattern
39+
40+
Two blocks (`e-table-row`, `e-table-cell`) have inline icon SVGs that should be extracted to a shared icon set. This is a recurring pattern that suggests a missing icon management system.
41+
42+
## No Test Coverage
43+
44+
The project has **zero automated tests** (see `TESTING.md`). The CI `pnpm test` commands pass silently due to `--if-present` flags. This means:
45+
- Regressions in the responsive settings system (the most complex subsystem) are undetectable
46+
- Block migration logic (`blocks-migration.php`, `migration.ts`) has no safety net
47+
- PHP rendering and Blade templates are only validated by manual testing
48+
49+
## Responsive Settings Complexity
50+
51+
The responsive settings system at `packages/webentor-core/core-js/blocks-filters/responsive-settings/` is the largest and most complex subsystem:
52+
- Registry-based architecture with ~10 individual setting modules
53+
- Each setting has: registration, properties, settings UI, and panel components
54+
- Generates Tailwind CSS classes across breakpoints
55+
- Has its own migration system
56+
- No unit tests covering any of this
57+
58+
The complexity-to-coverage ratio makes this the highest-risk area for regressions.
59+
60+
## Build & Tooling
61+
62+
### Dormant Playwright Setup
63+
- `playwright-report/` directory exists at root but no Playwright config or tests are present
64+
- Suggests E2E testing was explored but abandoned
65+
66+
### CI Test Gaps
67+
- `pnpm test` is called in CI but silently no-ops (no test scripts defined)
68+
- PHP code has no static analysis (no PHPStan/Psalm configured)
69+
- No PHP code style enforcement (no PHP-CS-Fixer/Pint)
70+
71+
## Security Considerations
72+
73+
### WordPress-Specific
74+
- `packages/webentor-starter/web/app/mu-plugins/webikon-wp-cleanup.php` — WP cleanup plugin lacks hooks to toggle features on/off (noted in its own TODO)
75+
- Block rendering relies on server-side Blade templates with ACF data — standard WordPress escaping practices should be audited for XSS
76+
77+
### Dependency Management
78+
- Large `node_modules` footprint (pnpm store) — standard for the ecosystem but worth monitoring for supply chain risks
79+
- Composer dependencies for WordPress (Bedrock) follow standard security practices
80+
81+
## Performance
82+
83+
### Block Editor Load
84+
- 27 core blocks + theme blocks all register in the editor
85+
- The responsive settings filter attaches to every block — potential editor performance impact at scale
86+
- No evidence of lazy loading or code splitting for block editor scripts
87+
88+
### Frontend
89+
- Alpine.js used for frontend interactivity (lightweight)
90+
- Slider library loaded via `_slider.ts`
91+
- Vite handles bundling and tree-shaking for production builds
92+
93+
## Fragile Areas
94+
95+
1. **Block migration** (`packages/webentor-core/app/blocks-migration.php` + `core-js/blocks-filters/responsive-settings/migration.ts`) — data format changes without tests
96+
2. **Responsive settings registry** — adding new settings requires changes across multiple files (registration, properties, settings UI, panel) with no automated verification
97+
3. **Config schema validation** — schemas exist in `packages/webentor-core/schemas/` but unclear how strictly they're enforced at runtime
98+
4. **Cross-package dependencies** — core and starter are tightly coupled through block definitions, Blade views, and config — changes in core can silently break starter

0 commit comments

Comments
 (0)