تخطَّ إلى المحتوى
NerdLevelTech

بناء تطبيق فوري مع Supabase — قاعدة بيانات، مصادقة، وتحديثات مباشرة في ٣٠ دقيقة

ابنِ تطبيق todo تعاوني فوري مع Supabase و Next.js. يغطي قاعدة بيانات Postgres وRow Level Security والمصادقة والاشتراكات الفورية وEdge Functions. كل خطوة مُختبَرة مباشرةً على الطبقة المجانية من Supabase.

Nerd Level Techحُدّث في نماذج اللغة والتكاملEnglish

ما الذي ستبنيه

تطبيق todo تعاوني فوري مع Supabase و Next.js. يسجّل المستخدمون الدخول بالبريد الإلكتروني، وإنشاء todos، ورؤية التحديثات فوراً عبر جميع العملاء المتصلين — بدون polling، بدون WebSockets لإدارتها، بدون backend للنشر. Supabase يتولى قاعدة البيانات والمصادقة والاشتراكات الفورية. أنت تكتب الواجهة الأمامية.

ما ستتعلمه:

  • إنشاء مشروع Supabase وتكوينه في دقيقتين
  • تصميم جدول Postgres مع Row Level Security (RLS)
  • إضافة مصادقة بريد إلكتروني بAufruf واحد
  • الاشتراك في تغييرات قاعدة البيانات في الوقت الفعلي
  • تخزين الملفات مع Supabase Storage
  • نشر Edge Function بدون خادم
  • شحن إلى الإنتاج على Vercel

ما ستحتاجه:

  • حساب Supabase (مجاني، بدون بطاقة ائتمان)
  • Node.js 18+ و npm
  • محرر كود (VS Code مُوصى به)
  • ٣٠ دقيقة

نتائج حقيقية: كل كتلة كود في هذا الدليل تم اختبارها على مشروع Supabase حي. لقطات الشاشة تُظهر لوحة التحكم الفعلية.


المتطلبات المسبقة

قبل البدء، تأكد من:

  1. Node.js 18+ مثبت (node --version يجب أن يُظهر v18 أو أعلى)
  2. npm أو pnpm مثبت
  3. حساب Supabase — سجّل في supabase.com (مجاني، بدون بطاقة ائتمان)
  4. إلمام أساسي بـ React و TypeScript

تقدير الوقت: ٣٠ دقيقة للدليل كامل، بما في ذلك الإعداد.


الخطوة ١ — إنشاء مشروع Supabase

١٫١ التسجيل وإنشاء منظمة

لوحة تحكم Supabase — نظرة عامة على المشروع مع الحالة والمقاييس والحوسبة

انتقل إلى supabase.com/dashboard وسجّل بالبريد الإلكتروني أو GitHub. بعد تسجيل الدخول، سترى شاشة "New organization".

  • الاسم: اسم شركتك أو فريقك (مثلاً "My App Team")
  • النوع: اختر الأنسب (Personal, Educational, Startup, Agency, Company)
  • الخطة: ابدأ بـ Free ($0/month)

انقر Create organization.

١٫٢ إنشاء مشروع

Supabase — إنشاء مشروع جديد مع الاسم وكلمة المرور والمنطقة

بعد إنشاء المنظمة، انقر New project:

  • الاسم: ai-guide-demo (أو اسم تطبيقك)
  • كلمة مرور قاعدة البيانات: أنشئ كلمة مرور قوية واحفظها في مكان آمن — ستحتاجها للوصول المباشر إلى قاعدة البيانات
  • المنطقة: اختر المنطقة الأقرب لمستخدميك (مثلاً West EU (Ireland) للمستخدمين الأوروبيين)
  • الخطة: Free

انقر Create new project. يوفّر Supabase قاعدة بيانات Postgres مخصصة وخادم API وخدمة مصادقة. يستغرق ذلك حوالي دقيقتين.

١٫٣ الحصول على مفاتيح API

بمجرد أن يكون المشروع جاهزاً، انتقل إلى Project Settings → API:

  • Project URL: https://your-project-id.supabase.co
  • anon/public key: eyJhbG... (آمن للاستخدام في المتصفح)
  • service_role key: eyJhbG... (سرّي — جانب الخادم فقط، لا تكشفه للعملاء)

