diff --git a/apps/docs/app/[lang]/[[...slug]]/page.tsx b/apps/docs/app/[lang]/[[...slug]]/page.tsx
index 5dd543dcb..920a8a40e 100644
--- a/apps/docs/app/[lang]/[[...slug]]/page.tsx
+++ b/apps/docs/app/[lang]/[[...slug]]/page.tsx
@@ -5,6 +5,7 @@ import { ChevronLeft, ChevronRight } from 'lucide-react'
import Link from 'next/link'
import { notFound } from 'next/navigation'
import { StructuredData } from '@/components/structured-data'
+import { CodeBlock } from '@/components/ui/code-block'
import { source } from '@/lib/source'
export const dynamic = 'force-dynamic'
@@ -22,31 +23,143 @@ export default async function Page(props: { params: Promise<{ slug?: string[]; l
pageTreeRecord[params.lang] ?? pageTreeRecord.en ?? Object.values(pageTreeRecord)[0]
const neighbours = pageTree ? findNeighbour(pageTree, page.url) : null
- const CustomFooter = () => (
-
- {neighbours?.previous ? (
-
-
-
{neighbours.previous.name}
-
- ) : (
-
- )}
+ const generateBreadcrumbs = () => {
+ const breadcrumbs: Array<{ name: string; url: string }> = [
+ {
+ name: 'Home',
+ url: baseUrl,
+ },
+ ]
- {neighbours?.next ? (
+ const urlParts = page.url.split('/').filter(Boolean)
+ let currentPath = ''
+
+ urlParts.forEach((part, index) => {
+ if (index === 0 && ['en', 'es', 'fr', 'de', 'ja', 'zh'].includes(part)) {
+ currentPath = `/${part}`
+ return
+ }
+
+ currentPath += `/${part}`
+
+ const name = part
+ .split('-')
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
+ .join(' ')
+
+ if (index === urlParts.length - 1) {
+ breadcrumbs.push({
+ name: page.data.title,
+ url: `${baseUrl}${page.url}`,
+ })
+ } else {
+ breadcrumbs.push({
+ name: name,
+ url: `${baseUrl}${currentPath}`,
+ })
+ }
+ })
+
+ return breadcrumbs
+ }
+
+ const breadcrumbs = generateBreadcrumbs()
+
+ const CustomFooter = () => (
+
+ {/* Navigation links */}
+
+ {neighbours?.previous ? (
+
+
+
{neighbours.previous.name}
+
+ ) : (
+
+ )}
+
+ {neighbours?.next ? (
+
+
{neighbours.next.name}
+
+
+ ) : (
+
+ )}
+
+
+ {/* Divider line */}
+
+
+ {/* Social icons */}
+
-
{neighbours.next.name}
-
+
- ) : (
-
- )}
+
+
+
+
+
+
+
)
@@ -57,6 +170,7 @@ export default async function Page(props: { params: Promise<{ slug?: string[]; l
description={page.data.description || ''}
url={`${baseUrl}${page.url}`}
lang={params.lang}
+ breadcrumb={breadcrumbs}
/>
{page.data.title}
{page.data.description}
-
+
>
@@ -128,8 +247,10 @@ export async function generateMetadata(props: {
url: fullUrl,
siteName: 'Sim Documentation',
type: 'article',
- locale: params.lang,
- alternateLocale: ['en', 'fr', 'zh'].filter((lang) => lang !== params.lang),
+ locale: params.lang === 'en' ? 'en_US' : `${params.lang}_${params.lang.toUpperCase()}`,
+ alternateLocale: ['en', 'es', 'fr', 'de', 'ja', 'zh']
+ .filter((lang) => lang !== params.lang)
+ .map((lang) => (lang === 'en' ? 'en_US' : `${lang}_${lang.toUpperCase()}`)),
},
twitter: {
card: 'summary',
@@ -152,8 +273,12 @@ export async function generateMetadata(props: {
alternates: {
canonical: fullUrl,
languages: {
- en: `${baseUrl}/en${page.url.replace(`/${params.lang}`, '')}`,
+ 'x-default': `${baseUrl}${page.url.replace(`/${params.lang}`, '')}`,
+ en: `${baseUrl}${page.url.replace(`/${params.lang}`, '')}`,
+ es: `${baseUrl}/es${page.url.replace(`/${params.lang}`, '')}`,
fr: `${baseUrl}/fr${page.url.replace(`/${params.lang}`, '')}`,
+ de: `${baseUrl}/de${page.url.replace(`/${params.lang}`, '')}`,
+ ja: `${baseUrl}/ja${page.url.replace(`/${params.lang}`, '')}`,
zh: `${baseUrl}/zh${page.url.replace(`/${params.lang}`, '')}`,
},
},
diff --git a/apps/docs/app/[lang]/layout.tsx b/apps/docs/app/[lang]/layout.tsx
index 7641682aa..5e9216796 100644
--- a/apps/docs/app/[lang]/layout.tsx
+++ b/apps/docs/app/[lang]/layout.tsx
@@ -2,11 +2,14 @@ import type { ReactNode } from 'react'
import { defineI18nUI } from 'fumadocs-ui/i18n'
import { DocsLayout } from 'fumadocs-ui/layouts/docs'
import { RootProvider } from 'fumadocs-ui/provider/next'
-import { ExternalLink, GithubIcon } from 'lucide-react'
-import { Inter } from 'next/font/google'
+import { Geist_Mono, Inter } from 'next/font/google'
import Image from 'next/image'
-import Link from 'next/link'
-import { LanguageDropdown } from '@/components/ui/language-dropdown'
+import {
+ SidebarFolder,
+ SidebarItem,
+ SidebarSeparator,
+} from '@/components/docs-layout/sidebar-components'
+import { Navbar } from '@/components/navbar/navbar'
import { i18n } from '@/lib/i18n'
import { source } from '@/lib/source'
import '../global.css'
@@ -14,6 +17,12 @@ import { Analytics } from '@vercel/analytics/next'
const inter = Inter({
subsets: ['latin'],
+ variable: '--font-geist-sans',
+})
+
+const geistMono = Geist_Mono({
+ subsets: ['latin'],
+ variable: '--font-geist-mono',
})
const { provider } = defineI18nUI(i18n, {
@@ -27,25 +36,18 @@ const { provider } = defineI18nUI(i18n, {
fr: {
displayName: 'Français',
},
+ de: {
+ displayName: 'Deutsch',
+ },
+ ja: {
+ displayName: '日本語',
+ },
zh: {
displayName: '简体中文',
},
},
})
-const GitHubLink = () => (
-
-
-
-
-
-)
-
type LayoutProps = {
children: ReactNode
params: Promise<{ lang: string }>
@@ -54,43 +56,82 @@ type LayoutProps = {
export default async function Layout({ children, params }: LayoutProps) {
const { lang } = await params
+ const structuredData = {
+ '@context': 'https://schema.org',
+ '@type': 'WebSite',
+ name: 'Sim Documentation',
+ description:
+ 'Comprehensive documentation for Sim - the visual workflow builder for AI Agent Workflows.',
+ url: 'https://docs.sim.ai',
+ publisher: {
+ '@type': 'Organization',
+ name: 'Sim',
+ url: 'https://sim.ai',
+ logo: {
+ '@type': 'ImageObject',
+ url: 'https://docs.sim.ai/static/logo.png',
+ },
+ },
+ inLanguage: lang,
+ potentialAction: {
+ '@type': 'SearchAction',
+ target: {
+ '@type': 'EntryPoint',
+ urlTemplate: 'https://docs.sim.ai/api/search?q={search_term_string}',
+ },
+ 'query-input': 'required name=search_term_string',
+ },
+ }
+
return (
-
-
+
+
+
+
+
+
-
-
-
+