Initialize Expo mobile app with tab navigation and monorepo support

- Expo managed project at apps/mobile/ with TypeScript
- Expo Router with 4 tabs: Map, Routes, Activities, Profile
- app.config.ts with monorepo experiment, bundle IDs, scheme
- Workspace packages linked: api, gpx, i18n, map-core, types
- Profile tab imports API_VERSION from @trails-cool/api to verify
  shared package resolution

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ullrich Schäfer 2026-04-12 23:05:57 +02:00
parent 48f990f4ec
commit 95fdbfee2f
No known key found for this signature in database
GPG key ID: A32FF691A0F752D9
17 changed files with 5439 additions and 31 deletions

41
apps/mobile/.gitignore vendored Normal file
View file

@ -0,0 +1,41 @@
# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files
# dependencies
node_modules/
# Expo
.expo/
dist/
web-build/
expo-env.d.ts
# Native
.kotlin/
*.orig.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision
# Metro
.metro-health-check*
# debug
npm-debug.*
yarn-debug.*
yarn-error.*
# macOS
.DS_Store
*.pem
# local env files
.env*.local
# typescript
*.tsbuildinfo
# generated native folders
/ios
/android

36
apps/mobile/app.config.ts Normal file
View file

@ -0,0 +1,36 @@
import { ExpoConfig, ConfigContext } from "expo/config";
export default ({ config }: ConfigContext): ExpoConfig => ({
...config,
name: "trails.cool",
slug: "trails-cool",
version: "0.0.1",
scheme: "trailscool",
orientation: "portrait",
icon: "./assets/icon.png",
userInterfaceStyle: "light",
newArchEnabled: true,
splash: {
image: "./assets/splash-icon.png",
resizeMode: "contain",
backgroundColor: "#ffffff",
},
ios: {
supportsTablet: true,
bundleIdentifier: "cool.trails.app",
},
android: {
adaptiveIcon: {
foregroundImage: "./assets/adaptive-icon.png",
backgroundColor: "#ffffff",
},
package: "cool.trails.app",
},
web: {
favicon: "./assets/favicon.png",
},
experiments: {
monorepo: true,
},
plugins: ["expo-router"],
});

View file

@ -0,0 +1,41 @@
import { Tabs } from "expo-router";
export default function TabLayout() {
return (
<Tabs
screenOptions={{
tabBarActiveTintColor: "#4A6B40",
headerShown: false,
}}
>
<Tabs.Screen
name="index"
options={{
title: "Map",
tabBarIcon: () => null,
}}
/>
<Tabs.Screen
name="routes"
options={{
title: "Routes",
tabBarIcon: () => null,
}}
/>
<Tabs.Screen
name="activities"
options={{
title: "Activities",
tabBarIcon: () => null,
}}
/>
<Tabs.Screen
name="profile"
options={{
title: "Profile",
tabBarIcon: () => null,
}}
/>
</Tabs>
);
}

View file

@ -0,0 +1,14 @@
import { View, Text, StyleSheet } from "react-native";
export default function ActivitiesScreen() {
return (
<View style={styles.container}>
<Text style={styles.text}>Activities</Text>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: "center", alignItems: "center" },
text: { fontSize: 18, color: "#666" },
});

View file

@ -0,0 +1,14 @@
import { View, Text, StyleSheet } from "react-native";
export default function MapScreen() {
return (
<View style={styles.container}>
<Text style={styles.text}>Map</Text>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: "center", alignItems: "center" },
text: { fontSize: 18, color: "#666" },
});

View file

@ -0,0 +1,17 @@
import { View, Text, StyleSheet } from "react-native";
import { API_VERSION } from "@trails-cool/api";
export default function ProfileScreen() {
return (
<View style={styles.container}>
<Text style={styles.text}>Profile</Text>
<Text style={styles.version}>API v{API_VERSION}</Text>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: "center", alignItems: "center" },
text: { fontSize: 18, color: "#666" },
version: { fontSize: 12, color: "#999", marginTop: 8 },
});

View file

@ -0,0 +1,14 @@
import { View, Text, StyleSheet } from "react-native";
export default function RoutesScreen() {
return (
<View style={styles.container}>
<Text style={styles.text}>Routes</Text>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: "center", alignItems: "center" },
text: { fontSize: 18, color: "#666" },
});

View file

@ -0,0 +1,5 @@
import { Stack } from "expo-router";
export default function RootLayout() {
return <Stack screenOptions={{ headerShown: false }} />;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
apps/mobile/assets/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

1
apps/mobile/index.ts Normal file
View file

@ -0,0 +1 @@
import "expo-router/entry";

30
apps/mobile/package.json Normal file
View file

@ -0,0 +1,30 @@
{
"name": "@trails-cool/mobile",
"version": "0.0.1",
"private": true,
"main": "index.ts",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web"
},
"dependencies": {
"@trails-cool/api": "workspace:*",
"@trails-cool/gpx": "workspace:*",
"@trails-cool/i18n": "workspace:*",
"@trails-cool/map-core": "workspace:*",
"@trails-cool/types": "workspace:*",
"expo": "~54.0.33",
"expo-router": "~4.0.22",
"expo-status-bar": "~3.0.9",
"react": "19.1.0",
"react-native": "0.81.5",
"react-native-safe-area-context": "~5.4.0",
"react-native-screens": "~4.11.0"
},
"devDependencies": {
"@types/react": "~19.1.0",
"typescript": "~5.9.2"
}
}

View file

@ -0,0 +1,6 @@
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"strict": true
}
}

View file

@ -2,10 +2,10 @@
### 1.1 App Scaffold
- [ ] 1.1.1 Initialize Expo managed project at `apps/mobile/` with TypeScript template
- [ ] 1.1.2 Configure pnpm workspace to include `apps/mobile` and resolve shared packages (`@trails-cool/types`, `@trails-cool/gpx`, `@trails-cool/i18n`)
- [ ] 1.1.3 Set up Expo Router with bottom tab navigation (Map, Routes, Activities, Profile) and placeholder screens
- [ ] 1.1.4 Add app icon, splash screen, and `app.config.ts` with bundle identifiers for iOS and Android
- [x] 1.1.1 Initialize Expo managed project at `apps/mobile/` with TypeScript template
- [x] 1.1.2 Configure pnpm workspace to include `apps/mobile` and resolve shared packages (`@trails-cool/types`, `@trails-cool/gpx`, `@trails-cool/i18n`)
- [x] 1.1.3 Set up Expo Router with bottom tab navigation (Map, Routes, Activities, Profile) and placeholder screens
- [x] 1.1.4 Add app icon, splash screen, and `app.config.ts` with bundle identifiers for iOS and Android
- [ ] 1.1.5 Configure EAS Build for development and preview profiles
### 1.2 API Contract Package

5243
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff