FOUNDRY
C8 Platform
← Tasks

[SC-01] Expo project initialization with TypeScript + Expo Router

completedcode_genP0

Description

## SC-01: Expo project initialization with TypeScript + Expo Router Section: Scaffold | Milestone: M1 | Owner: AG Lu ### Failing Tests - **package_json_exists** (file_exists): File `c8-audio/package.json` must exist - **app_json_exists** (file_exists): File `c8-audio/app.json` must exist - **tsconfig_exists** (file_exists): File `c8-audio/tsconfig.json` must exist - **expo_router_dep** (grep): Pattern `expo-router` in `c8-audio/package.json` (need 1+ matches) ### Acceptance Criteria - File `c8-audio/package.json` must exist - File `c8-audio/app.json` must exist - File `c8-audio/tsconfig.json` must exist - File matching `c8-audio/package.json` must contain pattern `expo-router` ### Codebase Conventions - Trilingual comments: // EN: ... // VI: ... // ES: ... - SPEC section refs in comments - Zod at module level with .safeParse() - (supabase as any) with eslint-disable - NextResponse.json() responses - Error format: { error: 'message' }
Assignee
-
Claimed By
Cloud Lu → Claude Sonnet
Created
22d ago
Completed
19d ago

Quality

Overall
79%
Pass
PASS
Graded By
-
Graded At
-

Cost

Input Tokens
-
Output Tokens
-
Est. USD
-

Result

{
  "cost": {
    "input_tokens": 23,
    "estimated_usd": 0.044499,
    "output_tokens": 2962
  },
  "model": "claude-sonnet-4-20250514",
  "status": "success",
  "transport": "anthropic_api",
  "latency_ms": 31179,
  "response_text": "I'll help you initialize an Expo project with TypeScript and Expo Router. Here's a step-by-step guide:\n\n## 1. Create New Expo Project with TypeScript\n\n```bash\n# Create a new Expo project with TypeScript template\nnpx create-expo-app@latest MyApp --template blank-typescript\n\n# Navigate to the project directory\ncd MyApp\n```\n\n## 2. Install Expo Router\n\n```bash\n# Install Expo Router and required dependencies\nnpx expo install expo-router react-native-safe-area-context react-native-screens expo-linking expo-constants expo-status-bar\n```\n\n## 3. Update Configuration Files\n\n### `app.json`\n```json\n{\n  \"expo\": {\n    \"name\": \"MyApp\",\n    \"slug\": \"myapp\",\n    \"version\": \"1.0.0\",\n    \"orientation\": \"portrait\",\n    \"icon\": \"./assets/icon.png\",\n    \"userInterfaceStyle\": \"light\",\n    \"splash\": {\n      \"image\": \"./assets/splash.png\",\n      \"resizeMode\": \"contain\",\n      \"backgroundColor\": \"#ffffff\"\n    },\n    \"assetBundlePatterns\": [\n      \"**/*\"\n    ],\n    \"ios\": {\n      \"supportsTablet\": true\n    },\n    \"android\": {\n      \"adaptiveIcon\": {\n        \"foregroundImage\": \"./assets/adaptive-icon.png\",\n        \"backgroundColor\": \"#ffffff\"\n      }\n    },\n    \"web\": {\n      \"bundler\": \"metro\",\n      \"output\": \"static\",\n      \"favicon\": \"./assets/favicon.png\"\n    },\n    \"plugins\": [\n      \"expo-router\"\n    ],\n    \"scheme\": \"myapp\"\n  }\n}\n```\n\n### `package.json` (update the main entry point)\n```json\n{\n  \"main\": \"expo-router/entry\",\n  \"scripts\": {\n    \"start\": \"expo start\",\n    \"android\": \"expo start --android\",\n    \"ios\": \"expo start --ios\",\n    \"web\": \"expo start --web\"\n  }\n}\n```\n\n## 4. Create App Directory Structure\n\nCreate the following directory structure:\n\n```\napp/\n├── (tabs)/\n│   ├── _layout.tsx\n│   ├── index.tsx\n│   └── explore.tsx\n├── modal.tsx\n└── _layout.tsx\n```\n\n## 5. Root Layout (`app/_layout.tsx`)\n\n```typescript\nimport FontAwesome from '@expo/vector-icons/FontAwesome';\nimport { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';\nimport { useFonts } from 'expo-font';\nimport { Stack } from 'expo-router';\nimport * as SplashScreen from 'expo-splash-screen';\nimport { useEffect } from 'react';\nimport { useColorScheme } from 'react-native';\n\nexport {\n  // Catch any errors thrown by the Layout component.\n  ErrorBoundary,\n} from 'expo-router';\n\nexport const unstable_settings = {\n  // Ensure that reloading on `/modal` keeps a back button present.\n  initialRouteName: '(tabs)',\n};\n\n// Prevent the splash screen from auto-hiding before asset loading is complete.\nSplashScreen.preventAutoHideAsync();\n\nexport default function RootLayout() {\n  const [loaded, error] = useFonts({\n    SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),\n    ...FontAwesome.font,\n  });\n\n  // Expo Router uses Error Boundaries to catch errors in the navigation tree.\n  useEffect(() => {\n    if (error) throw error;\n  }, [error]);\n\n  useEffect(() => {\n    if (loaded) {\n      SplashScreen.hideAsync();\n    }\n  }, [loaded]);\n\n  if (!loaded) {\n    return null;\n  }\n\n  return <RootLayoutNav />;\n}\n\nfunction RootLayoutNav() {\n  const colorScheme = useColorScheme();\n\n  return (\n    <ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>\n      <Stack>\n        <Stack.Screen name=\"(tabs)\" options={{ headerShown: false }} />\n        <Stack.Screen name=\"modal\" options={{ presentation: 'modal' }} />\n      </Stack>\n    </ThemeProvider>\n  );\n}\n```\n\n## 6. Tab Layout (`app/(tabs)/_layout.tsx`)\n\n```typescript\nimport React from 'react';\nimport FontAwesome from '@expo/vector-icons/FontAwesome';\nimport { Link, Tabs } from 'expo-router';\nimport { Pressable, useColorScheme } from 'react-native';\n\nimport Colors from '../../constants/Colors';\n\n/**\n * You can explore the built-in icon families and icons on the web at https://icons.expo.fyi/\n */\nfunction TabBarIcon(props: {\n  name: React.ComponentProps<typeof FontAwesome>['name'];\n  color: string;\n}) {\n  return <FontAwesome size={28} style={{ marginBottom: -3 }} {...props} />;\n}\n\nexport default function TabLayout() {\n  const colorScheme = useColorScheme();\n\n  return (\n    <Tabs\n      screenOptions={{\n        tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint,\n      }}>\n      <Tabs.Screen\n        name=\"index\"\n        options={{\n          title: 'Tab One',\n          tabBarIcon: ({ color }) => <TabBarIcon name=\"code\" color={color} />,\n          headerRight: () => (\n            <Link href=\"/modal\" asChild>\n              <Pressable>\n                {({ pressed }) => (\n                  <FontAwesome\n                    name=\"info-circle\"\n                    size={25}\n                    color={Colors[colorScheme ?? 'light'].text}\n                    style={{ marginRight: 15, opacity: pressed ? 0.5 : 1 }}\n                  />\n                )}\n              </Pressable>\n            </Link>\n          ),\n        }}\n      />\n      <Tabs.Screen\n        name=\"explore\"\n        options={{\n          title: 'Tab Two',\n          tabBarIcon: ({ color }) => <TabBarIcon name=\"code\" color={color} />,\n        }}\n      />\n    </Tabs>\n  );\n}\n```\n\n## 7. Home Screen (`app/(tabs)/index.tsx`)\n\n```typescript\nimport { StyleSheet, Text, View } from 'react-native';\nimport { SafeAreaView } from 'react-native-safe-area-context';\n\nexport default function TabOneScreen() {\n  return (\n    <SafeAreaView style={styles.container}>\n      <View style={styles.content}>\n        <Text style={styles.title}>Tab One</Text>\n        <View style={styles.separator} />\n        <Text>This is the first tab screen.</Text>\n      </View>\n    </SafeAreaView>\n  );\n}\n\nconst styles = StyleSheet.create({\n  container: {\n    flex: 1,\n    backgroundColor: '#fff',\n  },\n  content: {\n    flex: 1,\n    alignItems: 'center',\n    justifyContent: 'center',\n    padding: 20,\n  },\n  title: {\n    fontSize: 20,\n    fontWeight: 'bold',\n  },\n  separator: {\n    marginVertical: 30,\n    height: 1,\n    width: '80%',\n    backgroundColor: '#eee',\n  },\n});\n```\n\n## 8. Explore Screen (`app/(tabs)/explore.tsx`)\n\n```typescript\nimport { StyleSheet, Text, View } from 'react-native';\nimport { SafeAreaView } from 'react-native-safe-area-context';\n\nexport default function TabTwoScreen() {\n  return (\n    <SafeAreaView style={styles.container}>\n      <View style={styles.content}>\n        <Text style={styles.title}>Tab Two</Text>\n        <View style={styles.separator} />\n        <Text>This is the second tab screen.</Text>\n      </View>\n    </SafeAreaView>\n  );\n}\n\nconst styles = StyleSheet.create({\n  container: {\n    flex: 1,\n    backgroundColor: '#fff',\n  },\n  content: {\n    flex: 1,\n    alignItems: 'center',\n    justifyContent: 'center',\n    padding: 20,\n  },\n  title: {\n    fontSize: 20,\n    fontWeight: 'bold',\n  },\n  separator: {\n    marginVertical: 30,\n    height: 1,\n    width: '80%',\n    backgroundColor: '#eee',\n  },\n});\n```\n\n## 9. Modal Screen (`app/modal.tsx`)\n\n```typescript\nimport { StatusBar } from 'expo-status-bar';\nimport { Platform, StyleSheet, Text, View } from 'react-native';\nimport { SafeAreaView } from 'react-native-safe-area-context';\n\nexport default function ModalScreen() {\n  return (\n    <SafeAreaView style={styles.container}>\n      <View style={styles.content}>\n        <Text style={styles.title}>Modal</Text>\n        <View style={styles.separator} />\n        <Text>This is a modal screen.</Text>\n      </View>\n\n      {/* Use a light status bar on iOS to account for the black space above the modal */}\n      <StatusBar style={Platform.OS === 'ios' ? 'light' : 'auto'} />\n    </SafeAreaView>\n  );\n}\n\nconst styles = StyleSheet.create({\n  container: {\n    flex: 1,\n    backgroundColor: '#fff',\n  },\n  content: {\n    flex: 1,\n    alignItems: 'center',\n    justifyContent: 'center',\n    padding: 20,\n  },\n  title: {\n    fontSize: 20,\n    fontWeight: 'bold',\n  },\n  separator: {\n    marginVertical: 30,\n    height: 1,\n    width: '80%',\n    backgroundColor: '#eee',\n  },\n});\n```\n\n## 10. Constants File (`constants/Colors.ts`)\n\n```typescript\nconst tintColorLight = '#2f95dc';\nconst tintColorDark = '#fff';\n\nexport default {\n  light: {\n    text: '#000',\n    background: '#fff',\n    tint: tintColorLight,\n    tabIconDefault: '#ccc',\n    tabIconSelected: tintColorLight,\n  },\n  dark: {\n    text: '#fff',\n    background: '#000',\n    tint: tintColorDark,\n    tabIconDefault: '#ccc',\n    tabIconSelected: tintColorDark,\n  },\n};\n```\n\n## 11. Add Font File\n\nCreate an `assets/fonts/` directory and add the SpaceMono font file, or remove the font loading from the root layout if you don't want custom fonts.\n\n## 12. Update Metro Configuration (`metro.config.js`)\n\n```javascript\nconst { getDefaultConfig } = require('expo/metro-config');\n\nconst config = getDefaultConfig(__dirname);\n\nmodule.exports = config;\n```\n\n## 13. TypeScript Configuration (`tsconfig.json`)\n\n```json\n{\n  \"extends\": \"expo/tsconfig.base\",\n  \"compilerOptions\": {\n    \"strict\": true,\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"@/*\": [\"./*\"]\n    }\n  }\n}\n```\n\n## 14. Start the Development Server\n\n```bash\nnpx expo start\n```\n\nThis setup provides:\n- ✅ TypeScript support\n- ✅ Expo Router with file-based routing\n- ✅ Tab navigation\n- ✅ Modal presentation\n- ✅ Safe area handling\n- ✅ Dark/light theme support\n- ✅ Proper project structure\n\nYou can now press `i` for iOS simulator, `a` for Android emulator, or `w` for web development."
}
Task ID: 7ee4becc-736b-4f8b-b31b-ab78d150ebcd