Vue NativeVue Native
Guide
Components
Composables
Navigation
Architecture
  • iOS
  • Android
  • macOS
GitHub
Guide
Components
Composables
Navigation
Architecture
  • iOS
  • Android
  • macOS
GitHub

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.

Get started Run it in five minutes ↓
App.vue
<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 3 reactivity — the real vue package, not a fork.
VText
├─ iOS UILabel
├─ Android android.widget.TextView
└─ macOS NSTextField (label)
A real native control — @press is platform touch, not a DOM click.
  • ref(0) — Vue 3 reactivity — the real vue package, not a fork.
  • VText — iOS UILabel, Android android.widget.TextView, macOS NSTextField (label).
  • VButton — A real native control — @press is 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.

Not a drop-in for every Vue app: no DOM or window, no vue-router (use @thelacanians/vue-native-navigation), and styling is a flexbox subset via typed style objects — not CSS files. Read the limitations →

<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.

VView
├─iOSUIView
├─AndroidFlexboxLayout
└─macOSNSView (FlippedView)
VText
├─iOSUILabel
├─AndroidTextView
└─macOSNSTextField (label)
VButton
├─iOSUIControl-based view
├─AndroidCustom touch delegate
└─macOSClickableView (NSView)
VInput
├─iOSUITextField / UITextView
├─AndroidEditText
└─macOSNSTextField
VList
├─iOSUITableView
├─AndroidRecyclerView
└─macOSNSTableView
VImage
├─iOSUIImageView
├─AndroidImageView (Coil)
└─macOSNSImageView
VScrollView
├─iOSUIScrollView
├─AndroidScrollView
└─macOSNSScrollView

macOS-only components (VToolbar, VSplitView, VOutlineView) aren't shown here — see the macOS guide.

refcomputedwatchv-modelv-forv-if<script setup>

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.

Haptics.vue
<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>
codegen
generated/useHaptics.ts
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; create doesn'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 android

Hot reload of .vue files on device and emulator. One watcher per platform.

Full install guide → · Your first app →

</style>

GitHubExamplesGuideComponentsMIT Licensed

// Vue-first. Genuinely native. Honest about the rest.