{"id":49888290,"url":"https://github.com/boxlinknet/kwtsms-firebase","last_synced_at":"2026-05-15T19:33:47.239Z","repository":{"id":347194150,"uuid":"1192376829","full_name":"boxlinknet/kwtsms-firebase","owner":"boxlinknet","description":"Firebase Extension for kwtSMS SMS gateway. Send SMS, OTP verification, and notifications from Firebase with Firestore queue, Auth triggers, HTTPS callables, and scheduled sync.","archived":false,"fork":false,"pushed_at":"2026-04-09T15:22:02.000Z","size":428,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-09T16:28:32.968Z","etag":null,"topics":["arabic","cloud-functions","firebase","firebase-extension","firestore","kuwait","kwtsms","notifications","otp","sms","sms-gateway"],"latest_commit_sha":null,"homepage":"https://www.kwtsms.com/integrations.html","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/boxlinknet.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-26T06:41:02.000Z","updated_at":"2026-04-09T15:20:27.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/boxlinknet/kwtsms-firebase","commit_stats":null,"previous_names":["boxlinknet/kwtsms-firebase"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/boxlinknet/kwtsms-firebase","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boxlinknet%2Fkwtsms-firebase","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boxlinknet%2Fkwtsms-firebase/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boxlinknet%2Fkwtsms-firebase/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boxlinknet%2Fkwtsms-firebase/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/boxlinknet","download_url":"https://codeload.github.com/boxlinknet/kwtsms-firebase/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boxlinknet%2Fkwtsms-firebase/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33076221,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-15T11:35:32.926Z","status":"ssl_error","status_checked_at":"2026-05-15T11:35:31.362Z","response_time":103,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arabic","cloud-functions","firebase","firebase-extension","firestore","kuwait","kwtsms","notifications","otp","sms","sms-gateway"],"created_at":"2026-05-15T19:33:46.336Z","updated_at":"2026-05-15T19:33:47.226Z","avatar_url":"https://github.com/boxlinknet.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://www.kwtsms.com/images/kwtsms_logo_60.png\" alt=\"kwtSMS\" height=\"60\"\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003ekwtSMS Firebase Extension\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  Send SMS notifications, OTP codes, and alerts from Firebase using the \u003ca href=\"https://www.kwtsms.com\"\u003ekwtSMS\u003c/a\u003e gateway.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/boxlinknet/kwtsms-firebase/releases\"\u003e\u003cimg src=\"https://img.shields.io/github/v/release/boxlinknet/kwtsms-firebase?label=version\u0026color=FFA200\" alt=\"Version\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/boxlinknet/kwtsms-firebase/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-Apache--2.0-blue\" alt=\"License\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.typescriptlang.org/\"\u003e\u003cimg src=\"https://img.shields.io/badge/TypeScript-5.4-3178C6?logo=typescript\u0026logoColor=white\" alt=\"TypeScript\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://firebase.google.com/docs/extensions\"\u003e\u003cimg src=\"https://img.shields.io/badge/Firebase-Extension-FFCA28?logo=firebase\u0026logoColor=black\" alt=\"Firebase Extension\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://nodejs.org/\"\u003e\u003cimg src=\"https://img.shields.io/badge/node-%3E%3D20-339933?logo=node.js\u0026logoColor=white\" alt=\"Node.js\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.kwtsms.com\"\u003e\u003cimg src=\"https://img.shields.io/badge/SMS-kwtSMS-FFA200\" alt=\"kwtSMS\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n## About kwtSMS\n\n[kwtSMS](https://www.kwtsms.com) is a Kuwait-based SMS gateway that provides reliable A2P (application-to-person) messaging across Kuwait and 100+ countries. It supports transactional SMS (OTP, alerts, notifications) and promotional campaigns with Arabic and English content. kwtSMS is used by businesses, banks, and government entities in the GCC region for SMS delivery through local carrier routes.\n\n- API documentation: [kwtsms.com/integrations.html](https://www.kwtsms.com/integrations.html)\n- Client libraries: PHP, Python, JavaScript, Ruby, Go, Java, C#, Swift, Kotlin, Rust, Dart, Zig\n- Sender ID registration, transactional and promotional routing, real-time balance and coverage APIs\n\n## What this extension does\n\nInstall this extension in your Firebase project to send SMS through kwtSMS. Write a document to Firestore and the extension sends it as SMS automatically. No server setup, no SMS infrastructure to manage.\n\n**Cloud Functions (6 total):**\n\n| Function | Type | What it does |\n|----------|------|-------------|\n| `processQueue` | Firestore trigger | Sends SMS when a document is created in the queue collection |\n| `onUserCreate` | Auth trigger | Sends a welcome SMS when a new user signs up with a phone number |\n| `sendSms` | HTTPS callable | Sends SMS on demand from your client app (rate limited: 10/min per user) |\n| `handleOtp` | HTTPS callable | Generates and verifies one-time passwords (60s cooldown, 3 attempts, 5min expiry) |\n| `scheduledSync` | Scheduled | Syncs balance, sender IDs, and coverage from kwtSMS daily |\n| `onInstallHandler` | Lifecycle | Seeds settings, templates, and runs first sync on install |\n\n**Admin Dashboard (Firebase Hosting):**\n\n| Page | What it does |\n|------|-------------|\n| Dashboard | Balance, sent today, test mode/gateway status, recent activity |\n| Settings | Gateway toggles, sender ID, app name, country code, test SMS sender |\n| Templates | View/edit all templates (EN + AR), create custom, delete, revert to defaults |\n| SMS Logs | Filter by type/trigger/status/date, expandable detail rows, pagination, CSV export |\n| Help | Code examples, template variables reference, troubleshooting, error codes |\n\n**Security features:**\n\n- OTP codes hashed (SHA-256) with timing-safe comparison\n- Rate limiting: 10 sends/min per user (callable), 60s OTP cooldown\n- Generic error messages to prevent phone enumeration\n- Firestore rules with admin custom claim for dashboard access\n- Input validation and idempotency guards on all handlers\n- Credentials never logged at any level\n\n**Additional capabilities:**\n\n- Multilingual templates with `{{placeholder}}` support (English and Arabic)\n- Phone number normalization: strips prefixes, converts Arabic digits, prepends country codes\n- Configurable sender ID and default country code from synced API data\n- Global gateway on/off switch and test mode (no delivery, no credits consumed)\n- Firestore audit logs + Cloud Functions debug logging\n- Settings cache with 5s TTL to reduce Firestore reads\n\n## Prerequisites\n\n- [Firebase CLI](https://firebase.google.com/docs/cli) installed (`npm install -g firebase-tools`)\n- A Firebase project with **Firestore** and **Authentication** (email/password) enabled\n- A [kwtSMS account](https://www.kwtsms.com) with API access enabled\n- Node.js \u003e= 20\n\n## Installation\n\n### Step 1: Install the extension\n\n**From GitHub (recommended):**\n\n```bash\nfirebase ext:install https://github.com/boxlinknet/kwtsms-firebase --project=YOUR_PROJECT\n```\n\n**From Firebase Extensions Hub** (when available):\n\n```bash\nfirebase ext:install kwtsms/kwtsms-firebase --project=YOUR_PROJECT\n```\n\n**From local source:**\n\n```bash\ngit clone https://github.com/boxlinknet/kwtsms-firebase.git\ncd kwtsms-firebase/functions \u0026\u0026 npm install \u0026\u0026 npx tsc \u0026\u0026 cd ..\nfirebase ext:install . --project=YOUR_PROJECT\n```\n\nDuring installation, you will be prompted for:\n- **kwtSMS API username** (not your phone number, find it in your kwtSMS account settings)\n- **kwtSMS API password**\n- **Application name** (used in welcome/OTP templates)\n- **Cloud Functions location** (choose closest to your users)\n\nCredentials are stored securely in [Cloud Secret Manager](https://cloud.google.com/secret-manager).\n\n### Step 2: Deploy the dashboard (optional)\n\n```bash\ncd kwtsms-firebase/web\nnpm install\nnpm run build\ncd ..\nfirebase deploy --only hosting --project=YOUR_PROJECT\n```\n\n### Step 3: Set up admin access for the dashboard\n\nThe dashboard requires Firebase Auth with an admin custom claim. Create an admin user:\n\n```bash\n# Create a user in Firebase Console \u003e Authentication \u003e Users \u003e Add User\n# Then set the admin claim using the Firebase Admin SDK:\nfirebase functions:shell\n\u003e const admin = require('firebase-admin');\n\u003e admin.auth().setCustomUserClaims('USER_UID_HERE', { admin: true });\n```\n\n### Step 4: Verify installation\n\n1. Check Firestore: `sms_config/settings` and `sms_config/sync` documents should exist\n2. Check `sms_templates` collection: 8 default templates seeded\n3. Open the dashboard and log in with your admin user\n4. Send a test SMS from Settings page (test mode is ON by default, no real delivery)\n\n## Configuration\n\nThe extension creates a `sms_config/settings` document in Firestore with these defaults:\n\n| Setting | Default | Description |\n|---------|---------|-------------|\n| `gateway_enabled` | `true` | Global on/off switch for all SMS sending |\n| `test_mode` | `true` | Sends with test=1, no delivery, no credits consumed |\n| `debug_logging` | `false` | Enables verbose Cloud Functions logs |\n| `default_country_code` | `965` | Prepended to numbers without a country code |\n| `selected_sender_id` | `KWT-SMS` | Active sender ID from your kwtSMS account |\n| `app_name` | `My App` | Used in template placeholders (welcome, OTP messages) |\n\nTest mode is on by default. Change settings via the dashboard or edit the Firestore document directly. Set `test_mode` to `false` when you're ready for production.\n\n## Usage\n\n### Send SMS with Firestore queue\n\nWrite a document to the `sms_queue` collection:\n\n```javascript\nimport { getFirestore, addDoc, collection } from 'firebase/firestore';\n\nconst db = getFirestore();\n\n// Send with inline message\nawait addDoc(collection(db, 'sms_queue'), {\n  to: '96598765432',\n  message: 'Your order has been confirmed.',\n});\n\n// Send with template (Arabic)\nawait addDoc(collection(db, 'sms_queue'), {\n  to: '96598765432',\n  template: 'order_confirmed',\n  templateData: { customer_name: 'Ahmad', order_id: 'ORD-123' },\n  language: 'ar',\n});\n\n// Send to multiple recipients\nawait addDoc(collection(db, 'sms_queue'), {\n  to: '96598765432, 96612345678',\n  message: 'Flash sale starts now!',\n});\n```\n\nThe extension picks up the document, sends the SMS, and updates it with the result:\n\n```javascript\n{\n  status: 'sent',        // 'sent', 'failed', or 'skipped'\n  response: { ... },     // kwtSMS API response\n  test: true,            // whether test mode was active\n  processedAt: Timestamp\n}\n```\n\n### Send SMS with callable function\n\n```javascript\nimport { getFunctions, httpsCallable } from 'firebase/functions';\n\nconst functions = getFunctions();\nconst sendSms = httpsCallable(functions, 'ext-kwtsms-firebase-sendSms');\n\nconst result = await sendSms({\n  action: 'send',\n  to: '96598765432',\n  template: 'order_shipped',\n  templateData: { customer_name: 'Ahmad', order_id: 'ORD-123' },\n  language: 'en',\n});\n// result.data = { success: true, msgId: '...' }\n```\n\nRequires Firebase Auth. Rate limited to 10 requests per minute per user.\n\n### OTP verification\n\n```javascript\nconst handleOtp = httpsCallable(functions, 'ext-kwtsms-firebase-handleOtp');\n\n// Generate and send OTP\nawait handleOtp({ action: 'sendOtp', phone: '96598765432' });\n// { success: true, expiresIn: 300 }\n\n// Verify OTP code\nconst result = await handleOtp({\n  action: 'verifyOtp',\n  phone: '96598765432',\n  code: '123456',\n});\n// { success: true } or { success: false, error: 'Verification failed' }\n```\n\n- Codes expire after **5 minutes**\n- Maximum **3 verification attempts** per code\n- **60-second cooldown** between sends to the same phone\n- Codes are hashed before storage (SHA-256)\n\n## Templates\n\nThe extension seeds 8 default templates on install. Templates support English and Arabic with `{{placeholder}}` replacement. Edit via the dashboard or directly in the `sms_templates` Firestore collection.\n\n| Template | Placeholders |\n|----------|-------------|\n| `welcome` | `app_name` |\n| `otp` | `app_name`, `code`, `expiry_minutes` |\n| `order_confirmed` | `customer_name`, `order_id` |\n| `order_shipped` | `customer_name`, `order_id` |\n| `order_delivered` | `customer_name`, `order_id` |\n| `status_update` | `customer_name`, `order_id`, `status` |\n| `reminder` | `customer_name`, `reminder_text` |\n| `custom` | `message` |\n\nSystem templates can't be deleted but their body text can be changed and reverted to the original. Create custom templates via the dashboard.\n\n## Monitoring\n\n- **Dashboard**: Balance, sent count, gateway status, recent activity at a glance\n- **SMS Logs**: Filter and search all send attempts in the dashboard (or `sms_logs` collection)\n- **Balance**: Synced daily from kwtSMS API (or click \"Sync Now\" on dashboard)\n- **Debug logs**: Enable `debug_logging` in settings, then check Cloud Functions logs\n\n## Roadmap\n\n| Phase | Status | Scope |\n|-------|--------|-------|\n| 1. Extension core | v1.0.0 | Queue, Auth, callable, OTP, sync, templates, logging, security hardening |\n| 2. Dashboard | v1.0.0 | Settings UI, templates editor, SMS logs viewer, help page (Firebase Hosting) |\n| 3. Campaigns | Planned | Scheduled messages, reminders, bulk campaigns |\n| 4. Security | Planned | CAPTCHA, advanced rate limiting, abuse prevention |\n\n## Documentation\n\n- [kwtSMS API docs](https://www.kwtsms.com/integrations.html)\n- [kwtSMS JS client library](https://github.com/boxlinknet/kwtsms-js)\n- [Firebase Extensions docs](https://firebase.google.com/docs/extensions)\n\n## Support\n\n- kwtSMS support: [kwtsms.com/support.html](https://www.kwtsms.com/support.html)\n- Issues: [github.com/boxlinknet/kwtsms-firebase/issues](https://github.com/boxlinknet/kwtsms-firebase/issues)\n\n## License\n\nApache-2.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboxlinknet%2Fkwtsms-firebase","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fboxlinknet%2Fkwtsms-firebase","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboxlinknet%2Fkwtsms-firebase/lists"}