feat: Page Editor v1.0 - canonical schema, SSR parity, and migration
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
This commit is contained in:
42
docs/PAGE_EDITOR_SECTION_SCHEMA_V1.md
Normal file
42
docs/PAGE_EDITOR_SECTION_SCHEMA_V1.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# 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:
|
||||
|
||||
```text
|
||||
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 `SectionProp` objects: `{ "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.items` is the canonical feature/post-card list prop.
|
||||
- `feature-grid.features` is 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.features` values should be read as `items` at render time.
|
||||
- New editor writes should persist `feature-grid.items`.
|
||||
- A future payload-level `schemaVersion` should 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.
|
||||
Reference in New Issue
Block a user