Dev mode toggle โ€” the single entry point for the entire CMS layer

setDevMode(on) already exists. It's the floating Dev icon (44ร—44, dark with green </>). When OFF: only the icon is visible, sitting above any app UI. When ON: chips appear on sections, dock pills on the edges, panels open, inspector slides in. One toggle, the whole layer.

๐Ÿ“ฑ Dev mode OFF (visitor mode)
PRODUCTION
DEV OFF
9:41 ๐Ÿ“ถ ๐Ÿ”‹

Explore the World of Trees

Bring nature into the classroom with beautifully illustrated, curriculum-aligned resources.

What we offer

Books ยท News ยท Team ยท Resources

Get Started

Ready to bring trees to your classroom?

ยฉ 2026 Tree Academy

๐Ÿ Home
๐Ÿ“šBooks
๐Ÿ“ฐNews
๐Ÿ‘ฅTeam
๐Ÿ‘คAccount
๐Ÿ“ฑ Dev mode ON (operator mode)
CMS LAYER
DEV ON
9:41 ๐Ÿ“ถ ๐Ÿ”‹
S-1

Explore the World of Trees

Bring nature into the classroom with beautifully illustrated, curriculum-aligned resources.

S-3

What we offer

Books ยท News ยท Team ยท Resources

S-5

Get Started

Ready to bring trees to your classroom?

S-6

ยฉ 2026 Tree Academy

๐Ÿ Home
๐Ÿ“šBooks
๐Ÿ“ฐNews
๐Ÿ‘ฅTeam
๐Ÿ‘คAccount
โ–ฆ STR
โš™ INS
โŠŸ LAY
โ†ถ HIS
+ Section
+ Widget
๐Ÿ“
FVRE
TRACE
PB
S-3 ยท Services
Heading
Section type
Auto-collapse below
Background
๐Ÿ“ Dev toggle position โ€” the rules
PLACEMENT
๐Ÿ“ Position
  • Default: bottom-right, 12px from edges, 70px above app bar
  • Draggable to any corner
  • Position persists in localStorage
  • safe-area-inset-* respected (iOS notch)
๐ŸŽจ Style
  • 44ร—44 round button (44pt touch target)
  • Dark when OFF, green when ON
  • Subtle drop shadow + 1px border
  • Hover: scale to 1.1
  • Active: glow halo when ON
๐Ÿ”Œ What's gated
  • All dock pills (4 edges)
  • All section chips
  • All panels (inspector, structure, media, etc.)
  • Section outlines on hover
  • Selection / breadcrumb / dev tools
โšก Triggers
  • Click toggle
  • Keyboard: Ctrl+Shift+D
  • URL param: ?dev=1
  • localStorage: fvcms.dev=1
  • Auth: dev role only (when backend available)
โš™๏ธ The toggle implementation
CODE
// freshvibe-cms/cms/devToggle.js โ€” the floating Dev icon
export function mountDevToggle({
  setDevMode,       // required: the existing setDevMode from install-editor
  getDevMode,       // required: isDevMode()
  persist = true,
}) {
  // Create the toggle element
  const btn = document.createElement('button');
  btn.className = 'fvcms-dev-toggle';
  btn.setAttribute('aria-label', 'Toggle Dev mode');
  btn.innerHTML = '</>';

  // Restore position from localStorage
  const pos = JSON.parse(localStorage.getItem('fvcms.devTogglePos') || 'null');
  if (pos) {
    btn.style.left = pos.x + 'px';
    btn.style.top  = pos.y + 'px';
  } else {
    btn.style.right = '12px';
    btn.style.bottom = '70px';  // above app bar
  }

  // Sync visual state with dev mode
  const sync = () => {
    const on = getDevMode();
    btn.classList.toggle('on', on);
    document.body.classList.toggle('fvcms-dev-on', on);
  };

  // Click toggles dev mode (uses existing setDevMode)
  btn.addEventListener('click', () => {
    setDevMode(!getDevMode());
    sync();
  });

  // Drag to reposition
  let drag = null;
  btn.addEventListener('pointerdown', (e) => {
    const r = btn.getBoundingClientRect();
    drag = { x: e.clientX - r.left, y: e.clientY - r.top };
    btn.setPointerCapture(e.pointerId);
  });
  btn.addEventListener('pointermove', (e) => {
    if (!drag) return;
    const x = e.clientX - drag.x, y = e.clientY - drag.y;
    btn.style.left = clamp(x, 0, innerWidth  - 44) + 'px';
    btn.style.top  = clamp(y, 0, innerHeight - 44) + 'px';
    btn.style.right = btn.style.bottom = 'auto';
  });
  btn.addEventListener('pointerup', (e) => {
    if (!drag) return;
    if (persist) {
      const r = btn.getBoundingClientRect();
      localStorage.setItem('fvcms.devTogglePos', JSON.stringify({ x: r.left, y: r.top }));
    }
    drag = null;
  });

  sync();
  document.body.appendChild(btn);
  return btn;
}

Why use the existing setDevMode, not invent a new toggle

What the Dev toggle does NOT do

What "CMS layer" actually means here

State persistence

What changes for the previous mockups (the bottom-bar placement one)