@@ -5,6 +5,7 @@ import { ChevronLeft, ChevronRight } from 'lucide-react'
55import Link from 'next/link'
66import { notFound } from 'next/navigation'
77import { StructuredData } from '@/components/structured-data'
8+ import { CodeBlock } from '@/components/ui/code-block'
89import { source } from '@/lib/source'
910
1011export const dynamic = 'force-dynamic'
@@ -22,31 +23,143 @@ export default async function Page(props: { params: Promise<{ slug?: string[]; l
2223 pageTreeRecord [ params . lang ] ?? pageTreeRecord . en ?? Object . values ( pageTreeRecord ) [ 0 ]
2324 const neighbours = pageTree ? findNeighbour ( pageTree , page . url ) : null
2425
26+ const generateBreadcrumbs = ( ) => {
27+ const breadcrumbs : Array < { name : string ; url : string } > = [
28+ {
29+ name : 'Home' ,
30+ url : baseUrl ,
31+ } ,
32+ ]
33+
34+ const urlParts = page . url . split ( '/' ) . filter ( Boolean )
35+ let currentPath = ''
36+
37+ urlParts . forEach ( ( part , index ) => {
38+ if ( index === 0 && [ 'en' , 'es' , 'fr' , 'de' , 'ja' , 'zh' ] . includes ( part ) ) {
39+ currentPath = `/${ part } `
40+ return
41+ }
42+
43+ currentPath += `/${ part } `
44+
45+ const name = part
46+ . split ( '-' )
47+ . map ( ( word ) => word . charAt ( 0 ) . toUpperCase ( ) + word . slice ( 1 ) )
48+ . join ( ' ' )
49+
50+ if ( index === urlParts . length - 1 ) {
51+ breadcrumbs . push ( {
52+ name : page . data . title ,
53+ url : `${ baseUrl } ${ page . url } ` ,
54+ } )
55+ } else {
56+ breadcrumbs . push ( {
57+ name : name ,
58+ url : `${ baseUrl } ${ currentPath } ` ,
59+ } )
60+ }
61+ } )
62+
63+ return breadcrumbs
64+ }
65+
66+ const breadcrumbs = generateBreadcrumbs ( )
67+
2568 const CustomFooter = ( ) => (
26- < div className = 'mt-12 flex items-center justify-between border-border border-t py-8' >
27- { neighbours ?. previous ? (
69+ < div className = 'mt-12' >
70+ { /* Navigation links */ }
71+ < div className = 'flex items-center justify-between py-8' >
72+ { neighbours ?. previous ? (
73+ < Link
74+ href = { neighbours . previous . url }
75+ className = 'group flex items-center gap-2 text-muted-foreground transition-colors hover:text-foreground'
76+ >
77+ < ChevronLeft className = 'group-hover:-translate-x-1 h-4 w-4 transition-transform' />
78+ < span className = 'font-medium' > { neighbours . previous . name } </ span >
79+ </ Link >
80+ ) : (
81+ < div />
82+ ) }
83+
84+ { neighbours ?. next ? (
85+ < Link
86+ href = { neighbours . next . url }
87+ className = 'group flex items-center gap-2 text-muted-foreground transition-colors hover:text-foreground'
88+ >
89+ < span className = 'font-medium' > { neighbours . next . name } </ span >
90+ < ChevronRight className = 'h-4 w-4 transition-transform group-hover:translate-x-1' />
91+ </ Link >
92+ ) : (
93+ < div />
94+ ) }
95+ </ div >
96+
97+ { /* Divider line */ }
98+ < div className = 'border-border border-t' />
99+
100+ { /* Social icons */ }
101+ < div className = 'flex items-center gap-4 py-6' >
28102 < Link
29- href = { neighbours . previous . url }
30- className = 'group flex items-center gap-2 text-muted-foreground transition-colors hover:text-foreground'
103+ href = 'https://x.com/simdotai'
104+ target = '_blank'
105+ rel = 'noopener noreferrer'
106+ aria-label = 'X (Twitter)'
31107 >
32- < ChevronLeft className = 'group-hover:-translate-x-1 h-4 w-4 transition-transform' />
33- < span className = 'font-medium' > { neighbours . previous . name } </ span >
108+ < div
109+ className = 'h-5 w-5 bg-gray-400 transition-colors hover:bg-gray-500 dark:bg-gray-500 dark:hover:bg-gray-400'
110+ style = { {
111+ maskImage :
112+ "url('data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22%3E%3Cpath d=%22M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z%22/%3E%3C/svg%3E')" ,
113+ maskRepeat : 'no-repeat' ,
114+ maskPosition : 'center center' ,
115+ WebkitMaskImage :
116+ "url('data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22%3E%3Cpath d=%22M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z%22/%3E%3C/svg%3E')" ,
117+ WebkitMaskRepeat : 'no-repeat' ,
118+ WebkitMaskPosition : 'center center' ,
119+ } }
120+ />
121+ </ Link >
122+ < Link
123+ href = 'https://github.com/simstudioai/sim'
124+ target = '_blank'
125+ rel = 'noopener noreferrer'
126+ aria-label = 'GitHub'
127+ >
128+ < div
129+ className = 'h-5 w-5 bg-gray-400 transition-colors hover:bg-gray-500 dark:bg-gray-500 dark:hover:bg-gray-400'
130+ style = { {
131+ maskImage :
132+ "url('data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22%3E%3Cpath d=%22M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z%22/%3E%3C/svg%3E')" ,
133+ maskRepeat : 'no-repeat' ,
134+ maskPosition : 'center center' ,
135+ WebkitMaskImage :
136+ "url('data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22%3E%3Cpath d=%22M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z%22/%3E%3C/svg%3E')" ,
137+ WebkitMaskRepeat : 'no-repeat' ,
138+ WebkitMaskPosition : 'center center' ,
139+ } }
140+ />
34141 </ Link >
35- ) : (
36- < div />
37- ) }
38-
39- { neighbours ?. next ? (
40142 < Link
41- href = { neighbours . next . url }
42- className = 'group flex items-center gap-2 text-muted-foreground transition-colors hover:text-foreground'
143+ href = 'https://discord.gg/Hr4UWYEcTT'
144+ target = '_blank'
145+ rel = 'noopener noreferrer'
146+ aria-label = 'Discord'
43147 >
44- < span className = 'font-medium' > { neighbours . next . name } </ span >
45- < ChevronRight className = 'h-4 w-4 transition-transform group-hover:translate-x-1' />
148+ < div
149+ className = 'h-5 w-5 bg-gray-400 transition-colors hover:bg-gray-500 dark:bg-gray-500 dark:hover:bg-gray-400'
150+ style = { {
151+ maskImage :
152+ "url('data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22%3E%3Cpath d=%22M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515a.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0a12.64 12.64 0 0 0-.617-1.25a.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057a19.9 19.9 0 0 0 5.993 3.03a.078.078 0 0 0 .084-.028a14.09 14.09 0 0 0 1.226-1.994a.076.076 0 0 0-.041-.106a13.107 13.107 0 0 1-1.872-.892a.077.077 0 0 1-.008-.128a10.2 10.2 0 0 0 .372-.292a.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127a12.299 12.299 0 0 1-1.873.892a.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028a19.839 19.839 0 0 0 6.002-3.03a.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419c0-1.333.956-2.419 2.157-2.419c1.21 0 2.176 1.096 2.157 2.42c0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419c0-1.333.955-2.419 2.157-2.419c1.21 0 2.176 1.096 2.157 2.42c0 1.333-.946 2.418-2.157 2.418z%22/%3E%3C/svg%3E')" ,
153+ maskRepeat : 'no-repeat' ,
154+ maskPosition : 'center center' ,
155+ WebkitMaskImage :
156+ "url('data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22%3E%3Cpath d=%22M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515a.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0a12.64 12.64 0 0 0-.617-1.25a.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057a19.9 19.9 0 0 0 5.993 3.03a.078.078 0 0 0 .084-.028a14.09 14.09 0 0 0 1.226-1.994a.076.076 0 0 0-.041-.106a13.107 13.107 0 0 1-1.872-.892a.077.077 0 0 1-.008-.128a10.2 10.2 0 0 0 .372-.292a.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127a12.299 12.299 0 0 1-1.873.892a.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028a19.839 19.839 0 0 0 6.002-3.03a.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419c0-1.333.956-2.419 2.157-2.419c1.21 0 2.176 1.096 2.157 2.42c0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419c0-1.333.955-2.419 2.157-2.419c1.21 0 2.176 1.096 2.157 2.42c0 1.333-.946 2.418-2.157 2.418z%22/%3E%3C/svg%3E')" ,
157+ WebkitMaskRepeat : 'no-repeat' ,
158+ WebkitMaskPosition : 'center center' ,
159+ } }
160+ />
46161 </ Link >
47- ) : (
48- < div />
49- ) }
162+ </ div >
50163 </ div >
51164 )
52165
@@ -57,6 +170,7 @@ export default async function Page(props: { params: Promise<{ slug?: string[]; l
57170 description = { page . data . description || '' }
58171 url = { `${ baseUrl } ${ page . url } ` }
59172 lang = { params . lang }
173+ breadcrumb = { breadcrumbs }
60174 />
61175 < DocsPage
62176 toc = { page . data . toc }
@@ -82,7 +196,12 @@ export default async function Page(props: { params: Promise<{ slug?: string[]; l
82196 < DocsTitle > { page . data . title } </ DocsTitle >
83197 < DocsDescription > { page . data . description } </ DocsDescription >
84198 < DocsBody >
85- < MDX components = { defaultMdxComponents } />
199+ < MDX
200+ components = { {
201+ ...defaultMdxComponents ,
202+ CodeBlock,
203+ } }
204+ />
86205 </ DocsBody >
87206 </ DocsPage >
88207 </ >
@@ -128,8 +247,10 @@ export async function generateMetadata(props: {
128247 url : fullUrl ,
129248 siteName : 'Sim Documentation' ,
130249 type : 'article' ,
131- locale : params . lang ,
132- alternateLocale : [ 'en' , 'fr' , 'zh' ] . filter ( ( lang ) => lang !== params . lang ) ,
250+ locale : params . lang === 'en' ? 'en_US' : `${ params . lang } _${ params . lang . toUpperCase ( ) } ` ,
251+ alternateLocale : [ 'en' , 'es' , 'fr' , 'de' , 'ja' , 'zh' ]
252+ . filter ( ( lang ) => lang !== params . lang )
253+ . map ( ( lang ) => ( lang === 'en' ? 'en_US' : `${ lang } _${ lang . toUpperCase ( ) } ` ) ) ,
133254 } ,
134255 twitter : {
135256 card : 'summary' ,
@@ -152,8 +273,12 @@ export async function generateMetadata(props: {
152273 alternates : {
153274 canonical : fullUrl ,
154275 languages : {
155- en : `${ baseUrl } /en${ page . url . replace ( `/${ params . lang } ` , '' ) } ` ,
276+ 'x-default' : `${ baseUrl } ${ page . url . replace ( `/${ params . lang } ` , '' ) } ` ,
277+ en : `${ baseUrl } ${ page . url . replace ( `/${ params . lang } ` , '' ) } ` ,
278+ es : `${ baseUrl } /es${ page . url . replace ( `/${ params . lang } ` , '' ) } ` ,
156279 fr : `${ baseUrl } /fr${ page . url . replace ( `/${ params . lang } ` , '' ) } ` ,
280+ de : `${ baseUrl } /de${ page . url . replace ( `/${ params . lang } ` , '' ) } ` ,
281+ ja : `${ baseUrl } /ja${ page . url . replace ( `/${ params . lang } ` , '' ) } ` ,
157282 zh : `${ baseUrl } /zh${ page . url . replace ( `/${ params . lang } ` , '' ) } ` ,
158283 } ,
159284 } ,
0 commit comments