Skip to main content
Build with any web framework, access 50+ native capabilities through a single JavaScript function, and publish to both stores from a browser. The runtime runs on the WKWebView (iOS) and the Chromium-based WebView (Android) with hardware acceleration, automatic DOM optimization, smart caching and JIT compilation enabled. Native capabilities are implemented in Swift and Java and exposed to JavaScript through a typed SDK.
Despia is built for builders who want the flexibility of the web with the power of native development - and ship to iOS and Android without a CLI, terminal, or complex build setup. App Store and Google Play submission is handled entirely from a browser.

50+ Native Capabilities

Biometrics, background GPS, push notifications, in-app purchases, home widgets, HealthKit, and more. Implemented in Swift and Java, called from JavaScript.

One-Click Publishing

App Store and Google Play submission from a browser. Code signing and provisioning are handled automatically.

Full Native Export

Export complete Xcode and Android Studio projects. Add native SDKs, modify the runtime, or build independently.

Quickstart

Install the SDK and call your first native capability.
Install the npm package and import the default export. No initialization or setup required.
npm install despia-native
import despia from 'despia-native';
import despia from 'despia-native';

despia('successhaptic://');                                  // haptic feedback
const device = await despia('get-uuid://', ['uuid']);        // native device ID
console.log(device.uuid);
That is it. No initialization. No setup. Open your app in the Despia runtime and it works.

Core concepts

Environment detection, deployment models, and the fundamentals every Despia app relies on before adding native features.

Environment detection

Gate native calls on a runtime check. The despia string is present in the user agent when running inside the Despia runtime.
const isDespia    = navigator.userAgent.toLowerCase().includes('despia')
const isDespiaIOS = isDespia && (
    navigator.userAgent.toLowerCase().includes('iphone') ||
    navigator.userAgent.toLowerCase().includes('ipad')
)
const isDespiaAndroid = isDespia && navigator.userAgent.toLowerCase().includes('android')

Deployment models

The default. The binary ships without embedded web assets. On each launch, the runtime fetches the current build from your configured hosting URL. Web content updates do not require App Store resubmission.

Capabilities

Despia exposes native device features through a single JavaScript function. Each capability is self-contained - no native SDK setup, no platform-specific code.

Identity Vault

Encrypted key-value storage backed by iCloud KV Storage on iOS and Android App Backup on Android. Persists across uninstall and reinstall. Biometric authentication is configured per key.
await despia('setvault://?key=userId&value=user123&locked=false')
const data = await despia('readvault://?key=userId', ['userId'])
Setting locked=true requires Face ID or Touch ID before the value is returned.
await despia('setvault://?key=sessionToken&value=abc123&locked=true')
const token = await despia('readvault://?key=sessionToken', ['sessionToken'])

GPS location

Real-time location tracking with configurable intervals, distance thresholds, live frontend callbacks, and optional server delivery. Background tracking is supported on both platforms including Samsung, Huawei, Xiaomi, and OnePlus.
window.onLocationChange = function(data) {
    if (!data.active) { finalizeRoute(); return }
    drawPointOnMap(data.latitude, data.longitude)
    if (data.speed > 0) {
        updatePaceDisplay((1000 / data.speed / 60).toFixed(2) + ' min/km')
    }
    if (data.horizontalAccuracy > 10) return
}

despia('location://?buffer=60&movement=100')
const data      = await despia('stoplocation://', ['locationSession'])
const drain     = data.locationSession[0]?.battery - data.locationSession.at(-1)?.battery
GPS location reference

Haptic feedback

Five haptic types mapped to native UIFeedbackGenerator on iOS and HapticFeedbackConstants on Android.
despia('lighthaptic://');
despia('heavyhaptic://');
despia('successhaptic://');
despia('warninghaptic://');
despia('errorhaptic://');

UI controls

Show and hide the loading spinner, status bar, and configure status bar color at runtime.
despia('spinneron://');
despia('spinneroff://');
despia('hidebars://on');
despia('statusbarcolor://{255, 255, 255}');

Device identity

Read the app version, build number, and a persistent device UUID that survives reinstalls.
const appInfo  = await despia('getappversion://', ['versionNumber', 'bundleNumber']);
const deviceId = await despia('get-uuid://', ['uuid']);

Contacts and clipboard

Request contact access, read the address book, and read the current clipboard contents.
despia('requestcontactpermission://');
const contacts  = await despia('readcontacts://', ['contacts']);
const clipboard = await despia('getclipboard://', ['clipboarddata']);

Media and sharing

Take a screenshot, save an image from a URL to the camera roll, and trigger the native share sheet.
despia('takescreenshot://');
despia('savethisimage://?url=https://example.com/image.jpg');
despia('shareapp://message?=Check out this app&url=https://myapp.com');

Push notifications

Register the device for push and map it to your OneSignal external user ID on every app load.
despia(`setonesignalplayerid://?user_id=${userId}`);

Native safe area

CSS variables for top and bottom device insets, injected automatically by the runtime.
.header { padding-top:    var(--safe-area-top);    }
.footer { padding-bottom: var(--safe-area-bottom); }

Integrations

Third-party SDK bridges built into the runtime. RevenueCat for billing, AppsFlyer for attribution, and Local CDN for offline media caching.

Monetization

Native App Store and Google Play billing through RevenueCat. No billing SDK configuration required on the web layer.
RevenueCat must be enabled in Despia > App > Settings > Integrations > RevenueCat and your API key configured before purchases will work.
const isDespia = navigator.userAgent.toLowerCase().includes('despia')

if (isDespia) {
    despia(`revenuecat://launchPaywall?external_id=${userId}&offering=default`)
} else {
    window.location.href = `https://pay.rev.cat/<your_token>/${encodeURIComponent(userId)}`
}
async function checkEntitlements() {
    const data   = await despia('getpurchasehistory://', ['restoredData'])
    const active = (data.restoredData ?? []).filter(p => p.isActive)
    if (active.some(p => p.entitlementId === 'premium')) unlockPremium()
}

checkEntitlements()
window.onRevenueCatPurchase = checkEntitlements
RevenueCat reference

Analytics and attribution

AppsFlyer attribution, deep linking, and event tracking. Attribution data is recorded at install time and injected into the web layer on every page load.
AppsFlyer must be enabled in Despia > App > Settings > Integrations > AppsFlyer and your AppsFlyer dev key configured. Currently available on iOS, with Android coming soon.
const referrer = despia.appsFlyerReferrer     // e.g. "tiktok_ad", "organic"
const uid      = despia.appsFlyerUID
despia("appsflyer://set_user_id?customer_user_id=" + encodeURIComponent(userId))
despia("appsflyer://set_email?email=" + encodeURIComponent(email))
AppsFlyer reference

Offline media caching

Since PhoneGap launched in 2009, every hybrid framework has struggled with offline media. Files pass through JavaScript - Base64 encoding, Blob URL conversions, memory usage that scales with file size. A 500MB video in Capacitor peaks at approximately 1.6GB of JS heap. After 7,500 apps built on Despia’s predecessor runtime, this pattern was consistent enough to justify solving properly. Local CDN bypasses JavaScript entirely for file operations. Downloads go directly to the native file system via NSURLSession (iOS) and WorkManager (Android). Files stream back through the on-device HTTP server at http://localhost to the hardware decoder. Memory usage is O(1) regardless of file size. Downloads continue when the app is backgrounded or closed. On iOS, native download progress appears in the system download activity. On Android, it shows in the native download manager. Both platforms handle retry on network failure automatically. On completion, an optional push notification fires. When the app reopens, window.contentServerChange(item) is called for each download that completed while the app was not running.
window.contentServerChange = (item) => {
    videoElement.src = item.local_cdn
}

despia(`localcdn://write?url=${remoteUrl}&filename=videos/course.mp4&index=course_ep1&push=true&pushmessage="Episode 1 ready"`)
const data = await despia(
    `localcdn://read?index=${encodeURIComponent(JSON.stringify(['course_ep1']))}`,
    ['cdnItems']
)
videoElement.src = data.cdnItems[0].local_cdn
CapacitorDespia Local CDN
Peak JS memory (500 MB file)~1,666 MB~100 bytes
Storage limit50-100 MBFull device capacity
Background downloadsNoYes
PlaybackSoftware decodedHardware accelerated
Local CDN reference

Advanced

Distribution, rendering, extending the runtime, tool compatibility, and MCP server setup.

Publishing

Despia handles the full submission pipeline from a browser with no CLI, no local toolchain, and no manual credential management. Toggle capabilities, configure runtime settings, manage iOS targets (App Clips, Share Extensions, Home Widgets), and submit. Code signing, provisioning profiles, and store submission are automated through the built-in CI/CD pipeline. For teams that want full control, native projects can be exported at any time as complete Xcode and Android Studio projects including all Swift and Java source. The Despia editor and the self-managed path are not mutually exclusive. Web content changes do not require a new binary. Only changes to native configuration or runtime behavior trigger a new build.

Rendering

Despia uses WKWebView on iOS and the Chromium-based WebView on Android - the same engines that power Safari and Chrome. Both use hardware-accelerated compositing, JIT-compiled JavaScript, and GPU-accelerated WebGL and Canvas 2D. CSS animations run on the compositor thread independently of JavaScript. For requirements that cannot be met by the web platform - highly custom gesture recognizers, frame-by-frame game loops - the native export and custom bridge paths are available.

Extending the runtime

The bridge pattern is consistent across both platforms. Intercept a new scheme in WebViewController.swift (iOS) or MainActivity.java (Android), execute native code, and write the result back. The SDK resolves custom bridges identically to built-in capabilities.

