diff --git a/src/frontend/src/App.tsx b/src/frontend/src/App.tsx index 1779313..a558fb9 100644 --- a/src/frontend/src/App.tsx +++ b/src/frontend/src/App.tsx @@ -10,6 +10,18 @@ import { Toc } from './Toc' import { Footer } from './Footer' import { ChatLayout, AgentUILayout, CopilotWidget, PlaygroundLayout } from './layouts' +function SkipLink({ enabled }: { enabled?: boolean }) { + if (!enabled) return null + return ( + + Skip to main content + + ) +} + export default function App() { const [config, setConfig] = useState({}) const [nav, setNav] = useState({}) @@ -100,8 +112,14 @@ export default function App() { // Update SEO meta tags dynamically const updateSEO = (title: string, path: string, description?: string) => { - // Update title - document.title = `${title} | ${config.site?.title || 'Documentation'}` + // Update title using SEO titleTemplate if available + const titleTemplate = config.seo?.titleTemplate || '%s | %s' + const siteName = config.site?.title || 'Documentation' + if (titleTemplate.includes('%s')) { + document.title = titleTemplate.replace('%s', title).replace('%s', siteName) + } else { + document.title = `${title} | ${siteName}` + } // Update canonical URL let canonical = document.querySelector('link[rel="canonical"]') as HTMLLinkElement @@ -137,6 +155,30 @@ export default function App() { document.head.appendChild(ogUrl) } ogUrl.content = window.location.origin + path + + // Update Twitter meta tags if configured + if (config.seo?.twitter) { + Object.entries(config.seo.twitter).forEach(([key, value]) => { + let twitterMeta = document.querySelector(`meta[name="twitter:${key}"]`) as HTMLMetaElement + if (!twitterMeta) { + twitterMeta = document.createElement('meta') + twitterMeta.name = `twitter:${key}` + document.head.appendChild(twitterMeta) + } + twitterMeta.content = value + }) + } + + // Set default image if available + if (config.seo?.defaultImage) { + let ogImage = document.querySelector('meta[property="og:image"]') as HTMLMetaElement + if (!ogImage) { + ogImage = document.createElement('meta') + ogImage.setAttribute('property', 'og:image') + document.head.appendChild(ogImage) + } + ogImage.content = config.seo.defaultImage + } } const handleItemClick = (item: NavItem) => { @@ -271,6 +313,7 @@ export default function App() { if (config.chat?.enabled) { return (
+
{renderLayout()}