I built a tool that clones a phone app from screenshots into React Native
A few weeks ago I wanted to clone an app. Not a website, an actual phone app. And I realized pretty fast that it is a completely different problem, and nobody had a good answer for it.
Here is the thing. Cloning a website is basically a solved party trick now. You open the dev tools and the whole DOM is right there, the CSS, the fonts, the asset URLs. A model reads all of that and spits out a copy. There are tools that do it really well.
A phone app gives you none of that. No markup to read, no stylesheet to copy. You get pixels. That is it. So every website-cloner trick is useless the second you point it at an iOS or Android app.
So I asked myself what I can always get from any app. The answer is kind of dumb but it is the whole idea: screenshots. You can always screenshot an app. No jailbreak, no decompiling, no SDK. A screenshot of an iPhone app and a screenshot of an Android app are the same thing to me, an image.
So screenshots became the input.
The problem with screenshots
An image has no numbers in it. You cannot read "16px padding" off a PNG, you are guessing. And if you let a model guess once, you get that thing everyone has seen: it looks kind of right, the vibe is there, but the spacing is off and the colors are slightly wrong and it feels like a knockoff.
So the core of the tool is not the "generate a screen" step. It is a loop. It builds a screen, renders it, screenshots its own output, puts that next to your original, and fixes whatever is different. Then it does it again, and keeps going until the two actually match. That loop is doing the measuring the DOM would have handed me for free on the web.
That is the part people keep calling the clever bit, and honestly it is the part that stops the output from looking like AI slop.
Navigation
Someone asked me on launch day how it handles navigation, since a static screenshot does not tell you how you got from one screen to the next. Fair question, it is the hard part.
It is not screenshot order, that is too unreliable. It reads the navigation chrome instead. A persistent bottom bar across the shots means tabs. A back chevron in a header means a stack push. And it matches labels, so a row that says "Settings" gets wired to the screen whose header says "Settings." All of that goes into an app-spec.json (a nav graph, plus the tokens and screens) before a single screen is built, and the Expo Router setup is generated from that graph.
Conditional flows are still the weak spot and I am upfront about it. A screen you only reach in some state needs a hint or it gets approximated.
The part I actually cared about
Most of these tools stop at a dead shell. It renders, none of the buttons do anything. I hate that.
So the tool splits every action into two buckets: does this need a server, or does it run on the device? Anything that needs a backend gets mocked with a clear TODO. Anything on-device gets built for real. In the Todoist clone you add a task and it saves. In the Spendee clone you log an expense and the balance changes. Close the app, open it again, your data is still there. A real app, not a picture of one.
Proving it works
Screenshots lie. A button that does nothing looks identical to a working one in a still image. So I do not trust a screenshot to tell me the clone works.
Every clone ships with a script that drives the app in a headless browser, loads every screen, runs each feature, and fails if anything throws or a feature is broken. If the "add a task, reload, it is still there" flow breaks, the build fails. No "looks fine in a screenshot" bugs.
What it cannot do
I would rather say this than have you find out:
- No backend. Data is mocked or on-device.
- Brand icons are approximated, not copied.
- It only clones the screens you actually capture.
How to use it
It is open source, MIT. It ships as a Claude Code skill (that is the reference setup) but it also works in Cursor, Codex, Windsurf, Gemini and a bunch more, all generated from one source of truth.
Next on the roadmap is screenshots to native SwiftUI and Compose, then decompiling an APK for the cases where you need exact values.
Repo: https://github.com/Birkenpapier/ai-app-cloner
If you try it, I actually want to know where it falls over. Clone something weird and tell me what broke.
Top comments (0)