Skip to content

notJust-dev/AIChat

Repository files navigation

ChatAI — Build an AI Chat App with Expo, Clerk & OpenAI

A full-stack mobile AI chat app built on the notJust.dev YouTube tutorial. It uses Expo Router (file-based routing), Clerk for authentication, an Expo Router API route as a backend proxy, the OpenAI API for text generation, zustand + expo-sqlite for persisted state, and react-native-keyboard-controller / react-native-enriched-markdown for the chat UI.

Prerequisites

  • Node.js 20+ and npm
  • Xcode (iOS) or Android Studio (Android) — Expo Go isn't enough here, this project uses native modules
  • A Clerk account → ntjst.dev/tu4Abaw
  • An OpenAI API key → platform.openai.com

Quick start

# 1. Clone
git clone git@github.com:notJust-dev/AIChat.git
cd AIChat

# 2. Install
npm install

# 3. Configure env
cp .env.example .env.local
#   then open .env.local and fill in:
#     EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
#     CLERK_SECRET_KEY=sk_test_...
#     OPENAI_API_KEY=sk-...

# 4. Run on a simulator/device
npm run ios       # iOS Simulator (macOS only)
npm run android   # Android Emulator
npm run web       # Web browser

# Or start Metro and pick a target from the menu:
npm start

Note on Expo Go: this app uses native modules (react-native-enriched-markdown, react-native-keyboard-controller, expo-sqlite, Clerk) so it must run in a dev client, not Expo Go. The commands above build a dev client for you the first time.

If you ever change app.json or add a config-plugin dependency, restart Metro with the cache cleared:

npx expo start --clear

Environment variables

Variable Where it's used Notes
EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY Client (src/app/_layout.tsx) EXPO_PUBLIC_ prefix means it ships in the JS bundle — must be the publishable key, never the secret one.
CLERK_SECRET_KEY Clerk CLI / Backend API Server-side only.
OPENAI_API_KEY API route (src/app/api/chat+api.ts) Server-side only — never prefix with EXPO_PUBLIC_.

Following along with the tutorial

This repo's commit history matches the steps in the video. Each commit is a single, self-contained piece of work, so you can check out any commit to see the project at that exact point.

git log --oneline
Commit (most recent first) What it adds
update claude.md Project guidance for AI tools
scroll to end Auto-scroll the chat to the latest message during streaming
streaming Token-by-token streaming from OpenAI to the UI
markdown Render messages with react-native-enriched-markdown
integrate openai Real OpenAI completions in the API route
setup api routes Expo Router API route returning a dummy response
list of user chats in the drawer Drawer sidebar showing all chats from the store
global chat state with zustand Persisted chat store (zustand + expo-sqlite)
chat ui Message list, message input, keyboard handling
navigation structure Stack.Protected + protected group + chat drawer
clerk auth with prebuilt components Sign-in with Clerk's <AuthView />
clerk skills / expo skills / claude.md Tooling setup
reset project Blank slate from the Expo template

Jumping to a specific step

To inspect the project at any tutorial step:

# read-only look — detaches HEAD
git checkout <commit-sha>

# return to the latest
git checkout main

To see exactly what changed in a step:

git show <commit-sha>          # diff + commit message
git diff <prev-sha>..<sha>     # diff between two steps

Working from a checkpoint

If you want to start coding from a commit (say, after chat ui and write streaming yourself):

git checkout -b my-attempt <commit-sha-of-chat-ui>
npm install            # the dependency list may differ at older commits
npx expo start --clear

Project layout

src/
  app/                              # Expo Router routes
    _layout.tsx                     # Providers + Stack.Protected auth gate
    sign-in.tsx                     # Clerk AuthView
    (protected)/
      _layout.tsx
      index.tsx                     # Redirect to /chat/new
      chat/
        _layout.tsx                 # Drawer navigator
        [id].tsx                    # Chat screen (id can be "new" or a UUID)
    api/
      chat+api.ts                   # POST /api/chat — OpenAI streaming proxy
  components/
    DrawerContent.tsx               # Custom drawer with chat list
    chat/
      MessageList.tsx
      MessageListItem.tsx
      MessageInput.tsx
  store/
    chatStore.ts                    # Zustand store, persisted to expo-sqlite
  lib/
    api.ts                          # apiUrl() helper for native/web fetch

See CLAUDE.md for deeper architecture notes (routing, drawer, store, streaming, keyboard handling, env vars).

Useful commands

npm start            # Metro / Expo dev server
npm run ios          # Run on iOS Simulator
npm run android      # Run on Android Emulator
npm run web          # Run on web
npm run lint         # ESLint (via expo lint)

npx expo start --clear        # Restart Metro with cache cleared (after app.json changes)
npx expo install <package>    # Install a package matching the project's SDK

Troubleshooting

  • API error: 404 when sending a message — restart Metro with npx expo start --clear. The API route is only served when web.output: "server" is in effect, and that change requires a full bundler restart.
  • Markdown / drawer / keyboard behavior looks broken — make sure you're running in the dev client (npm run ios / npm run android), not Expo Go. These features need native code.
  • Clerk says "publishable key is invalid" — double-check EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY in .env.local and restart Metro.
  • OPENAI_API_KEY is not set — the key must be in .env.local (no EXPO_PUBLIC_ prefix) and Metro must be restarted after adding it.

Watch the tutorial

Built live on the notJust.dev YouTube channel. Subscribe for more full-stack tutorials.

License

MIT

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors