الأدلة التقنية

تتبع ساعات عمل فريقك على خادمك باستخدام Titra وMongoDB

سجل ساعات عمل فريقك على كل مشروع واستخرج التقارير من سيرفرك دون مزود خارجي. نثبت Titra مع MongoDB، ونغلق التسجيل المفتوح من الواجهة ومن السيرفر لأن خيار الواجهة وحده لا يمنعه.

تتبع ساعات عمل فريقك على خادمك باستخدام Titra وMongoDB

إذا كنت تعمل في شركة خدمات أو استشارات أو في فريق تطوير يحاسب عملاءه بالساعة، فأنت تعرف السؤال الذي يأتي في نهاية كل شهر: كم ساعة أخذ مشروع هذا العميل فعلاً؟ والحل الأول الذي يبدأ به الجميع هو ملف Excel يكتب فيه كل موظف ساعاته، أو تقدير من الذاكرة يوم إصدار الفاتورة، ولكن مع الوقت سوف تجد أن كل موظف يكتب بطريقته، وأن نصف الساعات تسجل بعد أيام من العمل فتأتي تقريبية، وأن لا أحد يعرف إن كان الفريق قد تجاوز ميزانية المشروع إلا بعد أن يتجاوزها، والسبب أن الملف لا يربط الوقت بالمشروع والعميل والمهمة Task، ولا يعطيك تقريراً واحداً تثق به.

لذلك ينتقل الفريق عادة إلى الحل الثاني، وهو خدمة سحابية لتتبع الوقت Time Tracking مثل Toggl أو Harvest، وهذا يحل مشكلة الفوضى، ولكنه يأتي بمشكلة أخرى، وهي أن ساعات موظفيك وأسماء عملائك وأسعارك أصبحت على سيرفرات Servers شركة أخرى، وأنك تدفع اشتراكاً Subscription عن كل مستخدم، وكلما كبر الفريق كبرت الفاتورة.

والحل الأنسب في رأينا هو أن تشغل أداة تتبع الوقت على سيرفرك، وهنا يأتي دور Titra، وهو أداة مفتوحة المصدر Open Source تسجل فيها الوقت يدوياً أو بساعة إيقاف Stopwatch، وتربطه بمشروع وعميل ومهمة، وتحدد لكل مشروع السعر بالساعة Hourly Rate وهدفاً للساعات، ثم تعطيك تقارير Reports تفصيلية ويومية وإجمالية مع تصدير Export إلى CSV وExcel، وفيه فرق عمل Teams بصلاحيات Permissions، ودخول عبر LDAP أو OpenID Connect، وواجهة API.

ويناسب Titra شركات الخدمات والاستشارات وفرق التطوير الصغيرة والمتوسطة التي تصدر فواتيرها Invoices بالساعة، أو تريد أن تعرف أين يذهب وقتها، ولكنه ليس نظاماً للموارد البشرية HR ولا للرواتب Payroll، فهو يعرض ساعات العمل اليومية ولكنه لا يحتسب الحضور والانصراف بالمعنى النظامي.

وسوف نناقش في هذا المقال ما يلي:

  • أي إصدار Release من Titra نثبت، ولماذا لا نعتمد على أحدث إصدار حالياً.
  • تثبيت Titra مع MongoDB عبر Docker Compose خلف الـ Reverse Proxy، ومعنى كل متغير في الإعداد.
  • تسجيل المدير الأول ثم إغلاق التسجيل المفتوح من الواجهة ومن جهة السيرفر، لأن خيار الواجهة وحده لا يكفي.
  • إنشاء مشروع وتسجيل الوقت وقراءة التقارير.
  • النسخ الاحتياطي والاستعادة والتحديث، وأشهر المشكلات وحلولها.

ما تحتاجه قبل أن تبدأ

  • سيرفر مثبت عليه Docker وCompose، وإذا لم تثبته بعد فابدأ بدليل تثبيت Docker على Ubuntu.
  • الموارد Resources: يستهلك Titra قرابة 125 ميجابايت من الذاكرة RAM، ويستهلك MongoDB قرابة 150 ميجابايت، ولاحظ أن MongoDB 5 وما بعده يحتاج إلى معالج يدعم تعليمات AVX، وكل السيرفرات الحديثة تدعمها، ولكن بعض المحاكيات Emulators القديمة لا تدعمها.
  • نطاق Domain مثل time.example.com، وReverse Proxy يعمل بـ HTTPS ومتصل بشبكة Docker باسم proxy مثل Nginx Proxy Manager، ولأن Titra مبني على Meteor ويستخدم WebSockets فيجب أن تفعلها في الـ Reverse Proxy.
  • حساب SMTP إذا أردت أن يستعيد المستخدمون كلمات المرور بأنفسهم.

