Welcome to Tahdeeth Docs!
Tahdeeth is an enterprise-grade Over-the-Air update platform built for React Native. Deploy critical patches instantly — without app store delays or user disruption.
What is Tahdeeth?
Tahdeeth is a sovereign code-push solution designed for regulated industries. It runs on Saudi-hosted infrastructure and gives engineering teams full control over rollout speed, target audiences, and rollback.
It ships a lightweight client SDK and a powerful CLI — so you can push, monitor, and roll back updates without leaving your terminal.
Features
Instant Updates
Ship JS bundle patches without going through the app store review process.
Signature Verification
Every bundle is cryptographically signed and verified before install.
Auto Rollback
Bad update? Automatically roll back to the last stable bundle.
Multi-Environment
Separate staging and production keys with per-environment rollout control.
Retry Mechanism
Built-in retry logic ensures reliable delivery on poor connections.
Sovereign Infra
Runs on Saudi-hosted infrastructure. Your data never leaves the region.
Required prerequisites
| Prerequisite | Version |
|---|---|
| Expo SDK | ≥ 50 |
| @tahdeeth/cli | Latest |
Next Steps
Installation
Install the Tahdeeth SDK and its required peer dependency into your Expo project.
Install packages
Dependencies
| Package | Required | Purpose |
|---|---|---|
| @almawrid/react-native-tahdeeth | Yes | Core OTA update SDK |
| react-native-blob-util | Yes | Required for downloading update bundles |
react-native-blob-util is a native module. Run npx pod-install after installation on iOS.Next Steps
Initialization
Initialize the Tahdeeth SDK with your API key, then configure your native entry points so the SDK can serve OTA bundles at runtime.
Initialize the SDK
Call Tahdeeth.init() at the top of your entry file, before any component renders:
import Tahdeeth from '@almawrid/react-native-tahdeeth';Tahdeeth.init({apiKey: 'YOUR_API_KEY',});
Native Setup
Override getJSBundleFile() in your MainApplication.kt:
import com.tahdeeth.Tahdeethoverride fun getJSBundleFile(): String? {return Tahdeeth.bundleJS(this@MainApplication)}
Next Steps
Tahdeeth CLI
A command-line tool for managing Tahdeeth hot updates — build bundles, upload versions, and control app updates directly from your terminal.
Installation
npm install -g @almawrid/tahdeeth-cli# oryarn global add @almawrid/tahdeeth-cli
Quick Start
Four commands to go from zero to your first deployed update:
# 1. Initialize config in your project roottahdeeth-cli init# 2. Log in to your Tahdeeth accounttahdeeth-cli login# 3. Build the JS bundletahdeeth-cli build -p android# 4. Upload the bundletahdeeth-cli upload -p android -v 1.0.1
Commands
tahdeeth-cli initOne-time project setupCreates a tahdeeth.json config file in the current directory. Run once per project before using any other commands. If the file already exists, the command exits without overwriting it.
tahdeeth-cli init
You will be prompted for:
| Prompt | Description | Example |
|---|---|---|
| Server URL | Backend API base URL | https://api.yourbackend.com |
| Dashboard URL | Dashboard web URL | https://your.dashboard.com |
| Application ID | Your app's unique ID in Tahdeeth | abc123 |
Generated tahdeeth.json:
{"server_url": "https://api.yourbackend.com","dashboard_url": "https://your.dashboard.com","appId": "abc123"}
tahdeeth-cli loginAuthenticate with TahdeethOpens the dashboard login page in your browser and waits for the OAuth flow to complete. The token is stored securely in the system keychain. Requires a valid tahdeeth.json. If already logged in, run logout first.
tahdeeth-cli login
tahdeeth-cli logoutRemove stored credentialsRemoves your credentials from the system keychain.
tahdeeth-cli logout
tahdeeth-cli whoamiShow the logged-in userDisplays the currently authenticated user.
tahdeeth-cli whoami
tahdeeth-cli buildBuild a JS bundle for uploadBuilds a React Native / Expo JS bundle and compresses it into a zip archive. The project type is auto-detected from package.json.
| Option | Alias | Values | Default |
|---|---|---|---|
| --platform | -p | android · ios · both | both |
| --type | -t | bundle · hermes | bundle |
# Build for both platforms (default)tahdeeth-cli build# Android onlytahdeeth-cli build -p android# iOS onlytahdeeth-cli build -p ios# Hermes bytecode for Androidtahdeeth-cli build -p android -t hermes
Output files (inside bundles_outputs/):
| Platform | Type | Output file |
|---|---|---|
| Android | bundle | bundles_outputs/android/index.android.bundle.zip |
| Android | bundle | bundles_outputs/android/sourcemap.zip |
| iOS | bundle | bundles_outputs/ios/main.jsbundle.zip |
| iOS | bundle | bundles_outputs/ios/sourcemap.zip |
tahdeeth-cli uploadUpload a built bundle to your serverUploads a built bundle to your Tahdeeth server. Must be logged in with a valid tahdeeth.json. Run build first.
| Option | Alias | Values | Default |
|---|---|---|---|
| --platform | -p | android · ios · both | both |
| --version | -v | string | 1.0.0 |
# Upload both platforms (default version)tahdeeth-cli upload# Android — tag version 1.2.0tahdeeth-cli upload -p android -v 1.2.0# iOS — tag version 2.0.0tahdeeth-cli upload -p ios -v 2.0.0
Config File Reference
tahdeeth.json is created by init and read by login, build, and upload.
{"server_url": "https://api.yourbackend.com","dashboard_url": "https://your.dashboard.com","appId": "your-app-id"}
| Key | Description |
|---|---|
| server_url | Base URL of your Tahdeeth backend API |
| dashboard_url | Base URL of the dashboard (used for browser login) |
| appId | Application identifier used when uploading bundles |
Typical Workflow
Run init and login once per project. After that, every release is two commands.
# Run once per projecttahdeeth-cli inittahdeeth-cli login# Each releasetahdeeth-cli build -p both -t bundletahdeeth-cli upload -p both -v 1.2.0
Next Steps
Configuration
Customize SDK behavior by passing options to Tahdeeth.init().
Options
| Option | Type | Required | Description |
|---|---|---|---|
| apiKey | string | Yes | Environment-specific API key from the dashboard |
| baseURL | string | No | Override the default server URL for self-hosted deployments |
Example
Tahdeeth.init({apiKey: "YOUR_API_KEY",baseURL: "https://tahdeeth.cloider.com",});
baseURL defaults to https://tahdeeth.cloider.com. Only override it if you are running a self-hosted instance.Next Steps
Environments
Tahdeeth supports multiple deployment environments so you can safely test updates before rolling them out to production.
Overview
Staging
Test your updates before they reach end users. Use a dedicated staging API key.
Production
Live environment. Updates pushed here are delivered immediately to all users.
How it works
- key
Each environment has its own API key. Pass the correct key to
Tahdeeth.init()based on your build variant. - dashboard
Environments are managed from the Tahdeeth Dashboard. You can create, rename, or revoke keys at any time.
- shield
Updates are scoped per environment — a bundle pushed to staging will never be served to a production build.
Next Steps
Usage
Integrate the Tahdeeth update flow into your root component. The SDK checks for updates on each app launch and installs them silently in the background.
Full Integration Example
import React from "react";import { View } from "react-native";import BlobUtil from "react-native-blob-util";import Tahdeeth from "@almawrid/react-native-tahdeeth";import { useAsyncEffect } from "use-async-effect";Tahdeeth.init({apiKey: "YOUR_API_KEY",baseURL: "https://tahdeeth.cloider.com",});export default function App() {useAsyncEffect(async () => {try {const update = await Tahdeeth.fetchAvailableUpdate();if (!update.updateAvailable) return;const { bundleUrl, verified } =await Tahdeeth.validateDownloadedUpdate(update);if (!verified) return;await Tahdeeth.downloadBundleUri(BlobUtil,bundleUrl,update.version,{ restartAfterInstall: true });} catch (e) {console.error("Tahdeeth Update Error:", e);}}, []);return <View />;}
Update Flow
Check for updates
Fetch available update metadata from the Tahdeeth server.
const update = await Tahdeeth.fetchAvailableUpdate();
Validate the bundle
Verify the cryptographic signature before downloading. Tampered or invalid bundles are rejected automatically.
const { bundleUrl, verified } =await Tahdeeth.validateDownloadedUpdate(update);
Download and install
Download the bundle and restart the app to apply the update.
await Tahdeeth.downloadBundleUri(BlobUtil, bundleUrl, update.version,{ restartAfterInstall: true });
Next Steps
Security
Tahdeeth is built with security as a first-class concern. Every update bundle goes through a multi-layer verification process before it is applied to a device.
Signature Verification
Cryptographic Signing
Every bundle is signed by the Tahdeeth server using asymmetric cryptography. The SDK verifies the signature on-device before applying any update.
Tamper Protection
If a bundle has been modified in transit, signature verification will fail and the update is discarded — keeping your users safe.
Automatic Rejection
The SDK automatically rejects bundles that fail verification. No special error handling is required from your side.
What happens if verification fails?
The update is silently dropped. Your app continues running on the current bundle — no crash, no restart, no user impact. Failed verifications are logged to the Tahdeeth Dashboard for auditing.
Safe by default
Tahdeeth follows a strict fail-safe model: if anything goes wrong during the update process — verification failure, download error, or network timeout — the app falls back to the last known-good bundle automatically.