nativite
v0.1.0
Published
Build native iOS, macOS, and Android shells around Vite apps.
Maintainers
Readme
Nativite
Build native iOS, macOS, and Android shells around your Vite app.
Nativite gives you:
- Native project generation for Apple and Android targets
- A typed JS bridge for calling native code from web code
- A declarative native chrome API (
title bar,navigation,toolbars, sheets, drawers, etc.) - Live device CSS variables (
--nv-*) for safe areas, keyboard, appearance, and more
Status: early development. APIs are usable but may change between releases.
The nativite/chrome JavaScript API is the app-facing interface for native chrome. Native shells receive compiled Native Chrome Layout Protocol v2 (chrome.snapshot) messages; NCLP v2 is the stable host wire protocol for Nativite 1.0 and is documented in NCLP.md.
Who This Is For
Nativite is for teams that already have a Vite web app and want:
- shared product logic across web + native
- gradual native capability adoption
- native UI controls without rewriting the app in Swift/Kotlin
Installation
bun add nativitePeer dependencies:
typescript ^5vite >=5(required if you usenativite/vite)
Requirements
- macOS, Xcode, Xcode command line tools, and available simulators/devices (for iOS/macOS)
- Android Studio, Android SDK, a JDK, and a
gradlecommand onPATH(for Android) - Bun 1.x or Node 18+
Nativite does not install, download, vendor, or bootstrap native toolchain dependencies. Xcode, Xcode command line tools, simulators, Android Studio, the Android SDK, Java, and Gradle are machine prerequisites that should be installed and managed by the developer or their CI image. Nativite generates native project files and prints clear errors when required tooling is unavailable.
Quick Start: Vite App to Native Shell
This is the shortest drop-in path for an existing Vite app.
1. Add Nativite
bun add nativite2. Initialize native support
Run the init command from your Vite project root:
bunx nativite initThis creates nativite.config.ts using your package.json name and updates a
simple vite.config.ts to include nativite(). If your Vite config cannot be
edited safely, the command prints the exact manual import and plugin changes to
make.
By default, init keeps the first path narrow: it enables ios on macOS and
android on other hosts. Choose targets explicitly by repeating --platform:
bunx nativite init --platform ios --platform android3. Build native projects
bunx nativite buildThis runs a production Vite build for each configured target, writes the web
bundle, and creates or updates the matching native project under .nativite/.
4. Open the native project
Use the native IDE or simulator workflow you already use for the target platform:
open .nativite/ios/MyApp.xcodeproj
open .nativite/androidXcode and Android Studio own native build settings, signing, simulator/device selection, and launch. Nativite owns generating the native project code and the web bundles those projects embed.
5. Use Vite during native debug runs
Run your normal Vite dev server when you want the generated debug native project to load web code from Vite instead of the embedded production bundle.
bunx vite devNativite's Vite plugin writes .nativite/dev.json with the resolved dev server
URL so native debug builds can discover it.
Router and framework notes
- Prefer history fallback routes that work from
index.html; generated native shells load the same app entry as Vite. - Use platform-specific files such as
Button.ios.tsx,Button.android.tsx,Button.mobile.tsx, orButton.native.tsxwhen a route or component needs native-only behavior. - Add
/// <reference types="nativite/globals" />tovite-env.d.tsbefore using compile-time globals such as__PLATFORM__or__IS_NATIVE__. - Keep framework routing, state, and data loading in the web app. Reach for
nativite/chromeor native plugins only when the native shell needs to own a native control or capability.
Troubleshooting the first run
No platforms are configured.Add at least one entry inplatforms, or rerun init with--platform ios,--platform macos, or--platform android.- iOS/macOS launch issues usually mean Xcode command line tools or simulators are missing or unavailable.
- Android generation requires Android Studio, Android SDK, Java, and a
gradlecommand onPATH. - If init cannot edit your Vite config safely, apply the import and plugin changes it prints.
For a fuller walkthrough, see the drop-in quickstart. Use the advanced chrome and plugin APIs after the generated native shell is running and you need native-owned UI or custom native capabilities.
Manual Setup
If you prefer to configure the project by hand, create the files below.
1. Create nativite.config.ts
import { defineConfig, ios } from "nativite";
export default defineConfig({
app: {
name: "MyApp",
bundleId: "com.example.myapp",
version: "1.0.0",
buildNumber: 1,
},
platforms: [ios()],
});2. Add the Vite plugin
// vite.config.ts
import { defineConfig } from "vite";
import { nativite } from "nativite/vite";
export default defineConfig({
plugins: [nativite()],
});Prepare production native projects
bunx nativite buildThis prepares each configured native target for a production build. It runs a production Vite build, writes the matching web bundle, and creates or updates the native project that embeds that bundle:
.nativite/ios
.nativite/macos
.nativite/android
dist-ios
dist-macos
dist-androidOptional single-platform build:
bunx nativite build --platform iosFor app-store submission, archive or package the generated project with the
native toolchain. nativite build does not create final signed artifacts such as
.ipa, .aab, .apk, signed .app, or .dmg; those are produced by Xcode,
Android Studio, Gradle, xcodebuild, or CI using your signing configuration.
Configuration Overview
Required fields
app.nameapp.bundleIdapp.versionapp.buildNumberplatforms(at least one)
Built-in platform helpers
ios({ minimumVersion?, errorOverlay?, overrides? })macos({ minimumVersion?, overrides? })android({ minSdk?, targetSdk?, overrides? })
Notes:
ios(),macos(), andandroid()can be called with no arguments. Defaults are iOS17.0, macOS14.0, AndroidminSdk26, and AndroidtargetSdk35.ios.errorOverlaycontrols the default Vite HMR overlay behaviour in dev.NATIVITE_DEV_ERROR_OVERLAYstill takes precedence when set.android.targetSdkmust be an integer when provided.
Optional root fields
signingupdatespluginsplatformPluginsdefaultChromeiconsplash
updates currently enables OTA bundle checks and staged bundle application for
iOS and macOS generated runtimes. Android exposes the same JavaScript
ota.check() status shape, but it always reports { available: false } until
Android OTA staging/apply support is implemented.
JavaScript Runtime APIs
nativite/client
Low-level transport and event subscription:
import { bridge, ota } from "nativite/client";
if (bridge.isNative) {
const cameraResult = await bridge.call("camera", "capture", { quality: 0.9 });
console.log(cameraResult);
}
const unsub = bridge.subscribe("location:update", (payload) => {
console.log(payload);
});
const update = await ota.check();
console.log(update.available, update.version);
unsub();ota.check() is implemented by the Apple runtimes today. On Android it is a
compatibility placeholder that resolves to { available: false }.
nativite/chrome
Declarative native chrome state:
import { chrome, navigation, statusBar, titleBar, toolbar } from "nativite/chrome";
const cleanup = chrome(
titleBar({
title: "Inbox",
trailingItems: [{ id: "compose", label: "Compose", style: "primary" }],
}),
navigation({
items: [
{ id: "inbox", label: "Inbox", icon: "tray.fill" },
{ id: "search", label: "Search", icon: "magnifyingglass", role: "search" },
],
activeItem: "inbox",
}),
toolbar({
items: [{ id: "filter", label: "Filter" }],
}),
statusBar({ style: "auto" }),
);
const unsub = chrome.on("navigation.itemPressed", ({ id }) => {
console.log("Selected", id);
});
cleanup();
unsub();Also available on chrome:
chrome.messaging.postToParent/postToChild/broadcast/onMessagechrome.splash.preventAutoHide()chrome.splash.hide()
nativite/css
Typed helpers for --nv-* device variables:
import { NVVars } from "nativite/css";
const topInset = NVVars.getNumber("safe-top");
const isDark = NVVars.getBoolean("is-dark");
const stop = NVVars.observeNumber("keyboard-height", (height) => {
console.log("Keyboard height:", height);
});
stop();nativite/utils
Platform-conditioned value selection:
import { platform } from "nativite/utils";
const backLabel = platform(
{
ios: "Back",
android: "Navigate up",
web: "Back",
},
"Back",
);Custom Platforms
Use definePlatformPlugin() + platform() to add non-first-party runtimes:
import { definePlatformPlugin, platform } from "nativite";
const electronPlatform = definePlatformPlugin({
name: "electron-platform",
platform: "electron",
native: true,
mobile: false,
desktop: true,
extensions: [".electron", ".desktop", ".native"],
environments: ["electron"],
async generate(ctx) {},
async build(ctx) {},
});
// in defineConfig(...)
// platforms: [platform("electron", { /* custom config */ })]
// platformPlugins: [electronPlatform]Vite Integration Details
The plugin:
- creates per-platform environments (
ios,ipad,macos,android, plus plugin-defined) - resolves platform file variants (
.ios,.mobile,.native, etc.) - writes
manifest.jsonduring build hooks - handles native-request routing + HMR behavior for platform variants
Global compile-time constants
Add this in vite-env.d.ts:
/// <reference types="vite/client" />
/// <reference types="nativite/globals" />Then use:
__PLATFORM____IS_NATIVE____IS_MOBILE____IS_DESKTOP____DEV__
__IS_NATIVE__/__IS_MOBILE__/__IS_DESKTOP__ come from your platform plugin traits
(native, mobile, desktop). Defaults are native: true, mobile: false,
desktop: false when omitted. A platform can set both mobile and desktop
to true.
Public Exports
nativite: config helpers, schema, core public typesnativite/vite:nativite()nativite/client:bridge,otanativite/chrome:chrome+ chrome factory functions + chrome typesnativite/css:NVVars,NVVarNamenativite/utils: platform utility helpersnativite/globals: ambient globals types
package.json#exports is the complete public module list. Deep imports are
unsupported, and the CLI is exposed as the nativite binary rather than as an
importable nativite/cli runtime module.
Troubleshooting
No platforms are configured.- Add at least one entry in
platforms.
- Add at least one entry in
iOS/macOS build/launch issues
- Ensure Xcode command line tools are installed and simulators exist.
Android project generation fails with
gradle: command not found- Install Gradle or expose Android Studio's Gradle-compatible tooling on
PATH, then rerunbunx nativite build --platform android.
- Install Gradle or expose Android Studio's Gradle-compatible tooling on
Documentation Map
Deep technical docs are in docs/README.md.
Suggested starting points:
- Drop-in quickstart
- Chrome API internals
- Client bridge internals
- Vite plugin internals
- Platform registry
- iOS overview docs
- Android overview docs
Development (Repository)
bun install
bun run build
bun run typecheck
bun run lint
bun run test
bun run test:native:ios
bun run test:native:androidSee CONTRIBUTING.md for contribution workflow and SECURITY.md for vulnerability reporting.
Release notes are tracked in CHANGELOG.md and generated from changesets.
License
MIT

