11import type React from 'react'
2+ import type { Root } from 'fumadocs-core/page-tree'
23import { findNeighbour } from 'fumadocs-core/page-tree'
4+ import type { ApiPageProps } from 'fumadocs-openapi/ui'
35import { createAPIPage } from 'fumadocs-openapi/ui'
46import { Pre } from 'fumadocs-ui/components/codeblock'
57import defaultMdxComponents from 'fumadocs-ui/mdx'
@@ -18,7 +20,15 @@ import { i18n } from '@/lib/i18n'
1820import { getApiSpecContent , openapi } from '@/lib/openapi'
1921import { type PageData , source } from '@/lib/source'
2022
21- const SUPPORTED_LANGUAGES = new Set ( i18n . languages )
23+ const SUPPORTED_LANGUAGES : Set < string > = new Set ( i18n . languages )
24+ const BASE_URL = 'https://docs.sim.ai'
25+
26+ function resolveLangAndSlug ( params : { slug ?: string [ ] ; lang : string } ) {
27+ const isValidLang = SUPPORTED_LANGUAGES . has ( params . lang )
28+ const lang = isValidLang ? params . lang : 'en'
29+ const slug = isValidLang ? params . slug : [ params . lang , ...( params . slug ?? [ ] ) ]
30+ return { lang, slug }
31+ }
2232
2333const APIPage = createAPIPage ( openapi , {
2434 playground : { enabled : false } ,
@@ -46,21 +56,18 @@ const APIPage = createAPIPage(openapi, {
4656
4757export default async function Page ( props : { params : Promise < { slug ?: string [ ] ; lang : string } > } ) {
4858 const params = await props . params
49- const isValidLang = SUPPORTED_LANGUAGES . has ( params . lang )
50- const lang = isValidLang ? params . lang : 'en'
51- const slug = isValidLang ? params . slug : [ params . lang , ...( params . slug ?? [ ] ) ]
59+ const { lang, slug } = resolveLangAndSlug ( params )
5260 const page = source . getPage ( slug , lang )
5361 if ( ! page ) notFound ( )
5462
5563 const data = page . data as PageData & {
5664 _openapi ?: { method ?: string }
57- getAPIPageProps ?: ( ) => unknown
65+ getAPIPageProps ?: ( ) => ApiPageProps
5866 }
5967 const isOpenAPI = '_openapi' in data && data . _openapi != null
6068 const isApiReference = slug ?. some ( ( s ) => s === 'api-reference' ) ?? false
61- const baseUrl = 'https://docs.sim.ai'
6269
63- const pageTreeRecord = source . pageTree as Record < string , unknown >
70+ const pageTreeRecord = source . pageTree as Record < string , Root >
6471 const pageTree = pageTreeRecord [ lang ] ?? pageTreeRecord . en ?? Object . values ( pageTreeRecord ) [ 0 ]
6572 const rawNeighbours = pageTree ? findNeighbour ( pageTree , page . url ) : null
6673 const neighbours = isApiReference
@@ -76,7 +83,7 @@ export default async function Page(props: { params: Promise<{ slug?: string[]; l
7683 const breadcrumbs : Array < { name : string ; url : string } > = [
7784 {
7885 name : 'Home' ,
79- url : baseUrl ,
86+ url : BASE_URL ,
8087 } ,
8188 ]
8289
@@ -99,12 +106,12 @@ export default async function Page(props: { params: Promise<{ slug?: string[]; l
99106 if ( index === urlParts . length - 1 ) {
100107 breadcrumbs . push ( {
101108 name : data . title ,
102- url : `${ baseUrl } ${ page . url } ` ,
109+ url : `${ BASE_URL } ${ page . url } ` ,
103110 } )
104111 } else {
105112 breadcrumbs . push ( {
106113 name : name ,
107- url : `${ baseUrl } ${ currentPath } ` ,
114+ url : `${ BASE_URL } ${ currentPath } ` ,
108115 } )
109116 }
110117 } )
@@ -116,7 +123,6 @@ export default async function Page(props: { params: Promise<{ slug?: string[]; l
116123
117124 const CustomFooter = ( ) => (
118125 < div className = 'mt-12' >
119- { /* Navigation links */ }
120126 < div className = 'flex items-center justify-between py-8' >
121127 { neighbours ?. previous ? (
122128 < Link
@@ -143,10 +149,8 @@ export default async function Page(props: { params: Promise<{ slug?: string[]; l
143149 ) }
144150 </ div >
145151
146- { /* Divider line */ }
147152 < div className = 'border-border border-t' />
148153
149- { /* Social icons */ }
150154 < div className = 'flex items-center gap-4 py-6' >
151155 < Link
152156 href = 'https://x.com/simdotai'
@@ -225,7 +229,7 @@ export default async function Page(props: { params: Promise<{ slug?: string[]; l
225229 < StructuredData
226230 title = { data . title }
227231 description = { data . description || '' }
228- url = { `${ baseUrl } ${ page . url } ` }
232+ url = { `${ BASE_URL } ${ page . url } ` }
229233 lang = { lang }
230234 breadcrumb = { breadcrumbs }
231235 />
@@ -273,7 +277,7 @@ export default async function Page(props: { params: Promise<{ slug?: string[]; l
273277 < StructuredData
274278 title = { data . title }
275279 description = { data . description || '' }
276- url = { `${ baseUrl } ${ page . url } ` }
280+ url = { `${ BASE_URL } ${ page . url } ` }
277281 lang = { lang }
278282 breadcrumb = { breadcrumbs }
279283 />
@@ -351,17 +355,14 @@ export async function generateMetadata(props: {
351355 params : Promise < { slug ?: string [ ] ; lang : string } >
352356} ) {
353357 const params = await props . params
354- const isValidLang = SUPPORTED_LANGUAGES . has ( params . lang )
355- const lang = isValidLang ? params . lang : 'en'
356- const slug = isValidLang ? params . slug : [ params . lang , ...( params . slug ?? [ ] ) ]
358+ const { lang, slug } = resolveLangAndSlug ( params )
357359 const page = source . getPage ( slug , lang )
358360 if ( ! page ) notFound ( )
359361
360362 const data = page . data as PageData
361- const baseUrl = 'https://docs.sim.ai'
362- const fullUrl = `${ baseUrl } ${ page . url } `
363+ const fullUrl = `${ BASE_URL } ${ page . url } `
363364
364- const ogImageUrl = `${ baseUrl } /api/og?title=${ encodeURIComponent ( data . title ) } `
365+ const ogImageUrl = `${ BASE_URL } /api/og?title=${ encodeURIComponent ( data . title ) } `
365366
366367 return {
367368 title : data . title ,
@@ -425,13 +426,13 @@ export async function generateMetadata(props: {
425426 alternates : {
426427 canonical : fullUrl ,
427428 languages : {
428- 'x-default' : `${ baseUrl } ${ page . url . replace ( `/${ lang } ` , '' ) } ` ,
429- en : `${ baseUrl } ${ page . url . replace ( `/${ lang } ` , '' ) } ` ,
430- es : `${ baseUrl } /es${ page . url . replace ( `/${ lang } ` , '' ) } ` ,
431- fr : `${ baseUrl } /fr${ page . url . replace ( `/${ lang } ` , '' ) } ` ,
432- de : `${ baseUrl } /de${ page . url . replace ( `/${ lang } ` , '' ) } ` ,
433- ja : `${ baseUrl } /ja${ page . url . replace ( `/${ lang } ` , '' ) } ` ,
434- zh : `${ baseUrl } /zh${ page . url . replace ( `/${ lang } ` , '' ) } ` ,
429+ 'x-default' : `${ BASE_URL } ${ page . url . replace ( `/${ lang } ` , '' ) } ` ,
430+ en : `${ BASE_URL } ${ page . url . replace ( `/${ lang } ` , '' ) } ` ,
431+ es : `${ BASE_URL } /es${ page . url . replace ( `/${ lang } ` , '' ) } ` ,
432+ fr : `${ BASE_URL } /fr${ page . url . replace ( `/${ lang } ` , '' ) } ` ,
433+ de : `${ BASE_URL } /de${ page . url . replace ( `/${ lang } ` , '' ) } ` ,
434+ ja : `${ BASE_URL } /ja${ page . url . replace ( `/${ lang } ` , '' ) } ` ,
435+ zh : `${ BASE_URL } /zh${ page . url . replace ( `/${ lang } ` , '' ) } ` ,
435436 } ,
436437 } ,
437438 }
0 commit comments