Real native apps. Written in the Vue you already know.
Your Vue 3 components render as actual UIKit, Android, and AppKit views — no WebView, no DOM, no new component model to learn.
<script setup lang="ts">
import { ref, createStyleSheet }
from '@thelacanians/vue-native-runtime'
const count = ref(0)
const styles = createStyleSheet({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
button: {
backgroundColor: '#007AFF',
paddingHorizontal: 24,
paddingVertical: 12,
borderRadius: 8,
},
})
</script>
<template>
<VView :style="styles.container">
<VText>Count: </VText>
<VButton :style="styles.button" @press="count++">
<VText>Increment</VText>
</VButton>
</VView>
</template>vue package, not a fork. ref(0)— Vue 3 reactivity — the realvuepackage, not a fork.VText— iOSUILabel, Androidandroid.widget.TextView, macOSNSTextField(label).VButton— A real native control —@pressis platform touch, not a DOM click.
This is a real iOS and Android app. count is Vue reactivity. VText renders as a real UILabel.
<!-- why not just use… -->
Why not just use what's already there?
Capacitor / Ionic
Your Vue, but inside a WebView. You ship a browser.
React Native / Flutter
Truly native — if you leave Vue for JSX or Dart.
Vue Native
Truly native, in the Vue you already write. Real platform views, nothing to relearn.
<template>
Every component has three names.
You write one. A Vue custom renderer speaks all three — driving UIKit, AppKit, and Android Views directly. Not a WebView. Not the DOM.
macOS-only components (VToolbar, VSplitView, VOutlineView) aren't shown here — see the macOS guide.
All of it runs unmodified.
// createRenderer → NativeBridge → per-platform native factories
<native platform="ios">
Need Swift or Kotlin? Write it in the same file.
Drop a <native> block into your component with real Swift or Kotlin. Codegen writes the native module, its TypeScript types, and the registration.
<native platform="ios">
class HapticsModule: NativeModule {
var moduleName: String { "Haptics" }
func invoke(
method: String,
args: [Any],
callback: @escaping (Any?, String?) -> Void
) {
switch method {
case "vibrate":
let style = args[0] as? String
?? "medium"
vibrate(style: style)
callback(nil, nil)
default:
callback(nil, "Unknown method: \(method)")
}
}
func vibrate(style: String) {
let generator =
UIImpactFeedbackGenerator(style: .medium)
generator.prepare()
generator.impactOccurred()
}
}
</native>const { vibrate } = useHaptics()
await vibrate('medium') Kotlin via <native platform="android">. Native blocks guide →
capabilities
Real enough to build with.
- 30+ built-in components — VView, VText, VButton, VInput, VList, VScrollView, VImage, VModal, VPicker, VTabBar, VNavigationBar…
- 40+ composables — useCamera, useGeolocation, useBiometry, useHaptics, useAsyncStorage, useHttp, useWebSocket, useNotifications…
- Native stack, tab & drawer navigation
- 17 runnable example apps — auth, chat, camera, media player, macOS showcase…
// status
The honest version.
- iOS — production path
- Android — production path
- macOS — runtime available, manual setup;
createdoesn't scaffold the app shell yet
Pre-1.0 and hardening fast — memory-leak and race-condition fixes shipped across the iOS/Android bridge in recent releases. Flexbox subset, no browser globals. The dev watcher targets one platform at a time. Bun-first toolchain (Bun 1.3+; Node 20.19+ on the npm path). Small, focused, built in the open.
$ quick-start
Running in about five minutes.
bunx @thelacanians/vue-native-cli create my-app
cd my-app
bun install# terminal 1 — dev server
bunx @thelacanians/vue-native-cli dev --ios # or --android# terminal 2 — build & launch
bunx @thelacanians/vue-native-cli run ios # or: run androidHot reload of .vue files on device and emulator. One watcher per platform.