A production-ready ChatGPT mobile app clone built with React Native, Expo, OpenRouter, ElevenLabs, and Supabase. Features AI chat, voice mode, image generation, document analysis, and cloud sync.
- Multiple AI Models - GPT-4o, GPT-4o Mini, Claude 3.5 Sonnet, Gemini Pro 1.5, Llama 3.1 70B
- Real-time Streaming - Token-by-token streaming responses for instant feedback
- Conversation History - Persistent chat history with automatic cloud sync
- Smart Titles - AI-generated conversation titles
- Multi-turn Conversations - Full context awareness across messages
- Voice Input - Press and hold to record, release to send
- Whisper Transcription - OpenAI Whisper for accurate speech-to-text
- Text-to-Speech - ElevenLabs voices for natural AI responses
- Multiple Voices - Choose from Sarah, Rachel, Domi, Antoni, Elli, Josh
- Beautiful UI - Full-screen voice mode with animated visualizations
- Voice Messages Saved - Transcribed voice messages saved to chat history
- AI Image Creation - Generate images from text prompts
- Pollinations AI - Free image generation (no API key required)
- DALL-E Support - Optional OpenAI DALL-E integration
- Smart Detection - Automatically detects image generation requests
- Cloud Storage - Generated images saved to Supabase Storage
- Skeleton Loaders - Beautiful loading states while generating
- Multimodal AI - Claude 3.5 Sonnet and GPT-4o analyze document content
- Base64 Encoding - Documents sent securely to AI models
- File Attachments - Support for images and documents in messages
- Supabase Integration - Automatic cloud sync for conversations
- Multi-device Support - Access your chats from any device
- User Isolation - Each user sees only their own conversations
- Offline Support - Works offline, syncs when online
- Attachment Storage - Images and files stored in Supabase Storage
- Supabase Auth - Secure email/password authentication
- Session Management - Automatic session handling
- User Profiles - User-specific data isolation
- Secure Storage - API keys stored securely
- ChatGPT-inspired Design - Beautiful dark mode UI
- Smooth Animations - Spring animations, fades, and slides
- Haptic Feedback - Tactile feedback on interactions
- Responsive Input - Auto-expanding multi-line text input
- Image Attachments - Camera and gallery support
- Loading States - Skeleton loaders and progress indicators
- Temperature Control - Adjust AI response creativity (0-2)
- Max Tokens - Set response length limits
- Voice Selection - Choose your preferred AI voice
- Model Selection - Switch between different AI models
- Feature Toggles - Enable/disable haptics and voice mode
The project uses a feature-based architecture that scales beautifully:
reflecta-chat/
├── app/ # Expo Router (file-based routing)
│ ├── _layout.tsx # Root layout with theme
│ ├── +html.tsx # HTML document config
│ └── index.tsx # Main entry point
│
├── src/
│ ├── features/ # Feature modules (scalable)
│ │ ├── auth/ # Authentication feature
│ │ │ ├── screens/ # Auth screens
│ │ │ │ ├── AuthNavigator.tsx
│ │ │ │ ├── LoginScreen.tsx
│ │ │ │ └── SignupScreen.tsx
│ │ │ ├── store/ # Auth state management
│ │ │ │ └── authStore.ts
│ │ │ └── index.ts # Feature exports
│ │ │
│ │ └── chat/ # Chat feature (main)
│ │ ├── api/ # API clients
│ │ │ ├── openRouterClient.ts # OpenRouter API
│ │ │ ├── elevenLabsClient.ts # ElevenLabs TTS
│ │ │ └── whisperClient.ts # Whisper STT
│ │ ├── components/ # Reusable UI components
│ │ │ ├── ChatHeader.tsx
│ │ │ ├── ChatInput.tsx
│ │ │ ├── MessageBubble.tsx
│ │ │ ├── ConversationSidebar.tsx
│ │ │ ├── EmptyChat.tsx
│ │ │ └── VoiceMode.tsx
│ │ ├── screens/ # Full screens
│ │ │ ├── ChatScreen.tsx
│ │ │ └── SettingsScreen.tsx
│ │ ├── store/ # Zustand store
│ │ │ └── chatStore.ts
│ │ ├── types.ts # TypeScript types
│ │ └── index.ts # Feature exports
│ │
│ ├── services/ # Shared services
│ │ ├── attachmentService.ts # File/image uploads
│ │ ├── chatSyncService.ts # Cloud sync logic
│ │ └── imageGenerationService.ts # Image generation
│ │
│ ├── lib/ # Third-party integrations
│ │ └── supabase.ts # Supabase client
│ │
│ └── config/ # Configuration
│ └── env.ts # Environment variables
│
├── assets/ # Static assets
│ ├── fonts/
│ └── images/
│
└── docs/ # Documentation
└── changes/ # Change logs
✅ Scalable - Easy to add new features without touching existing code
✅ Maintainable - Each feature is self-contained
✅ Testable - Features can be tested in isolation
✅ Reusable - Components and services can be shared
✅ Type-safe - Full TypeScript support throughout
- Create a new folder in
src/features/ - Add
api/,components/,screens/,store/as needed - Export from
index.ts - Import and use in
app/routes
Example:
// src/features/new-feature/index.ts
export { NewFeatureScreen } from './screens/NewFeatureScreen';
export { useNewFeatureStore } from './store/newFeatureStore';- Node.js 18+
- npm or yarn
- Expo CLI (
npm install -g expo-cli) - iOS Simulator or Android Emulator (or Expo Go app)
# Clone the repository
git clone https://github.com/yourusername/reflecta-chat.git
cd reflecta-chat
# Install dependencies
npm install
# Start the development server
npm startpushenv is an open-source tool (maintained by shahnoor mujawar) that lets you securely share and manage environment variables with encrypted storage. Perfect for team collaboration!
# Install pushenv globally
npm i -g pushenv
# Pull encrypted environment variables (creates .env file automatically)
pushenv pull
# When prompted, enter the passphrase: reflectaThis will automatically create a .env file with all required environment variables. The tool uses encryption to safely store and share sensitive configuration data.
Note: pushenv is an open-source project created and maintained by shahnoor mujawar for secure environment variable management across teams.
If you prefer to set up environment variables manually:
- Create
.envfile in the project root:
# Required
EXPO_PUBLIC_SUPABASE_URL=your_supabase_url
EXPO_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
EXPO_PUBLIC_OPENROUTER_API_KEY=your_openrouter_key
# Optional (can also be set in Settings UI)
EXPO_PUBLIC_ELEVENLABS_API_KEY=your_elevenlabs_key
EXPO_PUBLIC_DEEPSEEK_API_KEY=your_deepseek_key
EXPO_PUBLIC_OPENAI_API_KEY=your_openai_key
- Configure Supabase (required for cloud sync):
- Create a Supabase project at supabase.com
- Set up tables:
conversations,messages,attachments - Create storage bucket:
chat-attachments - Add
EXPO_PUBLIC_SUPABASE_URLandEXPO_PUBLIC_SUPABASE_ANON_KEYto.env
-
OpenRouter API Key (Required for chat to work)
- Go to OpenRouter
- Create an account and generate an API key
- Add credits to your account
- Add to
.envasEXPO_PUBLIC_OPENROUTER_API_KEYOR set in Settings → API Keys - Note: Must be set in either
.envor Settings for chat to function
-
Supabase (Required for cloud sync and authentication)
- Create project at supabase.com
- Get URL and anon key
- Add to
.envasEXPO_PUBLIC_SUPABASE_URLandEXPO_PUBLIC_SUPABASE_ANON_KEY
-
ElevenLabs API Key (For text-to-speech in voice mode)
- Go to ElevenLabs
- Create an account and navigate to API settings
- Copy your API key
- Add to
.envasEXPO_PUBLIC_ELEVENLABS_API_KEYOR set in Settings → API Keys - Used for voice responses
-
DeepSeek API Key (For conversation summarization)
- Go to DeepSeek
- Create an account and generate an API key
- Add to
.envasEXPO_PUBLIC_DEEPSEEK_API_KEYOR set in Settings → API Keys - Used for rolling context window summaries
-
OpenAI API Key (For DALL-E image generation fallback)
- Go to OpenAI Platform
- Create an API key
- Add to
.envasEXPO_PUBLIC_OPENAI_API_KEY(NOT available in Settings UI) - Used as fallback when Pollinations AI fails (Pollinations is free and works without this key)
- Note: Image generation works without this key using free Pollinations AI
| Category | Technology | Purpose |
|---|---|---|
| Framework | React Native + Expo | Cross-platform mobile development |
| Language | TypeScript | Type safety and better DX |
| Navigation | Expo Router | File-based routing |
| State Management | Zustand | Lightweight state management |
| Persistence | AsyncStorage | Local storage |
| AI API | OpenRouter | Unified access to multiple AI models |
| Voice STT | OpenAI Whisper | Speech-to-text transcription |
| Voice TTS | ElevenLabs | Text-to-speech synthesis |
| Image Generation | Pollinations AI / DALL-E | AI image generation |
| Backend | Supabase | Database, auth, and storage |
| Animations | React Native Reanimated | Smooth animations |
| UI | Custom components | ChatGPT-inspired design |
- Open the app
- Configure API keys in Settings (if not done)
- Type a message or use voice mode
- Get instant AI responses with streaming
- Tap the microphone button in chat input
- Hold to record your message
- Release to send and get AI response
- Response is spoken automatically (if ElevenLabs key is set)
Simply ask for an image:
- "Generate an image of a sunset"
- "Create a picture of a robot"
- "Show me what a uniform looks like"
The app automatically detects image requests and generates them.
- Tap the + button in chat input
- Select "Gallery" or "Camera"
- Attach an image or PDF
- Ask questions about the document
- Conversations automatically sync to Supabase
- Works across devices when logged in
- Offline support - syncs when online
- User-specific data isolation
Real-time token streaming using XMLHttpRequest (works reliably in React Native):
streamChatCompletionWithCallback(
messages,
model,
temperature,
maxTokens,
onChunk, // Called for each token
onDone, // Called when complete
onError // Called on error
)Voice messages are transcribed and saved to chat:
// 1. Record audio
const { recording } = await Audio.Recording.createAsync(...)
// 2. Transcribe with Whisper
const text = await transcribeWithWhisper(audioUri)
// 3. Save to chat (same as text messages)
await sendMessage(text)Smart detection and generation:
// Detects patterns like "generate image", "create picture", etc.
if (isImageGenerationRequest(message)) {
const prompt = extractImagePrompt(message)
const image = await generateImage(prompt)
// Uploads to cloud storage automatically
}Automatic bidirectional sync:
// Fetch user's conversations from cloud
const cloudConversations = await fetchConversationsFromCloud(userId)
// Merge with local (newer wins)
const merged = mergeConversations(local, cloud, userId)
// Sync local changes to cloud
await syncConversationToCloud(conversation, userId)Zustand with persistence:
const useChatStore = create<ChatState>()(
persist(
(set, get) => ({ /* state and actions */ }),
{
name: 'chat-storage',
storage: createJSONStorage(() => AsyncStorage),
}
)
)conversations
id(uuid, primary key)user_id(uuid, foreign key)title(text)model(text)created_at(timestamp)updated_at(timestamp)
messages
id(uuid, primary key)conversation_id(uuid, foreign key)role(text: 'user' | 'assistant' | 'system')content(text)created_at(timestamp)
attachments
id(uuid, primary key)message_id(uuid, foreign key)user_id(uuid, foreign key)type(text: 'image' | 'file')name(text)mime_type(text)size(integer)storage_path(text)url(text)
Storage Bucket
chat-attachments- Stores images and files- Path:
{userId}/{messageId}/{attachmentId}.{ext}
# Start Expo dev server
npm start
# Run on iOS
npm run ios
# Run on Android
npm run android
# Run on web
npm run webnpm start- Start Expo dev servernpm run android- Run on Androidnpm run ios- Run on iOSnpm run web- Run on web
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- OpenAI for ChatGPT inspiration and Whisper
- OpenRouter for unified AI API access
- ElevenLabs for voice synthesis
- Supabase for backend infrastructure
- Expo for the amazing React Native platform
- Pollinations for free image generation
- pushenv - Open-source tool for secure environment variable management (maintained by shahnoor mujawar)
Built with ❤️ using React Native and Expo