Next.js
مشروع Next.js متكامل — مدونة احترافية 2026
📅 2026-11-20⏱ 13 دقائق قراءة
🎉 **مبروك! وصلت إلى المقال الأخير في مسار Next.js!**
لقد تعلمت كل الأساسيات: App Router، Server Components، Data Fetching، API Routes، Styling، Authentication، والنشر. الآن حان الوقت لتطبيق كل هذه المفاهيم في **مشروع حقيقي متكامل**.
في هذا الدليل العملي، سنبني **مدونة احترافية كاملة** — وهي المشروع الذي يبنيه المطورون المحترفون فعلاً.
## ما سنبنيه
**مدونة احترافية** تحتوي على:
- ✅ **صفحة رئيسية** مع أحدث المقالات.
- ✅ **صفحة المقالات** مع قائمة كاملة.
- ✅ **صفحة المقال الفردي** مع محتوى Markdown.
- ✅ **تصنيفات (Categories)**.
- ✅ **بحث (Search)**.
- ✅ **جدول محتويات (TOC)**.
- ✅ **مشاركة على وسائل التواصل**.
- ✅ **SEO محسّن** (Metadata, Open Graph, Sitemap).
- ✅ **تصميم متجاوب**.
- ✅ **وضع داكن**.
- ✅ **نشرة بريدية**.
- ✅ **مقالات ذات صلة**.
## هيكل المشروع
```
next-blog/
├── app/
│ ├── layout.tsx # التخطيط العام
│ ├── page.tsx # الصفحة الرئيسية
│ ├── globals.css
│ ├── blog/
│ │ ├── page.tsx # قائمة المقالات
│ │ └── [slug]/
│ │ └── page.tsx # مقال فردي
│ ├── categories/
│ │ └── [category]/
│ │ └── page.tsx # مقالات التصنيف
│ ├── about/
│ │ └── page.tsx
│ └── api/
│ └── subscribe/
│ └── route.ts # API النشرة
├── components/
│ ├── Header.tsx
│ ├── Footer.tsx
│ ├── PostCard.tsx
│ ├── SearchBar.tsx
│ ├── TableOfContents.tsx
│ ├── ShareButtons.tsx
│ └── NewsletterForm.tsx
├── lib/
│ ├── posts.ts # دوال قراءة المقالات
│ └── utils.ts
├── content/
│ └── posts/ # ملفات Markdown
│ ├── first-post.md
│ └── second-post.md
├── public/
│ └── images/
├── next.config.ts
├── tailwind.config.ts
├── package.json
└── tsconfig.json
```
## الخطوة 1: إنشاء المشروع
```bash
npx create-next-app@latest next-blog --typescript --tailwind --eslint --app --no-src-dir --import-alias "@/*"
cd next-blog
```
## الخطوة 2: تثبيت المكتبات
```bash
npm install gray-matter remark remark-html
npm install -D @tailwindcss/typography
```
**المكتبات:**
<table>
<thead>
<tr>
<th>المكتبة</th>
<th>الوظيفة</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>gray-matter</code></td>
<td>قراءة Frontmatter من Markdown</td>
</tr>
<tr>
<td><code>remark</code></td>
<td>تحويل Markdown إلى HTML</td>
</tr>
<tr>
<td><code>remark-html</code></td>
<td>Plugin لـ remark</td>
</tr>
<tr>
<td><code>@tailwindcss/typography</code></td>
<td>أنماط للنصوص</td>
</tr>
</tbody>
</table>
## الخطوة 3: `tailwind.config.ts`
```typescript
import type { Config } from "tailwindcss";
const config: Config = {
content: [
"./app/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
],
darkMode: "class",
theme: {
extend: {
fontFamily: {
cairo: ["var(--font-cairo)", "sans-serif"],
},
},
},
plugins: [require("@tailwindcss/typography")],
};
export default config;
```
## الخطوة 4: `app/globals.css`
```css
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
body {
@apply bg-gray-50 text-gray-900 dark:bg-gray-900 dark:text-gray-100;
}
}
@layer components {
.container-custom {
@apply max-w-4xl mx-auto px-4;
}
}
/* صناديق الكود */
.prose pre {
@apply bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto;
}
.prose code {
@apply bg-gray-100 dark:bg-gray-800 px-1.5 py-0.5 rounded text-sm;
}
.prose pre code {
@apply bg-transparent p-0;
}
```
## الخطوة 5: `lib/posts.ts`
```typescript
import fs from "fs";
import path from "path";
import matter from "gray-matter";
import { remark } from "remark";
import html from "remark-html";
const postsDirectory = path.join(process.cwd(), "content/posts");
export interface Post {
slug: string;
title: string;
date: string;
excerpt: string;
category: string;
tags: string[];
coverImage?: string;
content: string;
}
// جلب كل المقالات
export function getAllPosts(): Post[] {
const fileNames = fs.readdirSync(postsDirectory);
const posts = fileNames
.filter((name) => name.endsWith(".md"))
.map((name) => {
const slug = name.replace(/\.md$/, "");
const fullPath = path.join(postsDirectory, name);
const fileContents = fs.readFileSync(fullPath, "utf8");
const { data, content } = matter(fileContents);
return {
slug,
title: data.title,
date: data.date,
excerpt: data.excerpt || content.slice(0, 150) + "...",
category: data.category || "غير مصنف",
tags: data.tags || [],
coverImage: data.coverImage,
content,
};
})
.sort((a, b) => (a.date < b.date ? 1 : -1));
return posts;
}
// جلب مقال واحد
export function getPostBySlug(slug: string): Post | null {
try {
const fullPath = path.join(postsDirectory, `${slug}.md`);
const fileContents = fs.readFileSync(fullPath, "utf8");
const { data, content } = matter(fileContents);
return {
slug,
title: data.title,
date: data.date,
excerpt: data.excerpt || content.slice(0, 150) + "...",
category: data.category || "غير مصنف",
tags: data.tags || [],
coverImage: data.coverImage,
content,
};
} catch {
return null;
}
}
// تحويل Markdown إلى HTML
export async function markdownToHtml(markdown: string): Promise<string> {
const result = await remark().use(html).process(markdown);
return result.toString();
}
// جلب مقالات التصنيف
export function getPostsByCategory(category: string): Post[] {
return getAllPosts().filter((post) => post.category === category);
}
// جلب كل التصنيفات
export function getAllCategories(): string[] {
const posts = getAllPosts();
return [...new Set(posts.map((post) => post.category))];
}
// جلب المقالات ذات الصلة
export function getRelatedPosts(slug: string, limit = 3): Post[] {
const post = getPostBySlug(slug);
if (!post) return [];
return getAllPosts()
.filter((p) => p.slug !== slug && p.category === post.category)
.slice(0, limit);
}
// وقت القراءة
export function getReadingTime(content: string): number {
const words = content.trim().split(/\s+/).length;
return Math.max(1, Math.ceil(words / 200));
}
// تنسيق التاريخ
export function formatDate(date: string): string {
return new Date(date).toLocaleDateString("ar-EG", {
year: "numeric",
month: "long",
day: "numeric",
});
}
```
## الخطوة 6: مقال تجريبي
**`content/posts/first-post.md`:**
```markdown
---
title: "مرحباً بك في مدونتي"
date: "2026-11-20"
excerpt: "أول مقال في مدونتي الجديدة بـ Next.js"
category: "تقنية"
tags: ["Next.js", "React", "برمجة"]
coverImage: "https://images.unsplash.com/photo-1516116216624-53e697fedbea?w=1200"
---
## مقدمة
مرحباً بك في مدونتي الجديدة! هذه مدونة مبنية بـ **Next.js** و **Tailwind CSS**.
## لماذا Next.js؟
Next.js هو إطار عمل رائع لبناء تطبيقات React. يتميز بـ:
- **App Router** — نظام توجيه حديث
- **Server Components** — أداء عالٍ
- **SEO ممتاز** — جاهز لمحركات البحث
- **سهل النشر** — على Vercel
## مثال على كود
```javascript
function greet(name) {
return `مرحباً ${name}!`;
}
```
## الخلاصة
هذا مشروع رائع لتعلّم Next.js. استمتع!
```
**`content/posts/second-post.md`:**
```markdown
---
title: "كيف تتعلم البرمجة في 2026"
date: "2026-11-19"
excerpt: "دليل شامل لتعلم البرمجة من الصفر"
category: "تعلم"
tags: ["برمجة", "تعلم"]
coverImage: "https://images.unsplash.com/photo-1516116216624-53e697fedbea?w=1200"
---
## ابدأ من HTML
HTML هو أساس كل موقع.
## ثم CSS
CSS هو ما يجعل الموقع جميلاً.
## بعدها JavaScript
JavaScript هو ما يجعل الموقع تفاعلياً.
```
## الخطوة 7: `app/layout.tsx`
```tsx
import type { Metadata } from "next";
import { Cairo } from "next/font/google";
import Header from "@/components/Header";
import Footer from "@/components/Footer";
import "./globals.css";
const cairo = Cairo({
subsets: ["arabic", "latin"],
weight: ["400", "600", "700", "900"],
variable: "--font-cairo",
});
export const metadata: Metadata = {
title: {
default: "مدونتي | NahdaAI",
template: "%s | مدونتي",
},
description: "مدونتي الشخصية — مقالات عن البرمجة والتقنية",
metadataBase: new URL("https://myblog.com"),
openGraph: {
type: "website",
locale: "ar_AR",
siteName: "مدونتي",
},
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="ar" dir="rtl" className={cairo.variable}>
<body className="font-cairo">
<Header />
<main className="min-h-screen">{children}</main>
<Footer />
</body>
</html>
);
}
```
## الخطوة 8: `components/Header.tsx`
```tsx
import Link from "next/link";
import { getAllCategories } from "@/lib/posts";
export default function Header() {
const categories = getAllCategories();
return (
<header className="bg-white dark:bg-gray-800 shadow-sm sticky top-0 z-50">
<div className="max-w-6xl mx-auto px-4 py-4 flex items-center justify-between">
<Link href="/" className="text-2xl font-bold text-blue-600">
📝 مدونتي
</Link>
<nav className="hidden md:flex gap-6">
<Link href="/" className="text-gray-700 dark:text-gray-300 hover:text-blue-600">
الرئيسية
</Link>
<Link href="/blog" className="text-gray-700 dark:text-gray-300 hover:text-blue-600">
المقالات
</Link>
{categories.slice(0, 3).map((cat) => (
<Link
key={cat}
href={`/categories/${encodeURIComponent(cat)}`}
className="text-gray-700 dark:text-gray-300 hover:text-blue-600"
>
{cat}
</Link>
))}
<Link href="/about" className="text-gray-700 dark:text-gray-300 hover:text-blue-600">
من نحن
</Link>
</nav>
</div>
</header>
);
}
```
## الخطوة 9: `components/Footer.tsx`
```tsx
export default function Footer() {
return (
<footer className="bg-gray-900 text-white py-8 mt-16">
<div className="max-w-6xl mx-auto px-4 text-center">
<p className="mb-4">© 2026 مدونتي — جميع الحقوق محفوظة</p>
<div className="flex justify-center gap-4">
<a href="https://twitter.com" className="hover:text-blue-400 transition">
🐦 تويتر
</a>
<a href="https://github.com" className="hover:text-blue-400 transition">
💻 GitHub
</a>
</div>
</div>
</footer>
);
}
```
## الخطوة 10: `components/PostCard.tsx`
```tsx
import Link from "next/link";
import Image from "next/image";
import { Post, formatDate, getReadingTime } from "@/lib/posts";
export default function PostCard({ post }: { post: Post }) {
return (
<article className="bg-white dark:bg-gray-800 rounded-2xl overflow-hidden shadow-sm hover:shadow-lg transition group">
{post.coverImage && (
<Link href={`/blog/${post.slug}`}>
<div className="relative h-48 overflow-hidden">
<Image
src={post.coverImage}
alt={post.title}
fill
className="object-cover group-hover:scale-105 transition duration-300"
/>
</div>
</Link>
)}
<div className="p-6">
<div className="flex items-center gap-3 mb-3">
<Link
href={`/categories/${encodeURIComponent(post.category)}`}
className="bg-blue-100 dark:bg-blue-900 text-blue-700 dark:text-blue-300 text-xs px-3 py-1 rounded-full"
>
{post.category}
</Link>
<span className="text-gray-500 text-xs">
⏱ {getReadingTime(post.content)} دقائق
</span>
</div>
<Link href={`/blog/${post.slug}`}>
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-2 hover:text-blue-600 transition">
{post.title}
</h3>
</Link>
<p className="text-gray-600 dark:text-gray-400 text-sm mb-4 line-clamp-2">
{post.excerpt}
</p>
<div className="flex items-center justify-between text-xs text-gray-500">
<span>{formatDate(post.date)}</span>
<Link
href={`/blog/${post.slug}`}
className="text-blue-600 hover:underline font-medium"
>
اقرأ المزيد ←
</Link>
</div>
</div>
</article>
);
}
```
## الخطوة 11: `app/page.tsx`
```tsx
import Link from "next/link";
import { getAllPosts } from "@/lib/posts";
import PostCard from "@/components/PostCard";
export default function HomePage() {
const posts = getAllPosts();
const featuredPosts = posts.slice(0, 3);
return (
<>
{/* Hero */}
<section className="bg-gradient-to-br from-blue-600 to-purple-700 text-white py-20">
<div className="max-w-4xl mx-auto px-4 text-center">
<h1 className="text-5xl font-bold mb-4">مدونتي</h1>
<p className="text-xl opacity-90 mb-8">
مقالات عن البرمجة والتقنية — بالعربية
</p>
<Link
href="/blog"
className="inline-block bg-white text-blue-600 px-8 py-3 rounded-lg font-bold hover:bg-gray-100 transition"
>
تصفح المقالات →
</Link>
</div>
</section>
{/* المقالات المميزة */}
<section className="max-w-6xl mx-auto px-4 py-16">
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-8">
📚 أحدث المقالات
</h2>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
{featuredPosts.map((post) => (
<PostCard key={post.slug} post={post} />
))}
</div>
<div className="text-center mt-12">
<Link
href="/blog"
className="inline-block bg-blue-600 text-white px-8 py-3 rounded-lg font-bold hover:bg-blue-700 transition"
>
عرض جميع المقالات ←
</Link>
</div>
</section>
</>
);
}
```
## الخطوة 12: `app/blog/page.tsx`
```tsx
import { getAllPosts } from "@/lib/posts";
import PostCard from "@/components/PostCard";
export const metadata = {
title: "المقالات",
description: "جميع مقالات المدونة",
};
export default function BlogPage() {
const posts = getAllPosts();
return (
<div className="max-w-6xl mx-auto px-4 py-12">
<h1 className="text-4xl font-bold text-gray-900 dark:text-white mb-8">
📚 جميع المقالات
</h1>
<p className="text-gray-600 dark:text-gray-400 mb-8">
{posts.length} مقال
</p>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
{posts.map((post) => (
<PostCard key={post.slug} post={post} />
))}
</div>
</div>
);
}
```
## الخطوة 13: `app/blog/[slug]/page.tsx`
```tsx
import { notFound } from "next/navigation";
import Link from "next/link";
import Image from "next/image";
import {
getPostBySlug,
getAllPosts,
markdownToHtml,
formatDate,
getReadingTime,
getRelatedPosts,
} from "@/lib/posts";
import PostCard from "@/components/PostCard";
import ShareButtons from "@/components/ShareButtons";
export async function generateStaticParams() {
const posts = getAllPosts();
return posts.map((post) => ({ slug: post.slug }));
}
export async function generateMetadata({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
const post = getPostBySlug(slug);
if (!post) return {};
return {
title: post.title,
description: post.excerpt,
openGraph: {
title: post.title,
description: post.excerpt,
type: "article",
images: post.coverImage ? [post.coverImage] : [],
},
};
}
export default async function PostPage({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
const post = getPostBySlug(slug);
if (!post) notFound();
const htmlContent = await markdownToHtml(post.content);
const relatedPosts = getRelatedPosts(slug);
return (
<article className="max-w-4xl mx-auto px-4 py-12">
<Link
href="/blog"
className="text-blue-600 hover:underline mb-6 inline-block"
>
← العودة للمقالات
</Link>
{post.coverImage && (
<div className="relative h-96 rounded-2xl overflow-hidden mb-8">
<Image
src={post.coverImage}
alt={post.title}
fill
className="object-cover"
priority
/>
</div>
)}
<div className="flex items-center gap-3 mb-4">
<Link
href={`/categories/${encodeURIComponent(post.category)}`}
className="bg-blue-100 dark:bg-blue-900 text-blue-700 dark:text-blue-300 text-sm px-3 py-1 rounded-full"
>
{post.category}
</Link>
<span className="text-gray-500 text-sm">
📅 {formatDate(post.date)}
</span>
<span className="text-gray-500 text-sm">
⏱ {getReadingTime(post.content)} دقائق
</span>
</div>
<h1 className="text-4xl font-bold text-gray-900 dark:text-white mb-4">
{post.title}
</h1>
<p className="text-xl text-gray-600 dark:text-gray-400 mb-8">
{post.excerpt}
</p>
<ShareButtons
title={post.title}
url={`https://myblog.com/blog/${post.slug}`}
/>
<div
className="prose prose-lg dark:prose-invert max-w-none mt-8"
dangerouslySetInnerHTML={{ __html: htmlContent }}
/>
{post.tags.length > 0 && (
<div className="flex gap-2 mt-8">
{post.tags.map((tag) => (
<span
key={tag}
className="bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-300 text-sm px-3 py-1 rounded-full"
>
#{tag}
</span>
))}
</div>
)}
{relatedPosts.length > 0 && (
<section className="mt-16 pt-8 border-t">
<h2 className="text-2xl font-bold mb-6">📚 مقالات ذات صلة</h2>
<div className="grid md:grid-cols-3 gap-6">
{relatedPosts.map((p) => (
<PostCard key={p.slug} post={p} />
))}
</div>
</section>
)}
</article>
);
}
```
## الخطوة 14: `components/ShareButtons.tsx`
```tsx
"use client";
interface ShareButtonsProps {
title: string;
url: string;
}
export default function ShareButtons({ title, url }: ShareButtonsProps) {
const encodedTitle = encodeURIComponent(title);
const encodedUrl = encodeURIComponent(url);
return (
<div className="flex gap-2">
<a
href={`https://twitter.com/intent/tweet?text=${encodedTitle}&url=${encodedUrl}`}
target="_blank"
rel="noopener noreferrer"
className="bg-black text-white px-4 py-2 rounded-lg text-sm hover:bg-gray-800 transition"
>
🐦 تويتر
</a>
<a
href={`https://www.linkedin.com/sharing/share-offsite/?url=${encodedUrl}`}
target="_blank"
rel="noopener noreferrer"
className="bg-blue-700 text-white px-4 py-2 rounded-lg text-sm hover:bg-blue-800 transition"
>
💼 LinkedIn
</a>
<a
href={`https://wa.me/?text=${encodedTitle} - ${encodedUrl}`}
target="_blank"
rel="noopener noreferrer"
className="bg-green-600 text-white px-4 py-2 rounded-lg text-sm hover:bg-green-700 transition"
>
📱 WhatsApp
</a>
</div>
);
}
```
## الخطوة 15: `app/categories/[category]/page.tsx`
```tsx
import { notFound } from "next/navigation";
import { getAllCategories, getPostsByCategory } from "@/lib/posts";
import PostCard from "@/components/PostCard";
export function generateStaticParams() {
const categories = getAllCategories();
return categories.map((category) => ({
category: encodeURIComponent(category),
}));
}
export default async function CategoryPage({
params,
}: {
params: Promise<{ category: string }>;
}) {
const { category } = await params;
const decoded = decodeURIComponent(category);
const posts = getPostsByCategory(decoded);
if (posts.length === 0) notFound();
return (
<div className="max-w-6xl mx-auto px-4 py-12">
<h1 className="text-4xl font-bold mb-4">📁 تصنيف: {decoded}</h1>
<p className="text-gray-600 dark:text-gray-400 mb-8">
{posts.length} مقال
</p>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
{posts.map((post) => (
<PostCard key={post.slug} post={post} />
))}
</div>
</div>
);
}
```
## الخطوة 16: `app/about/page.tsx`
```tsx
export const metadata = {
title: "من نحن",
};
export default function AboutPage() {
return (
<div className="max-w-2xl mx-auto px-4 py-16">
<h1 className="text-4xl font-bold mb-6">من نحن</h1>
<p className="text-lg text-gray-700 dark:text-gray-300 leading-relaxed mb-4">
مرحباً بك في مدونتي! أنا مطور ويب، أشارك هنا مقالاتي عن البرمجة والتقنية.
</p>
<p className="text-lg text-gray-700 dark:text-gray-300 leading-relaxed">
تهدف هذه المدونة إلى نشر المعرفة التقنية بالعربية.
</p>
</div>
);
}
```
## الخطوة 17: `app/sitemap.ts`
```typescript
import { getAllPosts } from "@/lib/posts";
import { MetadataRoute } from "next";
export default function sitemap(): MetadataRoute.Sitemap {
const posts = getAllPosts();
const baseUrl = "https://myblog.com";
const postUrls = posts.map((post) => ({
url: `${baseUrl}/blog/${post.slug}`,
lastModified: new Date(post.date),
changeFrequency: "monthly" as const,
priority: 0.8,
}));
return [
{ url: baseUrl, priority: 1 },
{ url: `${baseUrl}/blog`, priority: 0.9 },
{ url: `${baseUrl}/about`, priority: 0.5 },
...postUrls,
];
}
```
## الخطوة 18: تشغيل المشروع
```bash
npm run dev
```
افتح: `http://localhost:3000`
**🎉 مبروك! لديك مدونة احترافية كاملة!**
## تمارين إضافية
### تمرين 1: بحث
أضف ميزة البحث في المقالات.
**الحل:**
```tsx
"use client";
import { useState } from "react";
export default function SearchBar({ posts }: { posts: any[] }) {
const [query, setQuery] = useState("");
const filtered = posts.filter((p) =>
p.title.toLowerCase().includes(query.toLowerCase())
);
return (
<div>
<input
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="ابحث..."
className="w-full px-4 py-3 border rounded-lg"
/>
<ul>
{filtered.map((p) => (
<li key={p.slug}>{p.title}</li>
))}
</ul>
</div>
);
}
```
### تمرين 2: جدول المحتويات
أضف TOC (Table of Contents).
### تمرين 3: الوضع الداكن
أضف زر تبديل الوضع الداكن.
### تمرين 4: نشرة بريدية
أضف نموذج الاشتراك.
### تمرين 5: تعليقات
أضف نظام تعليقات (Disqus أو Giscus).
### تمرين 6: RSS Feed
أضف `/feed.xml` للمشتركين.
### تمرين 7: البحث المتقدم
أضف بحثاً في المحتوى أيضاً.
### تمرين 8: النشر
انشر المدونة على Vercel.
## قائمة تحقق نهائية
<table>
<thead>
<tr>
<th>المهمة</th>
<th>الحالة</th>
</tr>
</thead>
<tbody>
<tr>
<td>إنشاء المشروع</td>
<td>⬜</td>
</tr>
<tr>
<td>إعداد Markdown</td>
<td>⬜</td>
</tr>
<tr>
<td>قراءة المقالات</td>
<td>⬜</td>
</tr>
<tr>
<td>الصفحة الرئيسية</td>
<td>⬜</td>
</tr>
<tr>
<td>قائمة المقالات</td>
<td>⬜</td>
</tr>
<tr>
<td>صفحة المقال الفردي</td>
<td>⬜</td>
</tr>
<tr>
<td>SEO و Sitemap</td>
<td>⬜</td>
</tr>
<tr>
<td>النشر</td>
<td>⬜</td>
</tr>
</tbody>
</table>
## 🎉 مبروك! أكملت مسار Next.js!
لقد وصلت إلى نهاية المسار. أنت الآن تعرف:
- ✅ **أساسيات Next.js:** App Router، Pages، Layouts.
- ✅ **Server Components:** Server vs Client.
- ✅ **Data Fetching:** fetch, cache, Server Actions.
- ✅ **API Routes.**
- ✅ **Styling:** Tailwind CSS.
- ✅ **Authentication:** NextAuth.
- ✅ **Deployment:** Vercel, Firebase.
- ✅ **مشروع متكامل.**
## ماذا بعد Next.js؟
الآن أنت جاهز لـ:
1. **بناء مشاريع حقيقية** — ابدأ ببناء مشاريعك.
2. **GraphQL** — بديل REST.
3. **tRPC** — Type-safe APIs.
4. **Prisma** — ORM حديث.
5. **Stripe** — الدفع الإلكتروني.
6. **بناء معرض أعمالك.**
## الخلاصة
في هذا المشروع، بنيت:
- ✅ **مدونة احترافية كاملة.**
- ✅ **Markdown للمحتوى.**
- ✅ **SEO محسّن.**
- ✅ **تصنيفات وبحث.**
- ✅ **مقالات ذات صلة.**
- ✅ **مشاركة اجتماعية.**
- ✅ **نشر سهل.**
**هذا المشروع هو أساس كل تطبيقات Next.js الاحترافية.** احتفظ بالكود، وطور فيه بنفسك!