11"use client" ;
22
3- import { motion } from "framer-motion" ;
3+ import { motion , LazyMotion , domAnimation } from "framer-motion" ;
44import { ArrowLeft , Calendar , Clock , User } from "lucide-react" ;
55import Link from "next/link" ;
66import { MDXRemote , MDXRemoteSerializeResult } from "next-mdx-remote" ;
7+ import { serialize } from "next-mdx-remote/serialize" ;
78import type { BlogPost } from "@/lib/mdx" ;
9+ import { useState , useEffect } from "react" ;
810
911interface BlogPostClientProps {
1012 post : BlogPost ;
11- mdxSource : MDXRemoteSerializeResult ;
1213}
1314
14- export default function BlogPostClient ( { post, mdxSource } : BlogPostClientProps ) {
15+ export default function BlogPostClient ( { post } : BlogPostClientProps ) {
16+ const [ isMounted , setIsMounted ] = useState ( false ) ;
17+ const [ mdxSource , setMdxSource ] = useState < MDXRemoteSerializeResult | null > ( null ) ;
18+
19+ useEffect ( ( ) => {
20+ setIsMounted ( true ) ;
21+ serialize ( post . content ) . then ( setMdxSource ) ;
22+ } , [ post . content ] ) ;
23+
1524 const formattedDate = new Date ( post . date ) . toLocaleDateString ( "en-US" , {
1625 year : "numeric" ,
1726 month : "long" ,
@@ -49,29 +58,37 @@ export default function BlogPostClient({ post, mdxSource }: BlogPostClientProps)
4958 ) ,
5059 } ;
5160
61+ const MotionDiv = isMounted ? motion . div : 'div' ;
62+ const MotionHeader = isMounted ? motion . header : 'header' ;
63+
5264 return (
53- < div className = "min-h-screen bg-gradient-to-b from-[#0F172A] via-[#1e293b] to-[#0F172A] py-20" >
54- < article className = "max-w-4xl mx-auto px-4 sm:px-6 lg:px-8" >
55- < motion . div
56- initial = { { opacity : 0 , y : 20 } }
57- animate = { { opacity : 1 , y : 0 } }
58- transition = { { duration : 0.5 } }
59- >
60- < Link
61- href = "/blog"
62- className = "inline-flex items-center text-[#38BDF8] hover:underline mb-8"
65+ < LazyMotion features = { domAnimation } strict >
66+ < div className = "min-h-screen bg-gradient-to-b from-[#0F172A] via-[#1e293b] to-[#0F172A] py-20" >
67+ < article className = "max-w-4xl mx-auto px-4 sm:px-6 lg:px-8" >
68+ < MotionDiv
69+ { ...( isMounted && {
70+ initial : { opacity : 0 , y : 20 } ,
71+ animate : { opacity : 1 , y : 0 } ,
72+ transition : { duration : 0.5 }
73+ } ) }
6374 >
64- < ArrowLeft className = "w-4 h-4 mr-2" />
65- Back to Blog
66- </ Link >
67- </ motion . div >
75+ < Link
76+ href = "/blog"
77+ className = "inline-flex items-center text-[#38BDF8] hover:underline mb-8"
78+ >
79+ < ArrowLeft className = "w-4 h-4 mr-2" />
80+ Back to Blog
81+ </ Link >
82+ </ MotionDiv >
6883
69- < motion . header
70- initial = { { opacity : 0 , y : 20 } }
71- animate = { { opacity : 1 , y : 0 } }
72- transition = { { delay : 0.2 , duration : 0.5 } }
73- className = "mb-12"
74- >
84+ < MotionHeader
85+ { ...( isMounted && {
86+ initial : { opacity : 0 , y : 20 } ,
87+ animate : { opacity : 1 , y : 0 } ,
88+ transition : { delay : 0.2 , duration : 0.5 }
89+ } ) }
90+ className = "mb-12"
91+ >
7592 < span className = "inline-block px-3 py-1 text-sm font-medium rounded-full bg-[#38BDF8]/10 text-[#38BDF8] border border-[#38BDF8]/20 mb-4" >
7693 { post . category }
7794 </ span >
@@ -95,19 +112,26 @@ export default function BlogPostClient({ post, mdxSource }: BlogPostClientProps)
95112 </ div >
96113 ) }
97114 </ div >
98- </ motion . header >
115+ </ MotionHeader >
99116
100- < motion . div
101- initial = { { opacity : 0 , y : 20 } }
102- animate = { { opacity : 1 , y : 0 } }
103- transition = { { delay : 0.4 , duration : 0.5 } }
104- className = "max-w-none"
105- >
106- < div className = "p-8 rounded-xl glass mdx-content" >
107- < MDXRemote { ...mdxSource } components = { components } />
108- </ div >
109- </ motion . div >
110- </ article >
111- </ div >
117+ < MotionDiv
118+ { ...( isMounted && {
119+ initial : { opacity : 0 , y : 20 } ,
120+ animate : { opacity : 1 , y : 0 } ,
121+ transition : { delay : 0.4 , duration : 0.5 }
122+ } ) }
123+ className = "max-w-none"
124+ >
125+ < div className = "p-8 rounded-xl glass mdx-content" >
126+ { mdxSource ? (
127+ < MDXRemote { ...mdxSource } components = { components } />
128+ ) : (
129+ < div className = "text-gray-400" > Loading content...</ div >
130+ ) }
131+ </ div >
132+ </ MotionDiv >
133+ </ article >
134+ </ div >
135+ </ LazyMotion >
112136 ) ;
113137}
0 commit comments