Fv CMS — Logic Audit + World-Class UX Plan + Task List

Operator directives 2026-07-29 03:50: (1) do a logic audit, (2) FES should research world-class UX/UI for every new tool/widget, (3) minimal-to-no-typing, (4) CSS tab for techies, (5) inline text editing with Text Tools front-and-centre, (6) widget panel should link to CMS post admin and propagate edits to all instances of that post.

Part 1 — Logic Audit

What we have today vs. what we need. Spot the gaps before building.

1.1 The data model (what exists, what's the source of truth)

ConceptTodayShould beGap
Content types freshvibe-cms/runtime/content-types.js (PB records) Single source at avidtech6/freshvibe-cms, exposed via FES OK — content types are Fv CMS's job, FES reads them
Content items PocketBase (per app's collection) PB or selected adapter (IndexedDB / GitHub Gist / etc.) OK — backend adapter framework covers this
Widget definitions freshvibe-cms/modules/ (17 files, M-* prefixed) Gallery's cms-widgets/ (per migration plan) PENDING — migration needed, FES not yet aware
Tool atoms (pickers) Implicit in widget schemas (type: 'color', etc.) Proper tool atoms in cms-widgets/tools/ PENDING — extraction needed
Widget metadata (provenance, tier, deps) None Rich metadata in module.json per widget MISSING — schema not defined
Reverse index (tool → widgets) None Computed in FES, exposed via tools/:id MISSING
Evolution tier (experimental/stable/certified) None Auto-computed, exposed via metadata, updatable via CLI MISSING

1.2 The runtime (engine + editor)

ConceptTodayShould beGap
Editor mounts in app Editor fragments in app-fragments/ expect host to call editor-shell.mount() Auto-mount on page load via freshvibe-cms/bootstrap.js PENDING — bootstrap needs the auto-mount call
Click region → edit panel region-editor.js handles click on [data-fvw-region] Works, but the panel needs to know which widget to render PENDING — widget-to-panel binding missing
Panel shows widget's fields Manual in FES Inspector v2 Widget's interface field drives panel UI MISSING
Save → backend Save adapter (PB / file) Backend chosen per-app via env or annotation OK — adapter framework exists
Re-render after save rerender-watcher.js Watches DOM, debounces, re-renders OK

1.3 The FES (discovery layer)

EndpointTodayShould beGap
GET /api/agent/content-types List content types OK (live, P2.1)
GET /api/agent/content-types/batch?names=... Multi-get OK (live, P2.1)
GET /api/agent/content-types/resolve?intent=... Intent → content type OK (live, P2.1)
GET /api/agent/cms-widgets List all widgets (with metadata, filterable) MISSING
GET /api/agent/cms-widgets/:id Get widget + source + tools used MISSING
GET /api/agent/cms-widgets/by-content-type/:type Find widgets for a content type MISSING
GET /api/agent/cms-widgets/resolve?intent=... One-shot: content types + widgets + tools for an intent MISSING
GET /api/agent/cms-widgets/tools List all tool atoms (filterable) MISSING
GET /api/agent/cms-widgets/tools/:id Tool + which widgets use it (reverse index) MISSING
GET /api/agent/cms-widgets/dependencies/:id Full transitive dep tree for a widget MISSING
POST /api/agent/cms-widgets/:id/review Update evolution tier / open issue / resolve MISSING

1.4 The UX surface (what the operator sees)

SurfaceTodayShould beGap
Click region in app Region editor opens inspector Same, but inspector auto-loads widget's panel UI PENDING
Inspector tabs Fields / Style / Advanced (FES v2) Fields / Style / Advanced / Text (contextual) PENDING
Style tab controls Map to widget's style schema Same, but each control is a tool atom (color-picker, etc.) PENDING
Advanced tab Free-form CSS Same, but also: classes, attributes, custom JS OK
Text Tools tab (NEW) Inline-edit floating bar that appears when user clicks into a text area MISSING
Text Tools features Bold / Italic / Underline / Link / Heading level / Quote / Code / List / Undo / Redo MISSING
Open in CMS admin Button on every panel: "Edit in CMS admin" → opens PB admin for that record MISSING
Propagation: edit in admin, all instances update Re-render watcher fires on every backend write, regardless of source PENDING
World-class picker UX Generic browser inputs Color = swatches + palette + eyedropper. Image = library + upload + URL. Font = preview list. Etc. MISSING
No-typing (except anchors) Every field has a picker. Typing only for free text (title, body) and anchors (URLs). MISSING

1.5 The VibeCoder-Edge Tools gap

From memory: operator "I have never even seen the edge tools yet in action". The Edge Tools panel has never successfully opened for the operator. The panelManager bug (mgr.addPanel() not in the API) is gating.

Operator-facing bug: the Edge Tools panel — meant to be the system composer for picking widgets and adding sections — has never been usable. Until this is fixed, the operator has no way to compose live apps.
T-0.1
Fix the panelManager bug: oscar-dev-panel.js:116 uses wrong API. Change to window.OscarPanelManager.get() || window.OscarPanelManager.create() (1-line)
15 min
P1
T-0.2
Fix the 2-pill mobile bug that the panelManager fix introduces (recursive dock cycle in panel-manager.js mobile dock() path)
1 h
P1
T-0.3
Verify operator can now open Edge Tools panel on a live app (deploy, screenshot, confirm)
30 min
P1

Part 2 — World-Class UX Standards (FES research checklist)

For EVERY new tool or widget, FES does research and produces this checklist. "World-class" means: it's the best in class for that UI primitive, not "it works."

2.1 Tool atoms — research gold standards

ToolGold standardWhat world-class looks like
color-picker Figma, Linear, Vercel Eyedropper + swatches + palette + recent + skin-aware tokens + opacity slider + hex/RGB/HSL input (last-resort)
image-selector Notion, Webflow, Sanity 3 tabs: Library (per app's media) / Upload (drag-drop) / URL (paste). Live preview. Alt text required. Aspect ratio lock.
gradient-picker Stripe, Linear 2-3 stops, drag to position, angle dial, presets (linear/radial/conic), hex + opacity per stop, copy as CSS var
font-picker Webflow, Figma Grouped by family (sans/serif/mono/display). Each shows live preview at the chosen size/weight. "Use skin default" at top.
favicon-picker Webflow, Vercel Emoji / Upload SVG / Pick from library. Live preview at 16/32/180/512.
icon-picker Webflow, Sanity Search across lucide + heroicons + custom. Live preview. "Recently used" pinned. Drag-out into the panel.
spacing-control Webflow, Figma Linked or per-side. Slider + number + 4 text inputs. Snap to skin scale (4/8/16/24/32/48/64). Eyedropper reads from sibling.
shadow-control Webflow, Stripe Presets (none/sm/md/lg/xl/2xl) + custom. X/Y/blur/spread sliders. Color + opacity. Inner/outer toggle. Live preview on a sample card.
border-radius-control Figma, Webflow 4 corner toggle (linked vs per-corner). Slider with snap points. 0/full/pill presets.
typography-control Webflow, Figma Font family picker + weight + size + line-height + letter-spacing. Live preview. Style presets (display/h1/h2/body/caption).
link-builder Notion, Sanity URL / mailto / phone / anchor / page. New tab toggle. Nofollow toggle. "Search content" for internal links.
date-picker Linear, Vercel Calendar view + "today/tomorrow/next week" presets + timezone selector + ISO output.
slug-input WordPress, Ghost Auto-derived from title, editable, collision check (red = taken, green = free), live URL preview.
tag-input Notion, Linear Type-to-create. Comma to confirm. Autocomplete from existing. Per-tag color.
toggle iOS, Linear Switch with optional label. Disabled state. Group toggles (3+ together).
select Stripe, Linear Searchable dropdown. Recent selections. Multi-select with chips. Option icons.
markdown-editor GitHub, Notion Split-pane (edit | preview). Toolbar (B/I/H1/H2/link/code/quote/list). Slash commands. Drag-drop images.
rich-text Notion, Linear Block-based (Tiptap/ProseMirror). Slash menu. Inline + block formatting. Slash commands. Drag-to-reorder.

2.2 Widget panels — research gold standards

SurfaceGold standardWhat world-class looks like
Panel layout Elementor, Webflow, Sanity, Linear Top: widget name + breadcrumb + close. Tabs: Fields / Style / Text / Advanced. Body: tab content. Footer: save state + "Open in CMS admin" link.
Field rows Linear, Notion Icon (24px) + label + control (240px+). Helper text below on hover. Drag to reorder.
Style rows Figma, Webflow Grouped by category (Color, Typography, Spacing, Border, Shadow). Collapsible. Token-aware.
Text Tools (floating bar) Notion, Medium, Google Docs Floating pill above the selected text. Bold / Italic / Underline / Strike / Link / H1/H2/H3 / Quote / Code / List. Auto-hide on blur.
Advanced / CSS Webflow CodeMirror editor with autocomplete. CSS custom properties (--x-color, --x-space) injected. Apply button (or auto-apply on blur).
Save indicator Linear, Notion "Saved 2 seconds ago" / "Saving..." / "Unsaved changes" with timestamp. Color-coded (green/blue/orange).
Inline text editing Notion, Sanity Click into text area → focus ring + Text Tools bar appears. Type, see changes live. Click outside → save.

Part 3 — The Plan (phases + tasks)

Scope split (operator directive 2026-07-29 09:43): The phases below describe Fv CMS layer work (panel redesign, world-class UX). These are NOT roadmap Phase 2 of VibeCoder.

VibeCoder roadmap Phase 2 is the smaller, VibeCoder-side work: P2.2 (spec-enrichment via FES), P2.4 (editor save→PB bridge), P2.5 (plan validation), P2.6 (CRUD UI), P2.7 (region-to-content-type wiring). P2.1 and P2.3a are already done.

Fv CMS phase plan (this doc) is the bigger, CMS-layer work: panel redesign with 4 tabs, world-class pickers, inline text editing, CSS tab, "Open in CMS admin" link. Lives in freshvibe-cms/runtime/cms-panel.js and the gallery's cms-widgets/ section.

Both plans are valid. They just live in different repos. The CMS plan ships with the Fv CMS version bump; the VibeCoder plan ships with VibeCoder releases.
Phase 1: Foundation (P0 — must happen first)

Get the basic plumbing in place. The Edge Tools bug, the metadata schema, and the migration from Fv CMS to the gallery.

T-1.1
Fix the Edge Tools panelManager bug (T-0.1, T-0.2, T-0.3)
2 h
P1
T-1.2
Define the rich metadata schema (provenance, evolution, dependencies, interface). Write to fv-module-gallery/gallery-pact/widget-metadata.schema.json
2 h
P1
T-1.3
Extract the 5 starter tool atoms (color-picker, image-selector, gradient-picker, font-picker, favicon-picker) into cms-widgets/tools/
3 h
P1
T-1.4
Migrate the 17 modules from freshvibe-cms/modules/ to fv-module-gallery/cms-widgets/ with rich metadata, dependencies.tools, FV-CMS-WIDGET markers
4 h
P1
T-1.5
Build the FES widget registry (cms-widgets-registry.cjs) — scans the vendored tree, builds in-memory registry, 5-min cache
1 h
P1
T-1.6
Wire 8 FES endpoints (list, get, by-content-type, resolve, tools, tools/:id, dependencies, review) — all auth-checked, cache-aware
2 h
P1
T-1.7
Build the reverse index (tool → widgets). Computed in registry on load, exposed via tools/:id
1 h
P1
T-1.8
Build the evolution tier CLI (fv-review subcommand). Thin's around the bridge's POST /:id/review endpoint
1 h
P1
T-1.9
Deploy + verify: VibeCoder → FES.resolve?intent=blog returns BlogPost + 2 widgets + 3 tools, with maturity scores
1 h
P1
Phase 2: Panel redesign (P1 — world-class UX)

Rebuild the inspector to be world-class. Inline text editing, no-typing for most fields, CSS tab for techies, "Open in CMS admin" link.

T-2.1
Rebuild the panel layout: top chrome (name + breadcrumb + close), 4 tabs (Fields / Style / Text / Advanced), footer (save state + "Open in CMS admin")
3 h
P2
T-2.2
Refactor the field rendering: each field type maps to a tool atom. No more raw <input> for color/image/url/select/etc.
4 h
P2
T-2.3
Group Style tab: Color / Typography / Spacing / Border / Shadow. Each group collapsible. Token-aware (uses skin tokens).
3 h
P2
T-2.4
CSS tab (Advanced): CodeMirror editor with CSS custom property autocomplete. Apply button. Auto-apply on blur.
2 h
P2
T-2.5
Inline text editing: click into a text area → focus ring + floating Text Tools bar appears. Bold/Italic/Underline/Strike/Link/H1-3/Quote/Code/List.
4 h
P2
T-2.6
Text Tools bar: hide on blur, follow selection, work inside any contenteditable element
2 h
P2
T-2.7
"Open in CMS admin" link: button on every panel that links to {PB_URL}/_/#/collections/{type}/records/{id}
1 h
P2
T-2.8
Save indicator: "Saved 2 seconds ago" / "Saving..." / "Unsaved changes" with timestamp. Color-coded.
1 h
P2
T-2.9
Verify on 2 widgets (blog-post-card, listing-grid): click region → panel → edit field via tool atom → save → re-render → admin link works → inline text edit works
2 h
P2
Phase 3: Tool atoms — the rest (P2)

Extract the remaining atoms that widgets need.

T-3.1
icon-picker (lucide + heroicons + custom, searchable)
2 h
P2
T-3.2
spacing-control (linked or per-side, snap to scale)
2 h
P2
T-3.3
shadow-control (presets + custom sliders)
2 h
P2
T-3.4
border-radius-control, typography-control, link-builder, date-picker, slug-input, tag-input, toggle, select, markdown-editor, rich-text
6 h
P2
T-3.5
For each tool, the FES research checklist was followed (gold standard + world-class check)
in each task
P2
Phase 4: Edge Tools composer (P2)

Now that Edge Tools panel opens, build the actual composer. Widget picker + section picker. The operator's main tool for live app composition.

T-4.1
Widget picker: list 17+ widgets (with thumbnails, names, descriptions). Click → insert into the current section's region
3 h
P2
T-4.2
Section picker: add a new top-level .e-parent container (vertical / horizontal / grid)
2 h
P2
T-4.3
Section edit mode: drag to reorder widgets, resize, delete
3 h
P3
T-4.4
Theme picker: choose a skin (fresh-classic, fresh-soft, custom)
2 h
P3
Phase 5: Propagation (P3)

Edit in CMS admin → all instances of that post update. The realtime channel + invalidation.

T-5.1
PocketBase realtime channel: subscribe to record changes for the content types this app uses
3 h
P3
T-5.2
On realtime event, re-render all widgets bound to that record (use existing rerender-watcher.js)
2 h
P3
T-5.3
Test: edit a BlogPost in PB admin → app re-renders that post in all places it appears
1 h
P3
Phase 6: Migration cleanup (gated on operator approval)

Deprecate freshvibe-cms/modules/ in favor of the gallery. The runtime stays; the widgets and tools move.

T-6.1
Replace freshvibe-cms/modules/ with a re-export shim that points at the gallery's vendored copy
1 h
P3
T-6.2
Update all imports across the codebase to point at the gallery
2 h
P3
T-6.3
Once stable, delete freshvibe-cms/modules/
30 min
P3

Part 4 — Time estimates

PhaseTasksHoursDays (5h/day)
Phase 1: Foundation T-1.1 → T-1.9 17 h ~3.5 days
Phase 2: Panel redesign T-2.1 → T-2.9 22 h ~4.5 days
Phase 3: Tool atoms (rest) T-3.1 → T-3.5 12 h ~2.5 days
Phase 4: Edge Tools composer T-4.1 → T-4.4 10 h 2 days
Phase 5: Propagation T-5.1 → T-5.3 6 h ~1.5 days
Phase 6: Migration cleanup T-6.1 → T-6.3 3.5 h ~0.5 day
TOTAL 40 tasks ~70.5 h ~14 days

Phase 1 is the foundation — it unblocks everything else. Phase 2 is the UX transformation. Phases 3-5 are the polish. Phase 6 is the cleanup.

Part 5 — Order of operations (this week)

  1. Day 1: Phase 1 tasks 1.1-1.4 (Edge Tools fix + schema + tools + migration)
  2. Day 2: Phase 1 tasks 1.5-1.9 (registry + endpoints + CLI + verify)
  3. Day 3-4: Phase 2 (panel redesign, the big UX work)
  4. Day 5+: Phases 3-5 as time allows

By end of Day 2 we have the FES layer working. By end of Day 4 we have a world-class panel. Days 5+ are polish.

Part 6 — FES research checklist (template)

For every new tool or widget, FES produces this. Non-negotiable.

Tool/Widget: color-picker Author: FES + Mavis Date: 2026-07-29

1. Gold standards surveyed (3-5 references): 2. What world-class looks like for this tool: - Eyedropper (samples from the app) - Recent colors (last 8 used) - Skin-aware palette (skin tokens) - Hex / RGB / HSL input (last-resort, not primary) - Opacity slider (separate from color)

3. Anti-patterns to avoid: - Generic browser <input type="color"> (no eyedropper, no recent, no palette) - Big hex input as the primary (typing-heavy, no preview) - No opacity support - No skin awareness

4. Acceptance criteria: - [ ] Eyedropper works on the app's rendered content - [ ] Last 8 used colors persist per session - [ ] Skin tokens shown first, then custom - [ ] Opacity separate slider - [ ] Mobile-friendly (sheet-based picker on small viewports) - [ ] Keyboard accessible (Tab, Enter, Esc)

5. Test plan: - Open a widget, click color field → picker appears with all features - Pick a color → applied to widget → re-render → persists - Use eyedropper on the app's body → color picked - Mobile: picker is a bottom sheet, not modal

Apply this to EVERY tool/widget. Skip the checklist = don't ship.