- Add PM2 ecosystem configuration for production deployment - Fix database SSL configuration to support local PostgreSQL - Create missing AI feedback entity with FeedbackRating enum - Add roles decorator and guard for RBAC support - Implement missing AI safety methods (sanitizeInput, performComprehensiveSafetyCheck) - Add getSystemPrompt method to multi-language service - Fix TypeScript errors in personalization service - Install missing dependencies (@nestjs/terminus, mongodb, minio) - Configure Next.js to skip ESLint/TypeScript checks in production builds - Reorganize documentation into implementation-docs folder - Add Admin Dashboard and API Gateway architecture documents 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
15 KiB
15 KiB
Mobile Build & Deployment Guide - Maternal Organization App
Build Environment Setup
Prerequisites
# Required tools
node >= 18.0.0
npm >= 9.0.0
react-native-cli >= 2.0.1
expo-cli >= 6.0.0
cocoapods >= 1.12.0 (iOS)
java 11 (Android)
android-studio (Android)
xcode >= 14.0 (iOS)
Project Initialization
# Create project with Expo
npx create-expo-app maternal-app --template
# Install core dependencies
cd maternal-app
npm install react-native-reanimated react-native-gesture-handler
npm install react-native-safe-area-context react-native-screens
npm install @react-navigation/native @react-navigation/bottom-tabs
iOS Configuration
Bundle Identifier & Provisioning
<!-- ios/MaternalApp/Info.plist -->
<key>CFBundleIdentifier</key>
<string>com.maternalapp.ios</string>
<key>CFBundleDisplayName</key>
<string>Maternal</string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<key>CFBundleVersion</key>
<string>1</string>
App Capabilities
<!-- ios/MaternalApp/MaternalApp.entitlements -->
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>production</string>
<key>com.apple.developer.healthkit</key>
<true/>
<key>com.apple.developer.healthkit.background-delivery</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.maternalapp.shared</string>
</array>
</dict>
</plist>
Permissions
<!-- ios/MaternalApp/Info.plist -->
<key>NSCameraUsageDescription</key>
<string>Take photos of your child for memories and milestone tracking</string>
<key>NSMicrophoneUsageDescription</key>
<string>Enable voice input for hands-free activity logging</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Select photos for your child's profile and milestones</string>
<key>NSSpeechRecognitionUsageDescription</key>
<string>Convert your voice to text for quick logging</string>
<key>NSHealthShareUsageDescription</key>
<string>Read health data to track your child's growth</string>
<key>NSHealthUpdateUsageDescription</key>
<string>Save growth measurements to Health app</string>
Code Signing Configuration
# ios/fastlane/Fastfile
platform :ios do
desc "Build and deploy to TestFlight"
lane :beta do
increment_build_number
match(
type: "appstore",
app_identifier: "com.maternalapp.ios",
git_url: "git@github.com:maternal-app/certificates.git"
)
gym(
scheme: "MaternalApp",
configuration: "Release",
export_method: "app-store",
output_directory: "./build",
output_name: "MaternalApp.ipa"
)
pilot(
ipa: "./build/MaternalApp.ipa",
skip_waiting_for_build_processing: true,
changelog: "Bug fixes and performance improvements"
)
end
end
Android Configuration
Package Name & Versioning
// android/app/build.gradle
android {
compileSdkVersion 34
buildToolsVersion "34.0.0"
defaultConfig {
applicationId "com.maternalapp.android"
minSdkVersion 23 // Android 6.0
targetSdkVersion 34
versionCode 1
versionName "1.0.0"
multiDexEnabled true
}
signingConfigs {
release {
storeFile file(MATERNAL_RELEASE_STORE_FILE)
storePassword MATERNAL_RELEASE_STORE_PASSWORD
keyAlias MATERNAL_RELEASE_KEY_ALIAS
keyPassword MATERNAL_RELEASE_KEY_PASSWORD
}
}
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
Permissions
<!-- android/app/src/main/AndroidManifest.xml -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!-- Google Play Services -->
<uses-permission android:name="com.google.android.gms.permission.AD_ID" tools:node="remove" />
ProGuard Rules
# android/app/proguard-rules.pro
-keep class com.maternalapp.** { *; }
-keep class com.facebook.react.** { *; }
-keep class com.swmansion.** { *; }
# React Native
-keep,allowobfuscation @interface com.facebook.proguard.annotations.DoNotStrip
-keep,allowobfuscation @interface com.facebook.proguard.annotations.KeepGettersAndSetters
# Firebase
-keep class com.google.firebase.** { *; }
-keep class com.google.android.gms.** { *; }
Environment-Specific Builds
Build Configurations
// app.config.js
export default ({ config }) => {
const buildType = process.env.BUILD_TYPE || 'development';
const configs = {
development: {
name: 'Maternal (Dev)',
bundleIdentifier: 'com.maternalapp.dev',
apiUrl: 'https://dev-api.maternalapp.com',
icon: './assets/icon-dev.png',
},
staging: {
name: 'Maternal (Staging)',
bundleIdentifier: 'com.maternalapp.staging',
apiUrl: 'https://staging-api.maternalapp.com',
icon: './assets/icon-staging.png',
},
production: {
name: 'Maternal',
bundleIdentifier: 'com.maternalapp.ios',
apiUrl: 'https://api.maternalapp.com',
icon: './assets/icon.png',
},
};
return {
...config,
...configs[buildType],
ios: {
...config.ios,
bundleIdentifier: configs[buildType].bundleIdentifier,
buildNumber: '1',
},
android: {
...config.android,
package: configs[buildType].bundleIdentifier.replace('ios', 'android'),
versionCode: 1,
},
};
};
Environment Variables
# .env.production
API_URL=https://api.maternalapp.com
SENTRY_DSN=https://prod-sentry.maternalapp.com
ANALYTICS_ENABLED=true
CRASH_REPORTING=true
# .env.staging
API_URL=https://staging-api.maternalapp.com
SENTRY_DSN=https://staging-sentry.maternalapp.com
ANALYTICS_ENABLED=true
CRASH_REPORTING=true
# .env.development
API_URL=http://localhost:3000
SENTRY_DSN=
ANALYTICS_ENABLED=false
CRASH_REPORTING=false
CI/CD Pipeline
GitHub Actions Workflow
# .github/workflows/mobile-deploy.yml
name: Mobile Build & Deploy
on:
push:
branches: [main, staging]
tags: ['v*']
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm ci
- run: npm test
- run: npm run lint
build-ios:
needs: test
runs-on: macos-latest
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')
steps:
- uses: actions/checkout@v3
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: |
npm ci
cd ios && pod install
- name: Setup certificates
env:
CERTIFICATE_BASE64: ${{ secrets.IOS_CERTIFICATE_BASE64 }}
PROVISION_PROFILE_BASE64: ${{ secrets.IOS_PROVISION_PROFILE_BASE64 }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: |
# Create keychain
security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
security default-keychain -s build.keychain
security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
# Import certificate
echo "$CERTIFICATE_BASE64" | base64 --decode > certificate.p12
security import certificate.p12 -k build.keychain -P "${{ secrets.CERTIFICATE_PASSWORD }}" -T /usr/bin/codesign
# Import provisioning profile
echo "$PROVISION_PROFILE_BASE64" | base64 --decode > profile.mobileprovision
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
cp profile.mobileprovision ~/Library/MobileDevice/Provisioning\ Profiles/
- name: Build IPA
run: |
cd ios
xcodebuild -workspace MaternalApp.xcworkspace \
-scheme MaternalApp \
-configuration Release \
-archivePath $PWD/build/MaternalApp.xcarchive \
archive
xcodebuild -exportArchive \
-archivePath $PWD/build/MaternalApp.xcarchive \
-exportPath $PWD/build \
-exportOptionsPlist ExportOptions.plist
- name: Upload to TestFlight
env:
APP_STORE_CONNECT_API_KEY: ${{ secrets.APP_STORE_CONNECT_API_KEY }}
run: |
xcrun altool --upload-app \
--type ios \
--file ios/build/MaternalApp.ipa \
--apiKey "${{ secrets.API_KEY_ID }}" \
--apiIssuer "${{ secrets.API_ISSUER_ID }}"
build-android:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')
steps:
- uses: actions/checkout@v3
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Setup Java
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '11'
- name: Install dependencies
run: npm ci
- name: Setup keystore
env:
KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
run: |
echo "$KEYSTORE_BASE64" | base64 --decode > android/app/release.keystore
echo "MATERNAL_RELEASE_STORE_FILE=release.keystore" >> android/gradle.properties
echo "MATERNAL_RELEASE_KEY_ALIAS=${{ secrets.ANDROID_KEY_ALIAS }}" >> android/gradle.properties
echo "MATERNAL_RELEASE_STORE_PASSWORD=${{ secrets.ANDROID_STORE_PASSWORD }}" >> android/gradle.properties
echo "MATERNAL_RELEASE_KEY_PASSWORD=${{ secrets.ANDROID_KEY_PASSWORD }}" >> android/gradle.properties
- name: Build APK
run: |
cd android
./gradlew assembleRelease
- name: Build AAB
run: |
cd android
./gradlew bundleRelease
- name: Upload to Play Store
uses: r0adkll/upload-google-play@v1
with:
serviceAccountJsonPlainText: ${{ secrets.PLAY_SERVICE_ACCOUNT_JSON }}
packageName: com.maternalapp.android
releaseFiles: android/app/build/outputs/bundle/release/app-release.aab
track: internal
status: draft
TestFlight Configuration
App Store Connect Setup
// ios/fastlane/metadata/en-US/description.txt
Maternal is your AI-powered parenting companion, designed to reduce mental load and bring confidence to your parenting journey.
Key Features:
• Smart activity tracking with voice input
• AI assistant available 24/7 for parenting questions
• Real-time family synchronization
• Sleep predictions based on your baby's patterns
• Growth tracking with WHO percentiles
// ios/fastlane/metadata/en-US/keywords.txt
parenting,baby tracker,sleep tracking,feeding log,AI assistant,family app,childcare
Beta Testing Groups
# TestFlight Groups
internal_testing:
name: "Internal Team"
members: 10
builds: all
beta_families:
name: "Beta Families"
members: 50
builds: stable
feedback: enabled
early_access:
name: "Early Access"
members: 500
builds: release_candidate
Google Play Console Configuration
Store Listing
# Play Console Setup
app_details:
title: "Maternal - AI Parenting Assistant"
short_description: "Smart parenting companion with AI support"
full_description: |
Complete description...
category: "Parenting"
content_rating: "Everyone"
graphics:
icon: 512x512px
feature_graphic: 1024x500px
screenshots:
phone: [6 images minimum]
tablet: [optional]
Release Tracks
internal_testing:
testers: "internal-testers@maternalapp.com"
release_frequency: "daily"
closed_testing:
testers: 100
release_frequency: "weekly"
open_testing:
countries: ["US", "CA", "GB", "AU"]
release_frequency: "bi-weekly"
production:
rollout_percentage: 10 # Start with 10%
staged_rollout: true
Over-the-Air Updates
CodePush Setup
# Install CodePush
npm install react-native-code-push
# iOS setup
cd ios && pod install
# Register app with CodePush
code-push app add Maternal-iOS ios react-native
code-push app add Maternal-Android android react-native
Update Configuration
// App.js
import CodePush from 'react-native-code-push';
const codePushOptions = {
checkFrequency: CodePush.CheckFrequency.ON_APP_RESUME,
installMode: CodePush.InstallMode.ON_NEXT_RESTART,
mandatoryInstallMode: CodePush.InstallMode.IMMEDIATE,
updateDialog: {
title: 'Update Available',
mandatoryUpdateMessage: 'An important update is available.',
optionalUpdateMessage: 'An update is available. Would you like to install it?',
},
};
export default CodePush(codePushOptions)(App);
Deployment Commands
# Deploy update to staging
code-push release-react Maternal-iOS ios -d Staging
code-push release-react Maternal-Android android -d Staging
# Promote to production
code-push promote Maternal-iOS Staging Production -r 10%
code-push promote Maternal-Android Staging Production -r 10%
Performance Monitoring
Build Size Optimization
// metro.config.js
module.exports = {
transformer: {
minifierConfig: {
keep_fnames: true,
mangle: {
keep_fnames: true,
},
},
},
};
Bundle Analysis
# Analyze bundle size
npx react-native-bundle-visualizer
# iOS specific
npx react-native bundle --platform ios --dev false --entry-file index.js --bundle-output ios/main.jsbundle --assets-dest ios
# Android specific
cd android && ./gradlew bundleRelease --scan
Pre-Launch Checklist
iOS Submission
- TestFlight build approved
- App Store screenshots (6.5", 5.5")
- App preview video (optional)
- Privacy policy URL
- Support URL
- Marketing URL
- Age rating questionnaire
- Export compliance
- App Review notes
Android Submission
- Signed AAB uploaded
- Store listing complete
- Content rating questionnaire
- Target audience declaration
- Data safety form
- Privacy policy URL
- App category selected
- Closed testing feedback addressed
General Requirements
- COPPA compliance verified
- GDPR compliance documented
- Terms of service updated
- Support system ready
- Analytics tracking verified
- Crash reporting active
- Performance benchmarks met
- Accessibility tested