أي إصدار من Titra نثبت؟

نقل المشروع مستودعه Repository على GitHub من kromitgmbh/titra إلى titraio/titra، فأصبح اسم ال Docker Image الحالية هو titraio/titra، والاسم القديم kromit/titra ما زال يستقبل الوسوم Tags نفسها، وأحدث إصدار حتى أكتوبر 2026 هو v1.1.0 الذي صدر في 17 سبتمبر 2026 ومعه تحسينات أمنية Security Fixes.

وقد تتوقع أن الصحيح هو أن تثبت أحدث إصدار دائماً، ولكن إنشاء أي مشروع يفشل في هذا الإصدار، فتضغط Save ولا يحدث شيء، ويتلقى المتصفح الخطأ Internal server error [500]، وتعديل مشروع موجود يفشل بالخطأ نفسه، والسبب في الكود Source Code: الدالتان Functions createProject وupdateProject في الإصدار الجديد تستدعيان buildSafePayload وprojectAllowedFields دون أن تستوردهما Import، فيظهر في سجل الـ Container السطر ReferenceError: buildSafePayload is not defined، أما الإصدار السابق v1.0.12 فيعمل دون أي مشكلة، ولذلك يعتمد عليه هذا الدليل.

⚠️
راجع صفحة الإصدارات قبل التثبيت، فإذا صدر إصلاح بعد 1.1.0 مثل 1.1.1، فقم بتشغيله على نسخة اختبار وتأكد أن إنشاء المشاريع وتعديلها وتسجيل الوقت تعمل، ثم انتقل إليه لتحصل على التحسينات الأمنية.

تثبيت Titra بـ Docker Compose

نبدأ بإنشاء مجلد للخدمة يحفظ فيه ملف Compose وملف الإعدادات:

sudo mkdir -p /opt/titra
sudo chown $USER: /opt/titra
cd /opt/titra

بعد ذلك سوف ننشئ ملف .env الذي يحفظ العنوان الرئيسي للموقع Root URL وبيانات البريد، والبريد اختياري، ولاحظ أن قيمة MAIL_URL تتبع صيغة Meteor، فإذا كانت في كلمة المرور رموز خاصة فقم بترميزها بصيغة الروابط URL Encoding:

cat > .env <<'EOF'
ROOT_URL=https://time.example.com
MAIL_URL=smtps://titra%40example.com:ضع-كلمة-المرور@smtp.example.com:465
EOF
chmod 600 .env

الآن سوف ننشئ الملف /opt/titra/compose.yaml:

