Skip to main content
Project Structure

Module Overview

Estimated Time: 2 hours | Difficulty: Beginner-Intermediate | Prerequisites: Environment setup complete
A well-organized project structure is crucial for maintainability, especially as your app grows. Mobile projects have a unique structural challenge that web projects do not: you have platform-specific native directories (ios/ and android/) alongside your JavaScript source code, configuration files for multiple build systems (Gradle, Xcode, Metro, Babel), and assets that may need different resolutions for different screen densities. Without a clear structure, navigating between these layers becomes painful fast. This module covers industry-standard patterns used by companies like Shopify, Discord, and Coinbase. What You’ll Learn:
  • Default project structure (Expo and CLI)
  • Feature-based folder organization
  • Barrel exports and module organization
  • Configuration management
  • Environment variables
  • Path aliases and absolute imports

Default Project Structures

Expo Project Structure

React Native CLI Structure


For production apps, use a feature-based structure. The key insight: organize by business domain (auth, products, cart), not by technical role (components, screens, hooks). When a new developer joins and is asked to “fix the cart total calculation,” they should open one folder, not hunt across five. This pattern also maps naturally to team ownership — one squad owns the features/cart/ directory, another owns features/products/. A mobile-specific consideration: features often need platform-specific implementations. Rather than creating top-level ios/ and android/ source directories, use React Native’s file-extension convention (e.g., PaymentButton.ios.tsx and PaymentButton.android.tsx) within the feature folder. This keeps platform differences co-located with the feature they belong to.

Feature Module Pattern

Each feature is a self-contained module with everything it needs. Think of each feature folder as a mini-app: it owns its screens, components, hooks, services, types, and state. The benefit is isolation — a developer working on the “cart” feature does not need to understand the “auth” feature’s internals, and deleting a feature means removing one folder rather than hunting through a dozen shared directories. This pattern becomes especially valuable in React Native because features often have platform-specific behavior (e.g., Apple Pay on iOS vs Google Pay on Android) that stays contained within the feature folder rather than leaking into shared code.

Feature Structure Example


Barrel Exports

Barrel exports simplify imports and create a clean public API for each module:

Using Barrel Exports


Path Aliases

Configure path aliases for cleaner imports:

TypeScript Configuration

Babel Configuration

Install the plugin:

Usage


Environment Variables

Managing environment variables in React Native is more nuanced than in web development. On the web, tools like dotenv inject values at build time and you are done. In React Native, you need to consider: (1) JavaScript-side variables for your React code, (2) native-side variables for iOS Info.plist and Android build.gradle configurations, and (3) the fact that secrets bundled into a mobile app can be extracted by anyone who decompiles the binary. Never put truly secret API keys directly in your JS bundle — use a backend proxy instead.

Using Expo

Using React Native CLI

Environment-Specific Builds


Configuration Files

ESLint Configuration

Prettier Configuration

TypeScript Configuration


Git Configuration

.gitignore

.gitattributes


Naming Conventions

Files and Folders

Component Naming

Hook Naming

Type Naming


Quick Reference

Project Structure Checklist

1

Create Feature Folders

Organize code by feature, not by type (components, screens, etc.)
2

Set Up Path Aliases

Configure @/ aliases in tsconfig.json and babel.config.js
3

Create Barrel Exports

Add index.ts files to export public APIs from each module
4

Configure Environment Variables

Set up .env files and config constants
5

Add Linting and Formatting

Configure ESLint and Prettier for consistent code style

Mobile Project Structure Pitfalls

Structural mistakes that compound over time:Putting platform-specific code in shared directories. If shared/components/DatePicker.tsx contains Platform.OS === 'ios' ? ... branches that grow to 200+ lines, split it into DatePicker.ios.tsx and DatePicker.android.tsx. The file-extension convention keeps Metro happy and makes each platform’s code independently readable.Circular barrel exports. When features/auth/index.ts re-exports from features/auth/hooks/useAuth.ts, and that hook imports from features/products/index.ts, which imports from features/auth/index.ts — Metro’s module resolver can silently return undefined for the circular import. You will get a cryptic “X is not a function” runtime error with no useful stack trace. Break cycles by importing from the specific file, not the barrel, when a cross-feature dependency exists.Ignoring the ios/ and android/ native directories. These are not “generated files you never touch.” When you run npx pod-install or update Gradle plugin versions, files in these directories change. Commit them to version control. If a teammate’s ios/Pods/ is out of sync with yours, you will waste hours debugging build failures that have nothing to do with your JavaScript code.Storing secrets in app.json or .env files that get bundled. React Native bundles are just ZIP files containing JavaScript. Anyone can extract and read them. Use your backend as a proxy for secret API keys, and use Expo’s expo-secure-store or the native Keychain/Keystore for tokens that must live on-device.

Next Steps

Module 4: TypeScript in React Native

Learn TypeScript patterns and best practices for React Native development