Archived to docs/archive/retired-tasks/: - Ghost CMS tasks (6 folders) - retired April 2, 2026 - Paymenter tasks (2 folders) - retired April 3, 2026 - Ghost website pages Removed duplicate templates: - MEMORIAL-TEMPLATE.md (keeping lowercase version) - PORTRAIT-PROMPT-TEMPLATE.md (keeping lowercase version) - SESSION-REPORT-TEMPLATE.md (keeping lowercase version) - OPENER-TEMPLATE.md Chronicler #66
11 KiB
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:
- Preview Architecture: Iframe vs other approaches? CSS injection strategy?
- Syntax Highlighting: CodeMirror vs simpler textarea?
- React State: Best pattern for live updates + localStorage?
- Mobile Preview: How to implement viewport toggling?
- Gotchas: What breaks with iframe-based preview?
GEMINI'S KEY RECOMMENDATIONS
1. Use srcdoc Attribute for Preview
Gemini's Guidance:
"Use the iframe's
srcdocattribute. 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:
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-contentor.kg-canvas) to apply styling to inner HTML. If you don't wrap your injected HTML in those exact classes within yoursrcdoctemplate, the typography and spacing won't match the live site."
Why This Matters:
- Without
.gh-bodyand.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
useEffecthooks 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:
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:
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 theiframein adiv. Set the iframe towidth: 100%, and change thewidthof the wrapperdiv."
Why This Matters:
- CSS scale breaks media queries
- Defeats purpose of mobile preview
- Container resizing preserves breakpoints
Implementation:
<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)
- ✅ Architecture: Split-pane React component with iframe preview
- ✅ Preview:
srcdocattribute with proper HTML document structure - ✅ CSS Injection: Ghost Theme CSS → Fire/Frost CSS (correct order)
- ✅ Editor: Styled textarea (no CodeMirror for V1)
- ✅ State: Two-state pattern (instant + debounced)
- ✅ LocalStorage: Auto-save on 500ms debounce
- ✅ Tab Key: Intercept with
setTimeoutcursor fix - ✅ Viewport: Container width resizing (preserves media queries)
- ✅ Sandbox:
allow-same-origin allow-scripts - ✅ Templates: All include
.gh-bodyand.gh-contentwrappers
What We Avoided (Based on Gemini's Warnings)
- ❌ CodeMirror complexity (too heavy for build-less artifact)
- ❌ Direct iframe document manipulation (use
srcdocinstead) - ❌ CSS
transform: scale()for viewport (breaks media queries) - ❌ Relative URLs in CSS (use absolute URLs)
- ❌ 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
setTimeoutfor 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,
setTimeouttrick) - 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:
- Provide full context (not just "how do I...")
- Share our theories (shows thinking, not just asking)
- Ask specific questions (architecture, not code)
- 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
- ✅ Michael tests Ghost Page Builder artifact
- ⏳ Fix any issues discovered in testing
- ⏳ Mark Task #70 COMPLETE
- ⏳ Use tool to build 6 Ghost pages (Task #69)
- ⏳ 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