Add the native handler

if requestURL.absoluteString.hasPrefix("mycustom://") {
    let result = runMyNativeCode()
    webView.evaluateJavaScript("window.myResult = '\(result)';")
    decisionHandler(.cancel)
    return
}

Call it from your web app

import despia from 'despia-native';

const data = await despia('mycustom://', ['myResult'])
console.log(data.myResult)
A low-code plugin editor for defining custom capabilities from the Despia editor without a native project export is planned for mid/late 2026.

Works with any tool

Despia has no opinion on how your UI is built, what state management you use, or which tools generated your code.

Web frameworks

React, Vue, Angular, Svelte, Next.js, Nuxt, SvelteKit, Astro, Remix, vanilla JavaScript

AI coding tools

Cursor, Claude Code, Lovable, v0, Base44, or any tool that generates web code
AI coding tools generate despia() calls reliably because the API is a flat string command - no nested configuration objects, no provider wrappers, no initialization sequences.

MCP server

Despia provides an MCP server that gives AI coding assistants full knowledge of the despia-native API without requiring you to paste documentation into the chat. MCP URL: https://setup.despia.com/mcp
Add to ~/.cursor/mcp.json and restart Cursor.
{
  "mcpServers": {
    "despia": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://setup.despia.com/mcp"]
    }
  }
}
Requires Node.js v18+ for local tools.

Internals

How the bridge works under the hood, why scheme:// was chosen over JSON, and how localhost acts as a secure origin.
scheme:// interception was the standard pattern for hybrid app native bridges over a decade ago, when Despia’s runtime was first built. It remains in use intentionally.
  • Simple. A command in, a result out.
  • Predictable. Consistent behavior across iOS and Android.
  • Readable. Commands are understandable and debuggable without tooling.
  • Searchable. Trivial to locate across large codebases, including by AI coding tools.
The runtime is fully modernized. Native capabilities are implemented in current Swift and Java. Data-heavy operations route through the on-device HTTP server at http://localhost where appropriate.
Structured JSON messaging was evaluated. In practice, scheme:// performed better - particularly with AI-assisted development. AI generates flat command strings more reliably than nested JSON payloads, with fewer malformed structures and more predictable output. Commands are also easier to trace and reason about across a codebase.
For operations that do not fit the scheme pattern - file uploads, streaming, standard HTTP requests - Despia routes through an on-device HTTP server at http://localhost. Because http://localhost is a real secure origin in both WKWebView and Chromium, Service Workers, IndexedDB, Web Crypto, and standard URL routing work without modification. No Blob URL workarounds, no Base64 encoding, no arbitrary storage quotas.

Capability reference

A full index of everything built into Despia - core runtime features, integrated SDK bridges, infrastructure, and native web interception.

Core runtime

Hardware-backed Identity Vault, native biometrics (Face ID, Touch ID, fingerprint), background GPS including Samsung Low Power Mode, contacts, clipboard, haptics (5 types), native media and file system access, image saving, background audio, local push notifications, status bar controls, safe area CSS variables, device orientation per device class, prevent zoom, prevent sleep, fullscreen mode, splash screen, iOS Home Widgets, Siri Shortcuts, native share dialog, AirPrint, screen shield, PkPass for iOS and Android mobile wallets.

Integrated SDK bridges

RevenueCat - purchases, subscriptions, restore, paywalls. OneSignal - remote push with external user ID mapping. AppsFlyer - attribution, deep linking, event tracking. AdMob - advertising. HealthKit - all major health identifiers.

Infrastructure and compliance

ATT compliance, vendor ID tracking, developer-level device ID tracking via iCloud KV and Android App Backup, store location access, jailbreak detection with configurable blocking, NoCode iOS target management for App Clips, Share Extensions, and Home Widgets.

Native web interception

<input type="file"> routes to the native file picker. The capture attribute opens the native camera. accept="image/*" or accept="video/*" opens the native media gallery. Deeplinks and HTTPS deeplinks are handled natively.

Open source

The JavaScript SDK, offline asset bundler, and version gating package are all MIT licensed. Native implementations are included in full on project export.
PackageDescriptionLicense
despia-nativeJavaScript SDKMIT
@despia/localOffline asset bundlerMIT
despia-version-guardVersion gatingMIT
Native capability implementations are written in Swift and Java and included in full on project export.

Our History

Despia’s runtime has been in production since 2011, when co-founder John built Advanced WebView for his agency’s client apps. Over the following decade it was adopted by over 7,500 apps before becoming Despia in 2023 - a native-first runtime with a modern configuration editor and a full CI/CD pipeline built on top of that proven foundation.

Resources

NPM Package

despia-native

MCP Server

AI coding assistant integration

Local Server

Offline and instant-launch support