Skip to content

Why vibe-coded apps break on iPhone Duo

Ingenious Techlab TeamUpdated 2026-09-198 min read

Contents · 7 sections
  1. Vibe-coded app iPhone Duo checklist
  2. What your builder actually made
  3. Your AI has never seen iPhone Duo
  4. The patterns that break
  5. The rebuild trap
  6. A prompt to paste into your AI builder
  7. When to get help

If you built your app by describing it to an AI, it will almost certainly run on iPhone Duo. The risk is how it looks once the screen changes shape under it: when the phone opens, turns sideways, or shares the screen in Split View. A few patterns that AI tools reach for break at exactly that moment. This checklist is written for founders as much as developers, and each item links to the detail.

Vibe-coded app iPhone Duo checklist

  1. Find out what your builder actually made. Rork, Bolt and Replit Agent all generate Expo apps, so every fix here is a React Native fix.
  2. Ask for the screen size to be read live, not once. A size captured at launch is wrong as soon as the phone unfolds.
  3. Remove helpers that scale every size by screen width. On the open display they make everything 1.79 times bigger.
  4. Remove the portrait lock. The open display ignores it, so plan for landscape.
  5. Add a wide layout for screens over 600 points. The open display is 626 points wide, with room for a sidebar.
  6. Use the system tab bar. iPhone Duo moves system tab bars to the side; hand-drawn ones stay at the bottom.
  7. Pad each side of the screen separately. The left and right safe areas are different sizes on this device.
  8. Fix the layout before your next rebuild. The rebuild that picks up Apple’s new SDK is what exposes these problems.
  9. Paste our prompt into your builder. It covers every item above in one request.
  10. Check the result in Apple’s simulator with Xcode 27.1 beta, out since 18 September, or ask us to check it.

What your builder actually made

Most AI app builders that ship real App Store apps generate the same kind of project:

  • Rork says it generates “an Expo / React Native project”.
  • Bolt uses Expo when you ask for a mobile app, and publishes to the App Store through Expo’s build service, EAS.
  • Replit Agent uses Expo too, with Replit managing the cloud build.

That is good news. Expo and React Native lay out with flexbox, which adapts to new screen sizes well. It also means everything on our React Native iPhone Duo page and in Expo apps on iPhone Duo applies directly to your app.

Your AI has never seen iPhone Duo

Apple announced iPhone Duo on 9 September 2026. A model trained before that date has no idea a foldable iPhone exists, so it writes code for the phones it knows: one tall screen, one size, one orientation.

It is not careless; it is working from years of tutorials and examples written for exactly those phones. But unless your prompt mentions a screen that changes size while the app is running, nothing in the generated code will account for one.

The patterns that break

Screen size read once

The most common pattern in React Native examples reads the screen size at the top of a file:

const { width } = Dimensions.get('window');

That runs once, when the app starts. Open the phone, turn it sideways, or drag the Split View divider, and every size calculated from that number is now wrong. The fix is the useWindowDimensions() hook, which updates whenever the window changes. This blocker is drawn in full on the React Native page.

Scaling helpers that multiply everything

Some apps go a step further and scale every font, margin and card by the screen width, so the design “fits” any phone. Two popular libraries do this, and both read the screen size only once:

  • react-native-size-matters reads Dimensions.get('window') when it loads, then multiplies sizes by the screen’s short side divided by a 350-point base (source).
  • react-native-responsive-screen detects the screen’s width and height “when application loads”, and follows orientation changes only if you add its listener (README).

On a phone roughly 350 points wide, the factor is close to 1, and nobody notices. On iPhone Duo it is not:

Launched on Short side Scale factor
Closed outer display 466 pt ×1.33
Open inner display 626 pt ×1.79

Launch the app open and every size is 79% larger: a 22-point title becomes 39 points, and a screenful of content becomes half a screenful. Launch it closed, then unfold, and the factor stays at ×1.33, because it was only ever read once.

Scaled from a 350 pt base: ×1.79 versus Designed sizes, adaptive layoutTwo iPhone Duo inner displays, 626 points wide. Left: a layout sized by a helper that multiplies everything by the screen width divided by 350, so every element is 1.79 times its intended size and the content runs off the bottom. Right: the same content at its designed size, in two columns.scale ×1.79scale ×1.00

Left: Scaled from a 350 pt base: ×1.79

import { scale } from
  'react-native-size-matters';

// Screen width read once, at launch
const styles = StyleSheet.create({
  title: { fontSize: scale(22) },
  card: { height: scale(70) },
});

Right: Designed sizes, adaptive layout

// Points already suit every display
const styles = StyleSheet.create({
  title: { fontSize: 22 },
  card: { height: 70 },
});
// Add columns as width grows instead
Scale factor from react-native-size-matters’ source: the short side of the screen ÷ 350, read once. 626 ÷ 350 = 1.79 on the inner display.How to fix it — Scaled from a 350 pt base: ×1.79

The better design is the opposite instinct. Keep sizes as designed, because iOS points are already consistent across displays, and let the layout use the extra room: a second column, a sidebar, a wider reading width.

A portrait lock nobody asked for

Expo’s default project template sets "orientation": "portrait", and every project created from it inherits that lock. Apple is explicit that iPhone Duo’s inner display does not honour supported orientations, so the lock is simply ignored there. A screen designed only for portrait will be shown in landscape. See the portrait lock in app.json.

A phone layout on a small-tablet screen

Open, iPhone Duo’s inner display is 626 × 890 points and counts as regular width in both directions, which is the same class of space as an iPad. A single column of full-width cards, designed for a 400-point phone, becomes a stretched column with long lines and wasted space.

Ask for a second layout that switches on above 600 points wide. It is the same idea as the tablet layout many apps already have.

A tab bar drawn in JavaScript

Apple’s guidelines move tab bars and toolbars into a column at the side on the closed outer display and on the open display held sideways. That only happens to bars iOS draws itself. A tab bar built from ordinary views, or with Expo Router’s standard Tabs component, stays at the bottom while the rest of the system moves to the side.

JS tab bar: stays at the bottom versus Native tabs: expected at the sideTwo closed iPhone Duo outer displays, 466 by 678 points. Left: a tab bar drawn by the app stays across the bottom, taking height from content on a short, wide screen. Right: a system tab bar in a column down the right side, bottom-aligned below the Dynamic Island, leaving the full height for content.466 × 678 pt466 × 678 pt

Left: JS tab bar: stays at the bottom

import { Tabs } from 'expo-router';

// Drawn by React Navigation in JS
export default function Layout() {
  return <Tabs />;
}

Right: Native tabs: expected at the side

import { NativeTabs } from
  'expo-router/unstable-native-tabs';

// UITabBarController on iOS
export default function Layout() {
  return (
    <NativeTabs>
      <NativeTabs.Trigger name="home" />
    </NativeTabs>
  );
}
Import path for Expo SDK 54–57; from SDK 58 it is expo-router/native-tabs. Side placement for native tabs follows from Apple’s guidance and is not yet verified on the device.How to fix it — JS tab bar: stays at the bottom

Expo Router’s NativeTabs uses iOS’s own tab bar, which is the way to get the system placement. Here is where these patterns stand, all together:

AI-built apps on iPhone Duo: what works, what breaks

  • WorksFlexbox layoutsReflow at any size with no changes.
  • BreaksScreen size read once with Dimensions.getWrong after the first fold or Split View resize.
  • Breaksreact-native-size-mattersScales everything ×1.79 on the inner display, and never updates.
  • Breaksreact-native-responsive-screen without its listenerReads the screen size once, when the app loads.
  • BreaksA portrait lockThe inner display ignores it.
  • BreaksFixed widths such as width: 375A 375 pt column on a 626 pt display.
  • Looks datedA single-column phone layoutStretched across a regular-width display with room for a sidebar.
  • Looks datedA tab bar drawn in JavaScriptStays at the bottom while system bars move to the side.
  • Looks datedAn EAS build today (Xcode 26)Runs at a familiar size, not full screen, until rebuilt.
  • Needs nativeKeeping content off the foldNeeds a native module; JavaScript has no hinge API.

The rebuild trap

A vibe-coded app on iPhone Duo is probably fine today, for a reason that will not last. Apple’s iPhone Duo behaviour depends on the SDK an app is built with, and apps built without the iOS 27 SDK run at a familiar size and aspect ratio instead of filling the screen.

Bolt publishes through Expo’s EAS Build, and as of 15 September every EAS iOS image uses Xcode 26. Replit does not document which Xcode its builds use.

Apple has announced that from April 2027, every app uploaded to the App Store must be built with the iOS 27 SDK. At some point before then, your builder will rebuild your app with it. That rebuild, not the phone, is when the app starts filling the screen, and when every pattern above shows up at once. Fix the layout first, and that day is uneventful.

A prompt to paste into your AI builder

Paste this into Rork, Bolt, Replit Agent, Cursor or any assistant working on an Expo app. Then review the list of changes it gives back.

My Expo app must work on iPhone Duo, Apple's foldable
iPhone, announced in September 2026. Its screen changes
size while the app runs: 466 x 678 points when closed,
626 x 890 when open, 890 x 626 open sideways, and any
width in Split View.

Update the app so that:
1. Screen size is read with useWindowDimensions() inside
   components. Never use Dimensions.get() at the top of
   a file.
2. No helper scales sizes by screen width. Remove
   react-native-size-matters and
   react-native-responsive-screen scaling, and use the
   designed sizes.
3. app.json uses "orientation": "default", not
   "portrait".
4. Screens 600 points wide or more use a two-column
   layout.
5. Left and right safe-area insets from
   react-native-safe-area-context are applied
   separately, never one value for both sides.
6. Tabs use NativeTabs from expo-router instead of Tabs
   (Expo SDK 54 or later).
7. No widths are hard-coded, such as 375 or 390.
8. Video, timers and animation pause only when the app
   goes to the background, not when it becomes inactive.

List every file you changed and why.

When to get help

If the app matters to your business and you would rather not debug layout, send it to us for a free evaluation. We will reply with what is likely to break on iPhone Duo and what fixing it involves. No call, no obligation.

Related

Free evaluation of your app

Run the checklist — the blockers are enough — send it to us, and we will reply with your outstanding items prioritised and a realistic effort estimate. No call, no obligation.