feat: add EAS build configuration for local APK builds

- Add eas.json with development, preview, and production profiles
- Configure preview profile for APK builds (arm64-v8a only)
- Add build:apk npm script for local builds
- Update app.json with app name and Android package
- Add expo-build-properties dependency
- Update CLAUDE.md with build documentation
This commit is contained in:
2026-01-12 19:29:52 +01:00
parent e6b9dd9d34
commit fef30d428d
5 changed files with 129 additions and 23 deletions

View File

@@ -23,6 +23,7 @@ npm run android -w @caldav/client # Start on Android
npm run ios -w @caldav/client # Start on iOS
npm run web -w @caldav/client # Start web version
npm run lint -w @caldav/client # Run ESLint
npm run build:apk -w @caldav/client # Build APK locally with EAS
```
### Server (apps/server) - Express.js backend
@@ -42,6 +43,7 @@ npm run start -w @caldav/server # Run compiled server (port 3000)
| | NativeWind | Tailwind CSS for React Native |
| | Zustand | State management |
| | FlashList | High-performance lists |
| | EAS Build | Local APK/IPA builds |
| Backend | Express.js | Web framework |
| | MongoDB | Database |
| | Mongoose | ODM |
@@ -404,6 +406,29 @@ NODE_ENV=development # development = pretty logs, production = JSON
- `ChatStore`: Zustand store with addMessage(), addMessages(), updateMessage(), clearMessages() - loads from server on mount and persists across tab switches
- Event Detail and Note screens exist as skeletons
## Building
### Local APK Build with EAS
```bash
npm run build:apk -w @caldav/client
```
This uses the `preview` profile from `eas.json` which builds an APK with:
- `arm64-v8a` architecture only (smaller APK size)
- No credentials required (`withoutCredentials: true`)
- Internal distribution
**Requirements:** Android SDK and Java must be installed locally.
**EAS Configuration:** `apps/client/eas.json` contains build profiles:
- `development`: Development client with internal distribution
- `preview`: APK build for testing (used by `build:apk`)
- `production`: Production build with auto-increment versioning
**App Identity:**
- Package name: `com.gilmour109.calchat`
- EAS Project ID: `b722dde6-7d89-48ff-9095-e007e7c7da87`
## Documentation
Detailed architecture diagrams are in `docs/`:

View File

@@ -1,11 +1,10 @@
{
"expo": {
"jsEngine": "hermes",
"name": "caldav",
"name": "CalChat",
"slug": "caldav",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/images/icon.png",
"scheme": "caldav",
"userInterfaceStyle": "automatic",
"newArchEnabled": true,
@@ -13,38 +12,26 @@
"supportsTablet": true
},
"android": {
"adaptiveIcon": {
"backgroundColor": "#E6F4FE",
"foregroundImage": "./assets/images/android-icon-foreground.png",
"backgroundImage": "./assets/images/android-icon-background.png",
"monochromeImage": "./assets/images/android-icon-monochrome.png"
},
"package": "com.gilmour109.calchat",
"edgeToEdgeEnabled": true,
"predictiveBackGestureEnabled": false
},
"web": {
"output": "static",
"favicon": "./assets/images/favicon.png",
"bundler": "metro"
},
"plugins": [
"expo-router",
[
"expo-splash-screen",
{
"image": "./assets/images/splash-icon.png",
"imageWidth": 200,
"resizeMode": "contain",
"backgroundColor": "#ffffff",
"dark": {
"backgroundColor": "#000000"
}
}
]
"expo-router"
],
"experiments": {
"typedRoutes": true,
"reactCompiler": true
},
"extra": {
"router": {},
"eas": {
"projectId": "b722dde6-7d89-48ff-9095-e007e7c7da87"
}
}
}
}

28
apps/client/eas.json Normal file
View File

@@ -0,0 +1,28 @@
{
"cli": {
"version": ">= 16.28.0",
"appVersionSource": "remote"
},
"build": {
"development": {
"developmentClient": true,
"distribution": "internal"
},
"preview": {
"distribution": "internal",
"android": {
"buildType": "apk",
"withoutCredentials": true
},
"env": {
"ORG_GRADLE_PROJECT_reactNativeArchitectures": "arm64-v8a"
}
},
"production": {
"autoIncrement": true
}
},
"submit": {
"production": {}
}
}

View File

@@ -8,7 +8,8 @@
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"lint": "expo lint"
"lint": "expo lint",
"build:apk": "eas build --platform android --profile preview --local"
},
"dependencies": {
"@caldav/shared": "*",
@@ -18,6 +19,7 @@
"@react-navigation/native": "^7.1.8",
"@shopify/flash-list": "^2.0.2",
"expo": "~54.0.25",
"expo-build-properties": "^1.0.10",
"expo-constants": "~18.0.10",
"expo-font": "~14.0.9",
"expo-haptics": "~15.0.7",

64
package-lock.json generated
View File

@@ -28,6 +28,7 @@
"@react-navigation/native": "^7.1.8",
"@shopify/flash-list": "^2.0.2",
"expo": "~54.0.25",
"expo-build-properties": "^1.0.10",
"expo-constants": "~18.0.10",
"expo-font": "~14.0.9",
"expo-haptics": "~15.0.7",
@@ -7303,6 +7304,53 @@
"react-native": "*"
}
},
"node_modules/expo-build-properties": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/expo-build-properties/-/expo-build-properties-1.0.10.tgz",
"integrity": "sha512-mFCZbrbrv0AP5RB151tAoRzwRJelqM7bCJzCkxpu+owOyH+p/rFC/q7H5q8B9EpVWj8etaIuszR+gKwohpmu1Q==",
"license": "MIT",
"dependencies": {
"ajv": "^8.11.0",
"semver": "^7.6.0"
},
"peerDependencies": {
"expo": "*"
}
},
"node_modules/expo-build-properties/node_modules/ajv": {
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
"license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/expo-build-properties/node_modules/json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"license": "MIT"
},
"node_modules/expo-build-properties/node_modules/semver": {
"version": "7.7.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/expo-constants": {
"version": "18.0.11",
"resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-18.0.11.tgz",
@@ -8013,6 +8061,22 @@
"dev": true,
"license": "MIT"
},
"node_modules/fast-uri": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz",
"integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fastify"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fastify"
}
],
"license": "BSD-3-Clause"
},
"node_modules/fastq": {
"version": "1.19.1",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",