When I decided to build my first mobile app, I followed a tutorial that told me to download Android Studio.
I had an older budget laptop with 8GB of RAM. The moment I clicked "Launch Android Virtual Device (AVD)", the fan screamed like a jet engine. Chrome tabs crashed, the mouse cursor froze in place, and ten minutes later my entire operating system locked up. If you are learning to code in India or working on budget hardware, you know that exact feeling.
Nobody told me you do not need an emulator at all. You do not need a ₹1.5 lakh MacBook to build for iOS either. Here is how modern solo developers build, test, and release cross-platform mobile apps for ₹0 using React Native and Expo.
The Tech Stack Battle: React Native (Expo) vs Flutter
For a solo engineer or fresher building a portfolio, choosing between React Native and Flutter comes down to practical tradeoffs:
| Feature | React Native (with Expo) | Flutter (with Dart) |
|---|---|---|
| Language | TypeScript / JavaScript | Dart |
| Hardware Demand | Very low (Metro bundler runs fast) | Moderate (Dart compiler requires more RAM) |
| Code Sharing | Shares types, hooks, and API clients with Next.js web apps | Isolated to Flutter ecosystem |
| Cloud Builds | Free EAS Build (generates iOS/Android binaries without a Mac) | Requires local Xcode or CI/CD runner setup |
| UI Rendering | Native platform primitives (UIView / android.view) | Custom Skia/Impeller canvas engine |
If you already know JavaScript or React, pick React Native with Expo. It lets you write strict TypeScript, reuse your backend schemas, and preview the app directly on your physical Android or iPhone over local Wi-Fi.
Setting Up a Lightweight Dev Environment Without Emulators
Do not install heavy emulators if your laptop has 8GB or 16GB of RAM. Instead, run your development server on your laptop and test live on your physical phone:
- Install the Expo Go app on your Android phone or iPhone from the app store.
- Initialize your project using the Expo CLI template with TypeScript:
npx create-expo-app@latest my-mobile-app --template tabs
cd my-mobile-app
npx expo start
The terminal will print a QR code. Open the Expo Go app on your phone, scan the QR code, and your mobile screen will render your app in seconds. When you save a file in VS Code, Fast Refresh updates the phone screen in under 400 milliseconds.
Mobile Engineering Essentials: Safe Areas and Keyboard Handling
Mobile screens are messy. Devices have camera notches, rounded corners, dynamic islands, and software keyboards that cover input fields. If you ignore these, your app looks broken.
Here is a clean, reusable screen wrapper component handling safe area insets and keyboard avoidance:
// components/ScreenContainer.tsx
import React from 'react';
import {
KeyboardAvoidingView,
Platform,
ScrollView,
StyleSheet,
View,
} from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
interface ScreenContainerProps {
children: React.ReactNode;
scrollable?: boolean;
}
export function ScreenContainer({ children, scrollable = true }: ScreenContainerProps) {
const insets = useSafeAreaInsets();
const content = (
<View
style={[
styles.inner,
{
paddingTop: insets.top,
paddingBottom: insets.bottom,
paddingLeft: insets.left,
paddingRight: insets.right,
},
]}
>
{children}
</View
);
return (
<KeyboardAvoidingView
style={styles.container}
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
>
{scrollable ? (
<ScrollView
contentContainerStyle={styles.scrollContent}
keyboardShouldPersistTaps="handled"
>
{content}
</ScrollView
) : (
content
)}
</KeyboardAvoidingView
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#0f172a',
},
scrollContent: {
flexGrow: 1,
},
inner: {
flex: 1,
paddingHorizontal: 16,
},
});
Managing Local State and Fast In-Memory Storage
Never use slow, legacy AsyncStorage for critical tokens or frequent reads in production. Modern apps use synchronous key-value stores like react-native-mmkv or SQLite for offline-first performance:
// services/storage.ts
import { MMKV } from 'react-native-mmkv';
export const storage = new MMKV({
id: 'user-storage',
encryptionKey: 'your-secure-encryption-key',
});
export function saveAuthToken(token: string): void {
storage.set('auth_token', token);
}
export function getAuthToken(): string | undefined {
return storage.getString('auth_token');
}
export function clearAuthSession(): void {
storage.delete('auth_token');
}
MMKV operates directly via C++ JSI (JavaScript Interface) bindings. It reads and writes up to 30 times faster than old asynchronous storage bridges.
Shipping Your App for Free with EAS Build
In traditional iOS development, compiling an IPA file requires a physical Mac running Xcode. With Expo Application Services (EAS), you can trigger cloud compilation from a Windows, Linux, or Mac terminal:
# 1. Install EAS CLI globally
npm install -g eas-cli
# 2. Login to your free Expo account
eas login
# 3. Configure the build profile
eas build:configure
# 4. Build a standalone Android APK for direct phone installation
eas build -p android --profile preview
Expo cloud runners execute Gradle builds in the cloud and give you a direct download link for your compiled .apk. You can install it on your device or send it to interviewers without spending ₹1,000 on cloud server infrastructure.
The Real Portfolio Rule
When interviewers ask about mobile experience, do not show them screenshots. Hand them a live download link or a QR code that loads your app on their phone. When they see clean gesture animations, offline persistence, and zero keyboard overflow bugs, you immediately stand apart from candidates who only built basic web clones.
Next Steps
- Learn how to handle device themes properly in our guide on Production Dark Mode Systems.
- Test your backend payloads with our free JSON Formatter.
- Check model token limits with our Token Counter.
