Skip to content
This repository was archived by the owner on Oct 31, 2025. It is now read-only.

tomikng/expo-react-native-next-starter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

35 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸš€ React Native + Next.js Monorepo Starter

A modern, production-ready monorepo template for building universal apps with React Native, Expo, and Next.js.

TypeScript React React Native Next.js Expo

Quick Start β€’ Documentation β€’ Scripts β€’ Architecture


πŸ“‹ Table of Contents


πŸš€ Quick Start

Prerequisites

  • Node.js 20+ or 22 (LTS recommended) (Download)
  • Corepack enabled (included with Node.js 16.9+)

Installation

  1. Clone the repository

    git clone <your-repo-url>
    cd expo-react-native-next-starter
  2. Enable Corepack (if not already enabled)

    corepack enable

    This ensures you're using the correct Yarn version (4.5.0) specified in package.json.

  3. Install dependencies

    yarn install
  4. Start developing!

    # Start all apps in watch mode
    yarn watch
    
    # OR start individually:
    
    # Web development (Next.js)
    yarn web
    
    # Mobile development (Expo)
    yarn native
    
    # Storybook
    yarn storybook
  5. Open the apps


πŸ“‚ Project Structure

.
β”œβ”€β”€ apps/
β”‚   β”œβ”€β”€ expo/              # πŸ“± React Native mobile app
β”‚   β”‚   β”œβ”€β”€ app/           # Expo Router screens
β”‚   β”‚   β”œβ”€β”€ babel.config.js
β”‚   β”‚   └── package.json
β”‚   β”œβ”€β”€ next/              # 🌐 Next.js web application
β”‚   β”‚   β”œβ”€β”€ app/           # App Router pages
β”‚   β”‚   β”œβ”€β”€ next.config.js
β”‚   β”‚   └── package.json
β”‚   └── storybook/         # πŸ“š Component documentation
β”‚       β”œβ”€β”€ stories/
β”‚       └── package.json
β”œβ”€β”€ packages/
β”‚   β”œβ”€β”€ ui/                # 🎨 Shared UI components
β”‚   β”‚   └── src/
β”‚   β”œβ”€β”€ app/               # πŸ“¦ Shared app logic and screens
β”‚   β”‚   β”œβ”€β”€ features/      # Feature-based organization
β”‚   β”‚   └── provider/      # Context providers
β”‚   β”œβ”€β”€ api/               # πŸ”Œ API client and types
β”‚   β”‚   └── src/
β”‚   └── config/            # βš™οΈ Shared configuration
β”‚       └── src/           # Theme, colors, constants
β”œβ”€β”€ .github/
β”‚   └── workflows/         # CI/CD pipelines
β”œβ”€β”€ biome.json             # Linting & formatting config
β”œβ”€β”€ turbo.json             # Turbo build configuration
β”œβ”€β”€ package.json           # Root workspace config
└── tsconfig.base.json     # Base TypeScript config

Package Overview

Package Description Used By
@my/ui Reusable UI components (Button, Text, etc.) All apps
app Shared screens, features, and navigation logic Expo, Next.js
@my/api API client, types, and data fetching All apps
@my/config Theme, colors, spacing, constants All packages

πŸ”§ Available Scripts

Development

Command Description
yarn native Start Expo development server
yarn native:prebuild Generate native iOS/Android projects
yarn ios Run on iOS simulator
yarn android Run on Android emulator
yarn web Build packages and start Next.js dev server
yarn web:prod Build Next.js for production
yarn web:prod:serve Serve production build locally
yarn storybook Start Storybook development server
yarn watch Start all apps in watch mode (parallel)

Quality Checks

Command Description
yarn typecheck Run TypeScript type checking across all workspaces
yarn test Run all tests with Vitest
yarn test:watch Run tests in watch mode for development
yarn lint Check code quality with Biome
yarn lint:fix Auto-fix linting and formatting issues

Build & Maintenance

Command Description
yarn build Build all packages (excludes Next.js app)
yarn clean Remove all node_modules and reinstall
yarn lint-sherif Check workspace dependency consistency

πŸ“š Documentation

Development

Creating New Components

  1. Add component to packages/ui/src/

    // packages/ui/src/MyButton.tsx
    import { Pressable, Text } from 'react-native'
    
    export function MyButton({ title, onPress }) {
      return (
        <Pressable onPress={onPress}>
          <Text>{title}</Text>
        </Pressable>
      )
    }
  2. Export from packages/ui/src/index.tsx

    export * from './MyButton'
  3. Use in any app

    import { MyButton } from '@my/ui'

Creating New Screens

  1. Add screen to packages/app/features/

    // packages/app/features/profile/screen.tsx
    export function ProfileScreen() {
      return (
        <View>
          <Text>Profile Screen</Text>
        </View>
      )
    }
  2. Add to Expo Router

    // apps/expo/app/profile.tsx
    import { ProfileScreen } from 'app/features/profile/screen'
    export default ProfileScreen
  3. Add to Next.js

    // apps/next/app/profile/page.tsx
    import { ProfileScreen } from 'app/features/profile/screen'
    export default function ProfilePage() {
      return <ProfileScreen />
    }

Testing

This template uses Vitest for fast unit testing with a Jest-compatible API.

Running Tests

# Run all tests once
yarn test

# Run tests in watch mode (for development)
yarn test:watch

# Run tests in a specific workspace
cd packages/ui && yarn test

Writing Tests

Tests are co-located with source files using .test.ts or .test.tsx extensions:

// packages/ui/src/Button.test.tsx
import { render, fireEvent } from '@testing-library/react-native'
import { Button } from './Button'

describe('Button', () => {
  it('calls onPress when pressed', () => {
    const onPress = vi.fn()
    const { getByText } = render(
      <Button title="Click me" onPress={onPress} />
    )
    
    fireEvent.press(getByText('Click me'))
    expect(onPress).toHaveBeenCalledTimes(1)
  })
})

Example Test Files

  • apps/next/lib/utils.test.ts - Utility function tests
  • apps/next/app/layout.test.tsx - Metadata tests
  • packages/ui/src/Button.test.tsx - Component tests
  • packages/app/features/home/screen.test.tsx - Screen component tests

Code Quality

This template maintains high code quality through automated checks.

Type Checking

TypeScript type safety is enforced across all workspaces without suppressing errors.

# Type check all workspaces
yarn typecheck

# Type check a specific workspace
cd apps/next && yarn typecheck

Configuration:

  • Type checking is enabled in all workspaces
  • Test files are excluded from builds but still type-checked
  • The Next.js build will fail on TypeScript errors

Linting & Formatting

This template uses Biome - a fast, all-in-one toolchain that replaces ESLint and Prettier.

# Check for issues
yarn lint

# Auto-fix issues
yarn lint:fix

Pre-commit Hooks:

  • Automatically formats and lints staged files
  • Runs via Husky + lint-staged
  • Ensures code quality before commits

React Compiler

This template includes the React Compiler (formerly React Forget) - an experimental feature that automatically optimizes your React components.

What is React Compiler?

The React Compiler automatically memoizes components and values, eliminating the need for manual optimization with useMemo, useCallback, and memo. It analyzes your code at build time and adds optimizations automatically.

Benefits

βœ… Automatic Memoization - No more manual useMemo/useCallback
βœ… Better Performance - Fewer re-renders out of the box
βœ… Cleaner Code - Write idiomatic React without optimization clutter
βœ… Type-Safe - Works seamlessly with TypeScript

Configuration

React Compiler is already configured for both apps:

Expo (Babel):

// apps/expo/babel.config.js
plugins: [
  ['babel-plugin-react-compiler', {
    target: '18' // React Native compatibility
  }],
]

Next.js:

// apps/next/next.config.js
experimental: {
  reactCompiler: true
}

Usage

Just write normal React code - the compiler handles optimization:

// βœ… Before: Manual optimization
const MemoizedComponent = memo(function MyComponent({ data }) {
  const processed = useMemo(() => processData(data), [data])
  const handleClick = useCallback(() => {
    console.log(processed)
  }, [processed])
  
  return <Button onPress={handleClick} />
})

// βœ… After: Let the compiler handle it
function MyComponent({ data }) {
  const processed = processData(data)
  const handleClick = () => {
    console.log(processed)
  }
  
  return <Button onPress={handleClick} />
}

Learn More

Customization

Theme and Colors

Edit the shared configuration in packages/config/src/index.ts:

export const theme = {
  colors: {
    primary: '#007AFF',
    secondary: '#5856D6',
    background: '#FFFFFF',
    text: '#000000',
  },
  spacing: {
    xs: 4,
    sm: 8,
    md: 16,
    lg: 24,
    xl: 32,
  },
  borderRadius: {
    sm: 4,
    md: 8,
    lg: 12,
    full: 9999,
  },
}

API Configuration

Configure API endpoints in packages/api/src/client.ts:

const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'https://api.example.com'

export const apiClient = {
  get: async (endpoint: string) => {
    const response = await fetch(`${API_BASE_URL}${endpoint}`)
    return response.json()
  },
  // ... other methods
}

Environment Variables

Create .env.local files in each app:

# apps/next/.env.local
NEXT_PUBLIC_API_URL=https://api.example.com
NEXT_PUBLIC_APP_NAME=My App

# apps/expo/.env.local (using expo-constants)
EXPO_PUBLIC_API_URL=https://api.example.com

Deployment

Web (Next.js)

Vercel (Recommended):

# Install Vercel CLI
npm i -g vercel

# Deploy
vercel

Build for Production:

yarn web:prod

The build output will be in apps/next/.next/.

Environment Variables: Set environment variables in your hosting platform's dashboard or .env.production.

Mobile (Expo)

Development Build:

# Generate native projects
yarn native:prebuild

# iOS
yarn ios

# Android
yarn android

Production Build with EAS:

# Install EAS CLI
npm install -g eas-cli

# Configure EAS
cd apps/expo
eas build:configure

# Build for iOS
eas build --platform ios

# Build for Android
eas build --platform android

# Submit to stores
eas submit --platform ios
eas submit --platform android

Learn more:


πŸ—οΈ Architecture

Monorepo Structure

This template uses Yarn Workspaces + Turbo for efficient monorepo management:

Root (yarn workspace)
β”œβ”€β”€ apps/*          # Platform-specific applications
β”‚   β”œβ”€β”€ expo        # React Native mobile
β”‚   β”œβ”€β”€ next        # Next.js web
β”‚   └── storybook   # Component docs
└── packages/*      # Shared code
    β”œβ”€β”€ ui          # UI components
    β”œβ”€β”€ app         # App logic
    β”œβ”€β”€ api         # API client
    └── config      # Configuration

Package Dependencies

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Apps (Platform-Specific Entry Points) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β”‚
              β”œβ”€β”€> apps/expo (React Native)
              β”œβ”€β”€> apps/next (Next.js)
              └──> apps/storybook
              
              β”‚
              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         Shared Packages                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β”‚
              β”œβ”€β”€> app (screens & features)
              β”œβ”€β”€> @my/ui (components)
              β”œβ”€β”€> @my/api (data layer)
              └──> @my/config (theme)

Design Principles

  1. Universal First: Write once, run everywhere
  2. Type Safety: TypeScript everywhere
  3. Modular: Small, focused packages
  4. Fast Builds: Turbo caching + parallel execution
  5. Developer Experience: Fast feedback loops

Build System

Turbo orchestrates builds with intelligent caching:

{
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**"]
    },
    "typecheck": {
      "dependsOn": ["^build"]
    }
  }
}

Benefits:

  • βœ… Builds packages in correct order
  • βœ… Caches unchanged packages
  • βœ… Runs tasks in parallel
  • βœ… Incremental builds

πŸ§ͺ CI/CD Pipeline

The GitHub Actions CI pipeline is optimized for speed with parallel execution:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Stage 1: Quality Checks (Parallel)          β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Lint            β”‚  Type Check               β”‚
β”‚  β€’ Biome         β”‚  β€’ All packages           β”‚
β”‚  β€’ Format check  β”‚  β€’ Next.js app            β”‚
β”‚                  β”‚  β€’ Expo app               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚                β”‚
            β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
                     β–Ό
         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
         β”‚   Both must pass   β”‚
         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                     β”‚
         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
         β–Ό                      β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Build           β”‚  β”‚  Test            β”‚
β”‚  β€’ Packages      β”‚  β”‚  β€’ Vitest        β”‚
β”‚  β€’ Next.js       β”‚  β”‚  β€’ All tests     β”‚
β”‚  β€’ Expo check    β”‚  β”‚                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Pipeline Benefits

βœ… Fast Feedback - Quality checks run first and fail fast
βœ… Efficient - Build and test run in parallel
βœ… Cached - Dependencies and build artifacts are cached
βœ… Reliable - Consistent across all environments

Running CI Locally

# Run all quality checks
yarn lint && yarn typecheck

# Run tests
yarn test

# Run full build
yarn build && yarn web:prod

🀝 Contributing

Contributions are welcome! Please follow these guidelines:

Commit Convention

This project uses Conventional Commits:

# Format: <type>(<scope>): <description>

feat(ui): add new Button variant
fix(api): handle network errors properly
docs: update installation instructions
chore(deps): upgrade React to 19.0

Types:

  • feat: New feature
  • fix: Bug fix
  • docs: Documentation
  • style: Code style (formatting, etc.)
  • refactor: Code refactoring
  • test: Adding tests
  • chore: Maintenance

Development Workflow

  1. Fork & clone the repository
  2. Create a branch: git checkout -b feature/my-feature
  3. Make changes with conventional commits
  4. Run quality checks: yarn lint && yarn typecheck && yarn test
  5. Push & create a pull request

Code Style

  • Follow the existing code style
  • Use TypeScript for type safety
  • Write tests for new features
  • Update documentation as needed
  • Biome handles formatting automatically

πŸ“„ License

MIT License - see LICENSE for details.


Built with ❀️ using React Native, Expo, and Next.js

⬆ Back to Top

About

Template monorepo for next and react native apps

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors