Skip to main content

How it Works

Build your web app with any framework (React, Vue, Angular, Svelte, or vanilla JavaScript), then deploy it as a truly native application to the App Store and Google Play - complete with hardware acceleration, offline support, and deep OS integration. Your existing web app runs in a native Swift (iOS) and Kotlin (Android) runtime with 30+ pre-built native features accessible through simple JavaScript commands. No plugins, no dependencies, no maintenance headaches. Everything is configured from a browser-based editor - no Xcode, no Android Studio required. Enable features, manage app settings, and deploy to both stores with one click through Despia’s built-in CI/CD pipeline.

Deployment Models

Remote Hydration (default). The binary ships without embedded web assets. On each launch, the runtime fetches your current build from your configured hosting URL - Vercel, Netlify, AWS, or anything else. No App Store resubmission needed for web content updates. Connectivity is required on each launch. Local Server (optional). For apps that need to work offline or launch without a network dependency. Install @despia/local, which generates a despia/local.json manifest enumerating every asset your app requires. The runtime downloads and caches the complete asset graph on-device, then serves it from http://localhost - a real HTTP server on the device. After initial hydration, the app launches instantly from cache with no network request. Updates download in the background when connectivity returns and apply atomically on next launch. Because http://localhost is a real secure origin (unlike file:// used by other hybrid runtimes), Service Workers, IndexedDB, Web Crypto, and standard URL routing all work without workarounds. Learn more about Local Server →

Installation

npm install despia-native
Import in your components:
import despia from 'despia-native';
That’s it. Start calling native features.

Core Native Features

Haptic Feedback

// 5 different haptic types
despia('lighthaptic://');     // Light vibration
despia('heavyhaptic://');     // Heavy vibration  
despia('successhaptic://');   // Success feedback
despia('warninghaptic://');   // Warning alert
despia('errorhaptic://');     // Error feedback

// Example: Add to button press
const handleSave = async () => {
  try {
    await saveTask();
    despia('successhaptic://'); // Success vibration
    setShowSuccess(true);
  } catch (error) {
    despia('errorhaptic://');   // Error vibration
    setShowError(true);
  }
};

App Information & Device Data

// Get app version
const appInfo = await despia('getappversion://', ['versionNumber', 'bundleNumber']);
console.log(appInfo.versionNumber);  // "1.2.3"
console.log(appInfo.bundleNumber);   // "42"

// Get device ID
const deviceId = await despia('get-uuid://', ['uuid']);
console.log(deviceId.uuid);  // Unique device identifier

// Example: Display in settings
const [appInfo, setAppInfo] = useState(null);

useEffect(() => {
  const getInfo = async () => {
    if (navigator.userAgent.includes('despia')) {
      const info = await despia('getappversion://', ['versionNumber', 'bundleNumber']);
      setAppInfo(info);
    }
  };
  getInfo();
}, []);

return (
  <div>Version: {appInfo?.versionNumber}</div>
);

UI Controls

// Loading spinner
despia('spinneron://');       // Show loading
despia('spinneroff://');      // Hide loading

// Status bar
despia('hidebars://on');      // Full screen mode
despia('hidebars://off');     // Show status bar
despia('statusbarcolor://{255, 255, 255}');  // White status bar

// Example: Show loading during data fetch
const fetchData = async () => {
  despia('spinneron://');
  try {
    const data = await api.getData();
    setData(data);
  } finally {
    despia('spinneroff://');
  }
};

Advanced Features

In-App Purchases (RevenueCat Integration)

// Purchase a product
despia('revenuecat://purchase?external_id=user_777&product=monthly_premium');

// Restore purchases
const history = await despia('getpurchasehistory://', ['restoredData']);

// Check entitlement status
const activeSubs = history.restoredData.filter(p => 
  p.isActive && p.entitlementId === 'premium'
);

if (activeSubs.length > 0) {
  console.log('User has active entitlement');
}

// Launch RevenueCat paywall
despia('revenuecat://launchPaywall?external_id=user_777&offering=default');

// Example: Subscription button
const handleUpgrade = () => {
  if (navigator.userAgent.includes('despia')) {
    despia('revenuecat://launchPaywall?external_id=' + userId + '&offering=default');
  } else {
    // Web fallback - redirect to pricing page
    window.location.href = '/pricing';
  }
};

Identity Vault (Cross-Device Sync)

Key-value storage backed by iCloud KV Storage on iOS and Android App Backup on Android. Values can be locked behind biometric authentication. Persists across standard uninstall and reinstall cycles - useful for preventing trial abuse and multi-account fraud.
// Store data (syncs via iCloud KV on iOS, Android Backup KV on Android)
await despia('setvault://?key=userId&value=user123&locked=false');

// Retrieve data
const data = await despia('readvault://?key=userId', ['userId']);
console.log(data.userId);  // "user123"

// Lock with Face ID / Touch ID
await despia('setvault://?key=sessionToken&value=abc123&locked=true');

