Build Your First App in a Weekend
A step-by-step guide to building your first production-ready mobile app using automated tools.
GUIDE BODY
The New Way to Build Apps
Building a mobile app used to require months of work, deep technical knowledge, and a team of specialists. That has changed. AI tools can now generate production-quality code, design screens, write tests, and handle deployment. If you have a validated idea and basic technical literacy, you can ship a real app in days, not months.
This guide walks you through the entire process from blank screen to published app.
Prerequisites
You do not need to be an expert developer. But you do need:
- Basic programming knowledge: Understanding of variables, functions, and data structures. You should be able to read JavaScript or TypeScript code, even if you cannot write it from scratch.
- A computer with Node.js installed: Node 18 or later. Install from nodejs.org.
- An Apple Developer account ($99/year) if you want to publish to the iOS App Store.
- A Google Play Developer account ($25 one-time) for Android.
- A validated app idea: See our guide on validating app ideas.
Step 1: Choose Your Tech Stack
For most indie developers building cross-platform apps, the stack looks like this:
- React Native with Expo: Build for iOS and Android from one codebase
- TypeScript: Type safety that catches bugs early
- Supabase: Database, authentication, and serverless functions
- RevenueCat: Subscription management and in-app purchases
Why React Native?
Native development means maintaining two codebases (Swift for iOS, Kotlin for Android). React Native lets you write once and run on both platforms. Expo adds a managed workflow that handles the build system, over-the-air updates, and native module configuration.
# Create a new Expo project
npx create-expo-app my-app --template expo-template-blank-typescript
cd my-app
Step 2: Set Up Your Project Structure
A well-organized project saves you hours of confusion later. Here is a recommended structure:
my-app/
app/ # Screens (Expo Router file-based routing)
(auth)/ # Auth screens (login, signup)
(tabs)/ # Main app tabs
_layout.tsx # Root layout
components/ # Reusable UI components
hooks/ # Custom React hooks
lib/ # Third-party integrations
services/ # API and data layer
types/ # TypeScript type definitions
assets/ # Images, fonts, icons
supabase/
migrations/ # SQL migration files
Expo Router uses file-based routing, similar to Next.js. Each file in the app/ directory becomes a screen.
Step 3: Set Up Authentication
Every app needs user accounts. Supabase provides email/password auth, social login (Google, Apple, Twitter), and magic links out of the box.
npm install @supabase/supabase-js
Create a Supabase client:
// lib/supabase.ts
import { createClient } from '@supabase/supabase-js';
import AsyncStorage from '@react-native-async-storage/async-storage';
export const supabase = createClient(
process.env.EXPO_PUBLIC_SUPABASE_URL!,
process.env.EXPO_PUBLIC_SUPABASE_ANON_KEY!,
{
auth: {
storage: AsyncStorage,
autoRefreshToken: true,
persistSession: true,
},
}
);
Authentication Hook
// hooks/useAuth.ts
import { useEffect, useState } from 'react';
import { supabase } from '../lib/supabase';
import { Session } from '@supabase/supabase-js';
export function useAuth() {
const [session, setSession] = useState<Session | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
supabase.auth.getSession().then(({ data: { session } }) => {
setSession(session);
setLoading(false);
});
const { data: { subscription } } = supabase.auth.onAuthStateChange(
(_event, session) => setSession(session)
);
return () => subscription.unsubscribe();
}, []);
return { session, user: session?.user, loading };
}
Step 4: Design Your Screens
Before writing screen code, sketch your app on paper or in Figma. Identify:
- Onboarding flow: What do users see the first time they open the app?
- Core screens: What are the two to four screens where users spend most of their time?
- Settings: Profile, preferences, subscription management.
- Navigation: Tabs, stack navigation, or drawer?
Using AI for Screen Generation
AI tools excel at generating React Native screen code. When prompting an AI to generate screens, be specific:
- Describe the exact data shown on screen
- Specify the interaction patterns (pull to refresh, infinite scroll, swipe to delete)
- Mention the color scheme and design tokens
- Reference component libraries you are using
A good prompt looks like this:
Create a React Native screen that shows a list of workout sessions.
Each item displays: exercise name, duration, date, and calories burned.
Use FlatList with pull-to-refresh. Empty state shows an illustration
and "Start your first workout" CTA. Use dark theme (#0D0D0F background,
#111114 card background, #FF4500 accent color).
Step 5: Connect Your Database
Supabase gives you a Postgres database with a REST API generated automatically from your schema.
Create Tables
Write SQL migrations to define your schema:
-- supabase/migrations/001_initial.sql
CREATE TABLE profiles (
id UUID PRIMARY KEY REFERENCES auth.users(id),
display_name TEXT,
avatar_url TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Enable Row Level Security
ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;
-- Users can read and update their own profile
CREATE POLICY "Users manage own profile"
ON profiles FOR ALL
USING (auth.uid() = id);
Query Data from Your App
// services/profiles.ts
import { supabase } from '../lib/supabase';
export async function getProfile(userId: string) {
const { data, error } = await supabase
.from('profiles')
.select('*')
.eq('id', userId)
.single();
if (error) throw error;
return data;
}
Step 6: Add Core Features
With auth and data in place, build your app-specific features. Focus on the two or three features that make your app valuable. Everything else can wait.
Common Feature Patterns
Data lists with search and filter:
const [search, setSearch] = useState('');
const filtered = items.filter(item =>
item.name.toLowerCase().includes(search.toLowerCase())
);
Pull-to-refresh:
<FlatList
data={items}
refreshing={refreshing}
onRefresh={handleRefresh}
renderItem={({ item }) => <ItemCard item={item} />}
/>
Offline support: Cache data locally using AsyncStorage or expo-sqlite so the app works without an internet connection.
Step 7: Set Up Analytics
You cannot improve what you do not measure. Add analytics from day one.
// lib/posthog.ts
import PostHog from 'posthog-react-native';
const apiKey = process.env.EXPO_PUBLIC_POSTHOG_API_KEY;
export const posthog = apiKey
? new PostHog(apiKey, { host: 'https://us.i.posthog.com' })
: null;
export function trackEvent(name: string, properties?: Record<string, any>) {
if (!posthog) return;
posthog.capture(name, properties);
}
Track key events: sign up, core feature usage, subscription starts, and errors.
Step 8: Configure Monetization
If your app is free, skip this step. Otherwise, set up RevenueCat for subscriptions:
npm install react-native-purchases
RevenueCat handles receipt validation, subscription status, and cross-platform purchases. Configure your products in App Store Connect and Google Play Console, then map them in RevenueCat's dashboard.
Step 9: Build and Test
Development Testing
npx expo start
This starts the Expo development server. Test on:
- iOS Simulator (Mac only)
- Android Emulator (Android Studio)
- Physical devices using the Expo Go app
Preview Builds
For testing native features that Expo Go does not support:
npx eas build --profile preview --platform ios
This creates a build you can install directly on your test device.
Step 10: Submit to the App Store
Prepare your store listing:
- App name and subtitle: Clear and keyword-rich
- Screenshots: Show your app's best features. Use a tool like Screenshots.pro or create them in Figma.
- Description: Focus on benefits, not features. What problem does the app solve?
- Keywords: Research with AppTweak or Sensor Tower
- Privacy policy: Required by both stores. Use a generator like iubenda.
Build for Production
npx eas build --profile production --platform all
Submit
npx eas submit --platform ios
npx eas submit --platform android
EAS Submit handles uploading your build to App Store Connect and Google Play Console.
Timeline: What to Expect
| Phase | Duration | Output | |-------|----------|--------| | Setup | 1 day | Project, auth, database | | Core screens | 2-3 days | Main features working | | Polish | 1-2 days | Animations, error handling, edge cases | | Testing | 1-2 days | Bug fixes, device testing | | Store prep | 1 day | Screenshots, descriptions, metadata | | Review | 1-7 days | Apple/Google review process |
Total: roughly one to two weeks from start to store listing.
Common Mistakes to Avoid
- Building too many features: Ship with two or three core features. Add more based on user feedback.
- Skipping error handling: Every network call can fail. Show clear error messages and retry options.
- Ignoring performance: Test on older devices. A FlatList with 10,000 items needs virtualization.
- No analytics: You will be flying blind without event tracking. Add it on day one.
- Hardcoding strings: Use constants for colors, spacing, and text. It makes changes painless later.
Next Steps
Your app is live. Now the real work begins: listening to users, fixing bugs, adding features, and growing your audience. Check out our guides on user acquisition, ASO, and push notification strategy to keep the momentum going.