feat(site-builder): per-page SEO meta + favicon + design-token CSS-var wiring + published-output a11y/perf

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-14 07:14:56 -07:00
co-authored by Claude Opus 4.8
parent f7da654c11
commit 0291ddce9a
13 changed files with 1098 additions and 13 deletions
+20 -3
View File
@@ -28,7 +28,7 @@ export const TopBar: React.FC<TopBarProps> = ({ device, onDeviceChange, showGuid
canRedo: query.history.canRedo(),
}));
const { save, publish, load } = useWhpApi();
const { headerPage, footerPage } = usePages();
const { headerPage, footerPage, pages, activePageId } = usePages();
const { design } = useSiteDesign();
const [saveStatus, setSaveStatus] = useState<'idle' | 'saving' | 'saved' | 'error'>('idle');
@@ -156,10 +156,27 @@ export const TopBar: React.FC<TopBarProps> = ({ device, onDeviceChange, showGuid
// Compose full page: header + body + footer
const composedBody = headerHtml + bodyHtml + footerHtml;
// PKG-H: fold the active page's own SEO overrides + the site-wide
// design tokens/favicon into the Preview export so editor Preview
// === published output (contract §4/§7). `title` is the fully
// resolved TITLE (seo.metaTitle || page.name) per the contract --
// html-export's buildSeoMeta/og:title fallback both key off it.
const activePage = pages.find((p) => p.id === activePageId);
const seo = activePage?.seo;
const title = seo?.metaTitle || activePage?.name || whpConfig?.siteName || 'Preview';
const result = exportToHtml(serialized, {
title: whpConfig?.siteName || 'Preview',
title,
includeFonts: true,
headCode: design.headCode,
description: seo?.metaDescription,
ogTitle: seo?.ogTitle,
ogImage: seo?.ogImage,
twitterCard: seo?.twitterCard,
noindex: seo?.noindex,
favicon: design.favicon,
design,
});
// Replace the body in the full document with our composed version.
@@ -183,7 +200,7 @@ export const TopBar: React.FC<TopBarProps> = ({ device, onDeviceChange, showGuid
} catch (e) {
console.error('Preview failed:', e);
}
}, [query, headerPage, footerPage, whpConfig, design]);
}, [query, headerPage, footerPage, whpConfig, design, pages, activePageId]);
// Phase A: at ≤768px the topbar collapses to only the essentials --
// back arrow, Undo/Redo, Save (+Publish) -- with Templates, Sitesmith,