Component Details
Hero Component 02

PostCard.tsx
Next.js•Tailwind CSS
1// Dummy data for blog posts
2const dummyPosts = [
3 {
4 id: 1,
5 slug: "getting-started-with-nextjs",
6 title: "Getting Started with Next.js 14",
7 excerpt: "Learn how to build modern web applications with Next.js 14 and its new features including Server Actions and partial prerendering.",
8 category: "Web Development",
9 author: "Jane Doe",
10 date: "2024-01-15",
11 readTime: 5,
12 },
13 {
14 id: 2,
15 slug: "tailwind-css-best-practices",
16 title: "Tailwind CSS Best Practices for 2024",
17 excerpt: "Discover the most effective ways to use Tailwind CSS in your projects, from component architecture to performance optimization.",
18 category: "CSS",
19 author: "John Smith",
20 date: "2024-01-10",
21 readTime: 8,
22 },
23 {
24 id: 3,
25 slug: "react-performance-tips",
26 title: "Advanced React Performance Optimization",
27 excerpt: "Explore techniques to improve your React application performance including memoization, code splitting, and virtualization.",
28 category: "React",
29 author: "Alex Johnson",
30 date: "2024-01-05",
31 readTime: 10,
32 },
33];
34
35// PostCard Component
36interface PostCardProps {
37 slug: string;
38 title: string;
39 excerpt: string;
40 category: string;
41 author: string;
42 date: string;
43 readTime: number;
44}
45
46export function PostCard({
47 slug,
48 title,
49 excerpt,
50 category,
51 author,
52 date,
53 readTime,
54}: PostCardProps) {
55 function formatDate(dateString: string) {
56 const date = new Date(dateString);
57 const months = [
58 "Jan",
59 "Feb",
60 "Mar",
61 "Apr",
62 "May",
63 "Jun",
64 "Jul",
65 "Aug",
66 "Sep",
67 "Oct",
68 "Nov",
69 "Dec",
70 ];
71 return `${
72 months[date.getMonth()]
73 } ${date.getDate()}, ${date.getFullYear()}`;
74 }
75
76 return (
77 <Link href={`/blog/${slug}`}>
78 <Card className="hover:shadow-lg transition h-full">
79 <CardHeader>
80 <div className="flex items-start justify-between gap-2 mb-2">
81 <Badge variant="outline">{category}</Badge>
82 <span className="text-sm text-muted-foreground">
83 {readTime} min read
84 </span>
85 </div>
86 <CardTitle className="line-clamp-2">{title}</CardTitle>
87 </CardHeader>
88 <CardContent>
89 <p className="text-sm text-muted-foreground mb-4 line-clamp-2">
90 {excerpt}
91 </p>
92 <div className="flex justify-between items-center text-xs text-muted-foreground">
93 <span>{author}</span>
94 <span>{formatDate(date)}</span>
95 </div>
96 </CardContent>
97 </Card>
98 </Link>
99 );
100}
101
102// Homepage Component
103export default function Home() {
104 const posts = dummyPosts
105 .sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime())
106 .slice(0, 3);
107
108 return (
109 <div className="flex flex-col">
110 <main className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-0 py-12 w-full">
111 {/* Hero */}
112 <section className="mb-16">
113 <h1 className="text-4xl font-bold mb-4 text-balance">
114 Welcome to My Blog
115 </h1>
116 <p className="text-lg text-muted-foreground mb-8 max-w-2xl">
117 Explore articles about web development, design, and modern
118 technologies. Stay updated with the latest trends and best
119 practices.
120 </p>
121 <Link href="/blog">
122 <Button size="lg" className="cursor-pointer">
123 Read All Articles
124 </Button>
125 </Link>
126 </section>
127
128 {/* Recent Posts */}
129 <section>
130 <h2 className="text-3xl font-bold mb-8">Recent Articles</h2>
131 <div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
132 {posts.map((post) => (
133 <PostCard
134 key={post.id}
135 slug={post.slug}
136 title={post.title}
137 excerpt={post.excerpt}
138 category={post.category}
139 author={post.author}
140 date={post.date}
141 readTime={post.readTime}
142 />
143 ))}
144 </div>
145 </section>
146 </main>
147 </div>
148 );
149}