From Idea to App Store: Building My First Mobile App in 6 Weeks
Development

From Idea to App Store: Building My First Mobile App in 6 Weeks

Ricardo Gil
January 5, 2026
25 min read
#React Native #Mobile Development #Expo #iOS #Android #App Store #Case Study #Open Source #TypeScript

The Idea

It was November 2024, and I had just wrapped up another intense week of .NET development work. I was sitting at my desk, thinking about a conversation I'd had with my wife, Daniela, about wanting to start our day with scripture but always forgetting to open the Bible app on our phones.

That's when it hit me: What if there was a dead-simple app that just showed you a random Bible verse every time you opened it? No accounts, no complexity, no distractions—just you and the Word.

I'd been wanting to publish something to the App Store for a while, partly to diversify my technical portfolio beyond web development, and partly because I was curious about the mobile app publishing process. This felt like the perfect project: simple enough to actually finish, useful enough to be meaningful, and focused enough to ship quickly.

The Problem I Wanted to Solve:

  • Existing Bible apps were overwhelming (thousands of features, reading plans, social features)
  • People wanted quick spiritual refreshment, not commitment
  • Language barrier for Spanish speakers (most apps were English-first)
  • Privacy concerns (too many apps collecting data)

My Goals:

  1. Ship my first mobile app to the App Store
  2. Learn React Native and Expo
  3. Create something genuinely useful for daily spiritual life
  4. Make it bilingual (English/Spanish) from day one
  5. Keep it 100% free with no ads or tracking

The Technical Stack

I chose React Native with Expo for a few strategic reasons:

Why React Native:

  • Write once, deploy to both iOS and Android
  • JavaScript/TypeScript (already familiar from my Angular work)
  • Huge ecosystem and community
  • Hot reload for fast development

Why Expo:

  • Managed workflow (no need for Xcode/Android Studio initially)
  • Over-the-air updates
  • Easy push notifications setup
  • EAS Build for cloud builds (no Mac needed for iOS builds!)

Full Stack:

code
Frontend: React Native 0.81
Language: TypeScript 5.1
Framework: Expo 54
State Management: React Hooks (useState, useEffect)
Storage: AsyncStorage (for offline data)
API: Bolls.life Bible API (free, no auth)
Navigation: Expo Router

Why These Choices Matter:

  1. TypeScript: Type safety prevents stupid bugs. In a solo project, you ARE the QA team.

  2. AsyncStorage: All user data (favorites, downloaded books, preferences) stored locally. Zero backend costs, maximum privacy.

  3. Bolls.life API: After researching 5+ Bible APIs, this one was perfect:

    • Free and unlimited
    • Multiple translations
    • Simple REST endpoints
    • No authentication required
    • Support for verse-by-verse fetching (crucial for my offline feature)
  4. Expo Managed Workflow: I could build iOS apps from my Windows PC using EAS Build. Game-changer.

The Development Journey

Week 1: MVP (16 hours)

Day 1-2: Core Functionality

I started with the absolute minimum:

typescript
// The heart of the app - fetch a random verse
const fetchVerse = async () => {
  const response = await fetch(
    `https://bolls.life/get-random-verse/WEB/`
  );
  const data = await response.json();
  const cleanText = data.text.replace(/<[^>]*>/g, ''); // Strip HTML tags
  
  setVerse({
    text: cleanText,
    reference: `${data.book} ${data.chapter}:${data.verse}`,
    translation_id: 'WEB'
  });
};

Key Decision: Strip HTML tags from API responses. The API returns formatted text with and tags. I wanted plain text for simplicity.

Day 3: UI/UX Design

I'm not a designer, so I kept it minimal:

  • Clean typography (large, readable text)
  • Warm color palette (sage green, warm brown, off-white)
  • Dark mode from day one
  • One main action: "New Verse" button

Design Philosophy: Remove everything that doesn't serve the core experience.

Day 4-5: Essential Features

Added three critical features:

  1. Favorites: Long-press to save verses
  2. Share: Export verses to social media
  3. Copy: Quick clipboard copy
typescript
const toggleFavorite = async () => {
  const verseId = `${verse.reference}-${verse.translation_id}`;
  const newFavorite: SavedVerse = {
    ...verse,
    id: verseId,
    savedAt: Date.now()
  };
  await saveFavorites([newFavorite, ...favorites]);
};

Learning: React Native's Share API is beautiful—one line of code works on both platforms:

typescript
await Share.share({
  message: `${verse.text}\n\n— ${verse.reference}`
});

Week 2: Going Bilingual (12 hours)

The Spanish Challenge:

I wanted Spanish support from day one because:

  • My family in Venezuela would use it
  • 50+ million Spanish speakers in the US
  • Most Bible apps treat Spanish as an afterthought

Implementation:

typescript
const translations = {
  en: {
    title: "Daily Bible Verse",
    newVerse: "New Verse",
    share: "Share",
    copy: "Copy"
  },
  es: {
    title: "Versículo Bíblico Diario",
    newVerse: "Nuevo Versículo",
    share: "Compartir",
    copy: "Copiar"
  }
};

Supported Translations:

  • English: WEB (World English Bible), KJV (King James), ASV (American Standard)
  • Spanish: RVR1960 (Reina-Valera), LBLA (La Biblia de las Américas), NVI (Nueva Versión Internacional)

UI Challenge: Language switcher needed to be intuitive. I used flag emojis (🇺🇸/🇪🇸) with a dropdown. Simple, visual, works everywhere.

Week 3-4: The Offline Feature (20 hours)

This was the hardest part—and the most rewarding.

The Problem: Users wanted to read complete books offline (imagine flights, camping, poor signal areas).

The Challenge: Download entire books verse-by-verse without overwhelming the API.

My Solution:

typescript
const downloadBook = async (book: Book) => {
  const allVerses: BibleVerse[] = [];
  
  // Loop through each chapter
  for (let ch = 1; ch <= book.chapters; ch++) {
    let v = 1;
    let chapterComplete = false;
    
    while (!chapterComplete && v <= 250) {
      const url = `https://bolls.life/get-verse/${translation}/${bookId}/${ch}/${v}/`;
      const res = await fetch(url);
      
      if (!res.ok) {
        chapterComplete = true; // 404 = end of chapter
        break;
      }
      
      const data = await res.json();
      allVerses.push({
        text: data.text.replace(/<[^>]*>/g, ''),
        reference: `${bookName} ${ch}:${v}`,
        // ... more fields
      });
      
      v++;
      await new Promise(r => setTimeout(r, 50)); // Polite 50ms delay
    }
    
    // Update progress bar
    setProgress((ch / book.chapters) * 100);
  }
  
  // Save to AsyncStorage
  await AsyncStorage.setItem(`book_${bookName}`, JSON.stringify(allVerses));
};

