MCPcopy Index your code
hub / github.com/JoeSlain/Nexpo

github.com/JoeSlain/Nexpo @main

Chat with this repo
repository ↗ · DeepWiki ↗ · + Follow
113 symbols 337 edges 113 files 1 documented · 1%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

NEXPO banner

A production-ready monorepo template for building cross-platform applications with Next.js and React Native (Expo)

Based on Fernando Rojo's work

🎯 Quick Start

⚡️ Instantly clone & deploy on vercel

(You still need to setup supabase manually)

Deploy with Vercel

Manual setup

  1. Click "Use this template" on GitHub
  2. Clone your new repository
  3. Follow the Setup Instructions below

📦 What's Included

  • Solito - Cross-platform navigation between Next.js and React Native
  • Next.js 16 - React framework for production
  • Expo SDK 54 - React Native framework
  • React 19 with React Compiler
  • tRPC - End-to-end typesafe APIs
  • Supabase - Backend as a service (database, auth, storage)
  • Lingui - Internationalization (i18n)
  • Tamagui - Universal design system
  • Storybook - Component development and testing (web & native)
  • Testing - End-to-end (Playwright for web, Maestro for mobile), database (pgTAP), and API/integration (Vitest) tests
  • Sentry - Error tracking and monitoring
  • Turborepo - Monorepo build system
  • Biome - Fast formatter and linter
  • Husky - Git hooks

🗂 Project Structure

.
├── apps/
│   ├── expo/          # React Native app (Expo)
│   ├── next/           # Next.js web app
│   ├── storybook-native/  # React Native Storybook
│   └── storybook-web/     # Web Storybook
├── packages/
│   ├── app/            # Shared app code (features, providers, navigation)
│   └── api/            # tRPC router and Supabase server client
└── supabase/           # Supabase migrations and config

🏁 Setup Instructions

Prerequisites

  • Node.js 20+ and Yarn 4.7.0+
  • Docker (for local Supabase development)
  • Git

1. Install Dependencies

yarn install

2. Configure Environment Variables

This project uses environment-specific configuration files for development and production. Each app has separate .env.development and .env.production files.

Environment File Structure

Next.js (apps/next/): - .env.development - Development environment variables (auto-loaded when NODE_ENV=development) - .env.production - Production environment variables (auto-loaded when NODE_ENV=production) - .env.local - Local overrides (gitignored, highest priority, never commit this file)

Expo (apps/expo/): - .env.development - Development environment variables (loaded via helper script) - .env.production - Production environment variables (loaded via helper script) - .env.local - Local overrides (gitignored, highest priority, never commit this file)

Note: Next.js automatically loads environment files based on NODE_ENV. Expo uses a custom helper script (scripts/load-env.js) to achieve the same behavior.

Setup Instructions

  1. Update development values in apps/next/.env.development and apps/expo/.env.development:
  2. Set your local Supabase URL: http://127.0.0.1:54321
  3. Get your local Supabase anon key by running yarn supabase:status
  4. For Expo, set EXPO_PUBLIC_API_URL to http://localhost:3000/api/trpc (or your machine's IP for physical devices)

  5. Update production values in apps/next/.env.production and apps/expo/.env.production:

  6. Replace placeholder values with your actual production Supabase credentials
  7. Set production API URLs
  8. Configure production Sentry DSNs

  9. Create .env.local files (optional, for local overrides): bash # These files are gitignored and should contain only your local secrets touch apps/next/.env.local touch apps/expo/.env.local

Required Variables

Next.js: - NEXT_PUBLIC_SUPABASE_URL - Your Supabase project URL - NEXT_PUBLIC_SUPABASE_ANON_KEY - Your Supabase anon/public key - SUPABASE_SERVICE_ROLE_KEY - (Optional) For server-side operations with elevated permissions - NEXT_PUBLIC_SENTRY_DSN - (Optional) Sentry DSN for client-side error tracking - SENTRY_DSN - (Optional) Server-side Sentry DSN - SENTRY_ORG - (Optional) Sentry organization slug - SENTRY_PROJECT - (Optional) Sentry project slug

Expo: - EXPO_PUBLIC_SUPABASE_URL - Your Supabase project URL - EXPO_PUBLIC_SUPABASE_ANON_KEY - Your Supabase anon/public key - EXPO_PUBLIC_API_URL - Your Next.js API URL (for tRPC) - EXPO_PUBLIC_SENTRY_DSN - (Optional) Sentry DSN for error tracking

Root (for lingui-ai-translate): - OPENAI_API_KEY - (Optional) OpenAI API key for automated translations. Get your key from platform.openai.com

3. Setup Supabase

Local Development

Start Supabase locally:

yarn supabase:start

This will: - Start all Docker containers - Run database migrations - Load seed data

Get your local environment variables:

yarn supabase:status

Access Supabase Studio at: http://localhost:54323

Production Setup

  1. Create a project at supabase.com
  2. Get your project URL and API keys from the project settings
  3. Update your environment variables with production values
  4. Push your database schema:
# Link to your Supabase project (only needed once)
supabase link --project-ref your-project-ref

# Push migrations to production
supabase db push

⚠️ Important: The template includes a seed file. Review and modify supabase/seed.sql before deploying to production.

4. Update Supabase Project ID

Update the project ID in supabase/config.toml:

project_id = "your-project-name"

This helps distinguish different Supabase projects on the same machine.

5. Update API URLs

Expo tRPC Client

Update the production API URL in apps/expo/utils/trpc/client.tsx:

return process.env.EXPO_PUBLIC_API_URL || 'https://your-domain.com/api/trpc'

6. Start Development Servers

Web (Next.js)

yarn web

This will: - Automatically load .env.development and .env.local (if exists) based on NODE_ENV=development - Start the Next.js dev server - Run on http://localhost:3000

You can also run directly from the apps/next directory:

cd apps/next
yarn dev

Note: Next.js automatically loads environment files based on NODE_ENV. No dotenv-cli needed.

Mobile (Expo)

First, build a dev client:

cd apps/expo
yarn ios
# or
yarn android

Then, from the root:

yarn native

Or run directly from the apps/expo directory:

cd apps/expo
yarn start

The Expo scripts automatically load .env.development and .env.local (if exists) via the load-env.js helper script.

🚀 Deployment

Vercel (Next.js)

  1. Connect your repository to Vercel
  2. Set the root directory to apps/next
  3. Configure environment variables in Vercel dashboard:
  4. NEXT_PUBLIC_SUPABASE_URL - Your production Supabase URL
  5. NEXT_PUBLIC_SUPABASE_ANON_KEY - Your production Supabase anon key
  6. SUPABASE_SERVICE_ROLE_KEY - Your production service role key
  7. SENTRY_* - (Optional) Sentry configuration for production

Note: Vercel automatically sets NODE_ENV=production during build, so Next.js will load .env.production automatically. However, you should set production values in Vercel's environment variables dashboard for security.

  1. Vercel will automatically detect:
  2. Framework: Next.js
  3. Build Command: cd ../.. && npx turbo run build --filter=next-app
  4. Output Directory: .next

Or use the deploy button above after updating the repository URL.

Expo (Mobile Apps)

Deploy using EAS (Expo Application Services):

Prerequisites

  1. Install EAS CLI: bash npm install -g eas-cli

  2. Login to EAS: bash eas login

Configuration

The eas.json file is already configured with build profiles: - development: Development client builds (simulator/APK) - preview: Internal distribution builds (APK) - production: Production app store builds (App Bundle/IPA)

  1. Configure environment variables in EAS: bash cd apps/expo eas secret:create --scope project --name EXPO_PUBLIC_SUPABASE_URL --value "https://your-project.supabase.co" eas secret:create --scope project --name EXPO_PUBLIC_SUPABASE_ANON_KEY --value "your-production-anon-key" eas secret:create --scope project --name EXPO_PUBLIC_API_URL --value "https://your-domain.com/api/trpc" eas secret:create --scope project --name EXPO_PUBLIC_SENTRY_DSN --value "your-sentry-dsn" # Optional

Or configure them in the EAS dashboard.

  1. Update submit credentials (optional, for automated submissions): Edit apps/expo/eas.json and update the submit.production section with your:
  2. Apple ID, App Store Connect App ID, and Team ID (for iOS)
  3. Google Play service account key path (for Android)

Build and Submit

  1. Build for production: ```bash cd apps/expo

# Build for iOS npm run eas:build:ios:profile

# Build for Android npm run eas:build:android:profile

# Build for both platforms npm run eas:build:all -- --profile production ```

  1. Submit to app stores: ```bash cd apps/expo

# Submit iOS build npm run eas:submit:ios

# Submit Android build npm run eas:submit:android ```

OTA Updates

Publish over-the-air updates without rebuilding:

cd apps/expo

# Publish update to production channel
npm run eas:update:republish

# Or use interactive mode
npm run eas:update

Available EAS Scripts

The project includes several EAS-related scripts in apps/expo/package.json:

Build: - npm run eas:build:android - Build for Android - npm run eas:build:ios - Build for iOS - npm run eas:build:all - Build for both platforms - npm run eas:build:android:profile - Build Android with production profile - npm run eas:build:ios:profile - Build iOS with production profile

Submit: - npm run eas:submit:android - Submit Android build to Play Store - npm run eas:submit:ios - Submit iOS build to App Store

Update: - npm run eas:update - Publish OTA update (interactive) - npm run eas:update:republish - Publish update to production branch

Configuration: - npm run eas:configure - Configure EAS Build

🔔 Sentry Configuration

This template includes Sentry for error tracking. To enable:

  1. Create a project at sentry.io
  2. Get your DSN from project settings
  3. Set the environment variables (see above)
  4. Sentry will automatically initialize in both apps

🌍 Internationalization (i18n)

This template uses Lingui for i18n. Supported locales are configured in packages/app/lingui.config.js.

Workflow

The typical i18n workflow consists of three steps:

  1. Extract messages - Extract translatable strings from your code
  2. Translate messages - Translate messages using AI or manual translation
  3. Compile messages - Compile translations for runtime use

Extract messages

Extract translatable strings from your codebase:

yarn lingui:extract

This scans your code for t macros and other Lingui translation functions and generates .po files in packages/app/locales/.

Translate messages

Using AI Translation (Recommended)

This template includes lingui-ai-translate for automated translations using OpenAI's API.

Setup:

  1. Get your OpenAI API key from platform.openai.com
  2. Add it to your environment variables:

For root .env (used by lingui-ai-translate): bash OPENAI_API_KEY=your-openai-api-key-here

Or export it in your shell: bash export OPENAI_API_KEY=your-openai-api-key-here

  1. Run the translation command:

bash yarn lingui:translate

This will automatically translate all messages in your .po files to all configured locales using OpenAI's API. The translations preserve placeholders and formatting.

Manual Translation

You can also manually edit the .po files in packages/app/locales/ to translate messages yourself.

Compile messages

After translating, compile the messages for runtime use:

yarn lingui:compile

This generates optimized .js files that are used by your application at runtime.

📚 Storybook

This template includes Storybook for both web and React Native, allowing you to develop and test UI components in isolation.

Web Storybook

Start the web Storybook to view and test components in a browser environment:

yarn storybook:web

This will start Storybook on http://localhost:6006

React Native Storybook

Start the React Native Storybook to view and test components in a mobile environment:

yarn storybook:native

This will start Storybook on http://localhost:7007 and open the Expo app with Storybook UI integrated.

You can also run it directly from the apps/storybook-native directory:

cd apps/storybook-native
yarn storybook
# or run the Expo app directly
yarn ios
# or
yarn android

Story Locations

Stories are automatically loaded from: - apps/storybook-web/src/**/*.stories.tsx (web stories) - apps/storybook-native/src/**/*.stories.tsx (native stories) - packages/ui/src/**/*.stories.tsx (shared UI package stories)

Features

  • Tamagui Integration - Both Storybook apps use the shared Tamagui config from packages/app/tamagui.config.ts
  • Monorepo Support - Stories from shared packages are automatically loaded
  • TypeScript Support - Full TypeScript support for stories
  • Addons - W

Extension points exported contracts — how you extend this code

TamaguiCustomConfig (Interface)
(no doc)
packages/app/tamagui.config.ts
Context (Interface)
(no doc)
packages/api/src/trpc.ts
ButtonProps (Interface)
(no doc)
apps/storybook-web/src/stories/Button.tsx
PressableStateCallbackType (Interface)
(no doc)
packages/app/rnw-overrides.d.ts
TestUser (Interface)
(no doc)
packages/api/src/__tests__/helpers.ts
HeaderProps (Interface)
(no doc)
apps/storybook-web/src/stories/Header.tsx
ViewStyle (Interface)
(no doc)
packages/app/rnw-overrides.d.ts
TextProps (Interface)
(no doc)
packages/app/rnw-overrides.d.ts

Core symbols most depended-on inside this repo

createServerClient
called by 16
packages/api/src/supabase.ts
resolveLocalHostUrl
called by 4
packages/app/utils/resolve-localhost-url.ts
useTheme
called by 4
packages/app/provider/theme/index.tsx
buildLocaleInfo
called by 4
packages/app/provider/local/LocaleProvider.tsx
useAuth
called by 3
packages/app/provider/supabase/index.tsx
getFormatterPart
called by 3
packages/app/provider/local/LocaleProvider.tsx
isSupportedLocale
called by 3
packages/app/config/locales.js
parseLanguageTag
called by 2
packages/app/provider/local/LocaleProvider.tsx

Shape

Function 102
Interface 11

Languages

TypeScript100%

Modules by API surface

packages/app/provider/local/LocaleProvider.tsx12 symbols
packages/app/provider/theme/index.tsx6 symbols
packages/app/provider/local/LocaleProvider.native.tsx6 symbols
apps/next/e2e/helpers.ts6 symbols
packages/api/src/__tests__/helpers.ts5 symbols
packages/app/rnw-overrides.d.ts4 symbols
packages/app/provider/trpc/index.tsx3 symbols
packages/app/provider/theme/index.native.tsx3 symbols
packages/app/provider/supabase/index.tsx3 symbols
packages/app/features/home/login-test.tsx3 symbols
packages/app/features/home/locale-demo.tsx3 symbols
packages/app/features/home/auth-test-button.tsx3 symbols

Datastores touched

postgresDatabase · 1 repos

For agents

$ claude mcp add Nexpo \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact