Major improvements to WooNooW Page Editor system: Schema & Architecture: - Canonical section schema with unified sectionSchema.ts - Normalized feature-grid to use items (not features) - Standardized default values across all section types - Schema versioning with automatic migration on read Backend (PHP): - Enhanced PlaceholderRenderer with typed output contracts - Added fallback behavior for empty/invalid dynamic sources - Added caching support for post data resolution - New SchemaMigration class for backward compatibility - New Features class for feature flags - Enhanced PageSSR with full style support - Removed controller-level special-casing for related_posts Frontend (Admin SPA): - Updated CanvasRenderer with schema-aware transformation - Enhanced InspectorPanel with canonical schema metadata - Added new section renderers Frontend (Customer SPA): - New section components: BentoCategoryGrid, MarqueeBanner, ProductCarousel, ShoppableImage - Updated FeatureGridSection for items prop contract Testing: - Add PHP tests: SchemaMigrationTest, PlaceholderRendererTest, PageSSRTest - Add TypeScript tests: schema-integration, feature-grid-regression - Add parity tests for React vs SSR content matching - Add CI script: check-schema-drift.mjs - Add VERIFICATION_CHECKLIST.md Documentation: - RELEASE_NOTES-v1.0.md with full release notes - docs/PAGE_EDITOR_SECTION_SCHEMA_V1.md - docs/PAGE_EDITOR_SSR_COVERAGE_AUDIT.md
2.2 KiB
2.2 KiB
Page Editor Section Schema v1
Purpose
The Page Editor uses one canonical section contract for editor defaults, inspector fields, canvas rendering, storefront rendering, and PHP SSR expectations.
The TypeScript source of truth is:
admin-spa/src/routes/Appearance/Pages/schema/sectionSchema.ts
Canonical Rules
- Section type names use kebab-case in saved JSON, for example
feature-grid. - Section props are stored as
SectionPropobjects:{ "type": "static", "value": ... }or{ "type": "dynamic", "source": ... }. - Runtime renderers receive flattened prop values after adapter transformation or backend resolution.
- Repeater props must use arrays as their static value.
feature-grid.itemsis the canonical feature/post-card list prop.feature-grid.featuresis supported only as a legacy read fallback.
Current Section Types
| Type | Canonical repeater props | Notes |
|---|---|---|
hero |
none | Dynamic title/subtitle/image supported by inspector metadata |
content |
none | Rich text content may be dynamic |
image-text |
none | Dynamic title/text/image supported |
feature-grid |
items |
Legacy features is read as fallback |
cta-banner |
none | Static CTA content |
contact-form |
none | Webhook/redirect URLs are static settings |
bento-category-grid |
items |
Array of category/grid item objects |
product-carousel |
none | Product source/limit are scalar props |
shoppable-image |
hotspots |
Array of product hotspot objects |
marquee-banner |
none | Scalar text/separator/speed props |
Migration Notes
- Existing saved
feature-grid.featuresvalues should be read asitemsat render time. - New editor writes should persist
feature-grid.items. - A future payload-level
schemaVersionshould make legacy migration explicit.
Preview Resolution Contract
- Template preview samples are fetched from
GET /woonoow/v1/preview/samples/{cpt}. - Dynamic template preview sections are resolved through
POST /woonoow/v1/preview/resolve/{cpt}. - The editor must render resolved preview sections separately from the saved source sections so dynamic values do not overwrite
{ type: "dynamic", source: "..." }metadata.