Skip to Content
ConventionsFile Organization

File Organization

RNCopilot uses path aliases, a strict import order, and barrel files to keep the codebase navigable and refactor-friendly.

Path Aliases

Always use path aliases. Never use relative paths that climb more than one level.

AliasResolves ToExample
@/*src/*import { Button } from '@/common/components/Button'
~/*app/*import type { LayoutProps } from '~/types'

These aliases are configured in both tsconfig.json (TypeScript) and babel.config.js (bundler), so they work in your editor, tests, and at runtime.

// CORRECT import { Button } from '@/common/components/Button'; import { useAuthStore } from '@/providers/auth/authStore'; import { apiClient } from '@/services/api'; // WRONG -- climbing relative paths import { Button } from '../../../common/components/Button';

Relative imports within the same directory (e.g., ./helpers, ./types) are fine and expected. The rule only prohibits climbing more than one level (../../).

Import Order

Imports are grouped in this exact order, with a blank line between each group:

  1. React and React Native core
  2. Expo and third-party libraries
  3. Internal @/ path alias imports (types last within this group)
  4. Relative imports within the same feature or directory (types last)
import { useState } from 'react'; import { View, Pressable } from 'react-native'; import { useTranslation } from 'react-i18next'; import { StyleSheet } from 'react-native-unistyles'; import { Button } from '@/common/components/Button'; import { useAuthStore } from '@/providers/auth/authStore'; import type { MyProps } from '@/types'; import { localHelper } from './helpers'; import type { LocalType } from './types';

Within each group, type imports (import type) come after value imports.

Barrel Files

Every component directory has an index.ts that re-exports the public API:

// src/common/components/Button/index.ts export { Button } from './Button'; export type { ButtonProps, ButtonVariant, ButtonSize } from './Button.types';

Always import from the barrel, never from the implementation file:

// CORRECT import { Button } from '@/common/components/Button'; // WRONG import { Button } from '@/common/components/Button/Button';

Component Directory Structure

ComponentName/ ├── ComponentName.tsx # Required: component implementation ├── ComponentName.types.ts # Optional: props and related types ├── ComponentName.styles.ts # Optional: when styles are substantial └── index.ts # Required: barrel export

Feature Module Structure

Each feature is a self-contained module under src/features/:

src/features/<feature>/ ├── components/ # Feature-specific UI components ├── services/ # API calls (pure async functions, no React) ├── hooks/ # Custom hooks for this feature ├── stores/ # Zustand stores ├── types/ # TypeScript types and interfaces ├── schemas/ # Zod validation schemas └── constants/ # Feature-level constants

Not every feature needs all subdirectories. Only create the ones you need.

Top-Level Directory Layout

src/ ├── common/components/ # 33 shared UI components ├── config/ # Centralized env config with validation ├── features/ # Feature modules (auth, settings, etc.) ├── hooks/ # Global hooks ├── i18n/ # Translation files and config ├── integrations/ # Supabase client ├── providers/ # QueryProvider, auth store ├── services/api/ # Axios client with interceptors ├── theme/ # Semantic tokens, metrics, fonts ├── types/ # Global TypeScript types └── utils/storage/ # MMKV with typed keys app/ # Expo Router (file-based routing) ├── _layout.tsx # Root layout with providers ├── +not-found.tsx # 404 screen └── (main)/(tabs)/ # Tab navigator
Last updated on