احفظ هذه — ستحتاجها لتطبيق Next.js.

ما الذي يمكن أن يخطئ

  • "Project creation failed" — عادةً مشكلة سعة المنطقة. جرّب منطقة مختلفة.
  • "Invalid password" — كلمة المرور يجب أن تكون ٨ أحرف على الأقل مع أحرف كبيرة وصغيرة وأرقام.
  • المشروع عالق على "Setting up" — انتظر ٣-٥ دقائق. إذا استمر، احذف وأعد الإنشاء.

الخطوة ٢ — تصميم قاعدة البيانات مع RLS

٢٫١ إنشاء جدول todos

محرر الجداول Supabase — إنشاء جدول جديد مع الأعمدة

انتقل إلى Table Editor → New table وأنشئ جدول todos:

العمودالنوعالافتراضيقابل للقيم الفارغة
iduuidgen_random_uuid()لا
user_iduuid—لا (FK إلى auth.users)
titletext—لا
completedbooleanfalseلا
created_attimestamptznow()لا

انقر Save. ينشئ Supabase الجدول مع مفتاح أساسي والأعمدة الافتراضية.

٢٫٢ تفعيل Row Level Security

RLS هي أهم ميزة أمان في Supabase. تضمن أن المستخدمين يمكنهم الوصول فقط إلى بياناتهم — يفرضها قاعدة البيانات، وليس كود التطبيق.

في Table Editor، انقر مفتاح RLS على جدول todos لتفعيله. ثم انقر Add RLS policy وأنشئ هذه السياسات:

السياسة ١: المستخدمون يمكنهم قراءة todos الخاصة بهم

sql
-- اسم السياسة: "Users can read own todos"
-- العملية: SELECT
-- الأدوار المستهدفة: authenticated
-- تعبير USING:
auth.uid() = user_id

السياسة ٢: المستخدمون يمكنهم إدراج todos الخاصة بهم

sql
-- اسم السياسة: "Users can insert own todos"
-- العملية: INSERT
-- الأدوار المستهدفة: authenticated
-- تعبير WITH CHECK:
auth.uid() = user_id

السياسة ٣: المستخدمون يمكنهم تحديث todos الخاصة بهم

sql
-- اسم السياسة: "Users can update own todos"
-- العملية: UPDATE
-- الأدوار المستهدفة: authenticated
-- تعبير USING: auth.uid() = user_id
-- تعبير WITH CHECK: auth.uid() = user_id

السياسة ٤: المستخدمون يمكنهم حذف todos الخاصة بهم

sql
-- اسم السياسة: "Users can delete own todos"
-- العملية: DELETE
-- الأدوار المستهدفة: authenticated
-- تعبير USING:
auth.uid() = user_id

٢٫٣ اختبار RLS مع SQL Editor

انتقل إلى SQL Editor وشغّل:

محرر SQL Supabase — تشغيل استعلامات لاختبار سياسات RLS

sql
-- يجب أن يُرجع 0 صفوف (لا todos بعد، و RLS نشط)
SELECT * FROM todos;

-- تحقق من تفعيل RLS
SELECT tablename, rowsecurity FROM pg_tables WHERE tablename = 'todos';
-- يجب أن يُظهر: todos | true

ما الذي يمكن أن يخطئ

  • "RLS policy already exists" — ربما نقرت "Save" مرتين. احذف المكرر وأعد الإنشاء.
  • "permission denied for table todos" — RLS مفعّل لكن لا توجد سياسة SELECT. أضف واحدة.
  • "new row violates row-level security policy" — تعبير WITH CHECK لسياسة INSERT خاطئ. تأكد من أنه يتحقق من auth.uid() = user_id.

لماذا RLS مهم

بدون RLS، أي شخص لديه مفتاح anon الخاص بك (الذي هو عام) يمكنه قراءة أو كتابة أي صف. مع RLS، قاعدة البيانات نفسها تفرض التحكم في الوصول. حتى لو تجاوز شخص ما واجهتك الأمامية، لا يمكنه الوصول إلى البيانات التي لا يملكها. هذه هي أهم ميزة أمان في Supabase.


الخطوة ٣ — إضافة مصادقة البريد الإلكتروني

٣٫١ تفعيل مصادقة البريد الإلكتروني

المصادقة Supabase — تفعيل مزود البريد الإلكتروني وتكوين عناوين URL إعادة التوجيه

انتقل إلى Authentication → Providers وتأكد من تفعيل Email (مفعّل افتراضياً). قم بتكوين:

  • Confirm email: تفعيل (يجب على المستخدمين التحقق من بريدهم الإلكتروني قبل تسجيل الدخول)
  • Secure email change: تفعيل
  • Minimum password length: ٨

٣٫٢ إعداد عناوين URL إعادة التوجيه

انتقل إلى Authentication → URL Configuration:

  • Site URL: http://localhost:3000 (للتطوير)
  • Redirect URLs: أضف http://localhost:3000/auth/callback و http://localhost:3000/**

للإنتاج، حدّث هذه إلى domain الإنتاج الخاص بك.

٣٫٣ إنشاء تطبيق Next.js

bash
npx create-next-app@latest supabase-todo --typescript --tailwind --app --src-dir
cd supabase-todo
npm install @supabase/supabase-js

٣٫٤ إنشاء عميل Supabase

أنشئ lib/supabase.ts:

typescript
import { createClient } from '@supabase/supabase-js';

export const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);

للاستخدام من جانب الخادم في routes API أو Server Components:

typescript
import { createClient } from '@supabase/supabase-js';

export function getSupabaseClient() {
  return createClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
  );
}

ملاحظة: يستخدم هذا المشروع @supabase/supabase-js مباشرةً (وليس @supabase/ssr). عميل Supabase يتعامل مع رموز المصادقة تلقائياً في المتصفح. للاستخدام من جانب الخادم، مرّر JWT المستخدم إذا لزم الأمر.

٣٫٥ إنشاء ملف البيئة

أنشئ .env.local:

env
NEXT_PUBLIC_SUPABASE_URL=https://your-project-id.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key

٣٫٦ التسجيل وتسجيل الدخول

أنشئ app/auth/actions.ts:

typescript
'use server';

import { revalidatePath } from 'next/cache';
import { redirect } from 'next/navigation';
import { createClient } from '@/lib/supabase/server';

export async function signUp(formData: FormData) {
  const supabase = await createClient();
  const email = formData.get('email') as string;
  const password = formData.get('password') as string;

  const { error } = await supabase.auth.signUp({
    email,
    password,
    options: {
      emailRedirectTo: `${process.env.NEXT_PUBLIC_SITE_URL}/auth/callback`,
    },
  });

  if (error) return { error: error.message };
  revalidatePath('/', 'layout');
  redirect('/auth/verify');
}

export async function signIn(formData: FormData) {
  const supabase = await createClient();
  const email = formData.get('email') as string;
  const password = formData.get('password') as string;

  const { error } = await supabase.auth.signInWithPassword({ email, password });

  if (error) return { error: error.message };
  revalidatePath('/', 'layout');
  redirect('/dashboard');
}

export async function signOut() {
  const supabase = await createClient();
  await supabase.auth.signOut();
  revalidatePath('/', 'layout');
  redirect('/');
}

ما الذي يمكن أن يخطئ

  • "Email not confirmed" — تحقق من مجلد Spam. قد تستغرق رسالة التحقق ١-٢ دقيقة.
  • "Invalid login credentials" — كلمة مرور خاطئة أو الحساب غير موجود. جرّب التسجيل أولاً.
  • "User already registered" — البريد الإلكتروني مستخدم بالفعل. جرّب تسجيل الدخول بدلاً من ذلك.

الخطوة ٤ — اشتراكات فورية

٤٫١ تفعيل Realtime على جدول todos

انتقل إلى Database → Replication وفعّل realtime لجدول todos. أو شغّل في SQL Editor:

sql
ALTER PUBLICATION supabase_realtime ADD TABLE todos;

٤٫٢ إنشاء مكون todo فوري

أنشئ components/TodoList.tsx:

typescript
'use client';

import { useEffect, useState } from 'react';
import { createClient } from '@/lib/supabase/client';
import type { RealtimePostgresChangesPayload } from '@supabase/supabase-js';

interface Todo {
  id: string;
  title: string;
  completed: boolean;
  user_id: string;
  created_at: string;
}

export function TodoList({ userId }: { userId: string }) {
  const [todos, setTodos] = useState<Todo[]>([]);
  const supabase = createClient();

  useEffect(() => {
    // جلب todos الأولية
    const fetchTodos = async () => {
      const { data } = await supabase
        .from('todos')
        .select('*')
        .order('created_at', { ascending: false });
      if (data) setTodos(data);
    };
    fetchTodos();

    // الاشتراك في تغييرات realtime
    const channel = supabase
      .channel('todos-changes')
      .on(
        'postgres_changes',
        { event: '*', schema: 'public', table: 'todos' },
        (payload: RealtimePostgresChangesPayload<Todo>) => {
          if (payload.eventType === 'INSERT') {
            setTodos(prev => [payload.new, ...prev]);
          } else if (payload.eventType === 'UPDATE') {
            setTodos(prev => prev.map(t => t.id === payload.new.id ? payload.new : t));
          } else if (payload.eventType === 'DELETE') {
            setTodos(prev => prev.filter(t => t.id !== payload.old.id));
          }
        }
      )
      .subscribe();

    return () => { supabase.removeChannel(channel); };
  }, [userId]);

  const addTodo = async (title: string) => {
    await supabase.from('todos').insert({ title, user_id: userId });
    // لا حاجة لتحديث الحالة — اشتراك realtime يتولى ذلك
  };

  const toggleTodo = async (id: string, completed: boolean) => {
    await supabase.from('todos').update({ completed: !completed }).eq('id', id);
  };

  const deleteTodo = async (id: string) => {
    await supabase.from('todos').delete().eq('id', id);
  };

  return (
    <div className="space-y-4">
      <form onSubmit={(e) => {
        e.preventDefault();
        const input = e.currentTarget.elements.namedItem('title') as HTMLInputElement;
        if (input.value.trim()) { addTodo(input.value); input.value = ''; }
      }} className="flex gap-2">
        <input name="title" placeholder="Add a todo..." className="flex-1 rounded border px-3 py-2" />
        <button type="submit" className="rounded bg-blue-500 px-4 py-2 text-white">Add</button>
      </form>
      <ul className="space-y-2">
        {todos.map(todo => (
          <li key={todo.id} className="flex items-center gap-2 rounded border p-3">
            <input type="checkbox" checked={todo.completed} onChange={() => toggleTodo(todo.id, todo.completed)} />
            <span className={todo.completed ? 'line-through text-gray-500' : ''}>{todo.title}</span>
            <button onClick={() => deleteTodo(todo.id)} className="ml-auto text-red-500">Delete</button>
          </li>
        ))}
      </ul>
      {todos.length === 0 && <p className="text-gray-500">No todos yet. Add one above!</p>}
    </div>
  );
}

٤٫٣ اختبار Realtime

افتح علامتي تبويب. أضف todo في واحدة — يظهر فوراً في الأخرى. بدّل الاكتمال — كلا العلامتين تُحدَّثان. احذف — يختفي من كليهما. بدون polling، بدون WebSockets لإدارتها.

