An AI-powered mobile language learning app (like Doulingo) built with React Native + Expo. Practice real conversations with an AI teacher through live audio calls, track your daily learning goals, and progress through structured lessons across multiple languages.
| Welcome / Onboarding | Home Dashboard | AI Teacher (Audio Call) |
![]() |
![]() |
![]() |
- Welcome screen with animated mascot and multi-language greeting bubbles
- Email / password sign-up with email verification modal
- OAuth sign-in via Google, Facebook, and Apple
- Powered by Clerk — secure token storage with
expo-secure-store
- Choose from Spanish, French, Japanese, or Vietnamese
- Searchable language list showing learner counts
- Selection is persisted across sessions with Zustand + AsyncStorage
- Personalized greeting with your first name and a greeting in your chosen language
- Daily goal XP bar — track your progress toward 20 XP per day
- Continue Learning card — jump back into your current lesson
- Today's Plan — AI Conversation, new vocabulary, and lesson activities
- 12-day streak counter
- Lessons organised into units per language (e.g., A1 · Basics 1)
- Lessons / Practice tab toggle
- Lesson cards show activity count, XP reward, and completion status (locked / not started / in progress / completed)
- 12 lessons across 4 languages (3 per language), each with vocabulary, phrases, multiple-choice, and translation activities
- Real-time audio call with an AI language teacher via the Stream Video SDK
- Live captions for both teacher and learner — partial (real-time) and complete transcripts
- Push-to-talk microphone button with audio level feedback
- Call lifecycle: Idle → Loading → Ready → Connecting → Joined → Ended
- In-call feedback metrics: Speaking, Pronunciation, Grammar
- Lesson context card showing title, target phrases, and learning goals
- AI agent managed via backend vision-agent API (start / stop sessions)
- User avatar from Clerk or generated initials fallback
- Display name, email address, and active language
- Quick link to change language
- Sign-out with confirmation
| Category | Technology |
|---|---|
| Framework | React Native 0.81 + Expo ~54 |
| Language | TypeScript 5.9 |
| Routing | Expo Router ~6 (file-based) |
| Styling | NativeWind 5 (Tailwind CSS for RN) |
| Authentication | Clerk (@clerk/expo) |
| Real-time Audio | Stream Video React Native SDK |
| WebRTC | @stream-io/react-native-webrtc |
| State Management | Zustand 5 |
| Persistent Storage | AsyncStorage |
| Navigation | React Navigation 7 (bottom tabs) |
| Analytics | PostHog React Native |
| Fonts | Poppins (Regular / Medium / SemiBold / Bold) |
| Icons | @expo/vector-icons (Ionicons) |
Make sure the following tools are installed before you begin:
- Node.js v18 or later
- npm v9+ or yarn
- Expo CLI
- Android Studio (for Android emulator) or a physical Android device
- Xcode (macOS only, for iOS simulator)
# Install Expo CLI globally
npm install -g expo-cli
# Verify Node version
node -v # should be >= 18
# Install EAS CLI (optional, for production builds)
npm install -g eas-cligit clone https://github.com/tomnguyen103/MyFirstMobileApp.git
cd MyFirstMobileAppnpm install
patch-packageruns automatically via thepostinstallscript and applies any required dependency patches.
Create a .env file in the project root:
cp .env.example .env # if an example file exists, otherwise create it manuallyOpen .env and fill in all required values:
# Clerk — https://dashboard.clerk.com
EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
# PostHog — https://app.posthog.com
EXPO_PUBLIC_POSTHOG_KEY=phc_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
EXPO_PUBLIC_POSTHOG_HOST=https://app.posthog.com
# Backend API base URL (leave empty when using Expo Go local dev server)
EXPO_PUBLIC_API_BASE_URL=https://your-backend-url.comNever commit your
.envfile. It is listed in.gitignore.
- Create a project at dashboard.clerk.com
- Enable Email/Password, Google, Facebook, and Apple sign-in methods
- Copy the Publishable Key into
EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY
- Create an app at getstream.io
- Enable the Video & Audio product
- Configure your backend to use the Stream API key and secret for generating tokens
- Your backend exposes these endpoints used by the app:
POST /api/stream/audio-call— create an audio call sessionPOST /api/vision-agent/start— start the AI teacher agentPOST /api/vision-agent/stop— stop the AI teacher agent
- Create a project at app.posthog.com
- Copy the Project API Key and Host into your
.env
npm start
# or
npx expo startThen press one of the following keys in the terminal:
| Key | Action |
|---|---|
a |
Open on Android emulator / device |
i |
Open on iOS simulator (macOS only) |
w |
Open in web browser |
r |
Reload the app |
m |
Toggle developer menu |
npm run android
# or
npx expo run:androidnpm run ios
# or
npx expo run:iosnpm run web
# or
npx expo start --web# Type-check the entire project
npm run typecheck
# Lint the codebase
npm run lint
# Reset to a blank Expo project (caution: moves current app/ to app-example/)
npm run reset-projectMyFirstMobileApp/
├── app/ # File-based routing (Expo Router)
│ ├── _layout.tsx # Root layout — Clerk, PostHog, GestureHandler
│ ├── index.tsx # Entry redirect (onboarding / language / tabs)
│ ├── onboarding.tsx # Welcome screen with mascot
│ ├── language-selection.tsx # Searchable language picker
│ ├── oauth-callback.tsx # OAuth redirect handler
│ ├── (auth)/
│ │ ├── sign-up.tsx # Email sign-up + verification modal
│ │ └── sign-in.tsx # Email code sign-in + OAuth
│ ├── (tabs)/
│ │ ├── index.tsx # Home dashboard
│ │ ├── learn.tsx # Units & lessons browser
│ │ ├── ai-teacher.tsx # AI audio call interface
│ │ ├── chat.tsx # Coming soon
│ │ └── profile.tsx # User profile & settings
│ ├── lesson/[id].tsx # Dynamic lesson detail route
│ └── api/ # Expo API routes (backend)
│ ├── _clerk-auth.ts
│ └── stream/audio-call+api.ts
│ └── vision-agent/{start,stop}+api.ts
│
├── components/ # Reusable UI components
│ ├── CustomTabBar.tsx # Bottom navigation bar
│ ├── LiveCaptionsCard.tsx # Real-time caption display
│ ├── LoadingScreen.tsx # Splash / loading state
│ ├── VerificationModal.tsx # Email code verification dialog
│ └── GoogleIcon.tsx # SVG Google logo
│
├── hooks/
│ ├── useStreamAudioCall.ts # Stream SDK call lifecycle & captions
│ └── useLessonAnalytics.ts # PostHog lesson event tracking
│
├── store/
│ ├── languageStore.ts # Persisted selected language
│ └── lessonStore.ts # Lesson progress state
│
├── data/
│ ├── languages.ts # Supported languages list
│ ├── lessons.ts # Lesson definitions & AI prompts
│ ├── units.ts # Unit groupings per language
│ └── todaysPlan.ts # Daily plan activity items
│
├── lib/
│ ├── api.ts # API URL resolution helper
│ ├── stream.ts # Stream & vision-agent API calls
│ └── analytics.ts # PostHog identify & event helpers
│
├── types/
│ └── learning.ts # Language, Lesson, Unit, Activity types
│
├── assets/
│ ├── images/ # App graphics & mascot illustrations
│ └── fonts/ # Poppins font family (TTF)
│
├── app.json # Expo app configuration
├── package.json
├── tsconfig.json
├── metro.config.js
├── global.css # Global Tailwind/NativeWind styles
└── postcss.config.mjs
Launch
└── index.tsx
├── First time? → Onboarding → Language Selection → Sign Up / Sign In
└── Returning? → (Tabs)
├── Home — daily goal & lesson progress
├── Learn — units & structured lessons
├── AI Teacher — live audio call with AI agent
├── Chat — (coming soon)
└── Profile — settings & sign out
# Install EAS CLI
npm install -g eas-cli
# Log in to your Expo account
eas login
# Configure the project (first time only)
eas build:configure
# Build for Android (APK / AAB)
eas build --platform android
# Build for iOS (IPA)
eas build --platform ios
# Submit to stores
eas submit --platform android
eas submit --platform ios- Fork the repository
- Create a feature branch:
git checkout -b feature/your-feature-name - Commit your changes:
git commit -m "feat: add your feature" - Push to the branch:
git push origin feature/your-feature-name - Open a Pull Request against
main
This project is for educational and portfolio purposes.