// Reading locked data triggers biometric prompt
const token = await despia('readvault://?key=sessionToken', ['sessionToken']);

// Example: Prevent trial abuse
const checkTrialUsed = async () => {
  try {
    const data = await despia('readvault://?key=trialUsed', ['trialUsed']);
    if (data.trialUsed === 'yes') {
      return false; // Already used trial
    }
  } catch {
    // First time user
    await despia('setvault://?key=trialUsed&value=yes&locked=false');
    return true;
  }
};

Contacts Access

// Step 1: Request permission (call once, e.g., on settings page or first use)
despia('requestcontactpermission://');

// Step 2: Read contacts after permission granted (on UI interaction)
const contacts = await despia('readcontacts://', ['contacts']);

console.log(contacts.contacts);
// {
//   "John Appleseed": [
//     "+12345678910"
//   ],
//   "Ann Wilson": [
//     "+12345678910"
//   ]
// }

// Example: Request permission on mount, read on button click
useEffect(() => {
  despia('requestcontactpermission://');
}, []);

const shareWithContact = async () => {
  const data = await despia('readcontacts://', ['contacts']);
  setContactList(data.contacts);
  setShowPicker(true);
};

Push Notifications

// Register for push (only needed if auto register is turned off)
despia('registerpush://');

// Set OneSignal external user ID (Can be accessed via "include_external_user_ids" on the backend)
despia(`setonesignalplayerid://?user_id=${userId}`);

// Send local notification (Optional)
despia('sendlocalpushmsg://push.send?s=60&msg=Task Due&!#Your task is due soon&!#myapp://tasks/123');

// Example: Setup notifications on login
const setupNotifications = async (userId) => {
  if (navigator.userAgent.includes('despia')) {
    despia('registerpush://'); // Optional only if using manual flow
    despia(`setonesignalplayerid://?user_id=${userId}`);
  }
};

Biometric Authentication

// Example: Protect sensitive action
const deleteAccount = async () => {
  // Require biometric confirmation
  await despia('setvault://?key=deleteConfirm&value=yes&locked=true');
  
  try {
    const confirm = await despia('readvault://?key=deleteConfirm', ['deleteConfirm']);
    if (confirm.deleteConfirm === 'yes') {
      // Biometric passed - proceed with deletion
      await performAccountDeletion();
    }
  } catch {
    console.log('User cancelled or biometric failed');
  }
};

Clipboard

// Read clipboard
const clipboard = await despia('getclipboard://', ['clipboarddata']);
console.log(clipboard.clipboarddata);

// Example: Paste button
const handlePaste = async () => {
  const data = await despia('getclipboard://', ['clipboarddata']);
  setInputValue(data.clipboarddata);
};

Screenshots & Media

// Take screenshot
despia('takescreenshot://');

// Save image from URL
despia('savethisimage://?url=https://example.com/image.jpg');

// Example: Save generated image
const saveGeneratedImage = (imageUrl) => {
  if (navigator.userAgent.includes('despia')) {
    despia(`savethisimage://?url=${imageUrl}`);
    despia('successhaptic://');
  }
};

Native Sharing

// Share text and URL
despia('shareapp://message?=Check out this app&url=https://myapp.com');

// Example: Share button
const handleShare = () => {
  const message = `Check out ${productName}`;
  const url = `https://myapp.com/product/${productId}`;
  despia(`shareapp://message?=${encodeURIComponent(message)}&url=${url}`);
};

iOS Home Widgets

// Update widget with SVG content
const svg = `<svg>...</svg>`;
const refreshTime = 300; // seconds

despia(`widget://${svg}?refresh=${refreshTime}`); // (The SVG needs to come from a server URL)

// Example: Update widget with stats
const updateWidget = (taskCount, completedCount) => {
  const svg = `
    <svg width="200" height="200">
      <text x="10" y="30" font-size="24">Tasks: ${taskCount}</text>
      <text x="10" y="60" font-size="24">Done: ${completedCount}</text>
    </svg>
  `;
  despia(`widget://${svg}?refresh=300`);
};

Environment Detection

Native SDK calls should be gated on runtime detection. The despia user agent string is present when running inside the Despia runtime and absent in standard browsers.
// Basic check
if (navigator.userAgent.includes('despia')) {
  despia('successhaptic://');
} else {
  console.log('Haptic feedback unavailable in browser');
}

// React Hook example
const useNative = () => {
  const [isNative, setIsNative] = useState(false);
  
  useEffect(() => {
    setIsNative(navigator.userAgent.includes('despia'));
  }, []);
  
  return isNative;
};

const MyComponent = () => {
  const isNative = useNative();
  
  const handleAction = () => {
    if (isNative) {
      despia('successhaptic://');
    }
  };
  
  return (
    <button onClick={handleAction}>
      Save {isNative && '(with haptic)'}
    </button>
  );
};

