Next.jsAdvanced
Real-world Project: Blog Platform
Next.js দিয়ে complete blog — dynamic routes, data fetching, metadata, Server Actions বাংলায়।
13টি অংশবাংলা ভাষায়
চলুন Next.js-এর সব core concept দিয়ে একটি blog platform তৈরি করি।
Project Structure
app/ structuretext
text
app/
├── layout.tsx → root layout + metadata
├── page.tsx → blog list home
├── actions.ts → "use server" actions
├── blog/
│ ├── [slug]/
│ │ ├── page.tsx → single post (dynamic)
│ │ └── not-found.tsx
│ └── loading.tsx → list loading skeleton
└── ui/
├── post-card.tsx → client component
└── like-button.tsx → "use client"1. Root Layout + Metadata
app/layout.tsxtsx
tsx
import type { Metadata } from "next";
export const metadata: Metadata = {
title: {
default: "My Blog",
template: "%s | My Blog",
},
description: "আমাদের বাংলা ব্লগ",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="bn">
<body className="mx-auto max-w-3xl p-6">{children}</body>
</html>
);
}2. Blog List (Home)
app/page.tsxtsx
tsx
import Link from "next/link";
export default async function Page() {
const posts = await fetch("https://api.vercel.app/blog").then((r) =>
r.json()
);
return (
<main>
<h1 className="text-3xl font-bold">Latest Posts</h1>
<ul className="mt-6 space-y-4">
{posts.map((post: any) => (
<li key={post.id} className="rounded-lg border p-4 shadow-sm">
<Link
href={`/blog/${post.slug}`}
className="text-lg font-semibold text-blue-600"
>
{post.title}
</Link>
</li>
))}
</ul>
</main>
);
}3. Dynamic Post Page
app/blog/[slug]/page.tsxtsx
tsx
import { notFound } from "next/navigation";
export async function generateMetadata({
params,
}: {
params: Promise<{ slug: string }>;
}): Promise<Metadata> {
const { slug } = await params;
const post = await getPost(slug);
return { title: post?.title };
}
export default async function Page({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
const post = await getPost(slug);
if (!post) notFound();
return (
<article>
<h1 className="text-3xl font-bold">{post.title}</h1>
<p className="mt-4 text-gray-600">{post.content}</p>
</article>
);
}
async function getPost(slug: string) {
const res = await fetch(`https://api.vercel.app/blog/${slug}`);
if (!res.ok) return null;
return res.json();
}4. Server Action (Like)
app/actions.tsts
ts
"use server";
export async function incrementLikes(id: string) {
// database-এ like বাড়ান
console.log("Liked post:", id);
}app/ui/like-button.tsxtsx
tsx
"use client";
export default function LikeButton({ postId }: { postId: string }) {
return (
<button
onClick={() => {
fetch("/api/likes", { method: "POST", body: JSON.stringify({ postId }) });
}}
className="rounded-full bg-gray-100 px-4 py-1 text-sm hover:bg-gray-200"
>
♥ Like
</button>
);
}Practice
এই blog-এ dark mode, search (searchParams), comment form (Server Action) যোগ করুন — Next.js-এর সব core skill এখানেই ব্যবহৃত হয়।
শেষ প্যারায় নিজে practice করুন — কোড কপি করে নিজের এডিটরে চালিয়ে দেখুন।