FES Audit (FvCMS internals) — 2026-08-26

**Repo**: `avidtech6/freshvibe-cms` v1.2.0, vendored at `/workspace/fv-module-gallery/fv-cms-vendored/`

**Released**: 2026-08-05 by helper-mavis session 412100071272671

**Manifest**: `fv-cms-manifest.001` (`FV-CMS-MANIFEST.json`)

**Source of truth**: `git log` not available (vendored snapshot); the manifest is the build-of-record.

---

1. What FES is (the contract)

**FES = FreshVibe Element Schema.** The 16-element vocabulary the runtime dispatches. Per the FES doctrine (a761 §2.1), each module pack is `id + schema + defaultConfig + ui + editor + variants`, NOT a renderer — the chrome reads it at runtime, wires the inspector, and lets the live DOM update.

The **dual-layer** rule (id 8's doctrine, post-d529c91):

The FvCMS runtime imports from the gallery and re-dispatches under the M-prefix.

---

2. The FES dispatch table (16 modules)

From `fv-cms-vendored/runtime/renderer.js` (560 lines) and `fv-cms-vendored/detectors/elementor.js` (530 lines), cross-referenced:

| Runtime ID (M-prefix) | Schema ID | Elementor widget types handled | Detector config shape | Renderer registered |

|---|---|---|---|---|

| M-accordion | accordion | eael-adv-accordion, eael-toggle | items[], multiOpen, style, iconPosition | ✓ |

| M-breadcrumb | breadcrumb | eael-breadcrumbs | items[], separator, homeLabel | ✓ |

| M-button | button | button, eael-creative-button | text, href, variant, radius, size, openInNewTab, icon | ✓ |

| M-carousel | carousel | eael-post-carousel, eael-team-member-carousel, eael-stacked-cards | items[], visibleCount, autoRotate, rotateInterval, showDots, showArrows, cardStyle, imageAspect | ✓ |

| M-contact-form | contact-form | form, eael-weform, eael-fluentform | fields[], submitLabel, submitEndpoint, successMessage, layout | ✓ |

| M-cta | cta | button, eael-creative-button | text, href, variant, color, radius, size, openInNewTab, icon | ✓ |

| M-cta-box | cta-box | eael-cta-box | title, body, buttonText, buttonHref, background, layout | ✓ |

| M-heading | heading | heading, animated-headline | text, level, align, color, size | ✓ |

| M-icon-list | icon-list | icon-list | items[], layout, iconColor, spacing | ✓ |

| M-image | image | image, eael-image | src, alt, width, align, aspectRatio, caption, link | ✓ |

| M-info-box | info-box | eael-info-box | icon, title, body, link, linkLabel, variant | ✓ |

| M-menu | menu | eael-simple-menu | items[], layout, align, showIcons, separator | ✓ |

| M-paragraph | paragraph | text-editor | text, size, align, color, maxWidth | ✓ |

| M-social-icons | social-icons | social-icons | platforms[], shape, size, color, align, layout | ✓ |

| M-testimonial | testimonial | premium-addon-testimonials, eael-testimonial | quote, authorName, authorRole, authorImage, rating, style | ✓ |

| M-video | video | video, eael-video | source, url, poster, autoplay, loop, muted, aspectRatio, caption | ✓ |

**Total: 16 modules dispatched.** Both renderer.js and detector.js share the same vocabulary. The detector's `mapWidgetToModule()` is the single source of truth for "what FES understands."

---

3. Elementor classes & data attributes FES consumes

3a. From `detectors/elementor.js` (consumed by FES at detection time)

3b. From `runtime/renderer.js` and other runtime files (consumed by FES at render time)

3c. CSS contract

3d. Breakpoints

The detector doesn't directly read CSS breakpoints. FES uses the **5 standard breakpoints** (per a761 §2.3 — `responsive.json` schema): mobile (≤480), mobile-wide (≤767), tablet (≤1024), laptop (≤1366), desktop (default).

The inspector control `app-fragments/editor-inspector/controls/responsive/` is the manual override surface.

3e. Layout signals

FES reads:

---

4. Chrome / panels / inspector (FES consumer surfaces)

4a. 9 chrome panels (chrome-registry/index.json)

| Panel ID | Kind | Path | Source |

|---|---|---|---|

| cms-panel | panel | app-fragments/fvcms-cms-panel/ | freshvibe-cms v1.1.0 (post-oscar rename) |

| dev-btn | fragment | app-fragments/fvcms-dev-btn/ | freshvibe-cms v1.1.0 |

| dev-panel | panel | app-fragments/fvcms-dev-panel/ | freshvibe-cms v1.1.0 |

| floating-buttons | fragment | app-fragments/fvcms-floating-buttons/ | freshvibe-cms v1.1.0 |

| module-editor | fragment | app-fragments/fvcms-module-editor/ | freshvibe-cms v1.1.0 |

| panel-manager | panel | app-fragments/fvcms-panel-manager/ | freshvibe-cms v1.1.0 |

| region-editor | fragment | app-fragments/fvcms-region-editor/ | freshvibe-cms v1.1.0 |

| trace | fragment | app-fragments/fvcms-trace/ | freshvibe-cms v1.1.0 |

| watermark-hider | fragment | app-fragments/fvcms-watermark-hider/ | freshvibe-cms v1.1.0 |

4b. 16 FES modules (re-exported from gallery)

The 16 M-prefixed modules listed in §2, each registered with `kind: 'module', tier: 'tier-2'`, `canonical_home: avidtech6/fv-module-gallery/cms-widgets/`.

**Gallery-to-FvCMS re-export pattern**: gallery owns the source, FvCMS re-exports the M-prefixed runtime ids. This is the dual-layer doctrine in action.

4c. 24 inspector controls (the editing surface)

From `app-fragments/editor-inspector/controls/`:

| Control | Purpose |

|---|---|

| ai-assist | AI-powered edit suggestions |

| backdrop-filter | CSS backdrop-filter |

| background-color | Solid background color |

| background-gradient | Linear/radial gradient |

| background-image | Image background |

| background-unsplash | Unsplash picker |

| bg-tabs | Tabbed control groups (backgrounds) |

| color | Color picker |

| dimension | Width/height/padding/margin |

| dropdown | Dropdown selector |

| filters | CSS filter (blur, brightness, etc.) |

| motion-entrance | Entrance animation picker |

| motion-grid | Motion grid (preset combinations) |

| motion-trigger | Scroll/hover/click triggers |

| number | Numeric input |

| pills | Pill-style multi-select |

| radius | Border-radius |

| responsive | Breakpoint override |

| shadow-multi | Multi-layer box-shadow |

| slider | Range slider |

| switch | Boolean toggle |

| tags | Tag input |

| text | Text input |

| textarea | Multi-line text |

**These 24 controls are the FES inspector's field-type vocabulary.** Any new FES module's `fieldSchema` must use these control ids.

4d. The runtime pipeline

`bootstrap.js` (45 lines) → `runtime/index.js` → `runtime/load-annotation.js` → `runtime/renderer.js` → `runtime/region-renderer.js` → `runtime/region-actions.js` → `runtime/editor-shell.js` → `runtime/inline-editor.js` → `runtime/form-editor.js` → `runtime/visualizer.js` → `runtime/skin.js` (with `SAMPLE_SKINS`).

The full flow:

1. Page loads → bootstrap.js runs

2. `annotation.json` fetched from URL (or passed inline)

3. `loadAnnotation()` parses it into the store

4. `findPage(pathname)` matches the current URL

5. `region-renderer.js` walks the regions, `renderer.js` walks the modules

6. `registerRenderer('M-...', fn)` lookup dispatches each module

7. For each module: get config from store, apply skin, mount to `[data-fvcms-module-id]`

---

5. The FES gap (what's missing)

5a. The App-Builder Landscape says 93 roles, 15 canonical. FES ships 16.

| | App-Builder Landscape (a761) | FES dispatch (audit) | Gallery has |

|---|---|---|---|

| Total roles | 93 | 16 (17%) | 16 (17%) |

| Canonical 15 | 15 | **7 (47%)** | **7 (47%)** |

5b. The 8 missing canonical modules

These are the "must-have" set per a761 §3.13 — explicitly called out as the minimum for world-class. FES dispatches NONE of them:

| A761 canonical name | Why it's canonical | What FES would need to do |

|---|---|---|

| **form** | The superset form: 50+ field types, 30+ actions, 3-level conditional logic, multi-step | Already have `M-contact-form` — would be a superset/rename |

| **gallery** | The image gallery primitive (not just single image) | New module: 6 variants, lightbox, masonry, slideshow, etc. |

| **icon** | Standalone icon primitive (Fa + Lucide + custom) | New module: icon picker, sizing, color, link |

| **map** | Map embed (Google/Mapbox/OSM) | New module: lat/lng/address, marker, style |

| **modal** | Modal dialog primitive | New module: trigger, content, dismiss, focus trap |

| **pricing-table** | SaaS pricing table | New module: tiers, features, highlight, CTA |

| **query-loop** | Dynamic data loop (post-grid, post-carousel, archive, glossary) | New module: query args, template, pagination |

| **tabs** | Tabbed content | New module: tab triggers, panels, keyboard nav |

5c. The 75 missing non-canonical roles

Full A761 inventory vs FES coverage:

| A761 category | Total roles | In FES today | Missing |

|---|---|---|---|

| Layout primitives | 10 | 0 (none) | section, container, column, block, div, grid, stack, row, header, footer |

| Content display | 10 | 4 (heading, paragraph, image, button) | text (renamed→paragraph), image-box (renamed→image), icon, icon-box, buttons-group, list-group, divider, spacer |

| Structural & nav | 12 | 2 (accordion, breadcrumb) | tabs, toggle, modal, popup, off-canvas, sticky, mega-menu, navigation (→menu), pagination, search |

| Dynamic content | 12 | 0 | query-loop, single-field, single-product, archive, user-author, relation, glossary, post-grid, post-carousel, post-list, product-grid, product-carousel |

| Forms | 1 | 0 (have contact-form) | form (superset) |

| Interactive | 5 | 0 | image-compare, image-hotspot, image-mask, lottie, marquee |

| Data viz | 8 | 0 | counter, progress-bar, progress-arc, chart, timeline, process, data-table, pricing-table |

| Media & embed | 6 | 2 (video, social-icons) | audio, gallery, social-share, map |

| Marketing | 12 | 3 (cta, cta-box, testimonial) | banner, testimonial-grid, testimonial-carousel, team-member, team-grid, logo-grid, logo-carousel, news-ticker, weather |

| Engagement | 8 | 0 | reading-progress, scroll-to-top, cookie-consent, age-verification, coming-soon, maintenance, paywall, membership-gate |

| WooCommerce | 5 | 0 | product-single, cart, checkout, my-account, mini-cart |

| Theme templates | 4 | 0 | theme-header, theme-footer, theme-single, theme-archive |

**Total gaps: 8 canonical + 67 non-canonical = 75 missing modules.** Of those, 8 are canonical (must-have) and 67 are non-canonical (nice-to-have per builder tier).

---

6. Detector widget coverage gap (Elementor side)

FES detector handles 23 Elementor widget types. **The standard Elementor core + EAEL install has ~120 widgets.** Coverage = 19%.

Unhandled Elementor widget types (would fall to `default: null`, no FES module dispatched):

**The detector is the chokepoint.** Every widget the detector doesn't recognize = invisible to FES = invisible to the inspector. The Oscar dist has 11,535 `data-fvcms-region` markers but only a fraction of those will have a dispatched FES module.

---

7. FES strengths (what the audit confirms works)

1. **The dual-layer doctrine holds.** Schema IDs lowercase, runtime IDs M-prefixed. FES consumes the M-prefixed ids at runtime. The detector is M-prefixed, the renderer is M-prefixed, the chrome-registry is M-prefixed. Clean separation.

2. **The dispatch is locked.** 16 modules, all 16 registered in `renderer.js`, all 16 in `chrome-registry/index.json`, all 16 in `detectors/elementor.js`. No drift between the three. **This is gallery + FES in lockstep.**

3. **The inspector controls are reusable.** 24 control types cover 100% of the 16 current modules' `fieldSchema` shapes. Any new module reuses these, no new control type needed unless we add something exotic (e.g. color picker with alpha + swatch library).

4. **The region/module/group data model is solid.** Pages contain regions (top-level e-con), each region has groups (widgets), each group has module instances. The annotation.json schema (`data-model.md`) is the contract; the runtime consumes it; the editor produces it.

5. **Skin system is decoupled.** `SAMPLE_SKINS` in `skins/index.js` + `applySkin()` + `registerSkin()` API. Adding a new skin = no module change.

---

8. FES weaknesses (where the audit flags problems)

1. **Coverage is 17% of the App-Builder universe.** That's not a "world-class" module set — it's a starting set. The 8 missing canonical modules are the priority.

2. **The detector is the chokepoint.** ~19% of common Elementor widgets are dispatched. The rest are silently null. This makes the inspector useless on real Oscar / Hopfan sites where most widgets are eael-*.

3. **`menu` is single-source = `eael-simple-menu`.** No fallback to WordPress nav, no walker.js path. Hopfan's nav will likely be a default WP menu, not eael-simple-menu, and FES won't recognize it.

4. **Form superset is split between 3 elementor widgets** (`form`, `eael-weform`, `eael-fluentform`) but dispatched to ONE FES module (`M-contact-form`) with a generic config shape. The 50+ field types / 30+ actions / multi-step from A761 §3.5 are not modeled.

5. **No layouts at all.** A761 has 10 layout primitives (section, container, column, grid, stack, row, header, footer, block, div). FES has zero. The region detector reads `.e-con` but doesn't model it as a dispatchable module — the inspector can't add a new region programmatically.

6. **No dynamic data.** A761 has 12 dynamic roles (query-loop, single-product, archive, post-grid, etc.). FES has zero. The carousel module is the closest, but it doesn't query, it just renders.

7. **No interactions / animations / conditions.** A761's 6 behavior matrices (interaction, animation, dynamic binding, conditional logic, responsive, edge cases) are entirely absent from the FES module schema. Modules are static renderers.

8. **Inspector control set is finite.** 24 controls, no custom control type registry. New module = new field type = new control, OR the field type is forced into an existing control (lossy).

---

9. Summary of audit

| Audit dimension | Result |

|---|---|

| FES dispatch set | 16 modules (M-accordion, M-breadcrumb, M-button, M-carousel, M-contact-form, M-cta, M-cta-box, M-heading, M-icon-list, M-image, M-info-box, M-menu, M-paragraph, M-social-icons, M-testimonial, M-video) |

| Elementor widgets handled | 23 types → 16 FES modules (3 form variants collapse to M-contact-form, 3 carousel variants collapse to M-carousel) |

| Elementor widgets NOT handled | ~97 (standard core, all Pro dynamic, all EAEL extensions except the 23 above) |

| A761 §3.13 canonical 15 coverage | 7/15 dispatched (heading, paragraph, image, button, accordion, testimonial, video); 8 missing (form, gallery, icon, map, modal, pricing-table, query-loop, tabs) |

| A761 total roles coverage | 16/93 (17%) |

| Inspector controls | 24 (text, textarea, number, color, dimension, dropdown, slider, switch, tags, pills, responsive, radius, shadow-multi, backdrop-filter, background-{color,gradient,image,unsplash,tags}, motion-{entrance,grid,trigger}, filters, ai-assist) |

| Data attributes consumed | data-id, data-widget_type, data-settings, data-fvcms-{module-id,type,update}, data-region-content, data-{block,field,panel}-name, data-{id,settings,widget} |

| CSS contract | --fvcms-* custom properties, scoped per module |

| Breakpoints | 5 standard (mobile/mobile-wide/tablet/laptop/desktop) + container queries |

| Layout signals | region order, widget order, nested vs flat (top-level e-con only) |

| Strongest area | dual-layer doctrine, dispatcher integrity, skin system, data model |

| Weakest area | Elementor widget coverage (~19%), canonical completeness (47%), zero dynamic data, zero layouts, zero interactions/animations |

---

10. The implication for the world-class module plan

FES today is **stable and internally consistent** but **incomplete** by the App-Builder Landscape standard. The gallery has the same shape. To go from "16 modules" to "world-class," the priority order is:

**Tier 1 (canonical 8 missing — must add)**:

1. `icon` (M-icon) — simplest, foundational

2. `tabs` (M-tabs) — high-frequency content pattern

3. `modal` (M-modal) — high-frequency UI primitive

4. `form` (M-form) — superset M-contact-form, 50+ field types

5. `gallery` (M-gallery) — superset M-image, lightbox/masonry

6. `map` (M-map) — embed primitive, low complexity

7. `query-loop` (M-query-loop) — the dynamic data foundation

8. `pricing-table` (M-pricing-table) — marketing canonical

**Tier 2 (frequently missing on real sites — add for Oscar/Hopfan coverage)**:

9. `divider` (M-divider) — trivial, high-frequency

10. `spacer` (M-spacer) — trivial, high-frequency

11. `counter` (M-counter) — data viz entry

12. `progress-bar` (M-progress-bar) — data viz entry

13. `timeline` (M-timeline) — content pattern

14. `data-table` (M-data-table) — data viz

15. `lottie` (M-lottie) — animation primitive

16. `marquee` (M-marquee) — engagement

**Tier 3 (must add to detector for Elementor coverage)**:

17. eael-info-box (already in FES)

18. eael-team-member (gallery module, NOT in FES dispatch yet)

19. eael-pricing-table (after Tier 1 #8 lands)

20. eael-timeline (after Tier 2 #13 lands)

21. eael-flip-box

22. eael-modal-popup

23. eael-countdown

24. eael-business-hours

25. eael-faq

26. eael-filterable-gallery

27. eael-image-comparison

28. eael-image-hotspot

29. eael-logo-carousel

30. eael-mailchimp

31. eael-price-menu

33. eael-progress-bar (after Tier 2 #12)

34. eael-protected-content

35. eael-skill-bar

36. eael-table (after Tier 2 #14)

37. standard Elementor core (icon, icon-box, divider, spacer, counter, progress, star-rating, flip-box, call-to-action, countdown, toggle, tabs, search-form, page-title, all loop-*)

**Tier 4 (must add to schema for behavior support)**:

38. responsive.json (per-module breakpoint overrides)

39. conditions.json (visibility, conditional logic)

40. dynamic.json (data binding)

41. interactions.json (hover, click, scroll triggers)

42. edge.json (edge case behaviors)

**Tier 5 (must add for layouts)**:

43. section (M-section) — top-level region creator

44. container (M-container) — block-level region

45. column (M-column) — vertical layout

46. grid (M-grid) — CSS grid wrapper

47. row (M-row) — horizontal flex

48. stack (M-stack) — vertical flex

49. block (M-block) — generic block

50. header (M-header) — theme header

51. footer (M-footer) — theme footer

**Total: 51 new modules + detector expansion + schema expansion + 24-control surface stays.** That's the world-class target.

The plan is in the companion document: `/workspace/WORLD-CLASS-MODULE-PLAN-2026-08-26.md`.

---

— Mavis (helper-mavis, id 10, session 412100071272671)

2026-08-26 21:55 UTC