Why This Approach:

  1. Polite crawling: 50ms delay between requests (don't abuse the free API!)
  2. Chapter-by-chapter: Show progress, allow pause/resume
  3. 404 detection: API returns 404 when verses run out (graceful ending)
  4. Local storage: Once downloaded, completely offline

Result: Users can download any of the 66 Bible books. Genesis = 1,533 verses, stored in ~300KB. The entire Bible = ~31,000 verses, ~6MB.

UI Polish:

  • Real-time progress bar
  • Verse count updates as download progresses
  • Can read what's downloaded while download continues
  • Delete button to free up space

Week 5: Polish & Testing (8 hours)

Responsive Design:

Had to support:

  • Small phones (iPhone SE - 375px wide)
  • Regular phones (iPhone 14 - 390px)
  • Tablets (iPad - 768px+)
typescript
const [dimensions, setDimensions] = useState(Dimensions.get('window'));

useEffect(() => {
  const subscription = Dimensions.addEventListener('change', ({ window }) => {
    setDimensions(window);
  });
  return () => subscription?.remove();
}, []);

const isSmallDevice = dimensions.width < 375;
const isTablet = dimensions.width >= 768;

Dark Mode:

System-aware dark mode with manual override:

typescript
const [themeMode, setThemeMode] = useState<'light' | 'dark' | 'system'>('system');

const isDark = themeMode === 'dark' || 
  (themeMode === 'system' && useColorScheme() === 'dark');

Performance Optimization:

  1. Lazy loading for favorites (only load when tab opens)
  2. Memoized components for verse display
  3. Debounced search in downloaded books
  4. Image optimization for app icon/splash

Week 6: App Store Submission

The Requirements:

For Apple App Store:

  • Apple Developer account ($99/year)
  • App icons (1024x1024 PNG)
  • Screenshots (6.7" iPhone, 12.9" iPad)
  • Privacy policy
  • App description, keywords, category
  • Age rating (I chose 4+)

For Google Play:

  • Google Play Console ($25 one-time)
  • Feature graphic (1024x500)
  • Screenshots (phone + tablet)
  • Privacy policy
  • Store listing
  • Content rating

The Submission Process:

Building the iOS App:

bash
# Configure EAS
eas build:configure

# Build for iOS (cloud build, no Mac needed!)
eas build --platform ios

# Submit to App Store Connect
eas submit --platform ios

The Review Process:

  • Apple: Submitted November 18, 2024

    • Initial review: 24 hours
    • Rejected once (missing age rating explanation)
    • Fixed and resubmitted
    • Approved November 20, 2024
    • Total time: 2 days
  • Google Play: Currently in closed testing

    • 12 testers (friends, family, church members)
    • Running for 5 days
    • Collecting feedback before public launch

What I Learned About App Review:

  1. Apple is stricter but faster: Clear guidelines, quick turnaround
  2. Privacy policy is non-negotiable: Even if you collect zero data, you need one
  3. Screenshots matter: I got feedback that mine could be more compelling
  4. Keywords are limited: Apple allows 100 characters total. Choose wisely.

The Technical Challenges

Challenge #1: HTML in API Responses

Problem: The API returns verses with HTML formatting:

code
"For God <em>so</em> loved the world..."

Solution: Regex to strip tags:

typescript
const cleanText = text.replace(/<[^>]*>/g, '');

Why not parse HTML? React Native doesn't have a built-in HTML parser, and I didn't want to add a dependency for this simple use case.

Challenge #2: Verse Numbering Inconsistencies

Problem: Different translations have different verse counts (some split verses, some combine them).

Solution: The 404 detection pattern. When the API returns 404, that chapter is done. No hardcoded verse counts needed.

Challenge #3: AsyncStorage Limits

Problem: AsyncStorage has a 6MB limit on Android (10MB on iOS).

Solution:

  • Compress data (remove whitespace from JSON)
  • Store books separately (not one giant object)
  • Warn users when approaching limit
  • Provide "clear all downloads" option

Challenge #4: Building iOS Without a Mac

Problem: I develop on Windows. Xcode requires macOS.

Solution: Expo EAS Build is magic. Upload your code, they build it on their servers, you get back an IPA file ready for App Store Connect.

bash
eas build --platform ios
# ☁️ Builds in the cloud
# 📧 Email notification when done
# 📦 Download IPA or submit directly

Cost: $29/month for EAS priority builds (well worth it).

Challenge #5: Keeping App Size Small

Target: Under 25MB (psychological threshold for cellular downloads)

Strategies:

  1. No external fonts (use system fonts)
  2. Optimized PNG icons (use TinyPNG)
  3. No bundled images beyond icons
  4. Tree-shaking unused Expo modules

Result: 23.8 MB final app size ✅

The Results

App Store Metrics (First 6 Weeks)

Downloads:

  • Total Units: 31 downloads
  • Impressions: 396 (154% increase week-over-week)
  • Conversion Rate: 7.8%

User Engagement:

  • Sessions: 18 active sessions
  • Retention: Users open app 3.2 times/week on average
  • Crashes: 0 (zero crashes! 🎉)

Revenue: $0 (completely free, no monetization)

Rating: ⭐⭐⭐⭐⭐ 5.0 stars

Google Play (Closed Testing)

Testers: 12 people (friends, family, church members)

Feedback Highlights:

  • "Love how simple it is - no distractions"
  • "Spanish support is perfect for my parents"
  • "Dark mode is beautiful"
  • "Offline books are a game-changer for flights"

Requested Features:

  1. Search function (most requested)
  2. Daily notifications (set time for daily verse)
  3. Reading plans (structured Bible reading)
  4. Bookmarks (mark position in downloaded books)
  5. Verse highlighting/notes

Open Source Impact

GitHub Stats:

  • Stars: 3 ⭐
  • Forks: 1
  • Watchers: 2
  • Issues: 0 (no bugs reported!)

Why Open Source:

  1. Portfolio showcase (proves I ship code)
  2. Community contributions (future features)
  3. Learning resource for other devs
  4. Transparency (users can verify privacy claims)

Repository: https://github.com/gilricardo-com/daily-bible-verse

What I Learned

Technical Lessons

1. React Native Is Production-Ready

Coming from Angular/web development, I was skeptical. But React Native works. The performance is good, the ecosystem is mature, and Expo removes most of the pain.

2. Mobile UX Is Different

Things I took for granted on web:

  • Hover states don't exist (use press states)
  • Back button means different things (Android vs iOS)
  • Safe areas matter (notch, home indicator)
  • Touch targets need to be 44x44pt minimum
  • Loading states are critical (poor connections common)

3. Offline-First Is Complex

I massively underestimated the offline feature. Edge cases everywhere:

  • What if download interrupted?
  • How to handle partial data?
  • How to clear/update cached data?
  • Storage limits?
  • Progress indication?

4. APIs Can Be Simple

The Bolls.life API is beautiful in its simplicity:

code
GET /get-random-verse/WEB/  → Random verse
GET /get-verse/WEB/1/1/1/    → Genesis 1:1

No authentication, no rate limits, no complexity. Sometimes simple is best.

Business Lessons

1. Scope Ruthlessly

My original feature list had 20+ items. I shipped with 6 core features. The rest can wait.

MVP mindset: What's the ONE thing this app must do well?

2. Publish Fast, Iterate Later

I waited too long perfecting things before submitting. Could have launched 2 weeks earlier and gotten real user feedback sooner.

3. App Store Optimization Matters

Bad keyword choices: "bible verse generator" (high competition)
Good keyword choices: "daily bible verse offline" (specific, less competition)

Bad screenshot: Just showing the app
Good screenshot: Showing the benefit ("Read the Bible offline, anytime")

4. Free Apps Can Succeed Without Monetization

I have zero ads, no subscriptions, no freemium model. Just a useful tool.

Why?

  • Builds trust and credibility
  • Portfolio piece (showcases skills)
  • Aligns with my values (faith-based content should be accessible)
  • Could monetize later if I want (donations, premium features)

Personal Lessons

1. Shipping Feels Amazing

There's something uniquely satisfying about seeing your app on the App Store. "I made this, and now strangers can use it."

2. Imposter Syndrome Never Goes Away

Even after building web apps professionally for 6+ years, I felt like a fraud publishing a mobile app. "Who am I to do this?"

Do it anyway.

3. Side Projects Are Worth It

This project:

  • Taught me React Native
  • Gave me portfolio material
  • Led to interesting conversations with recruiters
  • Connected me with other Christian developers
  • Created something useful for people I care about

ROI: Priceless.

4. Start Where You Are

I didn't wait until I was an "expert" in mobile development. I had a need, researched for 2 days, and started building.

6 weeks later, I had a published app.

The Tech Stack Deep Dive

Let me break down some key technical decisions:

Why Expo Over Pure React Native?

Expo Pros:

  • Managed workflow (less configuration)
  • OTA updates (fix bugs without app store review)
  • EAS Build (build iOS on Windows)
  • Push notifications setup is 5 lines of code
  • Expo modules are well-maintained

Expo Cons:

  • Slightly larger app size (~5MB overhead)
  • Some native modules not available
  • Less control over native code (can eject if needed)

Verdict: For 95% of apps, Expo is the right choice. I can always eject later if needed.

State Management: Why No Redux/MobX?

Simple truth: This app doesn't need it.

State I manage:

  • Current verse (useState)
  • Favorites list (useState + AsyncStorage)
  • Downloaded books (useState + AsyncStorage)
  • UI state (modals, loading)

React hooks handle this perfectly. Adding Redux would be overengineering.

When I'd use Redux:

  • Complex state shared across 10+ components
  • Time-travel debugging needed
  • Middleware requirements (logging, crash reporting)

Navigation: Expo Router

I use Expo Router (file-based routing):

code
app/
  index.tsx        → Main screen
  favorites.tsx    → Favorites view
  book-detail.tsx  → Single book view
  settings.tsx     → Settings

Why file-based routing?

  • Familiar (works like Next.js)
  • Deep linking built-in
  • Type-safe navigation
  • Less boilerplate than React Navigation

Styling: StyleSheet vs Styled Components?

I use plain StyleSheet.create:

typescript
const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    backgroundColor: isDark ? '#1C1C1C' : '#F5F5F0'
  },
  verseText: {
    fontSize: isSmallDevice ? 20 : 24,
    lineHeight: 1.5,
    fontFamily: 'System'
  }
});

Why not styled-components?

  • StyleSheet is optimized by React Native
  • No runtime parsing
  • Better performance
  • Smaller bundle size

Trade-off: Less flexible, more verbose. But performance > convenience for mobile.

The Features Breakdown

Let me walk you through each feature's implementation:

Feature #1: Random Verse

How it works:

  1. Call API: GET https://bolls.life/get-random-verse/WEB/
  2. Parse JSON response
  3. Strip HTML tags
  4. Display verse + reference

Code:

typescript
const fetchVerse = async () => {
  setLoading(true);
  try {
    const url = `https://bolls.life/get-random-verse/${selectedVersion[language]}/`;
    const response = await fetch(url);
    const data = await response.json();
    
    setVerse({
      text: data.text.replace(/<[^>]*>/g, ''),
      reference: `${data.book} ${data.chapter}:${data.verse}`,
      translation_id: selectedVersion[language]
    });
  } catch (error) {
    setError(true);
  } finally {
    setLoading(false);
  }
};

Error handling:

  • Network error → Show "Try Again" button
  • API timeout → Show error message
  • Still allow access to offline content (favorites, downloaded books)

Feature #2: Favorites

Storage structure:

typescript
interface SavedVerse {
  id: string;              // "John 3:16-WEB"
  text: string;
  reference: string;
  translation_id: string;
  savedAt: number;         // timestamp
}

