بناء وظائف متينة وسير عمل مبني على الأحداث مع Inngest و Next.js

التطبيقات الحديثة مبنية على الأحداث — مستخدم يسجل حسابًا، دفعة تنجح، ملف يُرفع، نموذج ذكاء اصطناعي ينتهي من المعالجة. كل حدث يُطلق عملاً يجب أن يكون موثوقًا: إرسال بريد تأكيد، تحديث سجلات الفواتير، تغيير حجم الصور، أو بدء خط أنابيب متعدد الخطوات. لكن ربط كل هذا بنفسك مع قوائم الانتظار والعمال ومنطق إعادة المحاولة أمر مرهق.
Inngest يتبع نهجًا مختلفًا. بدلاً من إدارة البنية التحتية، تكتب وظائف متينة — وظائف TypeScript تنجو تلقائيًا من الأعطال وإعادات المحاولة ومهلات serverless. كل وظيفة تُشغَّل بواسطة أحداث وتتكون من خطوات تُنفَّذ مرة واحدة بالضبط، حتى لو انقطعت الوظيفة وأُعيد تنفيذها. لا قوائم انتظار لإدارتها، لا عمال للنشر، ولا خوادم Redis للمراقبة.
في هذا الدليل، ستبني خط أنابيب إعداد العملاء والفوترة لتطبيق SaaS — عندما يسجل مستخدم، ينسق Inngest سير عمل متعدد الخطوات يُعد حسابه ويرسل بريد ترحيب ويبدأ مؤقت الفترة التجريبية ويتعامل مع أحداث الفوترة اللاحقة. ستتعلم الخطوات المتينة وأنماط التوزيع وتنسيق الأحداث والوظائف المجدولة والتحكم في التدفق.
المتطلبات الأساسية
قبل البدء، تأكد من توفر:
- Node.js 20+ مثبت
- معرفة أساسية بـ React و TypeScript
- إلمام بـ Next.js App Router (مسارات API، Server Actions)
- محرر أكواد (يُنصح بـ VS Code)
لا تحتاج حساب Inngest للتطوير المحلي — خادم Inngest التطويري يعمل بالكامل على جهازك.
ما ستبنيه
خط أنابيب إعداد العملاء والفوترة لتطبيق SaaS يتضمن:
- وظيفة إعداد الحساب — تنشئ سجلات قاعدة البيانات وتُعد الإعدادات الافتراضية عند تسجيل المستخدم
- وظيفة بريد الترحيب — ترسل بريد إعداد منسق مع منطق إعادة المحاولة
- سير عمل إدارة الفترة التجريبية — يبدأ فترة تجريبية لمدة 14 يومًا ويرسل تذكيرات في اليوم 7 واليوم 13
- نمط التوزيع — يُشغل وظائف مستقلة متعددة من حدث واحد
- تنسيق الأحداث — ينتظر حدث
billing/subscription.createdقبل المتابعة - وظيفة مجدولة — تقرير يومي عن مخاطر فقدان العملاء للفريق
- التحكم في التدفق والتزامن — يمنع إغراق واجهات برمجة التطبيقات الخارجية
- مراقبة محلية كاملة — تتبع كل خطوة في لوحة خادم Inngest التطويري
الخطوة 1: إنشاء مشروع Next.js
أنشئ مشروع Next.js 15 جديد:
npx create-next-app@latest inngest-saas --typescript --tailwind --eslint --app --src-dir --use-npm
cd inngest-saasثبّت Inngest:
npm install inngestهذا هو التبعية الوحيدة التي تحتاجها. Inngest ليس له تبعيات نظيرة ويعمل مع أي بيئة تشغيل Node.js.
الخطوة 2: تهيئة عميل Inngest
أنشئ عميل Inngest المشترك الذي ستستخدمه جميع وظائفك.
// src/inngest/client.ts
import { Inngest } from "inngest";
export const inngest = new Inngest({
id: "inngest-saas",
});معرّف id يحدد تطبيقك. في بيئة الإنتاج، تظهر جميع الوظائف المسجلة تحت هذا المعرّف معًا في لوحة Inngest.
يمكنك أيضًا تعريف أنواع الأحداث للحصول على أمان كامل للأنواع:
// src/inngest/client.ts
import { Inngest } from "inngest";
type Events = {
"user/signup.completed": {
data: {
userId: string;
email: string;
name: string;
plan: "free" | "pro" | "enterprise";
};
};
"billing/subscription.created": {
data: {
userId: string;
subscriptionId: string;
plan: "pro" | "enterprise";
};
};
"user/trial.started": {
data: {
userId: string;
trialEndDate: string;
};
};
};
export const inngest = new Inngest({
id: "inngest-saas",
schemas: new EventSchemas().fromRecord<Events>(),
});مع هذا الإعداد، كل استدعاء inngest.send() وكل مشغل وظيفة مكتوب بالكامل — تحصل على إكمال تلقائي لأسماء الأحداث وفحوصات وقت التجميع على الحمولات.
الخطوة 3: إنشاء مسار API
يعمل Inngest بتسجيل نقطة نهاية HTTP واحدة في تطبيقك. خادم Inngest التطويري (والخدمة السحابية في الإنتاج) يستدعي هذه النقطة لتنفيذ وظائفك.
// src/app/api/inngest/route.ts
import { serve } from "inngest/next";
import { inngest } from "@/inngest/client";
import { provisionAccount } from "@/inngest/functions/provision-account";
import { sendWelcomeEmail } from "@/inngest/functions/send-welcome-email";
import { manageTrialWorkflow } from "@/inngest/functions/manage-trial";
import { dailyChurnReport } from "@/inngest/functions/daily-churn-report";
export const { GET, POST, PUT } = serve({
client: inngest,
functions: [
provisionAccount,
sendWelcomeEmail,
manageTrialWorkflow,
dailyChurnReport,
],
});كل وظيفة تكتبها يتم استيرادها هنا وتمريرها إلى serve(). Inngest يتعامل مع التوجيه والاستدعاء وإعادة المحاولة من خلال هذه النقطة الواحدة.
الخطوة 4: بناء وظيفة إعداد الحساب
أول وظيفة متينة لك. عندما يسجل مستخدم، تنشئ هذه الوظيفة سجلات قاعدة البيانات وتُعد مساحة العمل.
// src/inngest/functions/provision-account.ts
import { inngest } from "@/inngest/client";
export const provisionAccount = inngest.createFunction(
{
id: "provision-account",
retries: 3,
},
{ event: "user/signup.completed" },
async ({ event, step }) => {
// الخطوة 1: إنشاء سجل المستخدم في قاعدة البيانات
const user = await step.run("create-user-record", async () => {
console.log(`Creating user record for ${event.data.email}`);
return {
id: event.data.userId,
email: event.data.email,
name: event.data.name,
plan: event.data.plan,
createdAt: new Date().toISOString(),
};
});
// الخطوة 2: إنشاء مساحة عمل افتراضية
const workspace = await step.run("create-workspace", async () => {
console.log(`Creating workspace for user ${user.id}`);
return {
workspaceId: `ws_${user.id}`,
name: `${user.name}'s Workspace`,
};
});
// الخطوة 3: زرع الإعدادات الافتراضية
await step.run("seed-defaults", async () => {
console.log(`Seeding defaults for workspace ${workspace.workspaceId}`);
return { seeded: true };
});
// الخطوة 4: إرسال حدث بدء الفترة التجريبية
await step.sendEvent("start-trial", {
name: "user/trial.started",
data: {
userId: user.id,
trialEndDate: new Date(
Date.now() + 14 * 24 * 60 * 60 * 1000
).toISOString(),
},
});
return { user, workspace, status: "provisioned" };
}
);لماذا الخطوات مهمة
كل استدعاء step.run() هو نقطة حفظ. إذا تعطلت الوظيفة بعد الخطوة 2، سيعيد Inngest استدعاءها، لكن الخطوتين 1 و 2 لن تُعاد تنفيذهما — نتائجهما محفوظة. هذا ما يجعل الوظيفة متينة. تحصل على دلالات التنفيذ مرة واحدة بالضبط لكل خطوة بدون بنية تحتية إضافية.
خصائص الخطوات الرئيسية:
- محفوظة — بمجرد اكتمال الخطوة، تُخزن قيمتها المرجعة وتُعاد استخدامها عند إعادة المحاولة
- قابلة لإعادة المحاولة فرديًا — إذا فشلت الخطوة 3، تُعاد محاولة الخطوة 3 فقط
- قابلة للتسلسل — يجب أن تكون نتائج الخطوات قابلة للتحويل إلى JSON
الخطوة 5: بناء وظيفة بريد الترحيب
هذه الوظيفة تُشغَّل أيضًا عند user/signup.completed — نمط التوزيع في Inngest يعني أن وظائف متعددة يمكنها الاستماع لنفس الحدث.
// src/inngest/functions/send-welcome-email.ts
import { inngest } from "@/inngest/client";
export const sendWelcomeEmail = inngest.createFunction(
{
id: "send-welcome-email",
retries: 5,
throttle: {
limit: 10,
period: "1m",
},
},
{ event: "user/signup.completed" },
async ({ event, step }) => {
// الخطوة 1: تقديم قالب البريد
const emailHtml = await step.run("render-template", async () => {
return renderWelcomeTemplate({
name: event.data.name,
plan: event.data.plan,
});
});
// الخطوة 2: الإرسال عبر مزود البريد
const result = await step.run("send-email", async () => {
console.log(`Sending welcome email to ${event.data.email}`);
return {
messageId: `msg_${Date.now()}`,
to: event.data.email,
status: "sent",
};
});
// الخطوة 3: تسجيل حدث تحليلي
await step.run("track-analytics", async () => {
console.log(`Tracking welcome email sent for ${event.data.userId}`);
});
return result;
}
);
function renderWelcomeTemplate(data: { name: string; plan: string }) {
return `
<h1>مرحبًا بك في تطبيق SaaS، ${data.name}!</h1>
<p>أنت على خطة <strong>${data.plan}</strong>.</p>
<p>فترتك التجريبية لمدة 14 يومًا تبدأ الآن. استكشف جميع الميزات!</p>
`;
}التحكم في التدفق
تكوين throttle يحد هذه الوظيفة بـ 10 عمليات تنفيذ في الدقيقة. هذا أمر حيوي عند إرسال رسائل البريد الإلكتروني — لا تريد إغراق واجهة برمجة تطبيقات مزود البريد أو تشغيل حدود المعدل أثناء ذروة حركة المرور.
الخطوة 6: بناء سير عمل إدارة الفترة التجريبية
هنا يتألق Inngest حقًا — سير عمل طويل الأمد يمتد لأيام.
// src/inngest/functions/manage-trial.ts
import { inngest } from "@/inngest/client";
export const manageTrialWorkflow = inngest.createFunction(
{
id: "manage-trial-workflow",
retries: 3,
cancelOn: [
{
event: "billing/subscription.created",
match: "data.userId",
},
],
},
{ event: "user/trial.started" },
async ({ event, step }) => {
const userId = event.data.userId;
const trialEndDate = new Date(event.data.trialEndDate);
// الخطوة 1: الانتظار 7 أيام ثم إرسال بريد منتصف الفترة التجريبية
await step.sleep("wait-for-day-7", "7 days");
await step.run("send-mid-trial-email", async () => {
console.log(`Sending mid-trial reminder to user ${userId}`);
return { sent: true, type: "mid-trial" };
});
// الخطوة 2: الانتظار حتى اليوم 13 (6 أيام إضافية)
await step.sleep("wait-for-day-13", "6 days");
await step.run("send-trial-ending-email", async () => {
console.log(`Sending trial-ending warning to user ${userId}`);
return { sent: true, type: "trial-ending" };
});
// الخطوة 3: الانتظار لليوم الأخير
await step.sleep("wait-for-trial-end", "1 day");
// الخطوة 4: التحقق مما إذا كان المستخدم قد تحول
const hasSubscription = await step.run("check-subscription", async () => {
console.log(`Checking if user ${userId} has converted`);
return false;
});
if (!hasSubscription) {
// الخطوة 5: تخفيض الرتبة إلى الخطة المجانية
await step.run("downgrade-to-free", async () => {
console.log(`Downgrading user ${userId} to free plan`);
return { plan: "free" };
});
await step.run("send-downgrade-email", async () => {
console.log(`Sending downgrade notification to user ${userId}`);
return { sent: true, type: "downgraded" };
});
}
return { userId, converted: hasSubscription };
}
);المفاهيم الرئيسية هنا
step.sleep() — يوقف الوظيفة للمدة المحددة. الوظيفة لا تستهلك موارد حاسوبية أثناء النوم. Inngest يوقظها بعد الفترة ويستأنف من الخطوة التالية مع جميع نتائج الخطوات السابقة سليمة.
cancelOn — إذا وصل حدث billing/subscription.created بمعرّف userId مطابق، يلغي Inngest سير العمل تلقائيًا. المستخدم تحول — لا حاجة لإرسال رسائل نهاية الفترة التجريبية أو تخفيض رتبته.
هذه الوظيفة الواحدة تحل محل ما يتطلبه عادةً مهمة مجدولة وقائمة انتظار وآلة حالة وجدول قاعدة بيانات لتتبع حالة الفترة التجريبية.
الخطوة 7: بناء تقرير فقدان العملاء المجدول
يدعم Inngest الجدولة المبنية على cron للمهام المتكررة.
// src/inngest/functions/daily-churn-report.ts
import { inngest } from "@/inngest/client";
export const dailyChurnReport = inngest.createFunction(
{
id: "daily-churn-report",
},
{ cron: "0 9 * * *" }, // كل يوم في الساعة 9:00 صباحًا
async ({ step }) => {
// الخطوة 1: استعلام المستخدمين المعرضين للخطر
const atRiskUsers = await step.run("query-at-risk-users", async () => {
console.log("Querying users with trials ending in 3 days...");
return [
{ userId: "user_1", email: "alice@example.com", trialEndsIn: 2 },
{ userId: "user_2", email: "bob@example.com", trialEndsIn: 1 },
];
});
if (atRiskUsers.length === 0) {
return { report: "لا يوجد مستخدمون معرضون للخطر اليوم" };
}
// الخطوة 2: تجميع التقرير
const report = await step.run("compile-report", async () => {
return {
date: new Date().toISOString(),
atRiskCount: atRiskUsers.length,
users: atRiskUsers,
summary: `${atRiskUsers.length} مستخدمين معرضين لخطر فقدان العملاء`,
};
});
// الخطوة 3: الإرسال إلى Slack
await step.run("notify-team", async () => {
console.log(`Sending churn report to Slack: ${report.summary}`);
return { notified: true };
});
return report;
}
);مشغل cron يحل محل مشغل الحدث. هذه الوظيفة تعمل كل يوم في الساعة 9 صباحًا بغض النظر عن أي أحداث. الخطوات لا تزال توفر المتانة — إذا فشل إشعار Slack، تُعاد محاولة تلك الخطوة فقط.
الخطوة 8: إعداد خادم التطوير
شغّل خادم Inngest التطويري بجانب تطبيق Next.js:
npx inngest-cli@latest devفي نافذة طرفية منفصلة، شغّل تطبيق Next.js:
npm run devخادم التطوير يعمل على http://localhost:8288 ويكتشف وظائفك تلقائيًا باستدعاء نقطة /api/inngest. افتح لوحة خادم التطوير لرؤية جميع الوظائف المسجلة وإرسال أحداث اختبارية وتتبع التنفيذ خطوة بخطوة.
الخطوة 9: إطلاق الأحداث من تطبيقك
الآن اربط تدفق التسجيل بإرسال أحداث إلى Inngest.
// src/app/api/auth/signup/route.ts
import { NextResponse } from "next/server";
import { inngest } from "@/inngest/client";
export async function POST(request: Request) {
const body = await request.json();
const { email, name, plan } = body;
const userId = `user_${Date.now()}`;
// أرسل حدث التسجيل — Inngest يتعامل مع الباقي
await inngest.send({
name: "user/signup.completed",
data: {
userId,
email,
name,
plan: plan || "free",
},
});
return NextResponse.json({ userId, status: "created" });
}عندما يُطلق هذا الحدث، كلتا وظيفتي provisionAccount و sendWelcomeEmail تُنفذان بشكل متزامن — توزيع بدون أي تكوين. ثم ترسل وظيفة الإعداد user/trial.started، مما يُشغل manageTrialWorkflow. حدث واحد، ثلاث وظائف، خط أنابيب كامل.
الخطوة 10: تنسيق الأحداث مع step.waitForEvent()
أحيانًا تحتاج وظيفة للتوقف والانتظار لحدث خارجي قبل المتابعة. هذا هو تنسيق الأحداث — بديل قوي للاستطلاع.
// src/inngest/functions/onboarding-with-verification.ts
import { inngest } from "@/inngest/client";
export const onboardingWithVerification = inngest.createFunction(
{
id: "onboarding-with-verification",
},
{ event: "user/signup.completed" },
async ({ event, step }) => {
// الخطوة 1: إرسال بريد التحقق
await step.run("send-verification-email", async () => {
console.log(`Sending verification email to ${event.data.email}`);
return { sent: true };
});
// الخطوة 2: الانتظار حتى 24 ساعة لتحقق المستخدم
const verificationEvent = await step.waitForEvent(
"wait-for-email-verification",
{
event: "user/email.verified",
match: "data.userId",
timeout: "24h",
}
);
if (!verificationEvent) {
// انتهت المهلة — المستخدم لم يتحقق
await step.run("send-reminder", async () => {
console.log(`User ${event.data.userId} did not verify — sending reminder`);
return { reminded: true };
});
return { status: "unverified", reminded: true };
}
// المستخدم تحقق — متابعة الإعداد
await step.run("activate-full-access", async () => {
console.log(`User ${event.data.userId} verified — activating full access`);
return { activated: true };
});
return { status: "verified", activated: true };
}
);step.waitForEvent() يوقف الوظيفة حتى يصل حدث مطابق أو تنتهي المهلة. حقل match يضمن أنها تستأنف فقط عندما يتطابق userId في الحدث الوارد مع حدث التسجيل الأصلي.
الخطوة 11: التحكم في التزامن
عند معالجة الأحداث على نطاق واسع، غالبًا ما تحتاج لتقييد عدد عمليات التشغيل المتزامنة — مثلاً لاحترام حدود معدل واجهات برمجة التطبيقات.
// src/inngest/functions/sync-to-crm.ts
import { inngest } from "@/inngest/client";
export const syncToCRM = inngest.createFunction(
{
id: "sync-to-crm",
concurrency: {
limit: 5,
key: "event.data.crmProvider",
},
retries: 10,
backoff: {
type: "exponential",
minDelay: "1s",
maxDelay: "5m",
},
},
{ event: "user/signup.completed" },
async ({ event, step }) => {
await step.run("push-to-crm", async () => {
console.log(`Syncing user ${event.data.userId} to CRM`);
return { synced: true };
});
}
);تكوين concurrency يضمن تنفيذ 5 عمليات كحد أقصى في وقت واحد لكل مزود CRM. مع التراجع الأسي عند إعادة المحاولة، يتعامل هذا الإعداد مع حدود المعدل والأعطال العابرة بسلاسة.
الخطوة 12: اختبار وظائفك
وظائف Inngest هي مجرد TypeScript — يمكنك اختبارها بالوحدة عبر محاكاة أدوات الخطوة.
// src/inngest/functions/__tests__/provision-account.test.ts
import { describe, it, expect } from "vitest";
describe("provisionAccount", () => {
it("should create user and workspace", async () => {
const mockEvent = {
data: {
userId: "test_user_1",
email: "test@example.com",
name: "Test User",
plan: "free" as const,
},
};
const user = {
id: mockEvent.data.userId,
email: mockEvent.data.email,
name: mockEvent.data.name,
plan: mockEvent.data.plan,
createdAt: expect.any(String),
};
expect(user.email).toBe("test@example.com");
expect(user.plan).toBe("free");
});
});للاختبار التكاملي، يوفر خادم Inngest التطويري وضع اختبار حيث يمكنك إرسال أحداث والتحقق من مخرجات الوظائف برمجيًا.
الخطوة 13: النشر في بيئة الإنتاج
الخيار أ: Inngest Cloud (موصى به)
- أنشئ حسابًا على موقع Inngest
- احصل على مفتاح التوقيع ومفتاح الأحداث من لوحة التحكم
- أضف متغيرات البيئة:
# .env.production
INNGEST_SIGNING_KEY=signkey-prod-xxxxx
INNGEST_EVENT_KEY=eventkey-xxxxx- انشر تطبيق Next.js على Vercel أو Railway أو أي منصة
- سجّل عنوان URL لتطبيقك في لوحة Inngest
الخيار ب: استضافة ذاتية
Inngest مفتوح المصدر. يمكنك تشغيل خادم Inngest بنفسك:
docker run -p 8288:8288 inngest/inngest:latestعيّن متغير البيئة INNGEST_BASE_URL لتوجيه تطبيقك إلى مثيلك المستضاف ذاتيًا.
الخطوة 14: المراقبة وتصحيح الأخطاء
لوحة Inngest (السحابية وخادم التطوير) توفر:
- قائمة الوظائف — جميع الوظائف المسجلة مع مشغلاتها وتكوينها
- سجل التشغيل — كل تنفيذ مع أحداث الإدخال ومخرجات الخطوات والتوقيت
- تتبع الخطوات — جدول زمني مرئي لكل خطوة ضمن التشغيل
- تفاصيل الأخطاء — تتبع كامل للمكدس مع سجل إعادة المحاولة
- سجل الأحداث — كل حدث أُرسل إلى النظام مع تفاصيل الحمولة
مقارنة Inngest بالبدائل
| الميزة | Inngest | قائمة انتظار تقليدية (BullMQ) | مهام Cron |
|---|---|---|---|
| خطوات متينة | نعم | يدوي | لا |
| مبني على الأحداث | نعم | توجيه يدوي | لا |
| النوم لأيام | نعم (بدون تكلفة حوسبة) | يتطلب عاملاً مستمرًا | حلول مؤقتة |
| إعادة المحاولة مع تراجع | مدمج | تكوين يدوي | يدوي |
| التوزيع | تلقائي | توجيه يدوي | غير متاح |
| تطوير محلي | خادم تطوير بواجهة | يتطلب Redis | crontab |
| أمان الأنواع | TypeScript كامل | جزئي | لا يوجد |
| المراقبة | لوحة مدمجة | أدوات خارجية | ملفات سجل |
استكشاف الأخطاء وإصلاحها
الوظائف لا تظهر في خادم التطوير
تأكد من أن تطبيق Next.js يعمل ومسار /api/inngest متاح. خادم التطوير يكتشف الوظائف باستدعاء GET /api/inngest. تحقق من أن جميع الوظائف مستوردة وممررة إلى serve().
الخطوات تُعاد تنفيذها بشكل غير متوقع
نتائج الخطوات محفوظة بواسطة معرّف الخطوة (المعامل الأول لـ step.run()). إذا غيرت معرّف الخطوة، يعاملها Inngest كخطوة جديدة. حافظ على ثبات معرّفات الخطوات عبر عمليات النشر.
النوم لا يستيقظ في التطوير
خادم Inngest التطويري يعالج فترات النوم بوقت مسرّع للاختبار. إذا بدا النوم عالقًا، تحقق من سجلات خادم التطوير.
الخطوات التالية
- إضافة middleware — يدعم Inngest وسيط الوظائف للتسجيل والمصادقة والإبلاغ عن الأخطاء
- المعالجة الدفعية — استخدم
step.run()في حلقة لمعالجة مصفوفات العناصر - التزامن متعدد المستأجرين — استخدم مفاتيح التزامن لعزل حدود المعدل لكل عميل
- ربط خدمات حقيقية — دمج Resend للبريد و Stripe للفوترة و PostHog للتحليلات
- سير عمل الذكاء الاصطناعي — Inngest شائع لتنسيق خطوط أنابيب الذكاء الاصطناعي متعددة الخطوات
الخلاصة
لقد بنيت خط أنابيب كامل مبني على الأحداث لتطبيق SaaS مع Inngest و Next.js. تطبيقك الآن يتعامل مع إعداد المستخدمين وإدارة الفترات التجريبية وإشعارات البريد ومزامنة CRM وتقارير فقدان العملاء — كل ذلك بتنفيذ متين وإعادة محاولة تلقائية وبدون إدارة بنية تحتية.
النقاط الرئيسية:
- الوظائف المتينة تنجو من الأعطال وإعادات المحاولة بدون إعادة تنفيذ الخطوات المكتملة
- التوزيع المبني على الأحداث يتيح لوظائف متعددة الاستجابة لنفس الحدث بشكل مستقل
step.sleep()يمكّن سير عمل طويل الأمد بدون استهلاك موارد حوسبةstep.waitForEvent()يحل محل الاستطلاع واستدعاءات webhook بتنسيق أحداث تصريحي- التزامن والتحكم في التدفق يحميان واجهات برمجة التطبيقات الخارجية من الإغراق
- خادم التطوير يمنحك مراقبة كاملة أثناء التطوير المحلي
ناقش مشروعك معنا
نحن هنا للمساعدة في احتياجات تطوير الويب الخاصة بك. حدد موعدًا لمناقشة مشروعك وكيف يمكننا مساعدتك.
دعنا نجد أفضل الحلول لاحتياجاتك.
مقالات ذات صلة

بناء مهام خلفية للإنتاج باستخدام Trigger.dev v3 و Next.js
تعلم كيفية بناء مهام خلفية موثوقة ومهام مجدولة وسير عمل متعدد الخطوات باستخدام Trigger.dev v3 مع Next.js. يغطي هذا الدرس إنشاء المهام ومعالجة الأخطاء وإعادة المحاولة والمهام المجدولة والنشر في بيئة الإنتاج.

Upstash Redis و Next.js: تحديد معدل الطلبات والتخزين المؤقت وقوائم الرسائل
تعلم كيفية دمج Upstash Redis في تطبيق Next.js لتطبيق تحديد معدل الطلبات والتخزين المؤقت من جانب الخادم وقوائم الرسائل. يغطي هذا الدليل الشامل الإعداد وأنماط الإنتاج والنشر بدون خادم.

بناء وكيل ذكاء اصطناعي مستقل باستخدام Agentic RAG و Next.js
تعلم كيف تبني وكيل ذكاء اصطناعي يقرر بشكل مستقل متى وكيف يسترجع المعلومات من قواعد البيانات المتجهية. دليل عملي شامل باستخدام Vercel AI SDK و Next.js مع أمثلة قابلة للتنفيذ.