- TypeScript 94.5%
- CSS 3.4%
- JavaScript 2.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .forgejo/workflows | ||
| build | ||
| scripts | ||
| src | ||
| tests | ||
| .editorconfig | ||
| .gitignore | ||
| .prettierignore | ||
| .prettierrc | ||
| AGENTS.md | ||
| CHANGELOG.md | ||
| electron-builder.yml | ||
| electron.vite.config.ts | ||
| eslint.config.mjs | ||
| LICENSE | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
| tsconfig.node.json | ||
| tsconfig.web.json | ||
| vitest.config.ts | ||
اشتراكاتي · Ishtarkati
تطبيق سطح مكتب لتتبّع الاشتراكات والمدفوعات والتجديدات — يعمل محليًا بالكامل.
Offline-first desktop tracker for subscriptions, renewals and account payments.
كل البيانات في قاعدة SQLite محلية · نسخ احتياطي واستعادة · بدون حساب سحابي
Local SQLite storage · backup & restore · no cloud account required
العربية
المزايا
- إدارة الاشتراكات والحسابات: دورة الفوترة، تاريخ التجديد، حالة الدفع، والتصنيفات والوسوم.
- متابعة طرق الدفع: البطاقات (مع شريط انتهاء الصلاحية) والمحافظ الإلكترونية.
- لوحة رئيسية وتقارير: المصروفات، التدفق النقدي، التنبيهات، وتقويم الاستحقاقات.
- الميزانية الشهرية مع تنبيهات التجاوز.
- عملات متعددة مع أسعار صرف قابلة للتحديث وتجاوزات يدوية.
- تذكيرات سطح المكتب (مع إمكانية إسكاتها) وقفل اختياري برمز PIN.
- نسخ احتياطي تلقائي ويدوي إلى مجلد تختاره، مع استعادة كاملة، وإمكانية تشفير الملف بكلمة مرور أو برمز قفل التطبيق.
- نسخ استرجاع قابلة للعرض والإرجاع من الإعدادات، وتراجع فوري بعد أي حذف أو دمج.
- تحليلات: توقع التدفق النقدي لاثني عشر شهرًا، وكشف الحسابات الخاملة، وميزانية لكل تصنيف، وتقرير بالاشتراكات المتشابهة التي قد تُدفع مرتين.
- بحث فوري بفهرس FTS5، وقائمة حسابات تُعرض على صفحات مع التمرير.
- تقرير تشخيصي للدعم (بلا أي بيانات شخصية).
- إيقاف مؤقت لأي حساب (يبقى محفوظًا ويخرج من الاستحقاقات والتذكيرات)، واسترجاع أي قيمة مسجّلة في سجل التعديلات، وتقرير بتغيّر الأسعار.
- واجهة عربية/إنجليزية كاملة (RTL/LTR)، وثيم فاتح/داكن/حسب النظام.
- يعمل دون اتصال: الخطوط مضمّنة، والشبكة تُستخدم فقط لفحص التحديث (ويتجاهل الفشل بصمت).
التثبيت والتشغيل
npm install
npm run dev # تشغيل التطوير
npm test # الاختبارات
npm run typecheck # فحص الأنواع
npm run lint # فحص الكود
npm run gen:icon # توليد الأيقونات
npm run dist # بناء AppImage في release/
better-sqlite3وحدة أصلية:npm installيبنيها لإلكترون عبرpostinstall، وسكربتpretestيعيد بناءها لـ Node قبل الاختبارات ثم يعيدها لإلكترون بعدها.
التحميل
من صفحة Releases: نزّل أحدث ملف
ishtarkati-<version>.AppImage ثم:
chmod +x ishtarkati-<version>.AppImage
./ishtarkati-<version>.AppImage
البيانات المحلية
تُحفظ قاعدة البيانات في app.getPath('userData')/ishtarkati.db (SQLite + WAL).
حذف التطبيق لا يحذف بياناتك؛ استخدم نسخة احتياطية قبل أي إعادة تثبيت.
English
Features
- Subscription & account management: billing cycle, renewal date, payment status, categories and tags.
- Payment methods: credit cards (with expiry bar) and digital wallets.
- Dashboard and insights: spend, cash flow, attention lists and a due-date calendar.
- Monthly budget with over-budget warnings.
- Multi-currency amounts with refreshable FX rates and manual overrides.
- Desktop reminders (with snooze) and an optional PIN lock.
- Automatic and manual backups to a folder of your choice, with full restore, plus optional passphrase (or app-lock PIN) encryption of the backup file.
- Recovery copies can be listed and put back from Settings, and any delete or merge offers an undo.
- Analytics: a rolling 12-month cash-flow projection, dormant-account detection, a monthly budget per category, and a report of look-alike accounts that may be paid twice.
- Instant search backed by an FTS5 trigram index, and an accounts list that renders in pages.
- A support diagnostics report that contains no personal data.
- Pause/resume for any account (kept, but out of due lists and reminders), restoring a value straight from the account's change history, and a price-change report.
- Complete Arabic/English UI (RTL/LTR) and a light/dark/system theme.
- Offline-first: fonts are embedded and only the update check touches the network (it degrades silently on failure).
Install & run
npm install
npm run dev # development
npm test # tests
npm run typecheck # type checking
npm run lint # linting
npm run gen:icon # generate app icons
npm run dist # build the AppImage into release/
npm run lint # ESLint (includes the React hooks rules)
Tests
npm test runs Vitest over src/**/*.test.* and tests/; npm run test:coverage does the same and
enforces the thresholds in vitest.config.ts (what CI runs). npm run smoke boots the packaged
app on a temporary profile and checks the database it creates — the release workflow runs it before
publishing, so a build that starts broken never reaches the release page.
node scripts/gen-css.mjs regenerates the numeric helper block at the end of global.css; run it (or
let the design test tell you to) after adding a helper class. scripts/ also holds the icon generator
and the release script.
tests/harness/ boots the app's real SQLite schema in memory and installs a window.api backed
by it, so a test can render a page and click its real buttons while asserting database state:
// @vitest-environment jsdom
const db = createTestDb()
installApi(db)
renderWithProviders(<SubscriptionsListPage />)
await userEvent.click(screen.getByRole('button', { name: text('home.markPaid') }))
better-sqlite3is a native module:npm installrebuilds it for Electron viapostinstall, whilepretestrebuilds it for Node before the test run andposttestswitches it back for Electron.
Download
From the Releases page, download the
latest ishtarkati-<version>.AppImage, then:
chmod +x ishtarkati-<version>.AppImage
./ishtarkati-<version>.AppImage
Project layout
src/
├── main/ Electron main process (SQLite, backups, tray, IPC)
├── preload/ contextBridge API exposed as window.api
├── shared/ types, locales and constants shared by both sides
└── renderer/ React UI (components, pages, hooks, lib, styles/global.css)
Local data
The database lives at app.getPath('userData')/ishtarkati.db (SQLite with WAL).
Removing the app does not delete your data — take a backup before reinstalling.
البناء على المعيار / Built on the standard
هذا التطبيق ملتزم بـ debe/desktop-standard:
الستاك الثابت (Electron 44 + electron-vite 5 + React 19 + TypeScript 5.9)، ثيم متغيّرات CSS
في src/renderer/src/styles/global.css (بدون Tailwind وبدون لون مكتوب في المكوّنات)، شل
موحّد (قائمة جانبية + إصدار + ثيم ثلاثي + عربي/إنجليزي + إشعار تحديث من Forgejo)،
وبدون إيموجي.
This app follows the debe/desktop-standard
contract: fixed stack (Electron 44 + electron-vite 5 + React 19 + TypeScript 5.9), a
CSS-variable theme in src/renderer/src/styles/global.css (no Tailwind, no hardcoded
colours in components), the required shell (sidebar with version, tri-state theme,
ar/en toggle, Forgejo update notice) and no emoji.
التحقّق / Verify:
node path/to/desktop-standard/scripts/check-standard.mjs .
ملاحظات على الالتزام / Compliance notes
النقاط التالية مقصودة وموثّقة (كل الفحوص في check-standard.mjs ناجحة):
-
الإعدادات تُحفظ في قاعدة SQLite الخاصة بالتطبيق، لذا لا تُستخدم وحدتا
store.ts/paths.tsمن القالب — مصدر واحد للإعدادات بدلًا من ملف JSON منفصل. -
مسارات إضافية ضرورية للتطبيق فوق الهيكل الثابت:
src/renderer/src/{pages,hooks,lib,db,types}وsrc/shared/{locales,locale.ts,settingsKeys.ts,backupIPC.ts}. تبقى مكوّنات الواجهة فيcomponents/كما في المعيار. -
react-router-domمُبقى عليه للمسارات العميقة (تفاصيل الاشتراك، التعديل…). -
سكربتات إضافية للوحدة الأصلية:
rebuild:native(منpostinstall)، وpretest/posttestلتبديل بناءbetter-sqlite3بين Node (الاختبارات) وإلكترون (التشغيل والتغليف). -
test.ymlيشغّلnpm run test:coverage(لاnpm test) ليفرض حدود التغطية، ويضيف خطوةnpm run lintبعدها (المعيار يذكر الاختبارات وفحص الأنواع فقط). -
global.cssأكبر من قالب المعيار (2742 سطرًا و429 فئة، منها 141 فئة مساعدة مولَّدة آليًا مقابل 86 فئة في القالب). التطبيق يستخدم فئات المعيار القياسية للهيكل والأزرار والبطاقات والنوافذ والتنبيهات، ويضيف فوقها طبقة مساعدة رقمية للتخطيط (صفوف/أعمدة/شبكات/مسافات/أحجام/أنماط نصية) ترث قيمها من متغيرات المعيار ولا تحمل أي لون خاص. الطبقة مولَّدة بـ_migration/gen-css.pyولا تُكتب يدويًا، واختبارtests/design-standard.test.tsيفشل إذا استعمل أي مكوّن فئة غير معرّفة (وهو الخطأ الذي جعل الأيقونات تظهر بحجم كبير). -
خمس فئات من قالب المعيار لا تنطبق على شاشات هذا التطبيق ولم تُضف عن قصد:
detail-gridوdetail-item(صفحة التفاصيل هنا بطاقات لا جدول حقول)، وnotes-previewوcell-email(لا يوجد جدول ملاحظات/بريد)، وsettings-content(الإعدادات تمرّر مع الصفحة لا في حاوية مستقلة). الفئتان المناسبتانfilter-selectوexport-gridمُضافتان ومستعملتان. -
Settings persist in the app's SQLite database, so the template's
store.ts/paths.tsare not used — one source of configuration instead of a separate JSON file. -
Extra directories beyond the fixed skeleton are required by the app:
src/renderer/src/{pages,hooks,lib,db,types}andsrc/shared/{locales,locale.ts,settingsKeys.ts,backupIPC.ts}. UI components stay undercomponents/as in the standard. -
react-router-domis kept for the app's deep routes (subscription detail, edit, …). -
Extra npm scripts handle the native module:
rebuild:native(frompostinstall) andpretest/posttestto switch thebetter-sqlite3build between Node (tests) and Electron (dev + packaging). -
test.ymlrunsnpm run test:coverage(notnpm test) so the coverage thresholds are enforced, and adds annpm run lintstep after it (the standard's template only lists tests and type checking). -
global.cssis larger than the standard's template (2742 lines and 429 classes, of which 141 are generated helpers, against the template's 86 classes). The app uses the standard component classes for the shell, buttons, cards, modals and notices, and adds a numeric layout helper layer on top (rows, stacks, grids, spacing, sizes, text tones); every value resolves to a standard CSS variable and carries no brand colour of its own. The layer is generated by_migration/gen-css.py, never hand-written, andtests/design-standard.test.tsfails if any component references a classglobal.cssdoes not define — the mistake that made the icons render huge. -
Five classes from the standard's template deliberately do not exist here because this app has no screen they fit:
detail-grid/detail-item(the detail screen is a set of cards, not a field table),notes-previewandcell-email(there is no notes/e-mail table), andsettings-content(settings scroll with the page rather than in their own pane). The two that do apply,filter-selectandexport-grid, are defined and used.
الترخيص / License
هذا العمل مرخّص تحت CC BY-NC-SA 4.0 — استخدام غير تجاري مع مشاركة بالمثل.
This work is licensed under CC BY-NC-SA 4.0 — non-commercial, share-alike.