📋 Table of Contents
ما نبنيه
تطبيق متكامل لإدارة المهام: Next.js 15 App Router، وPostgreSQL عبر Neon (بدون خادم)، وPrisma ORM، وServer Actions (لا توجد مسارات منفصلة لواجهة برمجة التطبيقات للطفرات)، وAuth.js v5 GitHub OAuth، تم نشره في Vercel.
إعداد المشروع
npx create-next-app@latest taskapp \
--typescript --tailwind --eslint --app --src-dir --import-alias "@/*"
cd taskapp
قاعدة البيانات: PostgreSQL مع Neon + Prisma
أنشئ قاعدة بيانات مجانية علىنيون.تك. ثم :
npm install prisma @prisma/client
npx prisma init
في.env.local:
DATABASE_URL="postgresql://user:pass@ep-xxx.us-east-2.aws.neon.tech/neondb?sslmode=require"
NEXTAUTH_SECRET="your-random-secret-here"
GITHUB_CLIENT_ID="your-github-oauth-app-id"
GITHUB_CLIENT_SECRET="your-github-oauth-app-secret"
نماذج البيانات
// prisma/schema.prisma
model User {
id String @id @default(cuid())
email String @unique
name String?
createdAt DateTime @default(now())
tasks Task[]
}
model Task {
id String @id @default(cuid())
title String
status TaskStatus @default(PENDING)
priority Priority @default(MEDIUM)
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([userId])
}
enum TaskStatus { PENDING IN_PROGRESS COMPLETED CANCELLED }
enum Priority { LOW MEDIUM HIGH URGENT }
npx prisma migrate dev --name init
npx prisma generate
// src/lib/db.ts
import { PrismaClient } from '@prisma/client';
const globalForPrisma = globalThis as unknown as { prisma: PrismaClient };
export const db = globalForPrisma.prisma ?? new PrismaClient();
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = db;
مكونات الخادم وجلب البيانات
مكونات جهاز توجيه التطبيق هي مكونات الخادم بشكل افتراضي – فهي تعمل على الخادم ويمكنها الاستعلام مباشرة عن قاعدة البيانات:
// src/app/dashboard/page.tsx (Server Component)
import { db } from '@/lib/db';
import { auth } from '@/lib/auth';
import { redirect } from 'next/navigation';
export default async function DashboardPage() {
const session = await auth();
if (!session?.user) redirect('/');
const tasks = await db.task.findMany({
where: { userId: session.user.id, status: { not: 'CANCELLED' } },
orderBy: [{ priority: 'desc' }, { createdAt: 'desc' }],
take: 50,
});
return (
<main className="container mx-auto p-6">
<h1>My Tasks</h1>
{tasks.map(task => <TaskCard key={task.id} task={task} />)}
</main>
);
}
لا حاجة إلى مسار API. لا يوجد تأثير الاستخدام. لا توجد حالة تحميل نموذجية. يقوم المكون بجلب وعرض في طلقة واحدة.
إجراءات الخادم للطفرات
تحل إجراءات الخادم محل مسارات واجهة برمجة التطبيقات لعمليات إرسال النماذج والطفرات:
// src/actions/tasks.ts
'use server';
import { db } from '@/lib/db';
import { auth } from '@/lib/auth';
import { revalidatePath } from 'next/cache';
import { z } from 'zod';
const Schema = z.object({
title: z.string().min(1).max(200),
priority: z.enum(['LOW','MEDIUM','HIGH','URGENT']).default('MEDIUM'),
});
export async function createTask(formData: FormData) {
const session = await auth();
if (!session?.user?.id) throw new Error('Unauthorized');
const parsed = Schema.safeParse({
title: formData.get('title'),
priority: formData.get('priority') || 'MEDIUM',
});
if (!parsed.success) return { error: parsed.error.flatten().fieldErrors };
await db.task.create({ data: { ...parsed.data, userId: session.user.id } });
revalidatePath('/dashboard');
return { success: true };
}
|||| يؤدي الاستدعاء إلى إبطال ذاكرة التخزين المؤقت لـ Next.js لهذا المسار، مما يؤدي إلى عرض خادم جديد ببيانات جديدة.revalidatePathالمصادقة باستخدام Auth.js v5
📋 نسخ
npm install next-auth@beta @auth/prisma-adapter
// src/lib/auth.ts
import NextAuth from 'next-auth';
import GitHub from 'next-auth/providers/github';
import { PrismaAdapter } from '@auth/prisma-adapter';
import { db } from './db';
export const { auth, handlers, signIn, signOut } = NextAuth({
adapter: PrismaAdapter(db),
providers: [GitHub({ clientId: process.env.GITHUB_CLIENT_ID!, clientSecret: process.env.GITHUB_CLIENT_SECRET! })],
session: { strategy: 'database' },
callbacks: { session: ({ session, user }) => ({ ...session, user: { ...session.user, id: user.id } }) }
});
→ تصديرsrc/app/api/auth/[...nextauth]/route.ts.handlers as GET, handlers as POSTالنشر إلى Vercel
📋 نسخ
# Install Vercel CLI and deploy
npm install -g vercel
vercel
# Set environment variables
vercel env add DATABASE_URL
vercel env add NEXTAUTH_SECRET
vercel env add GITHUB_CLIENT_ID
vercel env add GITHUB_CLIENT_SECRET
vercel --prod
، ثم قم بتشغيلhttps://your-app.vercel.app/api/auth/callback/github.npx prisma migrate deployقائمة مرجعية الإنتاج
تحديد المعدل
- — Upstash Ratelimit على إجراءات الخادم ومسارات واجهة برمجة التطبيقاتحدود الخطأ
- – إضافةملفات احتياطية رشيقة
error.tsxجارٍ تحميل الحالات - – إضافةللتشويق الهياكل العظمية
loading.tsxالتحقق من صحة الإدخال - – استخدم Zod دائمًا في إجراءات الخادمتجمع الاتصالات
- – إضافةإلى عنوان URL للنيون
?pgbouncer=true&connection_limit=1رؤوس الأمان - – إضافة عبرالرؤوس ()
next.config.ts🔧 جاهز للشحن؟
Next.js 15 + PostgreSQL هو المكدس الكامل المهيمن في عام 2026. استكشاف
لماذا يعد TypeScript ضروريًالتطبيقات Next.js الأكبر حجمًا والرئيسيةأنماط غير متزامنة/منتظرةلمكونات الخادم والإجراءات.الأسئلة المتداولة
ما هو Next.js 15؟
أحدث Next.js: Turbopack مستقر (5× أسرع)، React 19 مطلوب، واجهات برمجة التطبيقات لطلب غير متزامن، إجراءات الخادم المحسنة. جهاز توجيه التطبيقات هو المعيار للمضي قدمًا.
جهاز توجيه التطبيق أو جهاز توجيه الصفحات في عام 2026؟
جهاز توجيه التطبيقات لجميع المشاريع الجديدة. يعمل جهاز توجيه الصفحات ولكنه لا يحصل على ميزات جديدة.
ما هي قاعدة البيانات التي يجب استخدامها مع Next.js؟
PostgreSQL عبر Neon (بدون خادم) + Prisma أو Drizzle ORM. Supabase إذا كنت بحاجة إلى مصادقة مضمنة وفي الوقت الفعلي.
ما هي إجراءات الخادم؟
يتم استدعاء وظائف الخادم غير المتزامن (التي تحمل علامة “استخدام الخادم”) من React. استبدال مسارات API للطفرات. نوع آمن، ويدعم التحديثات المتفائلة.
كيفية النشر؟
Vercel (تكوين صفري، تم إجراؤه بواسطة فريق Next.js). المضيف الذاتي: البناء التالي + البداية التالية خلف nginx أو Docker.
Vercel (zero config, made by Next.js team). Self-host: next build + next start behind nginx, or Docker.
🔗 Share this article
✍️ Leave a Comment