Native Safe Area Support

Automatic CSS variables for device-specific layouts:
.header {
  padding-top: var(--safe-area-top);
  background: white;
}

.footer {
  padding-bottom: var(--safe-area-bottom);
  background: white;
}

.sidebar {
  padding-left: var(--safe-area-left);
  padding-right: var(--safe-area-right);
}

Offline Support with Local Server

Install the build plugin:
npm install --save-dev @despia/local
Configure for your framework: Vite:
// vite.config.js
import { despiaLocalPlugin } from '@despia/local/vite';

export default {
  plugins: [despiaLocalPlugin()]
};
Next.js:
// next.config.js
const { despiaLocalPlugin } = require('@despia/local/next');

module.exports = despiaLocalPlugin({
  // your Next.js config
});
Webpack:
// webpack.config.js
const { DespiaLocalPlugin } = require('@despia/local/webpack');

module.exports = {
  plugins: [new DespiaLocalPlugin()]
};
This generates a despia/local.json manifest at build time enumerating every asset your app needs. The runtime downloads and caches the complete asset graph on-device, serves it from http://localhost, and applies updates atomically in the background. After initial hydration, your app launches with no network request and works fully offline. Learn more about Local Server →

OTA Updates with Version Gating

npm install despia-version-guard
Conditionally render features based on runtime version:
import { VersionGuard } from 'despia-version-guard';

const MyApp = () => (
  <div>
    {/* Always visible */}
    <OldFeature />
    
    {/* Only for users with runtime v21.0.3+ */}
    <VersionGuard min_version="21.0.3">
      <NewFeature />
    </VersionGuard>
  </div>
);
Prevents broken UI for users with older native containers.

Complete Feature Reference

Core Runtime APIs:
  • Hardware-backed Identity Vault - key-value storage secured by biometrics, synced via iCloud KV Storage (iOS) and Android App Backup (Android)
  • Native cross-platform biometrics (Face ID, Touch ID, fingerprint) linked to Identity Vault
  • True native background location - unified across iOS and Android, including Samsung Low Power Mode support
  • Contacts, clipboard
  • Haptics (5 types)
  • Native media and file system access, image saving
  • Native background audio support
  • Local push notifications
  • Status bar controls, safe area CSS variables
  • Device orientation per device class (phone, tablet, auto)
  • Prevent zoom, prevent sleep, fullscreen mode, splash screen
  • iOS Home Widgets, Siri Shortcuts
  • Native share dialog, AirPrint
  • Screen shield - prevents screenshots and recordings, cross-platform
  • PkPass support for iOS and Android mobile wallets
Integrated SDK Bridges:
  • RevenueCat - purchases, subscriptions, unified restore, paywalls
  • OneSignal - remote push notifications with unified registration and external user ID mapping
  • AdMob - advertising
  • HealthKit - all major health identifiers
Infrastructure & Compliance:
  • ATT (App Tracking Transparency) compliance built in
  • Vendor ID tracking
  • Developer-level ID tracking - persists across standard uninstall/reinstall cycles via iCloud KV and Android App Backup; prevents trial abuse and multi-account fraud
  • Store Location access - geo-blocking, content compliance, or web payments on iOS US store apps
  • Jailbreak detection with configurable blocking
  • NoCode iOS target management - App Clips, Share Extensions, and Home Widgets via editor toggles; no manual Xcode configuration required
Native Web Interception Layer: Despia intercepts standard web events and routes them to native equivalents automatically - no changes to your web code needed:
  • <input type="file"> - routed to the native file picker
  • capture attribute - opens the native camera modal
  • accept="image/*" or accept="video/*" - opens the native media gallery with native preview
  • Deeplinks and HTTPS deeplinks - handled natively, routed to Local Server when enabled
  • External link handling - configurable from web UI, consistent across both platforms
Full SDK reference →

Deployment Options

Despia Editor (recommended). A browser-based editor where you configure features, manage app targets, and deploy - no Xcode or Android Studio needed. Toggle native features on or off, configure runtime settings, manage iOS targets (App Clips, Share Extensions, Home Widgets), and submit to the App Store and Google Play through Despia’s built-in CI/CD pipeline. Code signing and provisioning are handled automatically. Export & Build Independently. Export complete Xcode and Android Studio projects at any time. The codebase is fully yours - extend it, add custom native SDKs, or build independently. Your web code stays standard web code, and your hosting stays your hosting.

Framework Compatibility

Works with any web framework:
  • React, Vue, Angular, Svelte
  • Next.js, Nuxt, SvelteKit, Astro, Remix
  • Vanilla JavaScript
  • AI builders: Lovable, Bolt, v0
  • No-code: WeWeb, Nordcraft

Source Code

Open source (MIT): Proprietary until export:
  • Native feature implementations (Swift/Kotlin)

Need Help?

Ready to add native features to your web app? Install despia-native and start calling native SDK methods in minutes.