Next.js📅 2026-11-16⏱ 10 دقائق قراءة⚡ مقال 6 من 10

API Routes في Next.js — دليل شامل 2026

دليل عملي مفصل لـ API Routes في Next.js — بناء APIs، Route Handlers، والتحقق من البيانات

في المقال السابق، تعلمت جلب البيانات. الآن سنتعلم API Routes — لبناء Backend كامل داخل Next.js.

في هذا الدليل العملي، سنأخذك خطوة بخطوة لفهم API Routes، مع تمارين وحلول.

ما هي API Routes؟

API Routes هي نقاط نهاية (Endpoints) تبنيها داخل Next.js، دون الحاجة لسيرفر منفصل.

الفائدة:

  • ✅ نفس المشروع (Frontend + Backend).
  • ✅ نشر واحد.
  • ✅ TypeScript مشترك.
  • ✅ لا CORS.

متى تستخدمها؟

  • عندما تحتاج API لتطبيقك.
  • عندما تريد دمج البيانات من مصادر متعددة.
  • عندما تحتاج التحقق من البيانات قبل الإرسال.
  • عندما تريد حماية API Keys.

Route Handlers

في App Router، تُسمى Route Handlers وتوضع في ملف route.ts.

المسارالملفالرابط
API أساسيapp/api/route.ts/api
API للمستخدمينapp/api/users/route.ts/api/users
API للمستخدم الواحدapp/api/users/[id]/route.ts/api/users/1
API للمقالاتapp/api/posts/route.ts/api/posts

أول API

app/api/hello/route.ts:

import { NextResponse } from "next/server";

export async function GET() {
  return NextResponse.json({
    message: "مرحباً من Next.js API!",
    timestamp: new Date().toISOString(),
  });
}

الاختبار:

GET http://localhost:3000/api/hello

النتيجة:

{
  "message": "مرحباً من Next.js API!",
  "timestamp": "2026-11-16T10:30:00.000Z"
}

🎉 مبروك! بنيت أول API!

طرق HTTP

app/api/users/route.ts:

import { NextResponse } from "next/server";

// GET /api/users
export async function GET() {
  return NextResponse.json([
    { id: 1, name: "أحمد" },
    { id: 2, name: "محمد" },
  ]);
}

// POST /api/users
export async function POST(request: Request) {
  const body = await request.json();
  return NextResponse.json(
    { success: true, user: body },
    { status: 201 }
  );
}

// PUT /api/users
export async function PUT(request: Request) {
  const body = await request.json();
  return NextResponse.json({ success: true, user: body });
}

// DELETE /api/users
export async function DELETE() {
  return NextResponse.json({ success: true });
}

// PATCH /api/users
export async function PATCH(request: Request) {
  const body = await request.json();
  return NextResponse.json({ success: true, patch: body });
}

// HEAD / OPTIONS (تلقائي)

قراءة الطلبات

1. قراءة Body (JSON)

export async function POST(request: Request) {
  const body = await request.json();
  return NextResponse.json({ received: body });
}

2. قراءة Body (Form)

export async function POST(request: Request) {
  const formData = await request.formData();
  const name = formData.get("name") as string;
  return NextResponse.json({ name });
}

3. قراءة Query Parameters

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const query = searchParams.get("q");
  const limit = searchParams.get("limit");

  return NextResponse.json({ query, limit });
}

الاختبار: /api/search?q=react&limit=5

4. قراءة Route Parameters

app/api/users/[id]/route.ts:

export async function GET(
  request: Request,
  { params }: { params: Promise<{ id: string }> }
) {
  const { id } = await params;
  return NextResponse.json({ id, name: `المستخدم ${id}` });
}

⚠️ لاحظ: في Next.js 15، params هو Promise.

5. قراءة Headers

export async function GET(request: Request) {
  const auth = request.headers.get("authorization");
  return NextResponse.json({ auth });
}

إرسال الاستجابات

1. JSON

return NextResponse.json({ message: "مرحباً" });

2. مع Status Code

return NextResponse.json(
  { error: "غير موجود" },
  { status: 404 }
);

3. مع Headers

return NextResponse.json(
  { message: "مرحباً" },
  {
    headers: {
      "Cache-Control": "no-store",
      "X-Custom-Header": "value",
    },
  }
);

4. نصوص

return new Response("نص عادي", {
  headers: { "Content-Type": "text/plain; charset=utf-8" },
});

5. إعادة توجيه

import { redirect } from "next/navigation";

export async function GET() {
  redirect("/");
}

أكواد الحالة

