@@ -6,108 +6,206 @@ import { HomeLayout } from 'fumadocs-ui/home-layout';
66import { baseOptions } from '@/app/layout.config' ;
77import Link from 'next/link' ;
88
9- export default async function BlogPostPage ( {
9+ // Blog listing component
10+ function BlogListing ( ) {
11+ const posts = blogSource . getPages ( ) ;
12+
13+ return (
14+ < div className = "mx-auto max-w-4xl" >
15+ < div className = "mb-12 text-center" >
16+ < h1 className = "text-4xl font-bold tracking-tight sm:text-5xl mb-4" >
17+ ObjectQL Blog
18+ </ h1 >
19+ < p className = "text-lg text-muted-foreground" >
20+ Updates, tutorials, and insights about the standard protocol for AI software generation
21+ </ p >
22+ </ div >
23+
24+ < div className = "space-y-8" >
25+ { posts
26+ . sort ( ( a , b ) => {
27+ const dateA = new Date ( a . data . date || 0 ) ;
28+ const dateB = new Date ( b . data . date || 0 ) ;
29+ return dateB . getTime ( ) - dateA . getTime ( ) ;
30+ } )
31+ . map ( ( post ) => (
32+ < article
33+ key = { post . url }
34+ className = "group rounded-xl border bg-card p-6 transition-all hover:shadow-md"
35+ >
36+ < Link href = { post . url } className = "block" >
37+ < div className = "mb-2 flex items-center gap-4 text-sm text-muted-foreground" >
38+ { post . data . date && (
39+ < time dateTime = { post . data . date } >
40+ { new Date ( post . data . date ) . toLocaleDateString ( 'en-US' , {
41+ year : 'numeric' ,
42+ month : 'long' ,
43+ day : 'numeric' ,
44+ } ) }
45+ </ time >
46+ ) }
47+ { post . data . authors && (
48+ < span > by { post . data . authors . join ( ', ' ) } </ span >
49+ ) }
50+ </ div >
51+
52+ < h2 className = "mb-2 text-2xl font-bold group-hover:text-primary transition-colors" >
53+ { post . data . title }
54+ </ h2 >
55+
56+ { post . data . description && (
57+ < p className = "text-muted-foreground mb-4" >
58+ { post . data . description }
59+ </ p >
60+ ) }
61+
62+ { post . data . tags && post . data . tags . length > 0 && (
63+ < div className = "flex flex-wrap gap-2" >
64+ { post . data . tags . map ( ( tag : string ) => (
65+ < span
66+ key = { tag }
67+ className = "inline-flex items-center rounded-full bg-primary/10 px-3 py-1 text-xs font-medium text-primary"
68+ >
69+ { tag }
70+ </ span >
71+ ) ) }
72+ </ div >
73+ ) }
74+ </ Link >
75+ </ article >
76+ ) ) }
77+ </ div >
78+
79+ { posts . length === 0 && (
80+ < div className = "text-center py-12" >
81+ < p className = "text-muted-foreground" > No blog posts yet. Check back soon!</ p >
82+ </ div >
83+ ) }
84+ </ div >
85+ ) ;
86+ }
87+
88+ // Blog post component
89+ function BlogPost ( { page } : { page : any } ) {
90+ const MDX = page . data . body ;
91+
92+ return (
93+ < article className = "mx-auto max-w-4xl" >
94+ < Link
95+ href = "/blog"
96+ className = "inline-flex items-center text-sm text-muted-foreground hover:text-foreground mb-8 transition-colors"
97+ >
98+ < svg
99+ xmlns = "http://www.w3.org/2000/svg"
100+ width = "16"
101+ height = "16"
102+ viewBox = "0 0 24 24"
103+ fill = "none"
104+ stroke = "currentColor"
105+ strokeWidth = "2"
106+ strokeLinecap = "round"
107+ strokeLinejoin = "round"
108+ className = "mr-2"
109+ >
110+ < polyline points = "15 18 9 12 15 6" />
111+ </ svg >
112+ Back to Blog
113+ </ Link >
114+
115+ < header className = "mb-8" >
116+ < h1 className = "text-4xl font-bold tracking-tight sm:text-5xl mb-4" >
117+ { page . data . title }
118+ </ h1 >
119+
120+ { page . data . description && (
121+ < p className = "text-xl text-muted-foreground mb-4" >
122+ { page . data . description }
123+ </ p >
124+ ) }
125+
126+ < div className = "flex flex-wrap items-center gap-4 text-sm text-muted-foreground border-t pt-4" >
127+ { page . data . date && (
128+ < time dateTime = { page . data . date } >
129+ { new Date ( page . data . date ) . toLocaleDateString ( 'en-US' , {
130+ year : 'numeric' ,
131+ month : 'long' ,
132+ day : 'numeric' ,
133+ } ) }
134+ </ time >
135+ ) }
136+ { page . data . authors && (
137+ < span > by { page . data . authors . join ( ', ' ) } </ span >
138+ ) }
139+ </ div >
140+
141+ { page . data . tags && page . data . tags . length > 0 && (
142+ < div className = "flex flex-wrap gap-2 mt-4" >
143+ { page . data . tags . map ( ( tag : string ) => (
144+ < span
145+ key = { tag }
146+ className = "inline-flex items-center rounded-full bg-primary/10 px-3 py-1 text-xs font-medium text-primary"
147+ >
148+ { tag }
149+ </ span >
150+ ) ) }
151+ </ div >
152+ ) }
153+ </ header >
154+
155+ < div className = "prose prose-slate dark:prose-invert max-w-none" >
156+ < MDX components = { { ...defaultMdxComponents } } />
157+ </ div >
158+
159+ < footer className = "mt-12 pt-8 border-t" >
160+ < Link
161+ href = "/blog"
162+ className = "inline-flex items-center text-sm text-primary hover:underline"
163+ >
164+ < svg
165+ xmlns = "http://www.w3.org/2000/svg"
166+ width = "16"
167+ height = "16"
168+ viewBox = "0 0 24 24"
169+ fill = "none"
170+ stroke = "currentColor"
171+ strokeWidth = "2"
172+ strokeLinecap = "round"
173+ strokeLinejoin = "round"
174+ className = "mr-2"
175+ >
176+ < polyline points = "15 18 9 12 15 6" />
177+ </ svg >
178+ Back to Blog
179+ </ Link >
180+ </ footer >
181+ </ article >
182+ ) ;
183+ }
184+
185+ export default async function BlogPage ( {
10186 params,
11187} : {
12188 params : { slug ?: string [ ] } ;
13189} ) {
190+ // If no slug, show blog listing
191+ if ( ! params . slug || params . slug . length === 0 ) {
192+ return (
193+ < HomeLayout { ...baseOptions } >
194+ < main className = "container py-12 md:py-24" >
195+ < BlogListing />
196+ </ main >
197+ </ HomeLayout >
198+ ) ;
199+ }
200+
201+ // Otherwise, show individual blog post
14202 const page = blogSource . getPage ( params . slug ) ;
15203 if ( ! page ) notFound ( ) ;
16204
17- const MDX = page . data . body ;
18-
19205 return (
20206 < HomeLayout { ...baseOptions } >
21207 < main className = "container py-12 md:py-24" >
22- < article className = "mx-auto max-w-4xl" >
23- < Link
24- href = "/blog"
25- className = "inline-flex items-center text-sm text-muted-foreground hover:text-foreground mb-8 transition-colors"
26- >
27- < svg
28- xmlns = "http://www.w3.org/2000/svg"
29- width = "16"
30- height = "16"
31- viewBox = "0 0 24 24"
32- fill = "none"
33- stroke = "currentColor"
34- strokeWidth = "2"
35- strokeLinecap = "round"
36- strokeLinejoin = "round"
37- className = "mr-2"
38- >
39- < polyline points = "15 18 9 12 15 6" />
40- </ svg >
41- Back to Blog
42- </ Link >
43-
44- < header className = "mb-8" >
45- < h1 className = "text-4xl font-bold tracking-tight sm:text-5xl mb-4" >
46- { page . data . title }
47- </ h1 >
48-
49- { page . data . description && (
50- < p className = "text-xl text-muted-foreground mb-4" >
51- { page . data . description }
52- </ p >
53- ) }
54-
55- < div className = "flex flex-wrap items-center gap-4 text-sm text-muted-foreground border-t pt-4" >
56- { page . data . date && (
57- < time dateTime = { page . data . date } >
58- { new Date ( page . data . date ) . toLocaleDateString ( 'en-US' , {
59- year : 'numeric' ,
60- month : 'long' ,
61- day : 'numeric' ,
62- } ) }
63- </ time >
64- ) }
65- { page . data . authors && (
66- < span > by { page . data . authors . join ( ', ' ) } </ span >
67- ) }
68- </ div >
69-
70- { page . data . tags && page . data . tags . length > 0 && (
71- < div className = "flex flex-wrap gap-2 mt-4" >
72- { page . data . tags . map ( ( tag : string ) => (
73- < span
74- key = { tag }
75- className = "inline-flex items-center rounded-full bg-primary/10 px-3 py-1 text-xs font-medium text-primary"
76- >
77- { tag }
78- </ span >
79- ) ) }
80- </ div >
81- ) }
82- </ header >
83-
84- < div className = "prose prose-slate dark:prose-invert max-w-none" >
85- < MDX components = { { ...defaultMdxComponents } } />
86- </ div >
87-
88- < footer className = "mt-12 pt-8 border-t" >
89- < Link
90- href = "/blog"
91- className = "inline-flex items-center text-sm text-primary hover:underline"
92- >
93- < svg
94- xmlns = "http://www.w3.org/2000/svg"
95- width = "16"
96- height = "16"
97- viewBox = "0 0 24 24"
98- fill = "none"
99- stroke = "currentColor"
100- strokeWidth = "2"
101- strokeLinecap = "round"
102- strokeLinejoin = "round"
103- className = "mr-2"
104- >
105- < polyline points = "15 18 9 12 15 6" />
106- </ svg >
107- Back to Blog
108- </ Link >
109- </ footer >
110- </ article >
208+ < BlogPost page = { page } />
111209 </ main >
112210 </ HomeLayout >
113211 ) ;
@@ -118,6 +216,15 @@ export async function generateStaticParams() {
118216}
119217
120218export function generateMetadata ( { params } : { params : { slug ?: string [ ] } } ) : Metadata {
219+ // Default metadata for blog listing
220+ if ( ! params . slug || params . slug . length === 0 ) {
221+ return {
222+ title : 'Blog' ,
223+ description : 'Updates, tutorials, and insights about the standard protocol for AI software generation' ,
224+ } ;
225+ }
226+
227+ // Metadata for individual blog post
121228 const page = blogSource . getPage ( params . slug ) ;
122229 if ( ! page ) notFound ( ) ;
123230
@@ -126,3 +233,4 @@ export function generateMetadata({ params }: { params: { slug?: string[] } }): M
126233 description : page . data . description ,
127234 } ;
128235}
236+
0 commit comments