wayBetter Store

(FOSS) طلب السحب هو التقديم

انشر عملك.

السمة ملف JSON واحد. والإضافة ملف JavaScript واحد. اصنعها، جرّبها في التطبيق، ثم أضفها إلى المتجر: مجلد واحد في طلب سحب واحد، أو الملف في بلاغ إن كنت لا تستخدم git. كلاهما يحتاج إلى حساب مجاني على git.crt.fyi، ولا شيء غيره.

1

اصنعها

ابدأ من ملف يعمل. أداة الإنشاء تكتب لك واحدًا؛ وقسم «إنشاء» في التطبيق نفسه (wayBetter ← إنشاء) فيه أمثلة وقيم السمة الحيّة.

سمة

ألوان، خطوط، زوايا، كثافة، تخطيط، خلفية، تأثيرات. ثلاثة ألوان تكفي؛ والبقية تُشتقّ ويبقى النص مقروءًا.

أو ابنِها في التطبيق: المظهر ← منشئ السمات ← تصدير. ويسرد THEMES.md كل ما تستطيع السمة ضبطه.

إضافة

صنف فيه start() وstop()، وترويسة تذكر من صنعها وما الذي تستخدمه.

أضف --ts لمشروع TypeScript. وفي PLUGINS.md واجهة API والأذونات وإعادة التحميل الحيّة.

hide-trends.plugin.js
/**
 * @name Hide Trends
 * @description Hides the trends box in the right column, so the timeline is the only thing moving.
 * @version 1.0.0
 * @author you
 * @permissions network:none
 */
module.exports = class HideTrends {
  start() { wayBetter.api.injectCSS('hide-trends', '[data-testid="sidebarColumn"] section { display: none }'); }
  stop()  { wayBetter.api.clearCSS('hide-trends'); }
};

يقرأ المتجر اسم الإضافة ومؤلفها وإصدارها ووصفها وأذوناتها من هذه الترويسة، واسم السمة ومؤلفها ووصفها من ملف JSON الخاص بها. وشاشة التثبيت تعرض القيم نفسها، فلا يمكن أن يختلف الاثنان أبدًا.

2

جرّبها

المتجر اختياري. الملف الذي يعمل قابل للمشاركة أصلًا.

  • أفلت الملف على نافذة wayBetter. ستظهر لك شاشة التثبيت نفسها التي يحصل عليها عنصر من المتجر: الاسم، المؤلف، الإصدار، SHA-256، الأذونات، الشيفرة.
  • فعّل وضع المطوّر (الإعدادات ← المطوّر) وأنت تعمل: الإضافة أو ملف السمة أو custom.css المحفوظ يُعاد تحميله في كل علامات التبويب دفعة واحدة.
  • شاركها من دون المتجر. أرسل الملف، أو رابط waybetter://install يشير إلى عنوان https على waybetter.fyi أو cdn1.crt.fyi أو إلى ملف خام على git.crt.fyi. لا تُثبَّت أبدًا من دون شاشة التثبيت.
3

أضف مجلدًا واحدًا

كل عنصر في المتجر مجلد تحت store/<app>/ في المستودع. اسم المجلد هو معرّف العنصر وعنوانه هنا: /store/plugins/<id>/.

store/x/ — عناصر wayBetter for X
store/x/plugins/hide-trends/
  hide-trends.plugin.js   the plugin, exactly as it installs
  item.json               { "category": "focus", "tags": ["trends", "sidebar"] }
  preview.svg             optional, 640×400 (.svg or .png); drawn for you without one

store/x/themes/midnight-mint/
  theme.json              the theme, as Appearance → Export writes it
  item.json               { "version": "1.0.0" }
  preview.svg             optional; drawn from the theme without one
category
الإضافات: reading أو writing أو filters أو focus أو tools. السمات: dark أو light، وتؤخذ من mode الخاص بالسمة إن تركتها.
tags
حتى 12 كلمة قد يبحث بها الناس.
version
للسمات فقط (إصدار الإضافة في ترويستها). ارفعه حين تغيّر الملف.
الوصف
جملة أو جملتان تصفان ما تفعله، من 50 حرفًا فأكثر. وأول 160 حرفًا تصبح وصف صفحتها في محركات البحث.

هذا هو التقديم كله. الصفحة والبطاقة ومدخل البحث ومعاينة الرابط والبيانات المنظَّمة ومدخل خريطة الموقع تُولَّد من الفهرس الموقَّع عند بناء الموقع. وفي store/README.md القواعد كاملة.

4

شغّل الفحوص

لا يوجد CI مستضاف. الفحوص أوامر تشغّلها قبل أن ترسل، ويشغّلها أحد المشرفين مجددًا قبل الدمج.