الكودالمعنىالاستخدام
200OKنجاح
201Createdإنشاء
204No Contentحذف
400Bad Requestطلب خاطئ
401Unauthorizedغير مصرح
403Forbiddenممنوع
404Not Foundغير موجود
500Internal Server Errorخطأ في السيرفر

مثال عملي: CRUD للمستخدمين

app/api/users/route.ts:

import { NextResponse } from "next/server";

let users = [
  { id: 1, name: "أحمد", email: "[email protected]" },
  { id: 2, name: "محمد", email: "[email protected]" },
];

// GET /api/users
export async function GET() {
  return NextResponse.json(users);
}

// POST /api/users
export async function POST(request: Request) {
  const body = await request.json();

  if (!body.name || !body.email) {
    return NextResponse.json(
      { error: "الاسم والبريد مطلوبان" },
      { status: 400 }
    );
  }

  const newUser = {
    id: Date.now(),
    name: body.name,
    email: body.email,
  };

  users.push(newUser);
  return NextResponse.json(newUser, { status: 201 });
}

app/api/users/[id]/route.ts:

import { NextResponse } from "next/server";

let users = [
  { id: 1, name: "أحمد", email: "[email protected]" },
  { id: 2, name: "محمد", email: "[email protected]" },
];

// GET /api/users/:id
export async function GET(
  request: Request,
  { params }: { params: Promise<{ id: string }> }
) {
  const { id } = await params;
  const user = users.find((u) => u.id === parseInt(id));

  if (!user) {
    return NextResponse.json(
      { error: "المستخدم غير موجود" },
      { status: 404 }
    );
  }

  return NextResponse.json(user);
}

// PUT /api/users/:id
export async function PUT(
  request: Request,
  { params }: { params: Promise<{ id: string }> }
) {
  const { id } = await params;
  const body = await request.json();
  const index = users.findIndex((u) => u.id === parseInt(id));

  if (index === -1) {
    return NextResponse.json(
      { error: "المستخدم غير موجود" },
      { status: 404 }
    );
  }

  users[index] = { ...users[index], ...body };
  return NextResponse.json(users[index]);
}

// DELETE /api/users/:id
export async function DELETE(
  request: Request,
  { params }: { params: Promise<{ id: string }> }
) {
  const { id } = await params;
  const index = users.findIndex((u) => u.id === parseInt(id));

  if (index === -1) {
    return NextResponse.json(
      { error: "المستخدم غير موجود" },
      { status: 404 }
    );
  }

  users.splice(index, 1);
  return new NextResponse(null, { status: 204 });
}

التحقق من البيانات

export async function POST(request: Request) {
  const body = await request.json();

  const errors = [];

  if (!body.name || body.name.length < 2) {
    errors.push("الاسم يجب أن يكون حرفين على الأقل");
  }

  if (!body.email || !body.email.includes("@")) {
    errors.push("البريد غير صحيح");
  }

  if (body.age && (body.age < 18 || body.age > 100)) {
    errors.push("العمر يجب أن يكون بين 18 و 100");
  }

  if (errors.length > 0) {
    return NextResponse.json(
      { errors },
      { status: 400 }
    );
  }

  // ... إنشاء المستخدم
}

استخدام API من Client

1. استخدام fetch

"use client";

import { useState, useEffect } from "react";

export default function UsersList() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    fetch("/api/users")
      .then((res) => res.json())
      .then(setUsers);
  }, []);

  return (
    <ul>
      {users.map((u) => (
        <li key={u.id}>{u.name}</li>
      ))}
    </ul>
  );
}

2. إرسال POST

"use client";

async function createUser(name: string, email: string) {
  const res = await fetch("/api/users", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ name, email }),
  });

  const data = await res.json();
  return data;
}

مثال: API للبحث

app/api/search/route.ts:

import { NextResponse } from "next/server";

const articles = [
  { id: 1, title: "تعلم Next.js", category: "برمجة" },
  { id: 2, title: "تعلم React", category: "برمجة" },
  { id: 3, title: "تعلم TypeScript", category: "برمجة" },
];

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const q = searchParams.get("q") || "";

  const results = articles.filter((article) =>
    article.title.toLowerCase().includes(q.toLowerCase())
  );

  return NextResponse.json({
    query: q,
    count: results.length,
    results,
  });
}

الاختبار: /api/search?q=react

تمارين عملية

تمرين 1: API بسيط

أنشئ /api/hello يعيد ترحيباً.

الحل:

import { NextResponse } from "next/server";

export async function GET() {
  return NextResponse.json({ message: "مرحباً" });
}

تمرين 2: GET مع Query

أنشئ API يقرأ ?name=.

