এই project-এ আমরা WordPress-কে traditional theme-based CMS হিসেবে ব্যবহার না করে একটি Headless CMS হিসেবে ব্যবহার করব।
WordPress থাকবে আমাদের Backend / Content Management System হিসেবে এবং Next.js থাকবে সম্পূর্ণ Frontend হিসেবে।
WordPress REST API-এর মাধ্যমে content JSON আকারে Next.js-এ পাঠাবে, আর Next.js সেই data ব্যবহার করে fast, SEO-friendly frontend তৈরি করবে।
এই project-এ আমরা শুরু থেকে শেষ পর্যন্ত দেখব:
- WordPress REST API setup
- Next.js App Router setup
- WordPress থেকে posts fetch করা
- TypeScript দিয়ে API response type করা
- Post listing তৈরি করা
- Dynamic single post page তৈরি করা
- Featured image দেখানো
- SEO metadata তৈরি করা
- Next.js image configuration
- ISR / revalidation
- Vercel deployment
┌──────────────────────┐
│ WordPress │
│ │
│ Content Management │
│ Posts │
│ Media │
│ Database │
└──────────┬───────────┘
│
│ REST API
│ JSON
▼
┌──────────────────────┐
│ Next.js │
│ │
│ Server Components │
│ App Router │
│ Data Fetching │
│ SEO │
│ UI │
└──────────┬───────────┘
│
▼
Website User
সহজভাবে বললে:
WordPress content তৈরি করবে → REST API content পাঠাবে → Next.js content render করবে।
Traditional WordPress-এ backend এবং frontend একই application-এর অংশ।
WordPress
├── Admin
├── Database
├── PHP
├── Theme
└── Frontend
Headless architecture-এ আমরা frontend আলাদা করে দিই।
WordPress
├── Admin
├── Database
└── API
↓
Next.js
↓
Frontend
এর ফলে content team WordPress-এর familiar editor ব্যবহার করতে পারে, কিন্তু frontend developer Next.js এবং React ecosystem-এর সম্পূর্ণ সুবিধা পায়।
এই architecture বিশেষভাবে useful যখন:
- frontend-এর উপর full design control দরকার
- performance গুরুত্বপূর্ণ
- SEO গুরুত্বপূর্ণ
- একই content website এবং অন্যান্য platform-এ ব্যবহার করতে হবে
- WordPress-এর content management সুবিধা রাখতে হবে
Content-heavy website-এর জন্য আমরা এই project-এ plain React-এর পরিবর্তে Next.js ব্যবহার করছি।
Plain React SPA-তে সাধারণত initial HTML-এর মধ্যে সম্পূর্ণ content থাকে না। Browser-এ JavaScript execute হওয়ার পর content load হয়।
Next.js-এর Server Components ব্যবহার করে আমরা server-side থেকে WordPress API call করতে পারি।
Browser
↓
Next.js Server
↓
WordPress REST API
↓
Content
↓
Rendered HTML
↓
Browser
এর ফলে:
- content server-side render করা যায়
- SEO ভালোভাবে handle করা যায়
- browser থেকে সরাসরি WordPress API call করার প্রয়োজন কমে
- Server Component-এ সরাসরি
async/awaitব্যবহার করা যায়
এই project-এ আমরা Next.js App Router ব্যবহার করছি।
WordPress থেকে content নেওয়ার দুটি common approach:
WordPress-এর built-in API।
Example:
https://your-wordpress-site.com/wp-json/wp/v2/posts
Advantages:
- WordPress-এর সঙ্গে built-in
- আলাদা plugin প্রয়োজন নেই
- setup সহজ
- beginner-friendly
GraphQL ব্যবহার করে প্রয়োজনীয় data নির্দিষ্ট করে query করা যায়।
এটি useful যখন:
- data structure complex
- একটি page-এ অনেক ধরনের related data প্রয়োজন
- REST API দিয়ে একাধিক request করতে হচ্ছে
- payload optimize করতে হবে
এই project-এ আমরা REST API ব্যবহার করছি কারণ setup সহজ এবং একটি moderate-size content site-এর জন্য যথেষ্ট।
প্রথমে একটি WordPress website তৈরি করুন।
Local development-এর জন্য Local ব্যবহার করতে পারেন, অথবা একটি live WordPress installation ব্যবহার করতে পারেন।
WordPress-এর REST API defaultভাবেই enabled থাকে।
Browser-এ এই URL open করুন:
https://your-wordpress-site.com/wp-json/wp/v2/posts
যদি JSON response পান, তাহলে API কাজ করছে।
এই endpoint আমাদের WordPress-এর posts return করবে।
WordPress dashboard থেকে যান:
Settings
→ Permalinks
→ Post name
→ Save Changes
আমরা post-এর slug ব্যবহার করে Next.js-এ dynamic URL তৈরি করব।
Example:
WordPress post title:
My First Post
Slug:
my-first-post
Next.js URL:
/posts/my-first-post
Basic blog-এর জন্য কোনো plugin প্রয়োজন নেই।
তবে custom content structure প্রয়োজন হলে ব্যবহার করতে পারেন:
Custom post type তৈরি করার জন্য।
Example:
Portfolio
Products
Courses
Projects
Post-এর সঙ্গে custom fields যোগ করার জন্য।
Example:
Price
Client Name
Project URL
Location
Course Duration
যদি ACF data REST API-এর মাধ্যমে ব্যবহার করতে চান, তাহলে সংশ্লিষ্ট field-এর Show in REST API setting enable করতে হবে।
Terminal-এ:
npx create-next-app@latest my-headless-siteSetup-এর সময়:
TypeScript → Yes
ESLint → Yes
Tailwind CSS → Yes
App Router → Yes
তারপর:
cd my-headless-siteVS Code ব্যবহার করলে:
code .WordPress API URL সরাসরি code-এর মধ্যে লিখব না।
এর পরিবর্তে .env.local তৈরি করুন:
WORDPRESS_API_URL=https://your-wordpress-site.com/wp-json/wp/v2এখানে নিজের WordPress URL বসান।
এর কয়েকটি সুবিধা আছে:
- configuration code থেকে আলাদা থাকে
- environment পরিবর্তন করা সহজ
- development এবং production-এর জন্য আলাদা URL ব্যবহার করা যায়
- hardcoded configuration কমে
এখন একটি lib folder তৈরি করুন:
lib/
└── wordpress.ts
এই file-এ WordPress API-এর সঙ্গে communication সম্পর্কিত function রাখব।
এর ফলে API logic পুরো application-এ ছড়িয়ে না গিয়ে একটি জায়গায় থাকবে।
const API_URL = process.env.WORDPRESS_API_URL!;WordPress API কী ধরনের data return করবে, সেটি TypeScript-এ define করা ভালো।
export interface Post {
id: number;
slug: string;
title: {
rendered: string;
};
excerpt: {
rendered: string;
};
content: {
rendered: string;
};
date: string;
_embedded?: {
"wp:featuredmedia"?: {
source_url: string;
alt_text: string;
}[];
};
}WordPress API থেকে data পাওয়ার পর TypeScript যেন বুঝতে পারে:
post.id
post.slug
post.title.rendered
post.content.rendered
এর ফলে:
- autocomplete পাওয়া যায়
- ভুল property ব্যবহার করার সম্ভাবনা কমে
- refactoring সহজ হয়
- API response-এর structure পরিষ্কার থাকে
lib/wordpress.ts-এ:
export async function getAllPosts(): Promise<Post[]> {
const res = await fetch(
`${API_URL}/posts?_embed&per_page=12`,
{
next: {
revalidate: 60,
},
}
);
if (!res.ok) {
throw new Error("Failed to fetch posts");
}
return res.json();
}এখানে কয়েকটি গুরুত্বপূর্ণ বিষয় আছে।
?_embed
_embed ব্যবহার করলে related embedded data, যেমন featured image, একই API response-এর মধ্যে পাওয়া যায়।
এটি না ব্যবহার করলে featured image-এর জন্য আলাদা API request প্রয়োজন হতে পারে।
per_page=12
একবারে সর্বোচ্চ ১২টি post নেওয়া হচ্ছে।
next: {
revalidate: 60,
}এর অর্থ হলো Next.js cached data ব্যবহার করবে এবং প্রায় ৬০ সেকেন্ড পর নতুন data check করতে পারবে।
এটি Incremental Static Regeneration (ISR)-এর caching/revalidation behavior-এর অংশ।
এখন slug ব্যবহার করে নির্দিষ্ট post fetch করব:
export async function getPostBySlug(
slug: string
): Promise<Post | null> {
const res = await fetch(
`${API_URL}/posts?slug=${slug}&_embed`,
{
next: {
revalidate: 60,
},
}
);
if (!res.ok) {
throw new Error("Failed to fetch post");
}
const posts: Post[] = await res.json();
return posts[0] ?? null;
}এখানে WordPress-এর API-তে:
?slug=my-post
দিয়ে নির্দিষ্ট post খোঁজা হচ্ছে।
File:
app/page.tsx
Code:
import Link from "next/link";
import { getAllPosts } from "@/lib/wordpress";
export default async function HomePage() {
const posts = await getAllPosts();
return (
<main className="max-w-3xl mx-auto p-6">
<h1 className="text-3xl font-bold mb-8">
My Blog
</h1>
<div className="space-y-6">
{posts.map((post) => (
<article key={post.id}>
<Link href={`/posts/${post.slug}`}>
<h2
className="text-xl font-semibold hover:underline"
dangerouslySetInnerHTML={{
__html: post.title.rendered,
}}
/>
</Link>
<div
className="text-gray-600 mt-2"
dangerouslySetInnerHTML={{
__html: post.excerpt.rendered,
}}
/>
</article>
))}
</div>
</main>
);
}Next.js Server Component-এর মধ্যে সরাসরি asynchronous data fetching করা যায়।
তাই এখানে:
const posts = await getAllPosts();ব্যবহার করতে পারছি।
Client-side React-এর মতো এখানে:
useEffect()
useState()
ব্যবহার করার প্রয়োজন নেই।
WordPress title, excerpt এবং content সাধারণত HTML format-এ পাঠায়।
Example:
<p>Hello World</p>React-এর মধ্যে HTML হিসেবে render করার জন্য:
dangerouslySetInnerHTML={{
__html: post.content.rendered,
}}ব্যবহার করা হচ্ছে।
নামটা ভয়ংকর, কারণ HTML injection-এর ঝুঁকি থাকতে পারে। তাই এই technique ব্যবহার করার সময় data source এবং sanitization সম্পর্কে সচেতন থাকতে হবে।
এই project-এ content WordPress API থেকে আসছে।
Folder structure:
app/
└── posts/
└── [slug]/
└── page.tsx
[slug] একটি dynamic route।
Example:
/posts/hello-world
/posts/my-first-post
/posts/nextjs-tutorial
সবগুলো একই page.tsx ব্যবহার করবে।
export async function generateStaticParams() {
const posts = await getAllPosts();
return posts.map((post) => ({
slug: post.slug,
}));
}এখানে WordPress-এর posts থেকে slug সংগ্রহ করে Next.js-কে জানানো হচ্ছে কোন কোন route generate করতে হবে।
Example:
[
{ slug: "hello-world" },
{ slug: "nextjs-tutorial" },
{ slug: "wordpress-guide" }
]এর ফলে build-এর সময় এই routeগুলো generate করা সম্ভব।
Next.js-এর Metadata API ব্যবহার করে প্রতিটি post-এর জন্য আলাদা title এবং description তৈরি করতে পারি।
import type { Metadata } from "next";
export async function generateMetadata({
params,
}: {
params: Promise<{ slug: string }>;
}): Promise<Metadata> {
const { slug } = await params;
const post = await getPostBySlug(slug);
if (!post) {
return {};
}
return {
title: post.title.rendered,
description: post.excerpt.rendered.replace(
/<[^>]+>/g,
""
),
};
}এখানে গুরুত্বপূর্ণ বিষয় হলো:
params: Promise<{ slug: string }>এবং:
const { slug } = await params;নতুন Next.js versions-এ params asynchronous হওয়ায় আগে await করতে হয়।
পুরোনো tutorial-এর code copy করলে এখানে error পাওয়ার সম্ভাবনা আছে।
export default async function PostPage({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
const post = await getPostBySlug(slug);
if (!post) {
notFound();
}
const featuredImage =
post._embedded?.["wp:featuredmedia"]?.[0];
return (
<article className="max-w-3xl mx-auto p-6">
<h1
className="text-4xl font-bold mb-4"
dangerouslySetInnerHTML={{
__html: post.title.rendered,
}}
/>
{featuredImage && (
<Image
src={featuredImage.source_url}
alt={
featuredImage.alt_text ||
post.title.rendered
}
width={1200}
height={630}
className="rounded-lg mb-6"
/>
)}
<div
className="prose prose-lg"
dangerouslySetInnerHTML={{
__html: post.content.rendered,
}}
/>
</article>
);
}এখানে:
notFound();ব্যবহার করছি যাতে post না পাওয়া গেলে Next.js-এর 404 page দেখায়।
WordPress-এর featured image _embedded property-এর মাধ্যমে পাওয়া যাচ্ছে।
const featuredImage =
post._embedded?.["wp:featuredmedia"]?.[0];তারপর:
<Image
src={featuredImage.source_url}
alt={featuredImage.alt_text}
width={1200}
height={630}
/>ব্যবহার করছি।
Next.js-এর Image component image optimization এবং performance-এর জন্য useful।
Next.js security-এর কারণে arbitrary external image domain থেকে image load করতে দেয় না।
তাই next.config.ts-এ WordPress domain configure করতে হবে।
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
images: {
remotePatterns: [
{
protocol: "https",
hostname: "your-wordpress-site.com",
},
],
},
};
export default nextConfig;your-wordpress-site.com-এর জায়গায় নিজের WordPress domain দিন।
এরপর development server restart করুন।
শেষে project structure মোটামুটি এমন হবে:
my-headless-site/
│
├── app/
│ ├── posts/
│ │ └── [slug]/
│ │ └── page.tsx
│ │
│ ├── page.tsx
│ └── sitemap.ts
│
├── lib/
│ └── wordpress.ts
│
├── .env.local
├── next.config.ts
├── package.json
└── tsconfig.json
Next.js App Router-এ sitemap.ts ব্যবহার করে sitemap তৈরি করা যায়।
Basic structure:
app/
└── sitemap.ts
এটি search engine-এর জন্য website-এর available URLs discover করতে সাহায্য করে।
এখন frontend deploy করব Vercel-এ।
Architecture হবে:
WordPress
│
│ REST API
▼
Next.js
│
▼
Vercel
WordPress backend যেখানে আছে সেখানেই থাকবে।
শুধু Next.js frontend Vercel-এ deploy হবে।
Code GitHub-এ push করুন।
Vercel-এ GitHub account connect করুন।
আপনার repository import করুন।
Environment Variable add করুন:
WORDPRESS_API_URL
Value:
https://your-wordpress-site.com/wp-json/wp/v2
Deploy করুন।
Deploy হওয়ার পরে Next.js frontend WordPress API থেকে content fetch করবে।
এই URL test করুন:
https://your-wordpress-site.com/wp-json/wp/v2/posts
JSON response আসছে কিনা দেখুন।
Check করুন:
next.config.ts
এর মধ্যে WordPress hostname ঠিক আছে কিনা।
তারপর development server restart করুন।
Check করুন:
app/posts/[slug]/page.tsx
এবং WordPress post-এর slug ঠিক আছে কিনা।
নতুন Next.js version-এ:
const { slug } = await params;ব্যবহার করতে হবে।
পুরোনো tutorial-এর synchronous params pattern ব্যবহার করলে error হতে পারে।
Check করুন:
WORDPRESS_API_URL=https://your-domain.com/wp-json/wp/v2শেষে /posts যোগ করবেন না।
কারণ code নিজেই:
`${API_URL}/posts`ব্যবহার করছে।
এই project শেষ করার পরে আপনি শুধু WordPress API call করা শিখবেন না।
আপনি একটি complete architecture বুঝবেন:
CMS
↓
REST API
↓
TypeScript
↓
Next.js Server Components
↓
Dynamic Routes
↓
Static Generation
↓
Metadata / SEO
↓
Image Optimization
↓
ISR / Revalidation
↓
Vercel Deployment
এটাই Headless WordPress-এর মূল workflow।
Basic implementation শেষ করার পরে পরবর্তী ধাপে এগুলো শিখতে পারেন।
Complex data structure হলে REST API-এর পরিবর্তে GraphQL ব্যবহার করতে পারেন।
এর মাধ্যমে একটি query-তেই প্রয়োজনীয় data নির্দিষ্ট করে নেওয়া যায়।
WordPress editor publish করার আগেই Next.js frontend-এ draft content preview করতে পারে।
বর্তমানে আমরা:
revalidate: 60ব্যবহার করছি।
আরও advanced architecture-এ WordPress-এর post update হওয়ার সঙ্গে সঙ্গে webhook ব্যবহার করে Next.js-কে specific page revalidate করতে বলা যায়।
তাহলে:
WordPress Post Updated
↓
Webhook
↓
Next.js
↓
Revalidate Page
↓
Updated Content
এটি periodic 60-second revalidation-এর চেয়ে আরও efficient হতে পারে।
এই project complete করার আগে নিশ্চিত করুন:
- WordPress installed
- WordPress REST API working
- Permalink set to Post name
- WordPress posts created
- Next.js project created
- TypeScript enabled
- App Router enabled
-
.env.localconfigured -
lib/wordpress.tscreated -
getAllPosts()working -
getPostBySlug()working - Homepage showing posts
- Dynamic
[slug]route working - Featured image working
-
next.config.tsconfigured - Dynamic metadata working
- Sitemap added
- Project pushed to GitHub
- Environment variable added to Vercel
- Production deployment working
শেষে আপনার setup হবে:
┌─────────────────┐
│ WordPress │
│ Headless CMS │
└────────┬────────┘
│
REST API
│
▼
┌─────────────────┐
│ Next.js │
│ App Router │
│ Server Side │
│ SEO │
│ Image Optimize │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Vercel │
│ Production │
└─────────────────┘
WordPress content manage করবে।
Next.js frontend render করবে।
আর Vercel frontend deploy করবে।
এটাই আমাদের Headless WordPress + Next.js architecture।
Official documentation:
- Next.js: https://nextjs.org/docs
- WordPress REST API: https://developer.wordpress.org/rest-api/
- WordPress REST API Handbook: https://developer.wordpress.org/rest-api/reference/
- Vercel: https://vercel.com/docs
- WPGraphQL: https://www.wpgraphql.com/
এই README-এর সঙ্গে সম্পর্কিত complete A-to-Z tutorial-এ পুরো projectটি step-by-step তৈরি করা হয়েছে।
ভিডিওতে আমরা WordPress backend থেকে শুরু করে Next.js frontend এবং Vercel deployment পর্যন্ত পুরো workflow দেখিয়েছি।
Practice করুন, শুধু code copy করবেন না।
নিজে হাতে project তৈরি করলে architecture-টা অনেক ভালোভাবে বুঝতে পারবেন।