في نسختك
git submodule update --init
bun install --frozen-lockfile
bun run check:store      # your folder, against the Store's rules
bun run test             # everything else, including the site's SEO test
  • المعرّفات والأسماءمعرّف المجلد (a-z 0-9 -، حتى 40)، name.plugin.js، بلا تكرار داخل التطبيق الواحد
  • الحجمملفات العناصر حتى 2 MiB، والمعاينات حتى 300 KB بنسبة 16:10
  • الترويسة@name و@version ووصف، وسطر @permissions يذكر network أو network:none
  • أذونات صادقةيُرفَض network:none حين تستدعي الشيفرة fetch أو XMLHttpRequest أو WebSocket أو EventSource أو sendBeacon؛ واستدعاءات API المقيَّدة يجب التصريح بها
  • لا شيفرة من مصدر بعيدلا eval ولا new Function ولا import()؛ ولا سكربتات أو ملفات خارجية في المعاينة؛ ولا @import أو عناوين خارجية في CSS السمة
  • الفهرسالعناصر تُبنى في فهرس تقبله التطبيقات (قواعد إطار العمل نفسه)، والفهرس المنشور ما زال يطابق توقيعه وقيم التجزئة
  • البحث والمشاركةعنوان الصفحة حتى 60 حرفًا، والوصف من 50 إلى 160، وكلاهما فريد
5

أرسلها

طريقان للمشاركة. كلاهما يحتاج حسابًا مجانيًا على git.crt.fyi: يمكن لأي شخص التسجيل، ويوافق أحد المشرفين على كل حساب جديد يدويًا.

طلب سحب

  1. انسخ المستودع (Fork) على git.crt.fyi.
  2. أضف مجلدك في فرع وشغّل الفحوص.
  3. افتح طلب السحب. القالب يسألك ماذا تفعل وما الذي تستخدمه.

لا تستخدم git؟ افتح بلاغًا

  1. اختر قالب السمة أو قالب الإضافة.
  2. أرفق الملف (ومعاينة، إن كانت لديك).
  3. يضيف أحد المشرفين المجلد عنك.

ثم يوقّع أحد المشرفين

مفتاح توقيع المتجر غير متصل عمدًا، فالدمج ليس نشرًا. بعد الدمج يقرأ أحد المشرفين الشيفرة، ويشغّل waybetter store build وwaybetter store sign على الجهاز الذي يحفظ المفتاح، ثم يدفع التغييرات. يُعاد بناء الموقع، ويحصل عنصرك على صفحته، ويراه كل تطبيق في المرة التالية التي يقرأ فيها الفهرس الموقَّع.

كل ما في الفهرس الموقَّع يضمنه ذلك المفتاح، ولهذا يقرأ إنسان كل إضافة قبل توقيعها.

{ }

صيغة الفهرس

ملف واحد لكل تطبيقات wayBetter. لا تعدّله يدويًا أبدًا: إنه يُبنى من المجلدات.

catalog.json (الصيغة 2)مفتوح
{ "format": 2, "name": "wayBetter Store", "generatedAt": "2026-09-30T…Z", "items": [
  { "apps": ["x"], "kind": "plugin", "id": "thread-reader", "name": "Thread Reader",
    "author": "wayBetter", "version": "1.2.0", "description": "…",
    "category": "reading", "tags": ["threads"],
    "url": "https://waybetter.fyi/store/plugins/bt-thread-reader.plugin.js",
    "file": "bt-thread-reader.plugin.js", "sha256": "<64 hex>", "size": 10961,
    "preview": "https://waybetter.fyi/store/previews/plugin-thread-reader.svg",
    "permissions": ["ui", "clipboard", "commands", "network:none"] }
] }
  • موقَّع. catalog.json.sig هو توقيع Ed25519 على البايتات نفسها في catalog.json. تتحقق التطبيقات منه بالمفتاح العام المضمَّن فيها، ثم تفحص حجم كل تنزيل وقيمة SHA-256 له.
  • صارم. الحقول غير المعروفة، أو أكثر من 500 عنصر، أو ملف يتجاوز 1 MiB، كلها ترفض الفهرس بكامله. store-catalog.schema.json هو مخطط JSON Schema؛ وفي STORE.md ضمن إطار العمل كل القواعد.
  • مشترك. كل عنصر يسمّي apps الخاصة به. يتحقق التطبيق من الملف كله ويحتفظ بعناصره فقط.
Aa

اللغات

ليست عناصر في المتجر: اللغات الـ51 كلها مدمجة في التطبيق وتُحمَّل عند الحاجة.

  • صحّح ترجمة أو أكملها في apps/desktop/locales/<tag>.json، بطلب سحب أو ببلاغ ترفق به الملف المعدَّل.
  • افحصها بالأمر bun run i18n:check: المفاتيح، العناصر النائبة، صيغ الجمع، بلا وسوم. يجب أن يطبع 0 error(s).
  • تصل مع تحديث التطبيق التالي، لا عبر المتجر. وفي TRANSLATING.md صياغة الرسائل وطريقة رؤية كلماتك في التطبيق.

شاهد ما هو موجود أصلًا.

كل عنصر في المتجر يعرض شيفرته. والإضافات المرفقة أفضل أمثلة على حسن استخدام واجهة API.