services:
  titra:
    image: titraio/titra:v1.0.12
    container_name: titra
    restart: unless-stopped
    depends_on:
      mongodb:
        condition: service_healthy
    environment:
      ROOT_URL: ${ROOT_URL}
      MONGO_URL: mongodb://mongodb:27017/titra?directConnection=true
      MAIL_URL: ${MAIL_URL}
      PORT: 3000
    networks:
      - internal
      - proxy
    healthcheck:
      test: ["CMD", "wget", "-q", "--spider", "http://127.0.0.1:3000/"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 30s

  mongodb:
    image: mongo:8.0.32
    container_name: titra-db
    restart: unless-stopped
    volumes:
      - titra_db:/data/db
    networks:
      - internal
    healthcheck:
      test: ["CMD", "mongosh", "--quiet", "--eval", "db.adminCommand('ping').ok"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 20s

volumes:
  titra_db:
    name: titra_db

networks:
  internal: {}
  proxy:
    external: true

في الإعداد أعلاه لاحظ التالي:

  • ROOT_URL: يجب أن يطابق النطاق الذي يفتحه المستخدمون حرفاً بحرف ومعه https://، والسبب أن Titra يبني منه الروابط واتصال WebSocket، وأي اختلاف بسيط يجعل الصفحة لا تكتمل.
  • MongoDB 8.0: ملف Compose الرسمي للمشروع يستخدم الإصدار 7.0، وTitra 1.0.12 يعمل على 8.0.32 دون مشكلة، واخترنا الفرع 8.0 لأنه إصدار رئيسي Major Release له دورة دعم مدتها خمس سنوات، أما 8.1 و8.2 و8.3 فإصدارات فرعية Minor Releases يتوقف إصلاح كل واحد منها عندما يصدر الذي بعده.
  • لماذا لا توجد مصادقة Authentication على MongoDB؟ لأن القاعدة على شبكة internal لا يصل إليها غير Titra، ولا ننشر منفذها Port، وإذا أردت حماية إضافية فأضف MONGO_INITDB_ROOT_USERNAME وMONGO_INITDB_ROOT_PASSWORD كما يشرح توثيق ال Docker Image الخاصة بـ mongo، ثم أنشئ مستخدماً لقاعدة titra وضع بياناته في MONGO_URL، وفي كل الأحوال لا تقم بنشر المنفذ 27017 على الانترنت.
  • لا ينشر الملف أي منفذ لـ Titra نفسه، فالـ Reverse Proxy يصل إلى titra:3000 عبر شبكة proxy.

الآن نقوم بإنشاء شبكة الـ Reverse Proxy إذا لم تكن موجودة، ثم تشغيل الخدمة ومتابعة السجلات Logs:

docker network create proxy
docker compose up -d
docker compose logs -f titra

والمخرج سوف يكون كما يلي:

titra  | Connecting to MongoDB...
titra  | Successfully connected to MongoDB
titra  | Starting titra...
titra  | titra started on port 3000

بعد ذلك أنشئ في الـ Reverse Proxy مضيفاً Proxy Host للنطاق time.example.com يوجه الطلبات إلى http://titra:3000، وفعل فيه Websockets Support وشهادة Certificate من Let's Encrypt وخيار Force SSL، وإذا نسيت تفعيل WebSockets فسوف تبقى الصفحة في حالة تحميل ولا تكتمل.

حساب المدير الأول وإغلاق التسجيل المفتوح

افتح https://time.example.com واضغط Register، ولاحظ أن أول من يسجل يصبح مدير النظام Administrator، لذلك سجل حسابك مباشرة بعد التشغيل قبل أن يسبقك إليه أحد:

نموذج التسجيل في Titra بحقول الاسم والبريد وكلمة المرور
تسجيل المستخدم الأول، الذي يصبح المدير

بعد التسجيل ينشئ Titra مشروعاً تجريبياً باسمك، والآن عليك أن تغلق التسجيل المفتوح Registration، فافتح قائمة المستخدم (الأحرف الأولى من اسمك أعلى يمين الصفحة)، واختر Administration ثم Global settings، وفعل في قسم Login خيار Disable new user registration، وبعدها يضيف المدير المستخدمين من تبويب Users.

وفي القسم نفسه خيارات LDAP وOpenID Connect لربط الدخول بنظام الدخول الموحد SSO، وخيار الوصول المجهول Anonymous Access عبر /try، فأبق هذا الخيار معطلاً في بيئة الإنتاج Production:

قسم Login في إعدادات Titra العامة مع خيارات التسجيل وLDAP وOpenID Connect
إعدادات الدخول: أغلق التسجيل الجديد بعد إنشاء حسابك

وقد يتساءل البعض: هل يكفي هذا الخيار لإغلاق التسجيل؟ والإجابة لا، والسبب أن Titra يستخدم الخيار في الواجهة فقط، فهو يخفي نموذج التسجيل ويعرض مكانه تحذيراً، ولكن السيرفر نفسه ما زال يقبل طلب إنشاء الحساب createUser الذي يرسله أي متصفح عبر اتصال WebSocket، وعند تجربة ذلك على Titra 1.0.12 بعد تفعيل الخيار أنشأ السيرفر الحساب الجديد وأعاد له رمز دخول Token كأن شيئاً لم يكن، وهذا يعني أن أي شخص يعرف كيف يعمل Meteor يستطيع أن يسجل في نظامك ويرى المشاريع العامة فيه.

والحل الأنسب هو أن تغلق التسجيل من جهة السيرفر أيضاً بالخيار forbidClientAccountCreation من إعدادات الحسابات في Meteor، والذي تمرره إلى الـ Container في متغير البيئة METEOR_SETTINGS، فأضف السطر الأخير التالي إلى قسم environment للخدمة titra في compose.yaml:

    environment:
      ROOT_URL: ${ROOT_URL}
      MONGO_URL: mongodb://mongodb:27017/titra?directConnection=true
      MAIL_URL: ${MAIL_URL}
      PORT: 3000
      METEOR_SETTINGS: '{"packages":{"accounts-base":{"forbidClientAccountCreation":true}}}'

ثم أعد إنشاء الـ Container:

docker compose up -d

في الإعداد أعلاه لاحظ التالي:

  • أي طلب تسجيل من المتصفح سوف يرفضه السيرفر بالخطأ Signups forbidden [403]، سواءً جاء من نموذج التسجيل أو مباشرة عبر WebSocket.
  • إضافة المستخدمين من تبويب Users في الإدارة تبقى تعمل، لأنها تنشئ الحساب على السيرفر وليس من المتصفح، وكذلك الحسابات التي ينشئها الدخول عبر LDAP أو OpenID Connect.
  • لا تقم بإضافة هذا السطر قبل أن تسجل حساب المدير، لأنه يمنع التسجيل الأول أيضاً.
  • إذا كان التسجيل مفتوحاً مدة من الوقت قبل أن تغلقه، فراجع قائمة Users واحذف أي حساب لا تعرفه.

وفي صفحة Global settings نفسها إعدادات أخرى تستحق المراجعة، مثل وحدة العملة Cost unit، وتنسيق التاريخ Date Format، وبداية الأسبوع (ضع 0 إذا كان أسبوع العمل عندكم يبدأ يوم الأحد)، وعدد ساعات يوم العمل، وعنوان المرسل للبريد.

إنشاء أول مشروع

اضغط + Project من صفحة Overview، وأهم الحقول Fields هي اسم المشروع، ولونه في الرسوم البيانية Charts، والعميل الذي تتجمع التقارير بحسبه، والمهمة الافتراضية، وفي قسم Billing & Budget تحدد السعر بالساعة وهدف الساعات، فيعرض Titra تقدمك نحو الهدف في شريط تقدم Progress Bar على بطاقة المشروع:

نموذج مشروع جديد في Titra مع الاسم واللون والمدة والوصف والعميل والمهمة الافتراضية
مشروع جديد باسم وعميل عربيين، ويقع السعر والهدف في قسم Billing & Budget أسفل النموذج

ولكي تشرك زملاءك في المشروع، افتحه للتعديل وأضفهم إلى فريقه مع أدوارهم Roles، أو اجعل المشروع عاماً Public لكل المستخدمين، إلا إذا قمت بتعطيل المشاريع العامة من الإعدادات.

تسجيل الوقت وقراءة التقارير

زر Track time يفتح نموذج اليوم، فتختار المشروع وتكتب المهمة وسوف يقترح عليك Titra مهامك السابقة، ثم تدخل الساعات بالكسور العشرية Decimal، فالقيمة 2.5 تعني ساعتين ونصفاً، أو تشغل ساعة الإيقاف وتحفظ عند الانتهاء، ومجموع اليوم يظهر أعلى النموذج، وفيه تبويبا Week وMonth لإدخال وقت عدة أيام دفعة واحدة:

نموذج تسجيل الوقت في Titra مع المشروع والمهمة وعدد الساعات وساعة الإيقاف
إدخال 2.5 ساعة لمهمة في المشروع

أما صفحة Details فتعرض الإدخالات Time Entries مع مرشحات Filters بحسب المشروع والفترة والشخص والعميل، وفيها تبويبات للعرض اليومي والإجمالي وساعات العمل والرسوم البيانية، وأزرار للتصدير إلى CSV وExcel ولتعليم الإدخالات بأنها مفوترة Billable:

جدول تفاصيل الوقت في Titra بثلاث مهام ومجموع 6.75 ساعة
ثلاثة إدخالات بمجموع 6.75 ساعة، مع حالة الفوترة وأزرار التصدير

وفي صفحة Overview تجد ملخصاً لكل مشروع يعرض الوقت الكلي والهدف والإيراد Revenue المحسوب من السعر، مع توزيع المهام والسجل الزمني لثلاثة أشهر:

صفحة Overview في Titra مع ملخص المشاريع والرسوم وبطاقة المشروع
ملخص المشروع: 6.75 ساعة من هدف 120، والإيراد بحسب السعر المحدد

ولاحظ أن الإيراد يظهر افتراضياً بعلامة €، فقم بتغييرها إلى عملتك من Cost unit في الإعدادات العامة.

كيف تتأكد أن كل شيء يعمل

  • يعرض الأمر docker compose ps الـ Containers الاثنين بحالة healthy، وتجد في السجل السطر titra started on port 3000.
  • يفتح https://time.example.com وتكتمل الصفحة، وهذا يعني أن WebSocket يعمل، وفي أدوات المطور Developer Tools سوف ترى اتصال /sockjs/.../websocket بالحالة 101.
  • ينقلك إنشاء مشروع إلى صفحة تعديله (/edit/project/...)، ويرفع إدخال الوقت مجموع اليوم.
  • بعد تفعيل Disable new user registration وإضافة METEOR_SETTINGS، افتح صفحة التسجيل من نافذة خاصة في المتصفح، وسوف تجد مكان النموذج تحذيراً بأن التسجيل معطل.
  • البيانات محفوظة في MongoDB، والأمر docker compose exec mongodb mongosh titra --quiet --eval 'db.timecards.countDocuments()' يعيد عدد الإدخالات.

النسخ الاحتياطي Backup والاستعادة Restore

كل بيانات Titra موجودة في قاعدة titra على MongoDB، لذلك انسخها مع الملفين compose.yaml و.env، والأداة mongodump موجودة أصلاً في ال Docker Image الخاصة بـ mongo، وهي تخرج أرشيفاً مضغوطاً Compressed Archive إلى المخرج القياسي stdout:

cd /opt/titra
mkdir -p backups
docker compose exec -T mongodb mongodump --db titra --archive --gzip > backups/titra-$(date +%F).archive.gz

وللاستعادة على سيرفر جديد، قم بتشغيل القاعدة وحدها، ثم انسخ الأرشيف إليها واستعده بالأداة mongorestore، ثم شغل التطبيق، ولاحظ أن الخيار --drop يحذف المجموعات Collections الموجودة قبل الاستعادة:

docker compose up -d mongodb
docker compose exec -T mongodb sh -c 'cat > /tmp/titra.archive.gz' < backups/titra-2026-09-26.archive.gz
docker compose exec -T mongodb mongorestore --archive=/tmp/titra.archive.gz --gzip --drop
docker compose up -d

والنسخة الاحتياطية التي لم تجرب استعادتها لا تعرف إن كانت تعمل، لذلك اختبرها دون أن تمس القاعدة العاملة باستعادة الأرشيف إلى قاعدة باسم آخر بالخيارين --nsFrom="titra.*" --nsTo="restoretest.*"، ثم قارن عدد الإدخالات فيها بالقاعدة الأصلية.

التحديث Upgrade إلى إصدار أحدث

  1. اقرأ ملاحظات الإصدار Release Notes، وقم بتشغيل الإصدار الجديد على نسخة اختبار مستعادة من النسخة الاحتياطية، وأنشئ فيها مشروعاً وعدله، وسجل وقتاً، وافتح التقارير قبل أن تحدث بيئة الإنتاج.
  2. خذ نسخة احتياطية بالأداة mongodump.
  3. غير الوسم في compose.yaml، ثم نفذ الأوامر التالية:
cd /opt/titra
docker compose pull
docker compose up -d
docker compose logs --tail 20 titra

وللرجوع إلى الإصدار السابق أعد الوسم القديم، وإذا كان الإصدار الجديد قد عدل البيانات فاستعد النسخة الاحتياطية أيضاً.

أما MongoDB فتحديثه داخل الفرع Branch نفسه يكفيه تغيير الوسم، مثل الانتقال من 8.0.32 إلى إصدار 8.0.x التالي، ولكن الانتقال بين الإصدارات الرئيسية يكون على مراحل، أي من 7.0 إلى 8.0 وليس من 5.0 إلى 8.0 مباشرة، وبعد كل مرحلة ترفع featureCompatibilityVersion، والطريق الأبسط أن تأخذ نسخة بالأداة mongodump من القاعدة القديمة، ثم تستعيدها بالأداة mongorestore في قاعدة جديدة بالإصدار الجديد.

مشكلات شائعة وحلولها

زر Save في مشروع جديد لا يفعل أي شيء

إذا كنت على v1.1.0 فهذا هو الخلل Bug الذي شرحناه في البداية، وسوف تجد الخطأ Internal server error [500] في أدوات المطور، والحل أن ترجع إلى v1.0.12 أو تنتقل إلى إصدار يصلحه، والتبديل بين الإصدارين لا يمس البيانات.

الصفحة تبقى في حالة تحميل خلف الـ Reverse Proxy

السبب واحد من اثنين: إما أن WebSockets غير مفعلة في الـ Reverse Proxy، أو أن ROOT_URL لا يطابق النطاق، كأن يبدأ بـ http:// بدلاً من https://، فقم بتصحيح الخطأ ثم أعد إنشاء الـ Container.

MongoDB يتوقف فور التشغيل

إذا ظهر في سجل الـ Container أن المعالج CPU لا يدعم AVX، فالسيرفر أو المحاكي قديم، والحل سيرفر بمعالج أحدث أو نمط محاكاة يمرر تعليمات المعالج (host CPU)، أما البقاء على MongoDB 4.4 فهو إصدار لم يعد مدعوماً ولا ننصح به.

Titra لا يتصل بـ MongoDB

تأكد أن الخدمتين على شبكة internal نفسها، وأن MONGO_URL يشير إلى اسم الخدمة mongodb، ولاحظ أن الخيار directConnection=true مطلوب مع سيرفر MongoDB مفرد لا ينتمي إلى مجموعة نسخ متماثلة Replica Set.

نسيت كلمة المرور ولا يوجد بريد مضبوط

اضبط MAIL_URL وأعد إنشاء الـ Container، ثم استخدم Forgot your password من صفحة الدخول، وإذا كان الحساب لمستخدم عادي فالمدير يستطيع إدارته من Administration ثم Users.

التواريخ تظهر بيوم خاطئ

راجع المنطقة الزمنية Time Zone في ملف المستخدم، وتنسيق التاريخ وبداية الأسبوع في الإعدادات العامة، والسبب أن Titra يحفظ التواريخ بتوقيت UTC ويعرضها بالمنطقة الزمنية للمتصفح.

الخلاصة

وصلنا لنهاية الموضوع، وأهم ما فيه:

  • ملف Excel لا يربط الوقت بالمشروع والعميل، والخدمات السحابية تحل ذلك ولكن بيانات فريقك تبقى عند شركة أخرى وتدفع عن كل مستخدم، وTitra يعطيك التتبع والتقارير وبياناتك في MongoDB على سيرفرك.
  • ثبت v1.0.12 حتى يصدر إصلاح بعد v1.1.0، لأن إنشاء المشاريع وتعديلها يفشل في 1.1.0.
  • اجعل ROOT_URL مطابقاً للنطاق مع https://، وفعل WebSockets في الـ Reverse Proxy.
  • سجل حساب المدير فور التشغيل، ثم أغلق التسجيل من الواجهة ومن السيرفر معاً بـ forbidClientAccountCreation في METEOR_SETTINGS، لأن خيار الواجهة وحده يخفي النموذج فقط.
  • لا تقم بنشر منفذ MongoDB، وخذ نسخة بـ mongodump وجرب استعادتها، وخذ نسخة قبل كل تحديث.

سجل التحديثات

  • سبتمبر 2026: كتابة الدليل واختباره على Titra v1.0.12 مع MongoDB 8.0.32 (مع تجربة v1.1.0 وتوثيق خلل إنشاء المشاريع فيه).
  • أكتوبر 2026: مراجعة الدليل والتأكد أن v1.1.0 ما زال أحدث إصدار وأن الخلل ما زال فيه ويشمل تعديل المشاريع أيضاً، وإضافة إغلاق التسجيل من جهة السيرفر بـ METEOR_SETTINGS لأن خيار Disable new user registration يخفي النموذج فقط، وتصحيح تصنيف إصدارات MongoDB الفرعية.
نشرة عرب رووت | ArabRoot

معرفة تستحق مكاناً في بريدك.

مقالات مختارة وأدوات مفيدة وأفكار لمشروعك القادم، في رسالة واحدة كل أسبوع.

يمكنك إلغاء الاشتراك متى شئت. الخصوصية

تم استلام طلبك. افتح بريدك واضغط رابط التأكيد لإتمام الاشتراك.