Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 

Repository files navigation

Headless WordPress + Next.js

React দিয়ে Frontend, WordPress দিয়ে Backend

এই 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

Architecture

┌──────────────────────┐
│      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 করবে।


কেন Headless WordPress?

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 সুবিধা রাখতে হবে

React নাকি Next.js?

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 ব্যবহার করছি।


REST API নাকি WPGraphQL?

WordPress থেকে content নেওয়ার দুটি common approach:

REST API

WordPress-এর built-in API।

Example:

https://your-wordpress-site.com/wp-json/wp/v2/posts

Advantages:

  • WordPress-এর সঙ্গে built-in
  • আলাদা plugin প্রয়োজন নেই
  • setup সহজ
  • beginner-friendly

WPGraphQL

GraphQL ব্যবহার করে প্রয়োজনীয় data নির্দিষ্ট করে query করা যায়।

এটি useful যখন:

  • data structure complex
  • একটি page-এ অনেক ধরনের related data প্রয়োজন
  • REST API দিয়ে একাধিক request করতে হচ্ছে
  • payload optimize করতে হবে

এই project-এ আমরা REST API ব্যবহার করছি কারণ setup সহজ এবং একটি moderate-size content site-এর জন্য যথেষ্ট।


1. WordPress Setup

প্রথমে একটি 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 করবে।


2. Permalink Setup

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

3. Optional WordPress Plugins

Basic blog-এর জন্য কোনো plugin প্রয়োজন নেই।

তবে custom content structure প্রয়োজন হলে ব্যবহার করতে পারেন:

Custom Post Type UI

Custom post type তৈরি করার জন্য।

Example:

Portfolio
Products
Courses
Projects

Advanced Custom Fields

Post-এর সঙ্গে custom fields যোগ করার জন্য।

Example:

Price
Client Name
Project URL
Location
Course Duration

যদি ACF data REST API-এর মাধ্যমে ব্যবহার করতে চান, তাহলে সংশ্লিষ্ট field-এর Show in REST API setting enable করতে হবে।


4. Next.js Project তৈরি করা

Terminal-এ:

npx create-next-app@latest my-headless-site

Setup-এর সময়:

TypeScript     → Yes
ESLint         → Yes
Tailwind CSS   → Yes
App Router     → Yes

তারপর:

cd my-headless-site

VS Code ব্যবহার করলে:

code .

5. Environment Variable

WordPress API URL সরাসরি code-এর মধ্যে লিখব না।

এর পরিবর্তে .env.local তৈরি করুন:

WORDPRESS_API_URL=https://your-wordpress-site.com/wp-json/wp/v2

এখানে নিজের WordPress URL বসান।

কেন Environment Variable?

এর কয়েকটি সুবিধা আছে:

  • configuration code থেকে আলাদা থাকে
  • environment পরিবর্তন করা সহজ
  • development এবং production-এর জন্য আলাদা URL ব্যবহার করা যায়
  • hardcoded configuration কমে

6. WordPress API Helper

এখন একটি lib folder তৈরি করুন:

lib/
└── wordpress.ts

এই file-এ WordPress API-এর সঙ্গে communication সম্পর্কিত function রাখব।

এর ফলে API logic পুরো application-এ ছড়িয়ে না গিয়ে একটি জায়গায় থাকবে।

const API_URL = process.env.WORDPRESS_API_URL!;

7. Post Type তৈরি করা

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;
    }[];
  };
}

কেন Interface ব্যবহার করছি?

WordPress API থেকে data পাওয়ার পর TypeScript যেন বুঝতে পারে:

post.id
post.slug
post.title.rendered
post.content.rendered

এর ফলে:

  • autocomplete পাওয়া যায়
  • ভুল property ব্যবহার করার সম্ভাবনা কমে
  • refactoring সহজ হয়
  • API response-এর structure পরিষ্কার থাকে

8. সব Posts Fetch করা

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

_embed ব্যবহার করলে related embedded data, যেমন featured image, একই API response-এর মধ্যে পাওয়া যায়।

এটি না ব্যবহার করলে featured image-এর জন্য আলাদা API request প্রয়োজন হতে পারে।

per_page=12

per_page=12

একবারে সর্বোচ্চ ১২টি post নেওয়া হচ্ছে।

revalidate: 60

next: {
  revalidate: 60,
}

এর অর্থ হলো Next.js cached data ব্যবহার করবে এবং প্রায় ৬০ সেকেন্ড পর নতুন data check করতে পারবে।

এটি Incremental Static Regeneration (ISR)-এর caching/revalidation behavior-এর অংশ।


9. Single Post Fetch করা

এখন 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 খোঁজা হচ্ছে।


10. Homepage / Post List

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>
  );
}

কেন async component?

