# Gemini Consultation: Ghost Page Builder Architecture

**Date:** March 22, 2026  
**Session:** Chronicler #39  
**Tool:** Task #70 - Ghost Page Builder  
**Consultation Duration:** ~20 minutes  
**Pattern:** Following The Translator's Gemini Collaboration Pattern

---

## CONTEXT

Building an interactive React tool for live preview of Ghost CMS page HTML with Fire/Frost CSS before publishing. Current workflow (write → paste → preview → edit → repeat) wastes significant time.

**Challenge:** Single `.jsx` artifact (no build step) with:
- Live HTML editor
- Real-time preview with custom CSS
- Ghost CMS compatibility
- Viewport testing (mobile/tablet/desktop)

---

## CONSULTATION QUESTIONS

Sent to Gemini for architectural guidance:

1. **Preview Architecture:** Iframe vs other approaches? CSS injection strategy?
2. **Syntax Highlighting:** CodeMirror vs simpler textarea?
3. **React State:** Best pattern for live updates + localStorage?
4. **Mobile Preview:** How to implement viewport toggling?
5. **Gotchas:** What breaks with iframe-based preview?

---

## GEMINI'S KEY RECOMMENDATIONS

### 1. Use `srcdoc` Attribute for Preview

**Gemini's Guidance:**
> "Use the iframe's `srcdoc` attribute. It is declarative, plays perfectly with React's state paradigm, and avoids cross-origin headaches because the browser treats it as same-origin by default."

**Why This Matters:**
- Avoids direct document manipulation
- Works seamlessly with React state
- No CORS issues
- Clean separation of concerns

**Implementation:**
```javascript
const generatePreviewHtml = (htmlContent) => {
  return `<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  
  <link rel="stylesheet" href="https://firefrostgaming.com/assets/built/screen.css">
  
  <style>${FIRE_FROST_CSS}</style>
</head>
<body class="gh-body">
  <div class="gh-content">
    ${htmlContent}
  </div>
</body>
</html>`;
};
```

### 2. CSS Injection Order Critical

**Gemini's Guidance:**
> "CSS Injection Order: 1. Ghost Theme CSS (Source v1.5.2), 2. Ghost Site-wide Head Injection (if separate), 3. Fire/Frost Custom CSS (This ensures your custom brand gradients override defaults)."

**Why This Matters:**
- Fire/Frost CSS must come LAST to override Ghost defaults
- Order affects gradient rendering
- Ensures brand consistency

### 3. Ghost Wrapper Classes Required

**Gemini's Critical Insight:**
> "Ghost uses specific wrapper classes (like `.gh-content` or `.kg-canvas`) to apply styling to inner HTML. If you don't wrap your injected HTML in those exact classes within your `srcdoc` template, the typography and spacing won't match the live site."

**Why This Matters:**
- Without `.gh-body` and `.gh-content`, preview won't match Ghost
- Typography, spacing, and layout depend on these classes
- Must be included in ALL sample templates

**Impact:** This prevented hours of "why doesn't my preview match Ghost?" debugging.

### 4. Skip CodeMirror, Use Styled Textarea

**Gemini's Guidance:**
> "CodeMirror is incredibly powerful, but getting v6 to work nicely inside a single-file, no-build React artifact (like a Claude Artifact) usually requires messy CDN imports and complex `useEffect` hooks to bind the editor to the DOM. It frequently breaks. For simple HTML editing, a well-styled `<textarea>` with a monospace font, a dark background, and disabled spellcheck is highly effective and completely bug-free in React state."

**Why This Matters:**
- Complexity vs value tradeoff
- Build-less artifact constraint
- Reliability over features for V1

**Decision:** Start simple, add syntax highlighting later if needed.

### 5. Two-State Pattern for Performance

**Gemini's Guidance:**
> "You need two pieces of state: one for the instant typing in the editor, and one for the iframe update/LocalStorage save. A 500ms debounce is the sweet spot."

**Implementation:**
```javascript
const [htmlInput, setHtmlInput] = useState("");
const [debouncedHtml, setDebouncedHtml] = useState("");

useEffect(() => {
  const timer = setTimeout(() => {
    setDebouncedHtml(htmlInput);
    localStorage.setItem('firefrost_ghost_draft', htmlInput);
  }, 500);

  return () => clearTimeout(timer);
}, [htmlInput]);
```

**Why This Matters:**
- Prevents iframe flashing on every keystroke
- Saves CPU/browser resources
- Better UX

### 6. Tab Key Intercept with Cursor Trick

**Gemini's Critical Detail:**
> "The `setTimeout(() => {...}, 0)` trick to wait for React state update before moving cursor position is the key detail we would have missed."

**Implementation:**
```javascript
const handleKeyDown = (e) => {
  if (e.key === 'Tab') {
    e.preventDefault();
    
    const start = e.target.selectionStart;
    const end = e.target.selectionEnd;
    
    const newValue = htmlInput.substring(0, start) + "  " + htmlInput.substring(end);
    
    setHtmlInput(newValue);
    
    // Wait for React state update before moving cursor
    setTimeout(() => {
      e.target.selectionStart = e.target.selectionEnd = start + 2;
    }, 0);
  }
};
```

**Why This Matters:**
- Without `setTimeout`, cursor position resets to end
- React state update timing issue
- Breaks indentation UX without this fix

**Impact:** This is a subtle React gotcha that only shows up when typing fast.

### 7. Viewport via Container Resizing (Not CSS Scale)

**Gemini's Guidance:**
> "Do not use `transform: scale()`. It completely breaks CSS media queries, which defeats the purpose of testing a mobile layout. Instead, wrap the `iframe` in a `div`. Set the iframe to `width: 100%`, and change the `width` of the wrapper `div`."

**Why This Matters:**
- CSS scale breaks media queries
- Defeats purpose of mobile preview
- Container resizing preserves breakpoints

**Implementation:**
```javascript
<div style={{ width: viewportWidths[viewport], height: "100%" }}>
  <iframe className="w-full h-full" ... />
</div>
```

### 8. Sandbox Flags: `allow-same-origin allow-scripts`

**Gemini's Guidance:**
> "For a Ghost preview, you will likely need exactly one more flag to make it perfectly accurate: `allow-scripts`. If you copy/paste any Ghost embed cards (like Twitter, YouTube, or Ghost's native image galleries), those components rely on a tiny bit of JavaScript to render correctly."

**Why This Matters:**
- Ghost embed cards need JS to render
- Without `allow-scripts`, embeds show as broken
- Safe for internal tool (Michael only)

**Decision:** Include both flags for accurate preview.

---

## GOTCHAS GEMINI IDENTIFIED

### 1. External Assets Must Use Absolute URLs

**Issue:** Relative paths fail inside `srcdoc`.

**Solution:** Always use `https://firefrostgaming.com/...` for images, fonts, etc.

### 2. Tab Key Default Behavior

**Issue:** Tab normally moves focus to next element.

**Solution:** Intercept with `preventDefault()` and insert spaces manually.

### 3. Ghost Wrapper Classes in Templates

**Issue:** Sample templates without `.gh-content` won't render correctly.

**Solution:** Include Ghost wrapper classes in ALL template strings.

---

## IMPLEMENTATION DECISIONS BASED ON CONSULTATION

### What We Built (Following Gemini's Guidance)

1. ✅ **Architecture:** Split-pane React component with iframe preview
2. ✅ **Preview:** `srcdoc` attribute with proper HTML document structure
3. ✅ **CSS Injection:** Ghost Theme CSS → Fire/Frost CSS (correct order)
4. ✅ **Editor:** Styled textarea (no CodeMirror for V1)
5. ✅ **State:** Two-state pattern (instant + debounced)
6. ✅ **LocalStorage:** Auto-save on 500ms debounce
7. ✅ **Tab Key:** Intercept with `setTimeout` cursor fix
8. ✅ **Viewport:** Container width resizing (preserves media queries)
9. ✅ **Sandbox:** `allow-same-origin allow-scripts`
10. ✅ **Templates:** All include `.gh-body` and `.gh-content` wrappers

### What We Avoided (Based on Gemini's Warnings)

1. ❌ CodeMirror complexity (too heavy for build-less artifact)
2. ❌ Direct iframe document manipulation (use `srcdoc` instead)
3. ❌ CSS `transform: scale()` for viewport (breaks media queries)
4. ❌ Relative URLs in CSS (use absolute URLs)
5. ❌ Missing Ghost wrapper classes (templates must include them)

---

## TIME SAVED

**Without Gemini Consultation:**
- Would have tried CodeMirror first (30-60 min debugging CDN imports)
- Would have missed `setTimeout` for Tab key (15-30 min frustration)
- Would have used CSS scale for viewport (30 min realizing media queries broken)
- Would have forgotten Ghost wrapper classes (60+ min of "why doesn't this match?")

**Estimated Time Saved:** 2-3 hours of trial-and-error debugging

**With Gemini Consultation:**
- 10 minutes to draft consultation prompt
- 5 minutes for Gemini response
- 50 minutes to build following guidance
- **Total:** 65 minutes with high confidence

---

## CONSULTATION QUALITY ASSESSMENT

**What Worked Well:**
- Detailed context (infrastructure, constraints, theories)
- Specific questions (architecture, gotchas, React patterns)
- Code samples in response (copy/paste ready)
- Follow-up on Tab key (Gemini offered proactively)

**Gemini's Strengths:**
- Deep React knowledge (two-state pattern, `setTimeout` trick)
- Ghost CMS expertise (wrapper classes, embed cards)
- Practical architecture (simple > complex for V1)
- Gotcha identification (CSS scale, relative URLs)

**Pattern Validation:**
The Translator's consultation pattern WORKS:
1. Provide full context (not just "how do I...")
2. Share our theories (shows thinking, not just asking)
3. Ask specific questions (architecture, not code)
4. Request gotchas/warnings (Gemini excels at this)

---

## FILES CREATED

**Consultation Documentation:**
- `docs/tasks/ghost-page-builder/gemini-consultation.md` (this file)

**Implementation:**
- `/home/claude/ghost-page-builder.jsx` (React artifact, 350+ lines)

**Related Tasks:**
- Task #70: Ghost Page Builder (TESTING phase)
- Task #69: Ghost Website Core Pages (BLOCKED on #70)

---

## NEXT STEPS

1. ✅ Michael tests Ghost Page Builder artifact
2. ⏳ Fix any issues discovered in testing
3. ⏳ Mark Task #70 COMPLETE
4. ⏳ Use tool to build 6 Ghost pages (Task #69)
5. ⏳ Document lessons learned from actual usage

---

## LESSONS FOR FUTURE CHRONICLERS

**When to Consult Gemini:**
- Building interactive tools (Gemini has deep React knowledge)
- Ghost CMS work (Gemini knows Ghost internals)
- Architectural decisions (Gemini excels at tradeoff analysis)
- CSS/DOM edge cases (Gemini catches gotchas)

**How to Write Good Consultation Prompts:**
- Full context (what we're building, why, constraints)
- Our theories (shows we've thought about it)
- Specific questions (architecture, not "write the code")
- Technical environment (React version, available libraries)

**What NOT to Ask Gemini:**
- "Write the whole thing for me" (we're the builders)
- Questions we can answer from docs (use Gemini for expertise)
- Vague "how do I..." questions (be specific)

---

**Gemini Consultation Pattern: VALIDATED** ✅

The Translator was right - Gemini collaboration dramatically improves tool quality when used strategically.

---

**Fire + Frost + Foundation = Where Love Builds Legacy** 💙🔥❄️

**Consultation Completed:** March 22, 2026  
**Documented By:** Chronicler #39  
**Pattern:** The Translator's Gemini Collaboration Pattern  
**Status:** Implementation complete, testing in progress