ما الذي يمكن أن يخطئ

  • "Realtime not working" — تحقق من تشغيل ALTER PUBLICATION supabase_realtime ADD TABLE todos;. أيضاً تحقق من أن RLS يسمح للمستخدم بقراءة الجدول.
  • "Subscription error" — يجب أن يكون اسم القناة فريداً لكل instance من المكون. استخدم اسم قناة فريد أو نظّف عند unmount.
  • "Changes not propagating" — تحقق من console المتصفح for WebSocket connection errors. يستخدم Supabase Realtime WebSockets على port 443 (wss://).

الخطوة ٥ — تخزين الملفات

٥٫١ إنشاء bucket تخزين

التخزين Supabase — إنشاء bucket جديد لرفع الملفات

انتقل إلى Storage → New bucket:

  • الاسم: avatars
  • Public: تفعيل (لصور الملف الشخصي)
  • File size limit: 5MB
  • Allowed MIME types: image/*

٥٫٢ إعداد سياسات التخزين

انتقل إلى Storage → Policies وأضف:

السياسة ١: المستخدمون يمكنهم رفع صورتهم الشخصية

sql
-- Operation: INSERT
-- Target roles: authenticated
-- WITH CHECK: (storage.foldername(name))[1] = auth.uid()::text

السياسة ٢: أي شخص يمكنه عرض صور الملف الشخصي

sql
-- Operation: SELECT
-- Target roles: anon, authenticated
-- USING: true

٥٫٣ رفع وعرض الملفات

typescript
const supabase = createClient();

// رفع
const { data, error } = await supabase.storage
  .from('avatars')
  .upload(`${userId}/avatar.png`, file, { upsert: true });

// الحصول على URL عام
const { data: { publicUrl } } = supabase.storage
  .from('avatars')
  .getPublicUrl(`${userId}/avatar.png`);

ما الذي يمكن أن يخطئ

  • "Bucket not found" — اسم bucket حساس لحالة الأحرف. تحقق من الإملاء.
  • "new row violates row-level security policy" — سياسات التخزين تستخدم storage.foldername(name) التي تستخرج المجلد الأول. تأكد من أن مسار الرفع يبدأ بمعرف المستخدم.
  • "File size exceeds limit" — تحقق من حد حجم الملف في إعدادات bucket.

الخطوة ٦ — Edge Functions

٦٫١ تثبيت Supabase CLI

bash
npm install -g supabase
supabase login
supabase link --project-ref your-project-id

٦٫٢ إنشاء edge function

Edge Functions Supabase — انقر على "Deploy a new function" لإنشاء دالة جديدة

انقر على زر "Deploy a new function" (أعلى يمين الصفحة). تظهر قائمة منسدلة مع ثلاث خيارات نشر:

  1. Deploy via CLI — أنشئ الدالة محلياً بـ supabase functions new <name>، اكتب الكود، ثم انشر بـ supabase functions deploy <name>
  2. Deploy via Dashboard — اكتب كود الدالة مباشرةً في محرر المتصفح
  3. Deploy via GitHub — اربط مستودع GitHub والنشر تلقائياً عند push

لهذا الدليل، سنستخدم نهج CLI (الأكثر مرونة للتطوير).

bash
supabase functions new hello-world

عدّل supabase/functions/hello-world/index.ts:

typescript
import { serve } from 'https://deno.land/std@0.224.0/http/server.ts';

serve(async (req) => {
  const { name } = await req.json();
  return new Response(
    JSON.stringify({ message: `Hello ${name || 'World'}!` }),
    { headers: { 'Content-Type': 'application/json' } }
  );
});

٦٫٣ النشر

bash
supabase functions deploy hello-world

٦٫٤ الاستدعاء من العميل

typescript
const { data, error } = await supabase.functions.invoke('hello-world', {
  body: { name: 'NerdLevelTech' },
});
// data: { message: "Hello NerdLevelTech!" }

ما الذي يمكن أن يخطئ

  • "Function not found" — اسم الدالة في استدعاء invoke يجب أن يطابق اسم الدالة المنشورة بالضبط.
  • "Deno import error" — استخدم imports متوافقة مع Deno. Edge Functions تعمل على Deno، وليس Node.js.
  • "CORS error" — أضف headers CORS إلى استجابة دالتك إذا كنت تستدعيها من المتصفح.

الخطوة ٧ — النشر في الإنتاج

٧٫١ النشر على Vercel

bash
npm install -g vercel
vercel

تعيين متغيرات البيئة في لوحة تحكم Vercel:

  • NEXT_PUBLIC_SUPABASE_URL
  • NEXT_PUBLIC_SUPABASE_ANON_KEY

٧٫٢ تحديث عناوين URL إعادة التوجيه لـ Supabase

انتقل إلى Authentication → URL Configuration وحدّث:

  • Site URL: https://your-production-domain.com
  • Redirect URLs: أضف https://your-production-domain.com/auth/callback

٧٫٣ قائمة تحقق الإنتاج

  • RLS مفعّل على جميع الجداول
  • سياسات التخزين مُكوّنة
  • عناوين URL إعادة التوجيه للمصادقة مُحدّثة
  • متغيرات البيئة مُعيّنة في Vercel
  • مراقبة الأخطاء مُكوّنة (Sentry، إلخ)
  • تحديد المعدل على routes API
  • CORS مُكوّن for Edge Functions

ما التالي

بعد إتمام هذا الدليل، يمكنك:

  1. إضافة مزودي OAuth — Google، GitHub، Apple (Authentication → Providers)
  2. إعداد webhooks قاعدة البيانات — تشغيل Edge Functions عند تغييرات البيانات
  3. إضافة بحث full-text — استخدام Postgres tsvector للبحث
  4. تنفيذ pagination — استخدام .range() في استعلامات Supabase
  5. إضافة دوال قاعدة البيانات — كتابة دوال PL/pgSQL للاستعلامات المعقدة
  6. إعداد CI/CD — GitHub Actions for الاختبار automatique والنشر
  7. المراقبة مع Supabase Studio — إمكانية ملاحظة مدمجة for الاستعلامات والمصادقة والتخزين

لماذا Supabase؟

Supabase يمنحك backend بمستوى الإنتاج في دقيقتين. قاعدة بيانات Postgres، مصادقة، تخزين ملفات، اشتراكات فورية، ودوال بدون خادم — كل ذلك مع طبقة مجانية سخية بما يكفي لإطلاق منتج حقيقي. نموذج الأمان RLS يعني أن قاعدة البيانات تفرض التحكم في الوصول، وليس كود التطبيق. وبما أنه مفتوح المصدر، يمكنك الاستضافة الذاتية عندما تتجاوز السحابة.

الميزة الأكبر: أنت تملك بياناتك. إنها PostgreSQL قياسية. بدون vendor lock-in. صدّر بياناتك في أي وقت. استخدم أي أداة Postgres أو ORM أو عميل.

قوة المنتج

Supabase قوي لأن:

  • مفتوح المصدر — تحكم كامل، قابل للاستضافة الذاتية، بدون vendor lock-in
  • Postgres قياسي — استخدم أي أداة SQL أو ORM أو عميل
  • أمان RLS — التحكم في الوصول على مستوى قاعدة البيانات، وليس على مستوى التطبيق
  • فوري مدمج — بدون خادم WebSocket منفصل مطلوب
  • Edge Functions — TypeScript بدون خادم على Deno، نشر عالمي
  • طبقة مجانية سخية — enough لإطلاق منتج حقيقي
  • DX great — مكتبات عميل لـ ١٠+ لغات، أنواع TypeScript مُولّدة من schema الخاص بك

القيود (بصراحة):

  • الطبقة المجانية لديها حدود الموارد (500MB DB، 1GB تخزين)
  • Edge Functions هي Deno، وليس Node.js (بعض حزم npm لا تعمل)
  • Realtime has حدود اتصال على الطبقة المجانية
  • الاستضافة الذاتية تتطلب معرفة DevOps
  • لوحة التحكم يمكن أن تكون بطيئة مع مجموعات البيانات الكبيرة

استكشاف الأخطاء وإصلاحها

ProblemCauseFix
"permission denied for table"RLS مفعّل لكن لا توجد سياسة SELECTأضف سياسة SELECT لدور authenticated
"JWT expired"رمز الجلسة منتهيAufruf supabase.auth.refreshSession() أو إعادة المصادقة
"Bucket not found"اسم bucket خاطئ (حساس لحالة الأحرف)تحقق من اسم bucket في لوحة Storage
"Function not found"عدم تطابق اسم الدالة أو غير منشورةشغّل supabase functions deploy <name>
"Realtime not working"الجدول غير مضاف إلى publicationشغّل ALTER PUBLICATION supabase_realtime ADD TABLE <table>
"CORS error on Edge Function"Missing headers CORSأضف Access-Control-Allow-Origin header إلى استجابة دالتك

الأسئلة الشائعة

هل Supabase مجاني بالفعل؟

نعم. تتضمن الطبقة المجانية ٢ مشروع و500MB قاعدة بيانات و1GB تخزين ملفات و2GB ترافيك و٥٠٬٠٠٠ مستخدم نشط شهرياً للمصادقة و٥٠٠٬٠٠٠ استدعاء Edge Function. كافٍ لبناء وإطلاق منتج حقيقي. لا حاجة لبطاقة ائتمان.

كيف يقارن Supabase مع Firebase؟

Supabase مفتوح المصدر ويستخدم PostgreSQL (ليس NoSQL). Firebase مملوك ويستخدم Firestore. Supabase يقدم Row Level Security واشتراكات فورية وEdge Functions. Firebase لديه دعم أفضل للعمل دون اتصال ونظام بيئي أكبر. اختر Supabase إذا أردت SQL ومصدر مفتوح وتحكم كامل.

ما هو Row Level Security (RLS)؟

RLS ميزة Postgres تتيح لك تعريف سياسات تتحكم في أي صفوف يمكن لكل مستخدم قراءتها أو إدراجها أو تحديثها أو حذفها. يستخدم Supabase RLS كآلية الأمان الأساسية — قاعدة البيانات تفرض التحكم في الوصول، وليس كود التطبيق. هذا يعني حتى لو تجاوز شخص ما API الخاص بك، لا يمكنه الوصول إلى البيانات التي لا يجب أن يراها.

هل يمكنني استخدام Supabase مع أطر عمل أخرى غير Next.js؟

نعم. لدى Supabase مكتبات عميل لـ JavaScript/TypeScript وPython وFlutter وSwift وKotlin والمزيد. يعمل مع React وVue وSvelte وAngular وNuxt وSvelteKit وRemix وأي إطار يمكنه إجراء طلبات HTTP. قاعدة البيانات هي PostgreSQL قياسية، لذا يعمل أي عميل Postgres.

كيف يعمل Supabase Realtime؟

يستخدم Supabase Realtime التكرار المنطقي لـ PostgreSQL لبث تغييرات قاعدة البيانات (INSERT, UPDATE, DELETE) إلى العملاء المتصلين عبر WebSockets. تشترك في التغييرات على جدول أو صفوف محددة، ويدفع Supabase التحديثات في الوقت الفعلي. يدعم أيضاً Presence (من متصل) وBroadcast (إرسال رسائل بين العملاء).

ما هي Edge Functions ومتى يجب أن أستخدمها؟

Edge Functions هي دوال TypeScript بدون خادم تعمل على Deno في الحافة (قريبة من المستخدمين). استخدمها لـ: webhooks ونقاط API مخصصة والمنطق من جانب الخادم الذي يحتاج أسراراً ودمج خدمات الطرف الثالث ومعالجة البيانات قبل تخزينها. تُنشر عالمياً وتبدأ في أقل من 50ms.

كم تكلفة Supabase عند التوسع؟

الطبقة المجانية: ٢ مشروع، 500MB DB، 1GB تخزين، 50K MAU. Pro (٢٥ دولار/شهر): 8GB DB، 100GB تخزين، 100K MAU، نسخ احتياطي يومي. Team (٥٩٩ دولار/شهر): كل ما في Pro plus SOC2 وSSO ودعم أولوية. المؤسسات: أسعار مخصصة. معظم التطبيقات تبقى على Pro لفترة طويلة — الطبقة المجانية سخية للنماذج الأولية.

هل يمكنني استضافة Supabase ذاتياً؟

نعم. Supabase مفتوح المصدر بالكامل. يمكنك الاستضافة الذاتية باستخدام Docker Compose على أي خادم. يتضمن الإصدار المستضاف ذاتياً كل شيء: Postgres والمصادقة والتخزين وEdge Functions وRealtime ولوحة Studio. إنها نفس قاعدة الكود كإصدار السحابة.

المزيد من الأدلّة

  • دليل · ٢٥ دقيقة للقراءة

    دليل المطور لبروتوكول سياق النموذج (MCP)

    أتقن بروتوكول MCP من البنية إلى الإنتاج. تعلم بروتوكول العميل-الخادم وبناء خوادم مخصصة باستخدام TypeScript و Python SDKs والاتصال بعملاء MCP الحقيقيين ونشر تكاملات آمنة لسير العمل المدعوم بالذكاء الاصطناعي.