ai-chat-demo

Project Url: margelo/ai-chat-demo
Introduction: A ChatGPT-style mobile chat app in React Native with context about Margelo
More: Author   ReportBugs   OfficialWebsite   
Tags:
MargeloChat running on iPhone 16

MargeloChat

A ChatGPT-style mobile chat app with a twist: it knows about Margelo. You talk to a streaming AI assistant that renders replies as live markdown, shows its reasoning, and answers any question about Margelo (the company, its people, and its open-source libraries) by searching a real knowledge base instead of guessing.

Ask it anything. For general questions it just replies; for Margelo questions it calls a retrieval tool, pulls matching facts from a vector database, and answers only from what it found.

[!NOTE] Read the full blog post about building a ChatGPT-Style AI Chat App in React Native here: https://blog.margelo.com/building-native-llm-chat-app-with-rag

How it works

  • Brain - OpenAI's Responses API, streamed over a WebSocket (react-native-nitro-websockets) rather than HTTP. The socket is prewarmed natively at app start, before the JS bundle loads, so it's already open by the first message. Reply text and reasoning summaries stream token-by-token; turns are chained with previous_response_id so the model remembers the conversation.
  • Knowledge base (RAG) - the model can call a search_margelo_kb tool, which queries a Pinecone index (integrated embedding, so raw text goes up and Pinecone embeds it server-side) over react-native-nitro-fetch. Margelo questions are answered from the retrieved context, never from the model's memory.
  • Rendering - replies render as native markdown with a streaming animation and tappable links (react-native-enriched-markdown). The collapsible "thought process" opens in a bottom sheet (react-native-true-sheet).
  • List - a keyboard-aware @legendapp/list with anchored end-space, for ChatGPT-style scroll and anchor behavior while a reply streams in.
  • Look - real Liquid Glass surfaces on iOS 26+ (@callstack/liquid-glass) with plain fallbacks everywhere else, a Skia shimmer "Thinking" label (@shopify/react-native-skia), and SF Symbols that fall back to Material Design Icons on Android.
  • Attachments - pick images (react-native-image-picker), sent to the model as base64 data URLs and shown as thumbnails (react-native-nitro-image).

Requirements

Runs on iOS and Android (New Architecture). Liquid Glass needs iOS 26+; on older iOS and on Android those surfaces fall back to a plain rounded style.

  • Xcode + CocoaPods, Node >= 22.11, and the React Native environment.
  • An OpenAI API key and a populated Pinecone index for the knowledge-base tool.

Note: this is a demo. The API keys live in the app bundle, which is fine locally but unsafe for production - anyone can extract them. For anything real, put a relay server in front and keep the keys server-side.

Setup

cd app
npm install
cp src/config.example.ts src/config.ts   # then fill in your keys
cd ios && pod install && cd ..

Open src/config.ts and add your OpenAI key, Pinecone key, and index host. This file is gitignored and never committed.

Run

cd app
npm start          # Metro
npm run ios        # build + launch on the iOS simulator/device
npm run android    # build + launch on the Android emulator/device

Other scripts (also run in CI):

npm run lint                 # eslint
npm run typecheck            # tsc --noEmit
npm run format               # prettier --write
npm run format:check         # prettier --check
npm run react-compiler-check # react-compiler healthcheck
npm test                     # jest

Project structure

app/
  src/
    config.ts                 # API keys (gitignored; copy from config.example.ts)
    theme.ts                  # dark theme + shared markdown design tokens
    markdownStyle.ts          # maps the theme onto the markdown renderer
    notImplemented.ts         # "demo only" alert for stubbed controls
    state/
      chatStore.ts            # zustand store: chat state, streaming, tool-call loop
    openai/
      protocol.ts             # builds Responses API requests, parses server events
      connectionManager.ts    # module-level WebSocket lifecycle + reconnect with backoff
    rag/
      searchKnowledgeBase.ts  # Pinecone knowledge-base search (the model's tool)
    hooks/
      useAttachments.ts       # image picking
    screens/
      RootDrawer.tsx          # pager: recents <-> chat
      ChatScreen.tsx          # the conversation, list, and composer wiring
      RecentsScreen.tsx       # chat history (mocked for the UI pass)
    components/
      ChatMessages.tsx        # subscription boundary: only re-renders on message changes
      Composer.tsx            # the input pill (grow/shrink, attachment thumbnails)
      AttachmentMenu.tsx      # the "+" dropdown for picking attachments
      MessageBubble.tsx       # user bubble / assistant markdown + reasoning trace
      ReasoningSheet.tsx      # bottom sheet showing the thinking trace
      ShimmerText.tsx         # Skia shimmer "Thinking" label
      Header.tsx              # top bar
      Glass.tsx               # Liquid Glass wrapper with a plain fallback
      Icon.tsx                # SF Symbol with a Material Design Icon fallback
      EmptyState.tsx          # centered logo before the first message
      ScrollToBottomButton.tsx

Open-source libraries

This app stands on the shoulders of these projects (thank you to their authors):

Apps
About Me
GitHub: Trinea
Facebook: Dev Tools
AI Daily Digest