Skip to main content

Overview

The Launch mobile app follows a well-organized structure that makes it easy for developers to find components, understand data flow, and maintain the codebase.

Prerequisites

  • Basic familiarity with Expo Router

Steps

Directory Structure

apps/mobile/
├── app/                         # Expo Router routes
│   ├── _layout.tsx              # Root layout/providers/navigation
│   ├── (tabs)/                  # Tabbed routes
│   │   ├── home/                # Home tab screens
│   │   ├── features/            # Feature catalog screens
│   │   └── settings/            # Settings tab screens
│   ├── auth/                    # Auth screens
│   ├── onboarding/              # Onboarding flow
│   ├── payments/                # Payments screens
│   ├── file-uploads/            # Uploads screens
│   ├── ai-chat.tsx              # AI chat screen
│   ├── notifications.tsx        # Notification settings
│   ├── appearance.tsx           # Theme and appearance
│   ├── delete-account.tsx       # Account deletion
│   └── error-screen/            # Global error fallback
├── components/                  # Reusable UI components (flat)
├── features/                    # Feature modules + registry
│   ├── feature-registry.tsx
│   ├── ai/
│   ├── payments/
│   ├── file-uploads/
│   └── sentry/
├── lib/                         # Clients, hooks, services
│   ├── auth/                    # Better Auth client + session context
│   ├── trpc/                    # tRPC client
│   ├── payments/                # Stripe/RevenueCat/Superwall
│   ├── ai/                      # Providers, prompts, config
│   ├── api/                     # API config + health
│   ├── upload/                  # Upload helpers
│   ├── hooks/                   # Shared hooks
│   ├── mutations/               # Client mutations
│   ├── notifications.ts         # Push setup + registration
│   └── google-services.json     # Firebase config (Android, placeholder)
├── constants/                   # Design tokens (colors/spacing/typography)
├── contexts/                    # App/theme contexts
├── modules/                     # Native modules (Expo Modules API)
├── themes/                      # Theme definitions
└── app.config.ts                # Expo config (replace placeholders)

Key Patterns

Component Organization

Components live primarily in a flat components/ folder. Grouping is done by naming and usage instead of deep subfolders (e.g., auth-button.tsx, model-select.tsx, screen-container.tsx). Small subfolders like __tests__ exist for tests, but the main component surface stays flat for easy imports.

Configuration & Feature Flags

There is no launch.config.ts in the repo. App configuration and feature flags live in:
  • app.config.ts (Expo config, plugins, bundle identifiers)
  • features/feature-registry.tsx (feature enable/disable, providers)
app.config.ts is required by Expo to wire native identifiers (bundle ID / package name), deep link schemes, and plugin configuration. The repo ships placeholder values so you can commit safely—replace them with your own before building.

Screen Patterns

Authentication Flow

// app/_layout.tsx - Route protection
<Stack.Screen name="auth" />
<Stack.Screen name="onboarding" />
<Stack.Screen name="(tabs)" />

Feature Registry

The feature registry composes optional modules (payments, AI, uploads, Sentry) in one place:
// apps/mobile/features/feature-registry.tsx
export const featureRegistry = [
  paymentsFeature(featureFlags),
  aiFeature(featureFlags),
  fileUploadsFeature(featureFlags),
  sentryFeature(featureFlags),
];

Component Composition

// Dashboard screen using reusable components
export default function HomeScreen() {
  const { data: session, isPending } = authClient.useSession();

  if (isPending) return <LoadingState />;

  return (
    <View>
      <AppText>Welcome</AppText>
      <AppText>{session?.user?.email}</AppText>
      <SignOutButton />
    </View>
  );
}

Design System Integration

Spacing

Use predefined spacing tokens instead of arbitrary values:
// Good
paddingTop: insets.top + Spacing.screen.headerSpacing,
paddingBottom: insets.bottom + Spacing.md,

// Avoid
paddingTop: 60,
paddingBottom: 16,

Colors

Colors are defined in the theme system and accessed consistently:
// Theme colors (dynamic)
const { colors, isDark } = useTheme();

// Static colors from constants
backgroundColor: ButtonColors.grayButton,

Typography

Font families are configured in the design system:
// Tailwind classes
className = "font-sans-bold text-4xl";

// Maps to Manrope-Bold font family

Best Practices

Component Creation

  1. Reusable components go in components/ (flat, with minimal subfolders)
  2. Screen-specific components can stay in the screen file if they won’t be reused
  3. Always export from the folder’s index.ts file
  4. Use TypeScript interfaces for props

State Management

  1. Authentication state - Use authClient.useSession()
  2. Theme state - Use useTheme() hook
  3. Form factor detection - Use useResponsive() for device types
  4. Local state - Use React’s useState and useEffect

Styling Approach

  1. NativeWind classes for most styling
  2. Style objects when dynamic values are needed
  3. Theme system for colors and fonts
  4. Spacing tokens for consistent layout

Adding New Features

New Screen

  1. Create screen file in app/
  2. Add route group or stack entry if needed
  3. Gate behind feature registry when optional
  4. Extract reusable components to components/

New Component

  1. Create component in components/
  2. Write TypeScript interface for props
  3. Add to the calling screen or feature module
This structure ensures the codebase remains organized, scalable, and easy to understand for new developers.

Troubleshooting

  • File not routing: confirm file name and path under app/
  • Import issues: use @/ aliases consistently

Next Steps