Next.js Server Component-এর মধ্যে সরাসরি asynchronous data fetching করা যায়।

তাই এখানে:

const posts = await getAllPosts();

ব্যবহার করতে পারছি।

Client-side React-এর মতো এখানে:

useEffect()
useState()

ব্যবহার করার প্রয়োজন নেই।


11. কেন dangerouslySetInnerHTML?

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 থেকে আসছে।


12. Dynamic Single Post Page

Folder structure:

app/
└── posts/
    └── [slug]/
        └── page.tsx

[slug] একটি dynamic route।

Example:

/posts/hello-world
/posts/my-first-post
/posts/nextjs-tutorial

সবগুলো একই page.tsx ব্যবহার করবে।


13. Static Params Generate করা

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 করা সম্ভব।


14. Dynamic SEO Metadata

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 পাওয়ার সম্ভাবনা আছে।


15. Single Post Component

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 দেখায়।


16. Featured Image

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।


17. External WordPress Image Allow করা

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 করুন।


18. Project Structure

শেষে 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

19. Sitemap

Next.js App Router-এ sitemap.ts ব্যবহার করে sitemap তৈরি করা যায়।

Basic structure:

app/
└── sitemap.ts

এটি search engine-এর জন্য website-এর available URLs discover করতে সাহায্য করে।


20. Vercel Deployment

এখন frontend deploy করব Vercel-এ।

Architecture হবে:

WordPress
   │
   │ REST API
   ▼
Next.js
   │
   ▼
Vercel

WordPress backend যেখানে আছে সেখানেই থাকবে।

শুধু Next.js frontend Vercel-এ deploy হবে।

Step 1

Code GitHub-এ push করুন।

Step 2

Vercel-এ GitHub account connect করুন।

Step 3

আপনার repository import করুন।

Step 4

Environment Variable add করুন:

WORDPRESS_API_URL

Value:

https://your-wordpress-site.com/wp-json/wp/v2

Step 5

Deploy করুন।

Deploy হওয়ার পরে Next.js frontend WordPress API থেকে content fetch করবে।


21. Common Problems

API কাজ করছে না

এই URL test করুন:

https://your-wordpress-site.com/wp-json/wp/v2/posts

JSON response আসছে কিনা দেখুন।


Featured Image দেখাচ্ছে না

Check করুন:

next.config.ts

এর মধ্যে WordPress hostname ঠিক আছে কিনা।

তারপর development server restart করুন।


Post page 404

Check করুন:

app/posts/[slug]/page.tsx

এবং WordPress post-এর slug ঠিক আছে কিনা।


params related error

নতুন Next.js version-এ:

const { slug } = await params;

ব্যবহার করতে হবে।

পুরোনো tutorial-এর synchronous params pattern ব্যবহার করলে error হতে পারে।


WordPress API data আসছে না

Check করুন:

WORDPRESS_API_URL=https://your-domain.com/wp-json/wp/v2

শেষে /posts যোগ করবেন না।

কারণ code নিজেই:

`${API_URL}/posts`

ব্যবহার করছে।


22. এই Project থেকে কী শিখলাম?

এই 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।


23. Next Level

Basic implementation শেষ করার পরে পরবর্তী ধাপে এগুলো শিখতে পারেন।

1. WPGraphQL

Complex data structure হলে REST API-এর পরিবর্তে GraphQL ব্যবহার করতে পারেন।

এর মাধ্যমে একটি query-তেই প্রয়োজনীয় data নির্দিষ্ট করে নেওয়া যায়।

2. Draft Preview

WordPress editor publish করার আগেই Next.js frontend-এ draft content preview করতে পারে।

3. On-demand Revalidation

বর্তমানে আমরা:

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 হতে পারে।


Final Checklist

এই 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.local configured
  • lib/wordpress.ts created
  • getAllPosts() working
  • getPostBySlug() working
  • Homepage showing posts
  • Dynamic [slug] route working
  • Featured image working
  • next.config.ts configured
  • Dynamic metadata working
  • Sitemap added
  • Project pushed to GitHub
  • Environment variable added to Vercel
  • Production deployment working

The Goal

শেষে আপনার 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।


Resources

Official documentation:


Video

এই README-এর সঙ্গে সম্পর্কিত complete A-to-Z tutorial-এ পুরো projectটি step-by-step তৈরি করা হয়েছে।

ভিডিওতে আমরা WordPress backend থেকে শুরু করে Next.js frontend এবং Vercel deployment পর্যন্ত পুরো workflow দেখিয়েছি।

Practice করুন, শুধু code copy করবেন না।

নিজে হাতে project তৈরি করলে architecture-টা অনেক ভালোভাবে বুঝতে পারবেন।

About

No description, website, or topics provided.

Resources

Stars

38 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors