1- import fs from "node:fs" ;
21import path from "node:path" ;
32import type { Metadata } from "next" ;
43import { notFound } from "next/navigation" ;
@@ -7,11 +6,16 @@ import { EditOnGitHub } from "@/src/design-system/EditOnGitHub";
76import { TableOfContents } from "@/src/design-system/TableOfContents" ;
87import { Typography } from "@/src/design-system/Typography" ;
98import { compileDoc } from "@/src/helpers/compileDoc" ;
9+ import {
10+ CONTENT_ROOT ,
11+ encodeDocId ,
12+ listDocSlugs ,
13+ resolveFile ,
14+ } from "@/src/helpers/docsParams" ;
1015import { getGitMetadata } from "@/src/helpers/gitMetadata" ;
1116import { githubEditUrl } from "@/src/helpers/githubEditUrl" ;
1217import { readFrontmatter } from "@/src/helpers/readFrontmatter" ;
13-
14- const CONTENT_ROOT = path . join ( process . cwd ( ) , "content/docs" ) ;
18+ import { toAbsoluteUrl } from "@/src/helpers/siteUrl" ;
1519
1620type Params = {
1721 slug : string [ ] ;
@@ -24,19 +28,7 @@ type PageProps = {
2428export const dynamicParams = false ;
2529
2630export function generateStaticParams ( ) : Params [ ] {
27- const params = walk ( CONTENT_ROOT )
28- . filter ( ( f ) => / \. m d x ? $ / . test ( f ) )
29- . map ( ( f ) => path . relative ( CONTENT_ROOT , f ) . replace ( / \. m d x ? $ / , "" ) )
30- . map ( ( rel ) => rel . split ( path . sep ) )
31- . map ( ( parts ) =>
32- parts [ parts . length - 1 ] === "index" ? parts . slice ( 0 , - 1 ) : parts ,
33- )
34- . filter ( ( slug ) => slug . length > 0 )
35- . map ( ( slug ) => ( { slug } ) ) ;
36-
37- // output: export requires at least one prerendered path; placeholder
38- // renders 404 via notFound() when no content is present.
39- return params . length > 0 ? params : [ { slug : [ "__empty__" ] } ] ;
31+ return listDocSlugs ( ) . map ( ( slug ) => ( { slug } ) ) ;
4032}
4133
4234export async function generateMetadata ( {
@@ -48,9 +40,31 @@ export async function generateMetadata({
4840 return { } ;
4941 }
5042 const { title, description } = readFrontmatter ( path . join ( CONTENT_ROOT , rel ) ) ;
43+
44+ const id = encodeDocId ( slug ) ;
45+ const ogImage = {
46+ url : toAbsoluteUrl ( `/docs-og/${ id } /opengraph-image` ) ,
47+ width : 1200 ,
48+ height : 630 ,
49+ type : "image/png" ,
50+ alt : title ? `${ title } documentation` : "ChilliCream documentation" ,
51+ } ;
52+
5153 return {
5254 title,
5355 description,
56+ openGraph : {
57+ type : "article" ,
58+ title,
59+ description,
60+ images : [ ogImage ] ,
61+ } ,
62+ twitter : {
63+ card : "summary_large_image" ,
64+ title,
65+ description,
66+ images : [ ogImage ] ,
67+ } ,
5468 } ;
5569}
5670
@@ -89,28 +103,3 @@ export default async function DocPage({ params }: PageProps) {
89103 </ div >
90104 ) ;
91105}
92-
93- function resolveFile ( slug : string [ ] ) : string | null {
94- const joined = slug . join ( "/" ) ;
95- const candidates = [
96- `${ joined } .md` ,
97- `${ joined } .mdx` ,
98- `${ joined } /index.md` ,
99- `${ joined } /index.mdx` ,
100- ] ;
101-
102- for ( const c of candidates ) {
103- if ( fs . existsSync ( path . join ( CONTENT_ROOT , c ) ) ) {
104- return c ;
105- }
106- }
107- return null ;
108- }
109-
110- function walk ( dir : string ) : string [ ] {
111- const entries = fs . readdirSync ( dir , { withFileTypes : true } ) ;
112- return entries . flatMap ( ( e ) => {
113- const full = path . join ( dir , e . name ) ;
114- return e . isDirectory ( ) ? walk ( full ) : [ full ] ;
115- } ) ;
116- }
0 commit comments