Expo Flighty is a feature-rich, production-ready starter kit for building cross-platform mobile and web applications with Expo and React Native. It provides a robust foundation with authentication, subscriptions, a beautiful UI, and a pre-configured backend, allowing you to launch your app faster.
- 🚀 Solid Foundation: Built on the latest Expo SDK for a stable and modern developer experience.
- ⚛️ Universal Routing: Expo Router for file-based, universal routing across iOS, Android, and Web.
- 🔐 Full Authentication Flow: Secure authentication powered by Clerk, including sign-in, sign-up, email verification, password reset, and social providers (OAuth).
- 💰 Subscription & Payments: Pre-built integration with Stripe for managing subscription plans and payments, handled securely via a Convex backend.
- 🎨 Beautiful & Customizable UI: A suite of pre-built, accessible components from React Native Reusables, styled with Tailwind CSS via NativeWind v4.
- 🌐 Internationalization (i18n): Ready-to-use translation support with
i18nextandexpo-localization. - 🔒 Type-Safe Environment Variables: Zod validation for environment variables to prevent runtime errors.
- 📦 Powerful Backend: Convex for real-time database, serverless functions, and secure webhook handling (e.g., for Stripe).
- 🎯 TypeScript Everywhere: Full end-to-end type safety for robust and maintainable code.
- ✨ Superior DX: Comes with Biome for lightning-fast linting and formatting.
| Category | Technology | Description |
|---|---|---|
| Framework | Expo | The leading framework for building universal React Native apps. |
| Routing | Expo Router | File-based router for universal navigation. |
| Backend | Convex | A modern backend-as-a-service with a real-time database and serverless functions. |
| Auth | Clerk | Complete user management and authentication solution. |
| Styling | Tailwind CSS + NativeWind | A utility-first CSS framework for rapid UI development. |
| UI Kit | React Native Reusables | A collection of beautiful, accessible, and customizable UI components. |
| Payments | Stripe | The complete payments platform for online businesses. |
| React-I18n | react-i18next | A powerful internationalization framework. |
| Schema | Zod | For validating environment variables and form data. |
| Linting | Biome | A high-performance toolchain for linting, formatting, and more. |
git clone <your-repo-url>
cd flighty
bun installCopy the .env.example file to .env.local and fill in the required keys.
cp .env.example .env.local| Variable | Description |
|---|---|
EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY |
Your publishable key from the Clerk dashboard. |
CLERK_SECRET_KEY |
Your secret key from the Clerk dashboard. Used for Convex functions. |
EXPO_PUBLIC_CONVEX_URL |
Your Convex project deployment URL. |
CONVEX_DEPLOYMENT |
Your Convex project deployment name. |
EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEY |
Your Stripe publishable key. |
STRIPE_SECRET_KEY |
Your Stripe secret key. |
STRIPE_WEBHOOK_SECRET |
The secret for verifying Stripe webhook events. |
EXPO_PUBLIC_POSTHOG_API_KEY |
(Optional) Your API key for PostHog analytics. |
EXPO_PUBLIC_URL_SCHEME |
The deep linking URL scheme for your app (e.g., my-app). |
EXPO_PUBLIC_API_BASE_URL |
The base URL for your web deployment, used for deep linking and OAuth callbacks (e.g., http://localhost:8081 for local dev or https://myapp.com for production). |
bun run dev- iOS Simulator: Press
i - Android Emulator: Press
a - Web Browser: Press
w
The project is organized to be scalable and maintainable.
├── app/ # Expo Router pages and layouts. The heart of your app's navigation.
├── assets/ # Static assets like images and fonts.
├── components/ # Reusable primitive components (Button, Input, etc.).
├── convex/ # Your Convex backend: schema, functions, and webhooks.
├── hooks/ # Custom React hooks for shared logic.
├── layouts/ # Screen layouts and complex components composed of smaller primitives.
├── lib/ # Core utilities and theme configuration.
├── types/ # TypeScript type definitions.
└── utils/ # Helper functions and configurations.
This starter kit uses Convex as its backend. The convex/ directory is a separate Node.js project, which is why it has its own package.json file (to manage server-side dependencies like stripe).
- Database Schema: The database schema is defined in
convex/schema.ts. It includes tables forusers,subscriptionPlans, andwebhookEvents. - Serverless Functions: You can write serverless functions (queries, mutations, and actions) in TypeScript files within
convex/. For example,convex/users.tsmanages user creation, andconvex/stripe.tshandles payment logic. - Deployment: Deploy your backend with
npx convex deploy. Your frontend connects to it via theEXPO_PUBLIC_CONVEX_URLenvironment variable.
The project uses @t3-oss/env-core and Zod for type-safe, validated environment variables, configured in utils/configs/env.config.ts.
- Client vs. Server: Variables exposed to the client (your React Native app) must be prefixed with
EXPO_PUBLIC_. This prevents accidentally leaking sensitive keys. - Validation: The script will throw an error at build time if any required environment variables are missing, catching issues early.
- Server-side Keys: Sensitive keys (like
STRIPE_SECRET_KEYorCLERK_SECRET_KEY) are not prefixed and should only be used in your Convex backend. Set them in the Convex dashboard.
The app is configured for multiple languages using i18next.
- Configuration: The setup is in
utils/configs/localtization/localization.config.ts. - Translations: Language JSON files are stored in
utils/configs/localtization/translations.json. - Usage: Use the
useTranslationhook fromreact-i18nextwithin your components to access translations. ALanguageSelectorcomponent is also included.
The starter includes a complete subscription flow powered by Stripe and Convex.
- Client-Side: The app uses
@stripe/stripe-react-nativeto securely handle payment information. Theuse-subscriptionhook provides the logic for initiating checkouts. - Backend Logic:
convex/stripe.tscontains an action to create Stripe checkout sessions. - Webhooks: A webhook endpoint is defined in
convex/http.tsto listen for events from Stripe (e.g.,checkout.session.completed,customer.subscription.updated). This is how your app knows when a subscription is active, canceled, or has failed. TheSTRIPE_WEBHOOK_SECRETis used to secure this endpoint.
# Development
bun run dev # Start development server
bun run ios # Start iOS simulator
bun run android # Start Android emulator
bun run web # Start web version
# Code Quality
bun run biome:check # Run all Biome checks (lint, format)
bun run biome:lint # Lint code
bun run biome:format # Format code
# Build
bun run build:android-dev # Build Android development
bun run build:ios-dev # Build iOS development
bun run build:android-prod # Build Android production
bun run build:ios-prod # Build iOS productionFor mobile deployment, we recommend using EAS Build.
# Install EAS CLI
npm install -g eas-cli
# Configure project
eas build:configure
# Build for app stores
eas build --platform all# Build for web
npm run build:web
# Deploy the `dist` directory to your preferred hosting platform (Vercel, Netlify, etc.).This project is licensed under the MIT License - see the LICENSE file for details.
⭐ Star this repo if it helps you build and launch your next amazing app!