Overview
God Encounters is a spiritual wellness platform connecting people through healing testimonies, guided audio (meditation, worship, Bible & prayer), journals, and a global healing map. It spans three surfaces: a native mobile app for end users, a web dashboard for moderators and admins, and a shared backend API.
This was the most architecturally complex project we'd shipped — a true full-stack platform with end-to-end content lifecycle management.
"Faith, healing, and community — in one place."
The Scale of the Challenge
Most mobile app projects have one surface. God Encounters has three, all sharing one API:
- Mobile app (Expo) — guest-facing, iOS + Android
- Web dashboard (TanStack Start) — moderation, content management, admin
- API (Hono + Drizzle ORM) — OpenAPI-documented, shared types, serves both
Add to that: Mapbox-powered geolocation, full-screen audio playback with a mini-player, AI-assisted content moderation, and push notifications — and you have a platform that required serious architectural planning.
System Architecture
graph TB
subgraph Clients["Client Surfaces"]
MOB[Mobile App<br/>Expo + React Native]
WEB[Web Dashboard<br/>TanStack Start]
end
subgraph API["Backend API (Hono)"]
ROUTES[OpenAPI Routes<br/>@hono/zod-openapi]
AUTH[Auth Middleware<br/>Supabase JWT]
MOD[Moderation Service<br/>Vercel AI SDK]
NOTIF[Push Service<br/>Expo tokens]
end
subgraph Data["Data Layer"]
PG[(PostgreSQL<br/>Supabase)]
DRIZZLE[Drizzle ORM<br/>+ Migrations]
STORAGE[Supabase Storage<br/>Audio + Images]
end
subgraph External["External Services"]
MAPBOX[Mapbox API]
OPENAI[OpenAI / Gemini]
EXPO_PUSH[Expo Push Service]
end
MOB -->|HTTPS| ROUTES
WEB -->|HTTPS| ROUTES
ROUTES --> AUTH
ROUTES --> DRIZZLE
ROUTES --> MOD
ROUTES --> NOTIF
DRIZZLE --> PG
ROUTES --> STORAGE
MOD --> OPENAI
NOTIF --> EXPO_PUSH
MOB --> MAPBOX
style Clients fill:#1A1A2E,stroke:#7DFF00,color:#fff
style API fill:#0D0D18,stroke:#7DFF00,color:#fff
style Data fill:#1A1A2E,stroke:#8A8A9A,color:#fff
style External fill:#0D0D18,stroke:#8A8A9A,color:#fff
Every route on the Hono API is documented via @hono/zod-openapi — input/output schemas are validated and typed automatically. Both client surfaces share the same TypeScript types generated from the API schema.
Content Lifecycle & AI Moderation
User-generated content (testimonies, journals, prayers) goes through a moderation pipeline before it appears publicly.
flowchart LR
USER([User submits<br/>testimony]) --> QUEUE[Moderation Queue<br/>Dashboard]
QUEUE --> AI{AI Scoring<br/>Vercel AI SDK}
AI -->|Score 0.8+| AUTO_APPROVE[Auto-approve<br/>candidate]
AI -->|Score 0.4-0.8| REVIEW[Human review<br/>required]
AI -->|Score < 0.4| REJECT[Suggest reject]
AUTO_APPROVE --> MODERATOR{Moderator<br/>decision}
REVIEW --> MODERATOR
REJECT --> MODERATOR
MODERATOR -->|Approve| LIVE[Content live<br/>+ map visible]
MODERATOR -->|Reject| REMOVED[Notified,<br/>content removed]
LIVE --> MAP[Healing Map<br/>pin appears]
LIVE --> FEED[Testimony feed]
style USER fill:#0D0D18,stroke:#7DFF00,color:#fff
style LIVE fill:#1A1A2E,stroke:#7DFF00,color:#fff
style MAP fill:#0D0D18,stroke:#7DFF00,color:#fff
The AI scoring uses Vercel AI SDK with OpenAI / Google Gemini. The moderator sees the AI score as a guide — they make the final call. This dramatically reduces the review queue while keeping humans in the loop.
The Healing Map
The centerpiece of the mobile experience is a Mapbox-powered global map with color-coded pins for testimonies, journals, and prayers.
Key implementation decisions:
@rnmapbox/mapsfor native Mapbox SDK on React Native — better performance than WebView-based alternatives- Approximate pins — exact user locations are never stored. Coordinates are fuzzy by ±500m to protect privacy
- Permission-aware UX — the map degrades gracefully when location permission is denied; users can still browse the global map without sharing their location
- Clustering — pins cluster at zoom levels where individual pins would overlap, with smooth zoom-in expansion
Audio Playback Architecture
The Listen & Reflect section provides meditation, worship, prayer, and Bible audio. The UX has two states: a full-screen player (when actively listening) and a persistent mini player (when navigating away).
stateDiagram-v2
[*] --> Idle
Idle --> Loading: Tap track
Loading --> Playing: Audio ready
Playing --> Paused: Tap pause
Paused --> Playing: Tap play
Playing --> MiniPlayer: Navigate away
MiniPlayer --> Playing: Tap expand
MiniPlayer --> Idle: Tap close
Playing --> Idle: Track ends
The audio player state is managed globally (Zustand) so it persists across navigation. The mini player floats above the bottom tab bar.
Web Dashboard (TanStack Start)
The moderator dashboard is a full SSR web app built with TanStack Start — a new full-stack React framework. It was an intentional choice over Next.js for its tight integration with TanStack Router and Query.
Dashboard surfaces:
- Moderation queue — testimonies with AI scores, approve/reject actions
- Content management — upload audio tracks with thumbnails, publish/draft states
- Trips & events — CRUD for events with images and location data
- Users — profile and role management
- Push notifications — compose and send notifications to registered Expo tokens
Monorepo with Turborepo
god-encounters/
apps/
mobile/ ← Expo SDK 54 app
web/ ← TanStack Start dashboard
api/ ← Hono API
packages/
db/ ← Drizzle schema + migrations
types/ ← Shared TypeScript types
config/ ← Shared build config
Turborepo handles task orchestration across packages — builds, type checks, and migrations run in the right order with caching.
Tech Stack
| Surface | Stack |
|---|---|
| Mobile | Expo SDK 54, Expo Router, React Native, NativeWind, TanStack Query, Zustand |
| Web Dashboard | TanStack Start, React, Vite, shadcn/ui, TanStack Router |
| API | Hono, @hono/zod-openapi, Drizzle ORM |
| Database | PostgreSQL (Supabase), Drizzle migrations |
| Auth | Supabase Auth (Google + email), server-side JWT |
| AI | Vercel AI SDK (OpenAI / Google Gemini) |
| Maps | Mapbox (@rnmapbox/maps) |
| Push | Expo push tokens + backend notification service |
| Monorepo | Turborepo + Bun workspaces |
Outcome
- Three production surfaces sharing one OpenAPI-documented API
- AI-assisted moderation pipeline reducing manual review burden
- Privacy-respecting Mapbox healing map with approximate coordinates
- Full audio player with persistent mini player UX
- Push notification infrastructure for iOS and Android outreach
- Operational visibility dashboard suitable for ongoing content management
Building a multi-surface platform with mobile, web, and backend? Let's talk →