The app you vibe-coded in Lovable doesn't have a <View> — that's why it can't go mobile
Here is the test that ends most "I'll just turn my web app into an app" plans: open the project your AI builder generated and search for <View>. You won't find one. You'll find <div>, <span>, <section> — the DOM. Lovable, Bolt, and v0 are web builders. The thing they hand you is a website, and a website does not become an iOS app because you wished hard enough.
This trips up a specific person: the builder who shipped a working web MVP in a weekend, got users, and now needs to be in the App Store. They assume "mobile" is a deploy target — a checkbox, a wrapper, a one-time export. It isn't. The gap between what these tools produce and what an app store accepts is structural, and no amount of prompting closes it.
The fix isn't a converter. It's not generating the web app in a form that was never going to run on a phone in the first place.
A <div> is not a <View>, all the way down
A web app is HTML rendered by a browser engine. Layout is the CSS box model; the runtime is the DOM. A native app has none of that. On iOS a view is a UIView; on Android it's an android.view.View. React Native's <View> compiles to those real platform views — there is no browser, no DOM, no <div>.
So when Lovable emits this:
<div className="flex flex-col gap-4 p-4">
<h1 className="text-2xl font-bold">Dashboard</h1>
<button onClick={save}>Save</button>
</div>…every token in it is web-only. div and h1 are DOM elements. className is a CSS class string. onClick is a DOM event. The native equivalent shares none of those primitives:
<View style={styles.column}>
<Text style={styles.title}>Dashboard</Text>
<Pressable onPress={save}><Text>Save</Text></Pressable>
</View>Different elements, different styling system, different event model, different text handling (you can't drop a bare string between tags in React Native — it has to be inside <Text>). This isn't a syntax difference you can sed your way through. It's two different rendering targets that happen to both be written in React.
That's why the export button you're looking for doesn't exist. There's nothing to export.

The converter cottage industry is re-coding your app by hand
Because a lot of people hit this wall at once, a market appeared to sell them a way over it. In 2026 you can find tools — CatDoes, Newly, RapidNative, and others — whose entire pitch is "paste your Lovable URL, get a native app." It's worth understanding what they actually do, because it's not what the marketing implies.
There are two honest answers and one dishonest one.
The honest approach: the tool reads your web app and regenerates it as React Native — a second AI pass that rewrites every <div> as a <View>, every Tailwind class as a style object, every DOM event as a native handler. That works as well as any AI code generation works, which is to say it gets you to a draft and leaves the edge cases — keyboard avoidance, safe areas, gesture handling, navigation — for you. You are now maintaining a second codebase that drifts from the first the moment you change either one.
The dishonest approach: wrap the existing website in a WKWebView (Capacitor and friends). This passes app review sometimes and produces a "native app" that is a browser tab in a trench coat — no native navigation, no platform feel, janky scrolling, and a rejection risk under Apple's guidelines for apps that are "just a web page." Your users can tell within three seconds.
Either way, the converter is a tax. You paid one tool to generate web-only code, and now you're paying a second tool to undo that decision. The cleaner move is to never make the web-only decision.
Expo Agent is the tell
Here's the strongest signal that the web-only default is the actual problem, not your prompting: in April 2026, Expo shipped Expo Agent (beta) — the first vibe-coding tool that targets native mobile from the first keystroke instead of the browser.
That exists because the whole first generation of AI builders quietly assumed "app" meant "web app." Expo Agent is the industry conceding that a mobile-first generation target is a different product, not a setting. If converting web output to native were easy, nobody would need to start native.
The takeaway isn't "use Expo Agent instead of Lovable." It's that the platform target is a decision made at line one, and changing it later is the expensive path.
The version that doesn't need a converter
The reason a <div> can't follow you to mobile is that the component is bound to the platform's primitives. Break that binding and the problem disappears: write against a component API that resolves to the right primitive on each platform.
That's the bet behind @otfdashkit/ui (web) and @otfdashkit/ui-native (mobile). Same component name, same props, two implementations underneath:
// Web — renders Radix + Tailwind, compiles to the DOM
import { Card, Button, Text } from '@otfdashkit/ui'
// Mobile — renders Tamagui, compiles to UIView / android.view.View
import { Card, Button, Text } from '@otfdashkit/ui-native'// …and the screen is byte-for-byte the same in both files:
<Card>
<Text>Dashboard</Text>
<Button onPress={save}>Save</Button>
</Card>There's no <div>-to-<View> pass because you never wrote a <div>. <Button> knows it's a Pressable on native and a <button> on web. <Text> is a <Text> on native and a <span> on web. The translation happens once, inside the library, and it's been tested — not regenerated per project by a model that's never seen your app.

This is also exactly the shape Expo itself is moving toward. SDK 56's universal components (Host, Row, Column, Text) render on iOS, Android, and web from one definition — the platform is validating the same-API thesis from the inside.
What this unlocks
When the component layer is platform-agnostic, "go mobile" stops being a migration and becomes a build target:
- One codebase, one design system, one set of components —
expo run:ios,expo run:android, and a web build, all from the same source. - No second repo to keep in sync. Fix a bug once.
- A file-system agent (Claude Code, Cursor) extends both platforms at once, because the component API it's reading is the same one that runs on the phone.
You don't get there by exporting. You get there by not generating disposable web-only code in the first place.
If you've already got a Lovable or Bolt web app and you're staring at the App Store wall, the converter tools will get you a rough draft and a maintenance headache. The durable answer is to rebuild the UI layer on components that were cross-platform from line one — and then the phone is just another target you already had.