← All posts
Case Study Custom Software Development React Native Expo TanStack AI

Building God Encounters: A Full-Stack Spiritual Platform with Maps, Audio & AI Moderation

March 20, 2026· 10 min read

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:

  1. Mobile app (Expo) — guest-facing, iOS + Android
  2. Web dashboard (TanStack Start) — moderation, content management, admin
  3. 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:

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:

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


Building a multi-surface platform with mobile, web, and backend? Let's talk →

Share this post

Want to build something like this?

15 minutes. We'll look at your business and scope what an AI automation built for it would actually do — concrete, no pitch deck.

Follow OffLift