A voice-first AI thinking partner for iOS and Android, built with Expo and React Native. Talk to it. It asks the smart follow-ups, finds the blind spots, and hands you a personalized action plan you can actually use.
"Think clearer. Decide better."
- Voice-first thinking sessions with animated waveform UI and ElevenLabs TTS.
- Agentic AI loop (Groq +
llama-3.3-70b-versatile) with four specialized agents:thinkingAgent— orchestrates the conversation.questionAgent— generates the perfect next follow-up.blindspotAgent— surfaces what you haven't considered.plannerAgent— produces a structured, prioritized action plan.
- Premium dark UI with Reanimated 2 (animated orbs, particles, waveforms, plan slide-up modal).
- Offline-first sessions cached locally with AsyncStorage, ready to sync to Supabase.
- Insights tab with weekly heatmap, donut chart, streak calendar, AI-written monthly summary.
- Settings tab with personality presets (Coach / Friend / Analyst), voice speed, and reminders.
- Freemium-ready: tiered limits and Pro upgrade UI wired to drop in RevenueCat.
| Layer | Tech |
|---|---|
| App framework | Expo SDK 54 (managed) + React Native 0.81 + React 19.1 + TypeScript |
| Navigation | expo-router v6 (file-based routing, auth-gated) |
| Styling | Inline styles + design tokens in constants/colors.ts |
| State | Zustand (store/sessionStore.ts) |
| AI | Groq — llama-3.3-70b-versatile (chat + structured) + whisper-large-v3-turbo (voice STT) |
| Web search | Tavily (https://api.tavily.com/search) — wired as a web_search tool the model calls on demand |
| TTS | ElevenLabs (21m00Tcm4TlvDq8ikWAM — Rachel) + expo-speech fallback |
| Audio recording | expo-av 16 (will migrate to expo-audio in SDK 55) |
| Auth + DB | Supabase (with local fallback if env not configured) |
| Storage | @react-native-async-storage/async-storage |
| Animations | Reanimated v4 + react-native-worklets |
| Charts | react-native-svg |
app/ ← Expo Router screens
├── _layout.tsx ← Auth gate + global providers
├── (auth)/ ← Welcome, login, signup
├── (tabs)/ ← Home, sessions, insights, profile
└── session/[id].tsx ← Active thinking session (voice + chat + action plan modal)
components/ ← Presentational pieces (ui/, session/, home/)
services/
├── groq.ts ← Groq SDK wrapper (text + json_object modes)
├── elevenlabs.ts ← TTS w/ device fallback
├── supabase.ts ← Supabase client (lazy, env-driven)
├── session.ts ← AsyncStorage-backed session repo
└── insights.ts ← Heatmap, breakdowns, AI monthly summary
agents/ ← Pure functions, each a single-responsibility AI agent
├── thinkingAgent.ts ← Orchestrator + next-turn / opening / title / finalize
├── questionAgent.ts ← Single open-ended follow-up
├── blindspotAgent.ts ← Structured blind-spot detection
└── plannerAgent.ts ← Structured action-plan JSON
hooks/ ← React hooks (useAuth, useSession, useVoice, useInsights)
store/sessionStore.ts ← Zustand store for the active session
constants/ ← colors, prompts, categories
types/ ← Shared TypeScript types
supabase/schema.sql ← Tables, RLS policies, profile trigger
The agentic loop lives in agents/thinkingAgent.ts. On each user message, the orchestrator builds a system prompt with the chosen category and personality, then calls Groq. After ~5 user turns it offers a plan. endSessionWithPlan() runs the plannerAgent + blindspotAgent in parallel and merges the results into a single structured ActionPlan.
Requires Node 20.19+ (Expo SDK 54 minimum).
cd pondr
npm installCopy .env.example to .env and fill in:
EXPO_PUBLIC_GROQ_API_KEY=
EXPO_PUBLIC_ELEVENLABS_API_KEY=
EXPO_PUBLIC_TAVILY_API_KEY=
EXPO_PUBLIC_SUPABASE_URL=
EXPO_PUBLIC_SUPABASE_ANON_KEY=
EXPO_PUBLIC_APP_ENV=development- Groq — sign up at console.groq.com. Free tier covers development.
- ElevenLabs — elevenlabs.io — free tier has plenty of characters for testing.
- Tavily — sign up at tavily.com → API Keys. Free tier: 1,000 credits/month, no card required. This is what lets the AI answer questions like "what's the weather in Kansas today?" or "who won the IPL final?". Without it, the model answers from training data only.
- Supabase — supabase.com. Run
supabase/schema.sqlin the SQL editor.
If any key is missing the app still runs — it gracefully falls back (device TTS, local-only auth, scripted fallback plans, and skipping the web-search tool), so you can demo end-to-end before wiring real services.
- Create a new Supabase project.
- In SQL editor, paste and run
supabase/schema.sql. - Copy your project URL and anon key into
.env.
Drop a 1024×1024 icon.png and portrait splash.png in assets/ and re-enable the references in app.json as described in assets/README.md. The app runs without them — Expo uses defaults.
npx expo startThen:
- Press
ito open in the iOS simulator (requires Xcode). - Press
ato open in the Android emulator (requires Android Studio). - Scan the QR code in Expo Go on your phone for instant device testing.
npx tsc --noEmitnpm install -g eas-cli
eas login
eas build:configure
eas build --platform all
eas submit --platform ios
eas submit --platform android- App Store Connect — appstoreconnect.apple.com
- Google Play Console — play.google.com/console
Bundle identifier (iOS) and package name (Android) are both com.pondr.app.
Pondr is freemium by default:
- Free — 3 sessions/week, voice mode, action plans, 7-day history.
- Pro ($9.99/mo or $59.99/year) — unlimited sessions, premium voices, full history, advanced insights, PDF export, faster AI.
Plug RevenueCat in by adding react-native-purchases, wrapping Profile → Upgrade with the paywall, and toggling isPro in the auth profile.
| Path | Purpose |
|---|---|
app/_layout.tsx |
Root layout + auth gate |
app/(auth)/welcome.tsx |
Animated onboarding |
app/(auth)/login.tsx |
Email + password sign-in |
app/(auth)/signup.tsx |
Account creation |
app/(tabs)/index.tsx |
Home + hero mic + recent + stats |
app/(tabs)/sessions.tsx |
Search, filter, replay sessions |
app/(tabs)/insights.tsx |
Heatmap, donut, AI summary |
app/(tabs)/profile.tsx |
Settings + Pro + sign out |
app/session/[id].tsx |
The thinking session itself |
components/ui/* |
Button, Card, Badge, LoadingDots |
components/session/* |
VoiceRecorder, MessageBubble, |
| ThinkingIndicator, ActionPlan, | |
| SessionSummary | |
components/home/* |
CategoryPicker, QuickStart, |
| StatsCard | |
agents/* |
The agentic AI brains |
services/* |
All external IO + persistence |
hooks/* |
React surface for everything |
- TTS playback uses ElevenLabs when
EXPO_PUBLIC_ELEVENLABS_API_KEYis set; otherwise it falls back toexpo-speech(free, on-device). - Voice recording is fully wired (waveform UI, permissions, file output). Out-of-the-box, Expo's managed workflow doesn't ship on-device transcription; the recorded audio URI is captured and the user is prompted to either dictate via the keyboard mic (chat mode) or type — both of which feed the agentic loop identically.
- To add real speech-to-text, integrate
@react-native-voice/voice(requires a dev client / EAS build) or stream the recording to a transcription API. The plumbing inhooks/useVoice.tsalready returns the audio URI for you.
MIT. Build something great with it.