الحل:

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const name = searchParams.get("name") || "زائر";
  return NextResponse.json({ message: `مرحباً ${name}` });
}

تمرين 3: POST

أنشئ API يستقبل JSON.

الحل:

export async function POST(request: Request) {
  const body = await request.json();
  return NextResponse.json({ received: body }, { status: 201 });
}

تمرين 4: CRUD كامل

أنشئ CRUD للمقالات.

الحل:

// app/api/posts/route.ts
let posts = [];

export async function GET() {
  return NextResponse.json(posts);
}

export async function POST(request: Request) {
  const body = await request.json();
  const post = { id: Date.now(), ...body };
  posts.push(post);
  return NextResponse.json(post, { status: 201 });
}

تمرين 5: مسار ديناميكي

أنشئ /api/users/[id].

الحل:

export async function GET(
  request: Request,
  { params }: { params: Promise<{ id: string }> }
) {
  const { id } = await params;
  return NextResponse.json({ id });
}

تمرين 6: التحقق

أضف تحققاً للبيانات.

الحل:

if (!body.email?.includes("@")) {
  return NextResponse.json(
    { error: "بريد غير صحيح" },
    { status: 400 }
  );
}

تمرين 7: حماية API

أضف تحقق من Authorization.

الحل:

export async function POST(request: Request) {
  const auth = request.headers.get("authorization");

  if (auth !== "Bearer secret-token") {
    return NextResponse.json(
      { error: "غير مصرح" },
      { status: 401 }
    );
  }

  // ...
}

تمرين 8: API متكامل

ابنِ API كامل مع CRUD + تحقق + حماية.

الحل: (راجع المثال الكامل أعلاه)

حل المشاكل الشائعة

🔴 المشكلة 1: API لا يعمل في Client

السبب: استخدام URL غير كامل.

الحل: استخدم URL نسبي:

fetch("/api/users");  // ✅

🔴 المشكلة 2: request.json() يفشل

السبب: Body فارغ أو غير JSON.

الحل:

try {
  const body = await request.json();
} catch {
  return NextResponse.json({ error: "JSON غير صحيح" }, { status: 400 });
}

🔴 المشكلة 3: CORS

السبب: الطلب من نطاق مختلف.

الحل: أضف headers:

return NextResponse.json(data, {
  headers: {
    "Access-Control-Allow-Origin": "*",
  },
});

🔴 المشكلة 4: API Routes لا تعمل مع output: 'export'

السبب: التصدير الثابت لا يدعم API Routes.

الحل: استخدم Vercel أو Firebase Functions.

🔴 المشكلة 5: params غير متاح

السبب: في Next.js 15، params هو Promise.

الحل:

{ params }: { params: Promise<{ id: string }> }
// ...
const { id } = await params;

جدول دوال API

الدالةالوظيفة
NextResponse.json()إرسال JSON
request.json()قراءة JSON
request.formData()قراءة Form
request.headers.get()قراءة Header
new URL(request.url)قراءة Query
new Response()استجابة مخصصة
redirect()إعادة توجيه

قائمة تحقق نهائية

المهمةالحالة
فهم Route Handlers⬜
GET و POST⬜
قراءة Body و Query⬜
المسارات الديناميكية⬜
التحقق من البيانات⬜
حماية API⬜
حل التمارين الثمانية⬜

ماذا بعد هذا المقال؟

الآن بعد أن أتقنت API Routes، أنت جاهز للمقال التالي:

  1. Styling — Tailwind و CSS.
  2. Authentication — المصادقة.
  3. Deployment — النشر.

الخلاصة

في هذا المقال، تعلمت:

  • ✅ ما هي API Routes.
  • ✅ Route Handlers.
  • ✅ طرق HTTP.
  • ✅ قراءة الطلبات.
  • ✅ إرسال الاستجابات.
  • ✅ CRUD كامل.
  • ✅ التحقق من البيانات.
  • ✅ حل 8 تمارين عملية.

تذكر: API Routes تجعل Next.js إطاراً كاملاً — Frontend و Backend.

📚 مقالات ذات صلة

Next.js

مشروع Next.js متكامل — مدونة احترافية 2026

مشروع عملي شامل لبناء مدونة كاملة بـ Next.js — مع Markdown، SEO، نشر تلقائي، وتصميم احترافي

Next.js

نشر تطبيق Next.js — دليل شامل 2026

دليل عملي مفصل لنشر تطبيق Next.js — Vercel، Firebase، Netlify، والتصدير الثابت

Next.js

المصادقة في Next.js — دليل شامل 2026

دليل عملي مفصل للمصادقة في Next.js — NextAuth.js، JWT، Middleware، وحماية المسارات