What we have today vs. what we need. Spot the gaps before building.
| Concept | Today | Should be | Gap |
|---|---|---|---|
| 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 |
| Concept | Today | Should be | Gap |
|---|---|---|---|
| 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 |
| Endpoint | Today | Should be | Gap |
|---|---|---|---|
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 |
| Surface | Today | Should be | Gap |
|---|---|---|---|
| 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 |
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.
oscar-dev-panel.js:116 uses wrong API. Change to window.OscarPanelManager.get() || window.OscarPanelManager.create() (1-line)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."
| Tool | Gold standard | What 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. |
| Surface | Gold standard | What 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. |
freshvibe-cms/runtime/cms-panel.js
and the gallery's cms-widgets/ section.
Get the basic plumbing in place. The Edge Tools bug, the metadata schema, and the migration from Fv CMS to the gallery.
fv-module-gallery/gallery-pact/widget-metadata.schema.jsoncms-widgets/tools/freshvibe-cms/modules/ to fv-module-gallery/cms-widgets/ with rich metadata, dependencies.tools, FV-CMS-WIDGET markerstools/:idfv-review subcommand). Thin's around the bridge's POST /:id/review endpointRebuild the inspector to be world-class. Inline text editing, no-typing for most fields, CSS tab for techies, "Open in CMS admin" link.
<input> for color/image/url/select/etc.{PB_URL}/_/#/collections/{type}/records/{id}Extract the remaining atoms that widgets need.
Now that Edge Tools panel opens, build the actual composer. Widget picker + section picker. The operator's main tool for live app composition.
.e-parent container (vertical / horizontal / grid)Edit in CMS admin → all instances of that post update. The realtime channel + invalidation.
Deprecate freshvibe-cms/modules/ in favor of the gallery. The runtime stays; the widgets and tools move.
freshvibe-cms/modules/ with a re-export shim that points at the gallery's vendored copyfreshvibe-cms/modules/| Phase | Tasks | Hours | Days (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.
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.
For every new tool or widget, FES produces this. Non-negotiable.
color-picker
Author: FES + Mavis
Date: 2026-07-29
<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
Apply this to EVERY tool/widget. Skip the checklist = don't ship.