Persisted in AsyncStorage:

typescript
await AsyncStorage.setItem('favorites', JSON.stringify(favorites));

UI features:

  • Heart icon (filled when favorited)
  • Long-press on any verse to favorite
  • Swipe-to-delete in favorites list
  • Sort by date (newest first)

Feature #3: Share & Copy

Share (native):

typescript
const handleShare = async () => {
  await Share.share({
    message: `${verse.text}\n\n— ${verse.reference} (${verse.translation_id})`
  });
};

Copy (clipboard):

typescript
import * as Clipboard from 'expo-clipboard';

const handleCopy = async () => {
  await Clipboard.setStringAsync(
    `${verse.text}\n\n— ${verse.reference}`
  );
  Alert.alert('✓', 'Copied to clipboard');
};

Why both? Share opens system share sheet (WhatsApp, Instagram, etc.). Copy gives quick access for pasting elsewhere.

Feature #4: Multi-Translation Support

Available translations:

English:

  • WEB (World English Bible) - Modern, public domain
  • KJV (King James Version) - Traditional, poetic
  • ASV (American Standard Version) - Literal translation

Spanish:

  • RVR1960 (Reina-Valera 1960) - Most popular in Latin America
  • LBLA (La Biblia de las Américas) - Modern, accurate
  • NVI (Nueva Versión Internacional) - Contemporary

Switching translations:

typescript
const changeVersion = async (versionCode: string) => {
  setSelectedVersion(prev => ({
    ...prev,
    [language]: versionCode
  }));
  await AsyncStorage.setItem(`version_${language}`, versionCode);
  
  // Reload current verse in new translation
  if (verse) {
    fetchSpecificVerse(verse.book, verse.chapter, verse.verse);
  }
};

UX detail: When switching translation, keep the same verse (re-fetch with new translation). Users can compare translations side-by-side.

Feature #5: Offline Book Downloads

The algorithm:

typescript
const downloadBook = async (book: Book) => {
  const bookId = bibleBooks.findIndex(b => b.name === book.name) + 1;
  const allVerses: BibleVerse[] = [];
  
  for (let chapter = 1; chapter <= book.chapters; chapter++) {
    let verse = 1;
    let chapterComplete = false;
    
    while (!chapterComplete) {
      const url = `https://bolls.life/get-verse/${translation}/${bookId}/${chapter}/${verse}/`;
      const response = await fetch(url);
      
      if (!response.ok) {
        chapterComplete = true; // 404 = no more verses
        continue;
      }
      
      const data = await response.json();
      allVerses.push({
        text: data.text.replace(/<[^>]*>/g, ''),
        reference: `${book.name} ${chapter}:${verse}`,
        chapter,
        verse
      });
      
      verse++;
      await sleep(50); // Polite delay
    }
    
    // Update progress
    setProgress((chapter / book.chapters) * 100);
  }
  
  // Save to storage
  const downloadedBook: DownloadedBook = {
    bookName: book.name,
    translation,
    verses: allVerses,
    downloadedAt: Date.now()
  };
  
  await AsyncStorage.setItem(
    `book_${book.name}_${translation}`,
    JSON.stringify(downloadedBook)
  );
};

Progress indication:

typescript
const progress = (currentChapter / totalChapters) * 100;
// Show progress bar: 0-100%
// Also show verse count updating in real-time

Memory management:

  • Download one book at a time
  • Allow cancellation mid-download
  • Clean up partial downloads if canceled

Feature #6: Dark Mode

Implementation:

typescript
const [themeMode, setThemeMode] = useState<'light' | 'dark' | 'system'>('system');

const isDark = 
  themeMode === 'dark' ||
  (themeMode === 'system' && useColorScheme() === 'dark');

const styles = createStyles(isDark);

Color palette:

Light Mode:

  • Background: #F5F5F0 (warm off-white)
  • Text: #2C2C2C (dark gray)
  • Button: #4A5D4E (sage green)
  • Accent: #8B7355 (warm brown)

Dark Mode:

  • Background: #1C1C1C (true black)
  • Text: #E5E5E5 (light gray)
  • Button: #6B7C6E (muted sage)
  • Accent: #A89378 (light brown)

Why not pure black? OLED burn-in concerns. Also, pure black (#000000) looks harsh. Slightly off-black is more comfortable.

The App Store Optimization (ASO) Strategy

Title & Subtitle

Title: "Daily Random Bible Verse"

Why this works:

  • Contains main keyword: "Bible Verse"
  • Explains core function: "Daily" + "Random"
  • Short enough to display fully (under 30 chars)

Subtitle (iOS): "Scripture Inspiration & Offline Reading"

Why this works:

  • Secondary keywords: "Scripture", "Inspiration", "Offline"
  • Benefit-focused, not feature-focused

Keywords (100 character limit)

My choices:

code
bible,verse,daily,scripture,offline,spanish,devotional,christian,faith,quotes,king james,rv1960

Research process:

  1. Used App Store search suggestions
  2. Checked competitor keywords (Bible Gateway, YouVersion)
  3. Prioritized low-competition, high-intent keywords
  4. Included Spanish terms (bilingual advantage)

Avoided:

  • Generic terms: "app", "free", "best"
  • Brand names: Can't rank for "YouVersion"
  • Duplicates: Title already contains "daily bible verse"

Screenshots (6.7" iPhone)

Screenshot 1 - Hero Shot:

  • Shows main screen with verse
  • Overlay text: "Daily Scripture Inspiration"
  • Clean, beautiful, immediately understandable

Screenshot 2 - Dark Mode:

  • Same layout in dark mode
  • Overlay: "Beautiful in Any Light"

Screenshot 3 - Offline Feature:

  • Downloaded books list
  • Overlay: "Complete Bible Books Offline"

Screenshot 4 - Bilingual:

  • Spanish interface
  • Overlay: "Disponible en Español"

Screenshot 5 - Features:

  • List of features with icons
  • No text overlay (let features speak)

Design principles:

  • Use real app UI (not marketing mockups)
  • Overlay text readable from thumbnail
  • Show benefits, not features
  • Demonstrate actual use

App Description

First 170 characters (preview):

code
Start each day with inspiration from the Bible. Daily Random Bible Verse delivers Scripture in English or Spanish, with complete offline reading.

Why this works:

  • Benefit first: "Start each day with inspiration"
  • Keywords naturally included
  • Addresses pain point: "complete offline reading"

Full description structure:

  1. Hook (2 sentences): What it does, who it's for
  2. Key features (bullet list): 6 main features
  3. Translations (paragraph): Detail language support
  4. Privacy (paragraph): No data collection, no ads
  5. Open source (paragraph): Link to GitHub
  6. Call to action: "Download now and start your daily journey with Scripture"

Category Selection

Primary: Books & Reference
Secondary: Lifestyle

Why not "Reference" only? Too competitive. "Lifestyle" has less competition in Bible app space.

Pricing

Free (no IAP, no subscriptions)

Why?

  1. Removes barrier to download
  2. Aligns with mission (make Scripture accessible)
  3. Portfolio piece (doesn't need to make money)
  4. Could add donations later if desired

Localization

Languages supported:

  • English (US)
  • Spanish (Latin America)

Localized elements:

  • App name
  • Description
  • Screenshots
  • Keywords

Impact: Shows up in Spanish App Store searches, appeals to bilingual users.

Roadmap: What's Next

Based on tester feedback and my vision, here's what's coming:

Phase 2: Core Enhancements (Q1 2025)

1. Search Functionality ⭐ Most requested

Find specific verses by:

  • Book, chapter, verse (e.g., "John 3:16")
  • Keywords (e.g., "love", "faith")
  • Topic (e.g., "hope", "forgiveness")

Technical approach:

  • Index all downloaded books locally
  • Use fuzzy matching for keywords
  • Highlight search terms in results

2. Daily Notifications

Push notification at user-selected time:

  • "Good morning! Here's today's verse..."
  • Customizable time
  • Randomized verse from user's preferred translation

Technical approach:

  • Expo Notifications API
  • Local notifications (no server needed)
  • Permission request with clear explanation

3. Reading Plans

Structured Bible reading:

  • "Read the Bible in a Year"
  • "Gospels in 30 Days"
  • "Psalms & Proverbs Monthly"

UI:

  • Progress tracking
  • Checkmarks for completed readings
  • Reminder notifications

Phase 3: Community Features (Q2 2025)

4. Verse of the Day (Community)

See what verse other users are reading:

  • Global VOTD (voted by community)
  • Most favorited verses this week
  • Trending verses

Privacy: Anonymous voting, no personal data

5. Sharing Improvements

Enhanced sharing:

  • Instagram Stories integration (beautiful templates)
  • Verse images (generated on-device)
  • Quote-style formatting

6. Reading Streaks

Gamification (light touch):

  • Track consecutive days opened
  • Milestone achievements
  • No pressure, just encouragement

Phase 4: Premium Features (Q3 2025)

7. Advanced Study Tools

For serious Bible students:

  • Cross-references
  • Commentaries (public domain)
  • Original language tools (Hebrew/Greek)
  • Word studies

Monetization: $2.99/month or $19.99/year

Why premium? Advanced features require:

  • Larger datasets
  • More complex UI
  • Server costs (for syncing notes)

8. Cloud Sync

Sync across devices:

  • Favorites
  • Reading progress
  • Notes (if added)
  • Downloaded books

Backend: Firebase (free tier sufficient for thousands of users)

Long-Term Vision

The Goal: Not to compete with YouVersion or Bible Gateway (they're amazing).

Instead: Be the simplest, most beautiful, most accessible Bible app for daily inspiration.

Core principles:

  • ✅ Remain free for core features
  • ✅ No ads, ever
  • ✅ Privacy-first
  • ✅ Open source
  • ✅ Multilingual
  • ✅ Offline-first

For Aspiring App Developers

If you're thinking about building your first mobile app, here's my advice:

1. Start Stupid Simple

Your first app should do ONE thing well. Don't build the next Instagram.

Good first apps:

  • Random quote generator
  • Tip calculator
  • Unit converter
  • Daily reminder app
  • Simple timer

Bad first apps:

  • Social network
  • Complex game
  • E-commerce platform
  • Anything requiring complex backend

2. Use Expo

Seriously. Don't fight me on this.

Yes, you give up some control. Yes, the app is slightly larger. But you'll ship 10x faster.

Start here:

bash
npx create-expo-app my-first-app
cd my-first-app
npm start

In 2 minutes, you're running an app on your phone.

3. Ship Fast, Learn Faster

My timeline:

  • Week 1-2: Build MVP
  • Week 3-4: Polish + testing
  • Week 5: Submit to stores
  • Week 6: Iterate based on feedback

Your timeline should be similar.

Don't spend 6 months perfecting before launch. Ship in 4-6 weeks. Get real users. Learn. Iterate.

4. Read These First

Essential reading:

  1. React Native Docs - Start here
  2. Expo Docs - Your best friend
  3. App Store Review Guidelines - Read before building
  4. Play Store Policies - Same

Helpful tutorials:

5. Tools I Used

Development:

  • VS Code (with React Native extension)
  • Expo Go app (for testing on real device)
  • React Native Debugger

Design:

  • Figma (mockups/wireframes)
  • Coolors.co (color palette generator)
  • TinyPNG (image compression)

Icon/Splash:

  • Figma (design)
  • Icon.kitchen (iOS icons from one image)
  • App Icon Generator (Android adaptive icons)

Testing:

  • iPhone 14 (physical device)
  • Expo Go (quick testing)
  • TestFlight (iOS beta testing)

Deployment:

  • EAS CLI (build + submit)
  • App Store Connect (Apple)
  • Google Play Console (Android)

6. Budget Reality Check

Costs to publish an app:

One-time:

  • Google Play: $25 (lifetime)
  • Apple Developer: $99/year
  • Domain (optional): $12/year

Monthly (if using Expo EAS):

  • Free tier: 30 builds/month (plenty for solo dev)
  • Paid tier: $29/month (unlimited builds + priority)

Total first year: $136-$484

My spending: $205 (Apple $99 + Google $25 + Expo $29x3 months)

7. Common Mistakes to Avoid

Mistake #1: Not testing on real devices

Simulators lie. Test on actual phones. Beg, borrow, or rent if you must.

Mistake #2: Ignoring platform differences

iOS and Android are different. Especially:

  • Navigation patterns
  • Back button behavior
  • Push notification permissions
  • Status bar handling

Mistake #3: Over-engineering

You don't need:

  • Redux (probably)
  • Complex folder structure
  • Microservices
  • Advanced testing setup (for v1)

You DO need:

  • Basic error handling
  • Loading states
  • Offline behavior
  • Good UX

Mistake #4: Perfectionism

Ship the 80% solution. Iterate.

Perfect is the enemy of done.

Mistake #5: Not reading guidelines

Apple and Google reject apps for stupid reasons:

  • Missing privacy policy
  • Crashes on launch
  • Incomplete functionality
  • Misleading descriptions

Read. The. Guidelines.

8. Your Launch Checklist

Pre-launch (1 week before):

  • App tested on 3+ devices
  • All features work offline
  • Error states handled
  • Loading states everywhere
  • Privacy policy written
  • Screenshots designed
  • App description written
  • Keywords researched

Launch day:

  • Submit to both stores
  • Share on Twitter/LinkedIn
  • Post in relevant subreddits (respectfully!)
  • Tell friends/family
  • Add to portfolio/resume
  • Update GitHub README

Post-launch (first week):

  • Monitor crash reports
  • Read user reviews
  • Fix critical bugs ASAP
  • Plan v1.1 features
  • Respond to user feedback

Conclusion

Building and publishing my first mobile app was one of the most rewarding experiences of my development career. It combined:

  • Technical learning (React Native, mobile UX, app stores)
  • Product thinking (what do users actually need?)
  • Execution (shipping something real)

Total time invested: ~60 hours over 6 weeks

Total cost: $205

Result: A published iOS app with real users, open source code showcasing my skills, and invaluable learning experience.

Most importantly: I created something useful. People use it daily for spiritual inspiration. That matters more than downloads or revenue.

Your Turn

Whether you're a seasoned web developer curious about mobile, a bootcamp grad building your portfolio, or someone with an idea and no technical background—you can do this.

Mobile app development is more accessible than ever:

  • Tools are better (Expo, React Native)
  • APIs are free (Bolls.life, and thousands of others)
  • Documentation is excellent
  • Community is helpful

You don't need:

  • A Mac (EAS Build handles iOS)
  • Years of experience
  • A big budget
  • A team

You DO need:

  • An idea
  • Willingness to learn
  • 4-6 weeks of focused work
  • $136 (minimum)

That's it.


Links & Resources

App:

Code:

API:

Tools:

Contact:


About the Author:

Ricardo Gil is a Full Stack Software Engineer with 6+ years of experience specializing in C#/.NET Core, Angular, and PostgreSQL. Originally from Venezuela, he immigrated to the United States in 2015 and has built scalable applications for healthcare, hospitality, and e-commerce industries. "Daily Random Bible Verse" is his first published mobile application, combining his technical expertise with his faith to create a tool for daily spiritual inspiration.


If you found this helpful, please star the GitHub repo and share this post with other aspiring app developers. Your support means the world!

Have questions about the app or mobile development in general? Leave a comment or email me at contact@gilricardo.com.

Related Posts

Building with Angular + Firebase? Check out my Photography E-Commerce Platform that combines Firebase auth with Stripe payments and AWS S3 storage.

Self-hosting your projects? Learn how I host production apps on a Raspberry Pi with PM2, Nginx, and Tailscale.

About the Author: Ricardo Gil is a full-stack software engineer specializing in .NET/C#, Angular, and cloud platforms. Read more or subscribe for updates.

📬Weekly Newsletter

Get the best home lab & AI content

No spam. One email per week. Unsubscribe anytime.

Share this article