Deploy targets

Six runtimes.
One bundle.

The AOT exporter emits the same bundle for every target. You pick the runtime - a single binary, the desktop, the edge, the browser, a phone or a board - and the app is identical. Swap the shape, not the code.

terminalCopy
# one export, every runtime - the bundle never changes
bext-lite build ./app --target native
bext-lite build ./app --target desktop
bext-lite build ./app --target edge
bext-lite build ./app --target mobile
One bundle, six runtimes

Where your PRISM app can run

Every card is the same exported bundle behind a different host. Deep-link any target from the home page; each is a complete, shippable runtime today.

Single static binary

One file. Double-click to run.
~4 MB totalV8 or QuickJS
$ bext-lite serve ./dist
  • A 1.8 MB self-contained host + your bundle - no Node, no V8 cage, no install step.
  • Hand-rolled HTTP/1.1, static assets, dynamic routes, ISR - single-tenant and fast.
  • Cross-compiles to Linux, macOS and Windows from one command.
Best for Internal tools, side-car services, air-gapped deploys.

Desktop app

Native apps, 10x smaller than Electron.
5-20 MBV8 (snapshot React)
$ bext-lite build ./app --target desktop
  • A Tauri shell wraps the embedded host and points a native WebView at it.
  • Bundles to .dmg / .msi / .deb / AppImage with code-signing & notarization built in.
  • Auto-update channel ships out of the box.
Best for Cross-platform SaaS-as-a-desktop-app from the same codebase.

Edge functions

PRISM at the edge, sub-MB cold.
sub-MB coldQuickJS on WASM
$ bext-lite build ./app --target edge
  • Compiles to a QuickJS-on-WASM module (Javy/WASI) that runs in any V8-isolate edge.
  • Platform adapters bridge to Workers KV, D1 and the native fetch.
  • Deploy to Cloudflare Workers or Fastly Compute with zero cold-start tax.
Best for Globally-distributed SSR with no servers to run.

Browser / offline

The whole app runs client-side.
~3.5 MB cachedQuickJS on WASM
$ bext-lite build ./app --target browser
  • Render routes inside a service worker - fully client, installable, offline-first.
  • The island runtime is already pure browser JS, so hydration is free.
  • Reads & writes go to local SQLite (WASM) with optional sync.
Best for Demos, local-first apps, zero-backend tools.

Mobile - iOS & Android

Native device APIs from your web code.
per-render <5 MBQuickJS (no JIT)
$ bext-lite mobile run ios
  • Call the camera, biometrics, geolocation, secure storage, haptics, share and notifications straight from JS with bext.device.* - one SDK channel, no native code to write.
  • QuickJS renders on-device with no JIT, so it ships through App Store review; React and string-builder pages both AOT-compile to native bundles.
  • A local SQLite ships for offline data, and deep-link & notification-tap events stream back into the app.
Best for Real native apps - camera, Face ID, offline data - from one web codebase.

IoT / embedded

Runs on a Raspberry Pi.
<5 MB + appQuickJS
$ bext-lite build ./app --target aarch64
  • QuickJS is a pure interpreter - no 4 GB pointer cage, runs on tiny ARM boxes.
  • Cross-compiles to aarch64 / armv7 with the same exported bundle.
  • Local SQLite + storage, no cloud dependency.
Best for Kiosks, gateways, on-prem appliances.
The engine decision

Two engines, one byte-faithful output

Every target evaluates the same bundle. Only the engine underneath changes - and the rendered HTML never does.

On desktop and server, bext-lite runs V8 with a snapshot React for maximum speed. Everywhere else it runs QuickJS, a tiny pure interpreter: iOS bans JIT and you cannot embed V8 in WASM, so QuickJS is what reaches the edge, the browser, mobile and embedded. Both engines load the same bundle plus the same 122 KB of pure-JS polyfills and call __bextPrismRender(props), so the HTML is verified byte-identical across every engine.

How it works

Pick a target and ship

Export once, choose the runtime that fits, and run the same app from a single self-contained bundle.

Get startedView on GitHub