# Building TimeSafari This guide explains how to build TimeSafari for different platforms using the comprehensive build system. ## Prerequisites - Node.js 18+ and npm - Git - For mobile builds: Xcode (macOS) or Android Studio - For desktop builds: Additional build tools based on your OS ## Forks If you have forked this to make your own app, you'll want to customize the iOS & Android files. You can either edit existing ones, or you can remove the `ios` and `android` directories and regenerate them before the `npx cap sync` step in each setup. ```bash npx cap add android npx cap add ios ``` You'll also want to edit the deep link configuration (see below). ## Initial Setup Install dependencies: ```bash npm install ``` ## Web Development ### Local Development ```bash npm run dev ``` ### Web Build for Server 1. Run the production build: ```bash rm -rf dist npm run build:web ``` The built files will be in the `dist` directory. 2. To test the production build locally: You'll likely want to use test locations for the Endorser & image & partner servers; see "DEFAULT_ENDORSER_API_SERVER" & "DEFAULT_IMAGE_API_SERVER" & "DEFAULT_PARTNER_API_SERVER" below. ```bash npm run serve ``` ### Web Build Commands ```bash # Development builds npm run build:web:dev # Development build with hot reload npm run build:web:test # Test environment build npm run build:web:prod # Production build npm run build:web:serve # Production build with serve # Docker builds npm run build:web:docker # Docker development build npm run build:web:docker:test # Docker test build npm run build:web:docker:prod # Docker production build ``` ### Web Build Script Details All web build commands use the `./scripts/build-web.sh` script, which provides: **Build Modes:** - **Development**: Starts Vite dev server with hot reload (default) - **Test**: Optimized for testing with minimal minification - **Production**: Optimized for production with full minification **Script Features:** - **Environment Validation**: Checks for Node.js, npm, npx, package.json - **Environment Setup**: Loads `.env` files based on build mode - **Clean Build**: Removes previous `dist/` directory - **Vite Build**: Executes `npx vite build --config vite.config.web.mts` - **Docker Support**: Optional Docker containerization - **Local Serving**: Built-in HTTP server for testing builds **Direct Script Usage:** ```bash # Direct script usage (no npm chaining) ./scripts/build-web.sh # Development build ./scripts/build-web.sh --dev # Development build (explicit) ./scripts/build-web.sh --test # Test environment build ./scripts/build-web.sh --prod # Production environment build ./scripts/build-web.sh --docker # Build with Docker containerization ./scripts/build-web.sh --docker:test # Test environment + Docker ./scripts/build-web.sh --docker:prod # Production environment + Docker ./scripts/build-web.sh --serve # Build and serve locally ./scripts/build-web.sh --help # Show help ./scripts/build-web.sh --verbose # Enable verbose logging ``` **Script Flow:** 1. **Environment Validation**: Check prerequisites (Node.js, npm, etc.) 2. **Environment Setup**: Load `.env` files, set NODE_ENV 3. **Clean Dist**: Remove previous build artifacts 4. **Vite Build**: Execute Vite with appropriate configuration 5. **Optional Docker**: Build Docker container if requested 6. **Optional Serve**: Start local HTTP server if requested **Exit Codes:** - `1` - Web cleanup failed - `2` - Environment setup failed - `3` - Vite build failed - `4` - Docker build failed - `5` - Serve command failed - `6` - Invalid build mode ### Compile and minify for test & production * If there are DB changes: before updating the test server, open browser(s) with current version to test DB migrations. * Update the ClickUp tasks & CHANGELOG.md & the version in package.json, run `npm install`. * Run a build to make sure package-lock version is updated, linting works, etc: `npm install && npm run build` * Commit everything (since the commit hash is used the app). * Put the commit hash in the changelog (which will help you remember to bump the version in the step later). * Tag with the new version, [online](https://gitea.anomalistdesign.com/trent_larson/crowd-funder-for-time-pwa/releases) or `git tag 1.0.2 && git push origin 1.0.2`. * For test, build the app (because test server is not yet set up to build): ```bash TIME_SAFARI_APP_TITLE="TimeSafari_Test" \ VITE_APP_SERVER=https://test.timesafari.app \ VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F \ VITE_DEFAULT_ENDORSER_API_SERVER=https://test-api.endorser.ch \ VITE_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app \ VITE_DEFAULT_PARTNER_API_SERVER=https://test-partner-api.endorser.ch \ VITE_DEFAULT_PUSH_SERVER=https://test.timesafari.app \ VITE_PASSKEYS_ENABLED=true npm run build:web ``` ... and transfer to the test server: ```bash rsync -azvu -e "ssh -i ~/.ssh/..." dist ubuntutest@test.timesafari.app:time-safari ``` (Let's replace that with a .env.development or .env.test file.) (Note: The test BVC_MEETUPS_PROJECT_CLAIM_ID does not resolve as a URL because it's only in the test DB and the prod redirect won't redirect there.) * For prod, get on the server and run the correct build: ... and log onto the server: * `pkgx +npm sh` * `cd crowd-funder-for-time-pwa && git checkout master && git pull && git checkout 1.0.2 && npm install && npm run build:web && cd -` (The plain `npm run build:web` uses the .env.production file.) * Back up the time-safari/dist folder & deploy: `mv time-safari/dist time-safari-dist-prev-2 && mv crowd-funder-for-time-pwa/dist time-safari/` * Record the new hash in the changelog. Edit package.json to increment version & add "-beta", `npm install`, commit, and push. Also record what version is on production. ## Docker Deployment The application can be containerized using Docker for consistent deployment across environments. ### Prerequisites - Docker installed on your system - Docker Compose (optional, for multi-container setups) ### Building the Docker Image 1. Build the Docker image: ```bash docker build -t timesafari:latest . ``` 2. For development builds with specific environment variables: ```bash docker build --build-arg NODE_ENV=development -t timesafari:dev . ``` ### Running the Container 1. Run the container: ```bash docker run -d -p 80:80 timesafari:latest ``` 2. For development with hot-reloading: ```bash docker run -d -p 80:80 -v $(pwd):/app timesafari:dev ``` ### Using Docker Compose Create a `docker-compose.yml` file: ```yaml version: '3.8' services: timesafari: build: . ports: - "80:80" environment: - NODE_ENV=production restart: unless-stopped ``` Run with Docker Compose: ```bash docker-compose up -d ``` ### Docker Commands ```bash # Docker operations npm run docker:up # Start Docker services npm run docker:up:test # Start test environment npm run docker:up:prod # Start production environment npm run docker:down # Stop Docker services npm run docker:logs # View logs ``` ### Production Deployment For production deployment, consider the following: 1. Use specific version tags instead of 'latest' 2. Implement health checks 3. Configure proper logging 4. Set up reverse proxy with SSL termination 5. Use Docker secrets for sensitive data Example production deployment: ```bash # Build with specific version docker build -t timesafari:1.0.0 . # Run with production settings docker run -d \ --name timesafari \ -p 80:80 \ --restart unless-stopped \ -e NODE_ENV=production \ timesafari:1.0.0 ``` ### Troubleshooting Docker 1. **Container fails to start** - Check logs: `docker logs ` - Verify port availability - Check environment variables 2. **Build fails** - Ensure all dependencies are in package.json - Check Dockerfile syntax - Verify build context 3. **Performance issues** - Monitor container resources: `docker stats` - Check nginx configuration - Verify caching settings ## Desktop Build (Electron) TimeSafari's Electron build system provides comprehensive desktop application packaging and distribution capabilities across Windows, macOS, and Linux platforms. The system supports multiple build modes, environment configurations, and package formats. ### Quick Start #### Development Build ```bash # Start development build (runs app) npm run build:electron:dev # Development build only npm run build:electron --dev ``` #### Production Build ```bash # Production build for all platforms npm run build:electron:prod # Platform-specific production builds npm run build:electron:windows:prod npm run build:electron:mac:prod npm run build:electron:linux:prod ``` #### Package-Specific Builds ```bash # AppImage for Linux npm run build:electron:appimage:prod # DEB package for Debian/Ubuntu npm run build:electron:deb:prod # DMG for macOS npm run build:electron:dmg:prod ``` ### Single Instance Enforcement The Electron app enforces single-instance operation to prevent: - Database corruption from multiple instances - Resource conflicts and performance issues - User confusion from multiple windows **Behavior:** - Only one instance can run at a time - Attempting to launch a second instance shows a user-friendly dialog - The existing window is focused and restored if minimized - Second instance exits gracefully **Implementation:** - Uses Electron's `requestSingleInstanceLock()` API - Handles `second-instance` events to focus existing window - Shows informative dialog explaining why only one instance is allowed #### Direct Script Usage ```bash # Direct script usage (no npm chaining) ./scripts/build-electron.sh --dev # Development build ./scripts/build-electron.sh --test # Test build ./scripts/build-electron.sh --prod # Production build ./scripts/build-electron.sh --prod --windows # Windows production ./scripts/build-electron.sh --test --appimage # Linux AppImage test ./scripts/build-electron.sh --dev --mac # macOS development ./scripts/build-electron.sh --prod --dmg # macOS DMG production ``` ### Build Architecture The Electron build process follows a multi-stage approach: ``` 1. Web Build (Vite) → 2. Capacitor Sync → 3. TypeScript Compile → 4. Package ``` **Stage 1: Web Build** - Vite builds web assets with Electron-specific configuration - Environment variables loaded based on build mode - Assets optimized for desktop application **Stage 2: Capacitor Sync** - Copies web assets to Electron app directory - Syncs Capacitor configuration and plugins - Prepares native module bindings **Stage 3: TypeScript Compile** - Compiles Electron main process TypeScript - Rebuilds native modules for target platform - Generates production-ready JavaScript **Stage 4: Package Creation** - Creates platform-specific installers - Generates distribution packages - Signs applications (when configured) ### Build Modes #### Development Mode **Purpose**: Local development and testing **Command**: `npm run build:electron:dev` **Features**: - Hot reload enabled - Debug tools available - Development logging - Unoptimized assets #### Testing Mode **Purpose**: Staging and testing environments **Command**: `npm run build:electron -- --mode test` **Features**: - Test API endpoints - Staging configurations - Optimized for testing - Debug information available #### Production Mode **Purpose**: Production deployment **Command**: `npm run build:electron -- --mode production` **Features**: - Production optimizations - Code minification - Security hardening - Performance optimizations ### Platform-Specific Builds #### Windows Builds **Target Platforms**: Windows 10/11 (x64) **Package Formats**: NSIS installer, portable executable ```bash # Windows development build npm run build:electron:windows:dev # Windows test build npm run build:electron:windows:test # Windows production build npm run build:electron:windows:prod ``` **Configuration**: - NSIS installer with custom options - Desktop and Start Menu shortcuts - Elevation permissions for installation - Custom installation directory support #### macOS Builds **Target Platforms**: macOS 10.15+ (x64, arm64) **Package Formats**: DMG installer, app bundle ```bash # macOS development build npm run build:electron:mac:dev # macOS test build npm run build:electron:mac:test # macOS production build npm run build:electron:mac:prod ``` **Configuration**: - Universal binary (x64 + arm64) - DMG installer with custom branding - App Store compliance (when configured) - Code signing support #### Linux Builds **Target Platforms**: Ubuntu 18.04+, Debian 10+, Arch Linux **Package Formats**: AppImage, DEB, RPM ```bash # Linux development build npm run build:electron:linux:dev # Linux test build npm run build:electron:linux:test # Linux production build npm run build:electron:linux:prod ``` **Configuration**: - AppImage for universal distribution - DEB package for Debian-based systems - RPM package for Red Hat-based systems - Desktop integration ### Package-Specific Builds #### AppImage Package **Format**: Self-contained Linux executable **Distribution**: Universal Linux distribution ```bash # AppImage development build npm run build:electron:appimage:dev # AppImage test build npm run build:electron:appimage:test # AppImage production build npm run build:electron:appimage:prod ``` **Features**: - Single file distribution - No installation required - Portable across Linux distributions - Automatic updates support #### DEB Package **Format**: Debian package installer **Distribution**: Debian-based Linux systems ```bash # DEB development build npm run build:electron:deb:dev # DEB test build npm run build:electron:deb:test # DEB production build npm run build:electron:deb:prod ``` **Features**: - Native package management - Dependency resolution - System integration - Easy installation/uninstallation #### DMG Package **Format**: macOS disk image **Distribution**: macOS systems ```bash # DMG development build npm run build:electron:dmg:dev # DMG test build npm run build:electron:dmg:test # DMG production build npm run build:electron:dmg:prod ``` **Features**: - Native macOS installer - Custom branding and layout - Drag-and-drop installation - Code signing support ### Build Scripts Reference #### Main Build Scripts ```bash # Development builds npm run build:electron:dev # Development build and run npm run build:electron --dev # Development build only # Testing builds npm run build:electron:test # Test environment build # Production builds npm run build:electron:prod # Production environment build ``` #### Platform-Specific Scripts ```bash # Windows builds npm run build:electron:windows # Windows production build npm run build:electron:windows:dev # Windows development build npm run build:electron:windows:test # Windows test build npm run build:electron:windows:prod # Windows production build # macOS builds npm run build:electron:mac # macOS production build npm run build:electron:mac:dev # macOS development build npm run build:electron:mac:test # macOS test build npm run build:electron:mac:prod # macOS production build # Linux builds npm run build:electron:linux # Linux production build npm run build:electron:linux:dev # Linux development build npm run build:electron:linux:test # Linux test build npm run build:electron:linux:prod # Linux production build ``` #### Package-Specific Scripts ```bash # AppImage builds npm run build:electron:appimage # Linux AppImage production build npm run build:electron:appimage:dev # AppImage development build npm run build:electron:appimage:test # AppImage test build npm run build:electron:appimage:prod # AppImage production build # DEB builds npm run build:electron:deb # Debian package production build npm run build:electron:deb:dev # DEB development build npm run build:electron:deb:test # DEB test build npm run build:electron:deb:prod # DEB production build # DMG builds npm run build:electron:dmg # macOS DMG production build npm run build:electron:dmg:dev # DMG development build npm run build:electron:dmg:test # DMG test build npm run build:electron:dmg:prod # DMG production build ``` #### Direct Script Usage All npm scripts use the underlying `./scripts/build-electron.sh` script: ```bash # Direct script usage examples ./scripts/build-electron.sh --dev # Development build ./scripts/build-electron.sh --test # Test build ./scripts/build-electron.sh --prod # Production build ./scripts/build-electron.sh --prod --windows # Windows production ./scripts/build-electron.sh --test --appimage # Linux AppImage test ./scripts/build-electron.sh --dev --mac # macOS development ./scripts/build-electron.sh --prod --dmg # macOS DMG production ``` #### Utility Scripts ```bash # Cleanup scripts npm run clean:electron # Clean Electron build artifacts # Development scripts npm run electron:dev # Start development server npm run electron:dev-full # Full development workflow npm run electron:setup # Setup Electron environment ``` ### Build Output Structure #### Development Build ``` electron/ ├── app/ # Web assets ├── build/ # Compiled TypeScript ├── dist/ # Build artifacts (empty in dev) └── node_modules/ # Dependencies ``` #### Production Build ``` electron/ ├── app/ # Web assets ├── build/ # Compiled TypeScript ├── dist/ # Distribution packages │ ├── TimeSafari.exe # Windows executable │ ├── TimeSafari.dmg # macOS installer │ ├── TimeSafari.AppImage # Linux AppImage │ └── TimeSafari.deb # Debian package └── node_modules/ # Dependencies ``` ### Code Signing and Notarization #### macOS Code Signing For public distribution on macOS, you need to code sign and notarize your app: 1. Set up environment variables: ```bash export CSC_LINK=/path/to/your/certificate.p12 export CSC_KEY_PASSWORD=your_certificate_password export APPLE_ID=your_apple_id export APPLE_ID_PASSWORD=your_app_specific_password ``` 2. Build with signing: ```bash npm run build:electron:mac:prod ``` #### Windows Code Signing For Windows distribution, configure Authenticode signing: 1. Set up environment variables: ```bash export CSC_LINK=/path/to/your/certificate.p12 export CSC_KEY_PASSWORD=your_certificate_password ``` 2. Build with signing: ```bash npm run build:electron:windows:prod ``` ### Running the Packaged App #### Linux - **AppImage**: Make executable and run ```bash chmod +x electron/dist/TimeSafari-*.AppImage ./electron/dist/TimeSafari-*.AppImage ``` - **DEB**: Install and run ```bash sudo dpkg -i electron/dist/timesafari_*_amd64.deb timesafari ``` #### macOS - **`.app` bundle**: Double-click `TimeSafari.app` in Finder - **`.dmg` installer**: 1. Double-click the `.dmg` file 2. Drag the app to your Applications folder 3. Launch from Applications Note: If you get a security warning when running the app: 1. Right-click the app 2. Select "Open" 3. Click "Open" in the security dialog #### Windows - **NSIS installer**: Run the `.exe` installer and follow the setup wizard - **Portable**: Extract and run the portable executable ### Troubleshooting #### Common Build Issues **TypeScript Compilation Errors**: ```bash # Clean and rebuild npm run clean:electron cd electron && npm run build ``` **Native Module Issues**: ```bash # Rebuild native modules cd electron && npm run build ``` **Asset Copy Issues**: ```bash # Verify Capacitor sync npx cap sync electron ``` #### Platform-Specific Issues **Windows**: - Ensure Windows Build Tools installed - Check NSIS installation - Verify code signing certificates **macOS**: - Install Xcode Command Line Tools - Configure code signing certificates - Check app notarization requirements **Linux**: - Install required packages (rpm-tools, etc.) - Check AppImage dependencies - Verify desktop integration ### Performance Optimization #### Build Performance - Use concurrent TypeScript compilation - Optimize asset copying - Minimize file system operations - Cache node_modules between builds #### Runtime Performance - Optimize main process initialization - Minimize startup dependencies - Use lazy loading for features - Monitor memory usage and implement proper cleanup ### Security Considerations #### Production Builds - Disable developer tools - Remove debug information - Enable security policies - Implement sandboxing #### Update Security - Secure update channels - Package integrity verification - Rollback capabilities For detailed documentation, see [docs/electron-build-patterns.md](docs/electron-build-patterns.md). ## Mobile Builds (Capacitor) ### iOS Build Prerequisites: macOS with Xcode installed #### Automated Build Script The recommended way to build for iOS is using the automated build script: ```bash # Standard build and open Xcode ./scripts/build-ios.sh # Build with specific version numbers ./scripts/build-ios.sh --version 1.0.3 --build-number 35 # Build without opening Xcode (for CI/CD) ./scripts/build-ios.sh --no-xcode # Show all available options ./scripts/build-ios.sh --help ``` The script handles all the necessary steps including: - Environment setup and validation - Web asset building - Capacitor synchronization - iOS asset generation - Version number updates - Xcode project opening #### iOS Build Commands ```bash # Standard builds npm run build:ios # Standard build and open Xcode npm run build:ios:dev # Development build npm run build:ios:test # Test build npm run build:ios:prod # Production build # Auto-run builds npm run build:ios:test:run # Test build with auto-run npm run build:ios:prod:run # Production build with auto-run # Debug and release builds npm run build:ios:debug # Debug build npm run build:ios:debug:run # Debug build with auto-run npm run build:ios:release # Release build npm run build:ios:release:run # Release build with auto-run # Additional operations npm run build:ios:studio # Open in Xcode Studio npm run build:ios:ipa # Generate IPA file npm run build:ios:clean # Clean build artifacts npm run build:ios:sync # Sync Capacitor npm run build:ios:assets # Generate assets npm run build:ios:deploy # Deploy to device/simulator ``` #### Manual Build Process If you need to build manually or want to understand the individual steps: #### First-time iOS Configuration - Generate certificates inside XCode. - Right-click on App and under Signing & Capabilities set the Team. #### Each Release 0. First time (or if dependencies change): - `pkgx +rubygems.org sh` - ... and you may have to fix these, especially with pkgx: ```bash gem_path=$(which gem) shortened_path="${gem_path:h:h}" export GEM_HOME=$shortened_path export GEM_PATH=$shortened_path ``` 1. Build the web assets & update ios: ```bash rm -rf dist npm run build:web npm run build:capacitor npx cap sync ios ``` - If that fails with "Could not find..." then look at the "gem_path" instructions above. 3. Copy the assets: ```bash # It makes no sense why capacitor-assets will not run without these but it actually changes the contents. mkdir -p ios/App/App/Assets.xcassets/AppIcon.appiconset echo '{"images":[]}' > ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json mkdir -p ios/App/App/Assets.xcassets/Splash.imageset echo '{"images":[]}' > ios/App/App/Assets.xcassets/Splash.imageset/Contents.json npx capacitor-assets generate --ios ``` 4. Bump the version to match Android & package.json: ``` cd ios/App && xcrun agvtool new-version 35 && perl -p -i -e "s/MARKETING_VERSION = .*;/MARKETING_VERSION = 1.0.2;/g" App.xcodeproj/project.pbxproj && cd - # Unfortunately this edits Info.plist directly. #xcrun agvtool new-marketing-version 0.4.5 ``` 5. Open the project in Xcode: ```bash npx cap open ios ``` 6. Use Xcode to build and run on simulator or device. * Select Product -> Destination with some Simulator version. Then click the run arrow. 7. Release * Someday: Under "General" we want to rename a bunch of things to "Time Safari" * Choose Product -> Destination -> Any iOS Device * Choose Product -> Archive * This will trigger a build and take time, needing user's "login" keychain password (user's login password), repeatedly. * If it fails with `building for 'iOS', but linking in dylib (.../.pkgx/zlib.net/v1.3.0/lib/libz.1.3.dylib) built for 'macOS'` then run XCode outside that terminal (ie. not with `npx cap open ios`). * Click Distribute -> App Store Connect * In AppStoreConnect, add the build to the distribution: remove the current build with the "-" when you hover over it, then "Add Build" with the new build. * May have to go to App Review, click Submission, then hover over the build and click "-". * It can take 15 minutes for the build to show up in the list of builds. * You'll probably have to "Manage" something about encryption, disallowed in France. * Then "Save" and "Add to Review" and "Resubmit to App Review". ### Android Build Prerequisites: Android Studio with Java SDK installed #### Automated Build Script The recommended way to build for Android is using the automated build script: ```bash # Standard build and open Android Studio ./scripts/build-android.sh # Build with specific version numbers ./scripts/build-android.sh --version 1.0.3 --build-number 35 # Build without opening Android Studio (for CI/CD) ./scripts/build-android.sh --no-studio # Show all available options ./scripts/build-android.sh --help ``` #### Android Build Commands ```bash # Standard builds npm run build:android # Standard build and open Android Studio npm run build:android:dev # Development build npm run build:android:test # Test build npm run build:android:prod # Production build # Auto-run builds npm run build:android:test:run # Test build with auto-run npm run build:android:prod:run # Production build with auto-run # Debug and release builds npm run build:android:debug # Debug build npm run build:android:debug:run # Debug build with auto-run npm run build:android:release # Release build npm run build:android:release:run # Release build with auto-run # Additional operations npm run build:android:studio # Open in Android Studio npm run build:android:apk # Generate APK npm run build:android:aab # Generate AAB (App Bundle) npm run build:android:clean # Clean build artifacts npm run build:android:sync # Sync Capacitor npm run build:android:assets # Generate assets npm run build:android:deploy # Deploy to device/emulator ``` #### Manual Build Process 1. Build the web assets: ```bash rm -rf dist npm run build:web npm run build:capacitor ``` 2. Update Android project with latest build: ```bash npx cap sync android ``` 3. Copy the assets ```bash npx capacitor-assets generate --android ``` 4. Bump version to match iOS & package.json: android/app/build.gradle 5. Open the project in Android Studio: ```bash npx cap open android ``` 6. Use Android Studio to build and run on emulator or device. ## Android Build from the console ```bash cd android ./gradlew clean ./gradlew build -Dlint.baselines.continue=true cd - ``` ... or, to create the `aab` file, `bundle` instead of `build`: ```bash ./gradlew bundleDebug -Dlint.baselines.continue=true ``` ... or, to create a signed release: * Setup by adding the app/gradle.properties.secrets file (see properties at top of app/build.gradle) and the app/time-safari-upload-key-pkcs12.jks file * In app/build.gradle, bump the versionCode and maybe the versionName * Then `bundleRelease`: ```bash cd android ./gradlew bundleRelease -Dlint.baselines.continue=true cd - ``` ... and find your `aab` file at app/build/outputs/bundle/release At play.google.com/console: - Go to the Testing Track (eg. Closed). - Click "Create new release". - Upload the `aab` file. - Hit "Next". - Save, go to "Publishing Overview" as prompted, and click "Send changes for review". - Note that if you add testers, you have to go to "Publishing Overview" and send those changes or your (closed) testers won't see it. ### Capacitor Operations ```bash # Build Capacitor assets npm run build:capacitor # Sync Capacitor npm run build:capacitor:sync ``` ## Testing ### Web Testing ```bash # Run web tests npm run test:web ``` ### Mobile Testing ```bash # Run mobile tests npm run test:mobile # Android tests npm run test:android # iOS tests npm run test:ios ``` ### Device Checks ```bash # Check Android device connection npm run check:android-device # Check iOS device/simulator npm run check:ios-device ``` ### Test Prerequisites ```bash # Test prerequisites npm run test:prerequisites ``` ## Auto-Run System The auto-run system provides automated development workflows: ```bash # Auto-run with default settings npm run auto-run # Auto-run test environment npm run auto-run:test # Auto-run production environment npm run auto-run:prod # Platform-specific auto-run npm run auto-run:ios npm run auto-run:android npm run auto-run:electron ``` ## Cleaning ```bash # Clean Android npm run clean:android # Clean iOS npm run clean:ios # Clean Electron npm run clean:electron ``` ## Fastlane Integration ### iOS Fastlane ```bash # Beta release npm run fastlane:ios:beta # App Store release npm run fastlane:ios:release ``` ### Android Fastlane ```bash # Beta release npm run fastlane:android:beta # Play Store release npm run fastlane:android:release ``` ## Code Quality ```bash # Lint code npm run lint # Fix linting issues npm run lint-fix ``` ## Build Architecture ### Web Build Process 1. **Environment Setup**: Load platform-specific environment variables 2. **Asset Building**: Vite builds optimized web assets 3. **PWA Generation**: Service worker and manifest creation 4. **Output**: Production-ready files in `dist/` directory ### Electron Build Process 1. **Web Build**: Vite builds web assets for Electron 2. **Capacitor Sync**: Copies assets to Electron app directory 3. **TypeScript Compile**: Compiles main process code 4. **Native Module Rebuild**: Rebuilds native dependencies 5. **Package Creation**: Generates platform-specific installers ### Mobile Build Process 1. **Web Build**: Vite builds web assets 2. **Capacitor Sync**: Syncs with native platforms 3. **Asset Generation**: Creates platform-specific assets 4. **Native Build**: Platform-specific compilation 5. **Package Creation**: APK/IPA generation ## Environment Configuration ### Environment Files - `.env.development` - Development environment - `.env.test` - Testing environment - `.env.production` - Production environment ### Key Environment Variables ```bash # API Servers VITE_DEFAULT_ENDORSER_API_SERVER=https://api.endorser.ch VITE_DEFAULT_IMAGE_API_SERVER=https://image-api.timesafari.app VITE_DEFAULT_PARTNER_API_SERVER=https://partner-api.endorser.ch # Platform Configuration VITE_PLATFORM=web|electron|capacitor VITE_APP_SERVER=https://timesafari.app # Feature Flags VITE_PASSKEYS_ENABLED=true ``` ## Android Configuration for deep links You must add the following intent filter to the `android/app/src/main/AndroidManifest.xml` file: ```xml ``` ... though when we tried that most recently it failed to 'build' the APK with: http(s) scheme and host attribute are missing, but are required for Android App Links [AppLinkUrlError] ## Troubleshooting ### Common Issues #### Build Failures ```bash # Clean and rebuild npm run clean:electron npm run build:electron:dev ``` #### Native Module Issues ```bash # Rebuild native modules cd electron && npm run build ``` #### Asset Issues ```bash # Regenerate assets npm run build:ios:assets npm run build:android:assets ``` ### Platform-Specific Issues #### Windows - Ensure Windows Build Tools installed - Check NSIS installation - Verify code signing certificates #### macOS - Install Xcode Command Line Tools - Configure code signing certificates - Check app notarization requirements #### Linux - Install required packages (rpm-tools, etc.) - Check AppImage dependencies - Verify desktop integration #### iOS - Install Xcode and Command Line Tools - Configure signing certificates - Check provisioning profiles #### Android - Install Android Studio and SDK - Configure signing keys - Check device/emulator setup ## Additional Resources - [Electron Build Patterns](docs/electron-build-patterns.md) - [iOS Build Scripts](docs/ios-build-scripts.md) - [Android Build Scripts](docs/android-build-scripts.md) - [Web Build Scripts](docs/web-build-scripts.md) - [Build Troubleshooting](docs/build-troubleshooting.md) --- ## Appendix: Build System Organization ### Build Process Overview TimeSafari's build system follows a multi-stage process that prepares assets, combines scripts, and generates platform-specific outputs. #### Pre-Build Preparation **1. Service Worker Script Preparation** ```bash # Optional: Format third-party service worker scripts npx prettier --write ./sw_scripts/ ``` **What this does:** - Formats cryptographic libraries (`nacl.js`, `noble-curves.js`, `noble-hashes.js`, etc.) - These scripts are automatically combined during the build process - Improves readability and makes version control diffs cleaner - **Note**: This is optional and only needed when updating third-party scripts **2. Automatic Pre-Build Steps** The `prebuild` script automatically runs before any build: ```json "prebuild": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src && node sw_combine.js && node scripts/copy-wasm.js" ``` **What happens automatically:** - **ESLint**: Checks and fixes code formatting in `src/` - **Script Combination**: `sw_combine.js` combines all `sw_scripts/*.js` files into `sw_scripts-combined.js` - **WASM Copy**: `copy-wasm.js` copies SQLite WASM files to `public/wasm/` #### Build Architecture **Web Build Process:** ``` 1. Pre-Build: ESLint + Script Combination + WASM Copy 2. Environment Setup: Load .env files, set NODE_ENV 3. Vite Build: Bundle web assets with PWA support 4. Service Worker: Inject combined scripts into PWA 5. Output: Production-ready files in dist/ ``` **Electron Build Process:** ``` 1. Web Build: Vite builds web assets for Electron 2. Capacitor Sync: Copies assets to Electron app directory 3. TypeScript Compile: Compiles main process code 4. Native Module Rebuild: Rebuilds native dependencies 5. Package Creation: Generates platform-specific installers ``` **Mobile Build Process:** ``` 1. Web Build: Vite builds web assets 2. Capacitor Sync: Syncs with native platforms 3. Asset Generation: Creates platform-specific assets 4. Native Build: Platform-specific compilation 5. Package Creation: APK/IPA generation ``` #### Service Worker Architecture **Script Organization:** - `sw_scripts/` - Individual third-party scripts - `sw_combine.js` - Combines scripts into single file - `sw_scripts-combined.js` - Combined service worker (317KB, 10K+ lines) - `vite.config.utils.mts` - PWA configuration using combined script **PWA Integration:** ```typescript // vite.config.utils.mts pwaConfig: { strategies: "injectManifest", filename: "sw_scripts-combined.js", // Uses our combined script // ... manifest configuration } ``` **What Gets Combined:** - `nacl.js` - NaCl cryptographic library - `noble-curves.js` - Elliptic curve cryptography (177KB) - `noble-hashes.js` - Cryptographic hash functions (91KB) - `safari-notifications.js` - Safari-specific notifications - `additional-scripts.js` - Additional service worker functionality #### Environment Configuration **Environment Files:** - `.env.development` - Development environment - `.env.test` - Testing environment - `.env.production` - Production environment **Key Environment Variables:** ```bash # API Servers VITE_DEFAULT_ENDORSER_API_SERVER=https://api.endorser.ch VITE_DEFAULT_IMAGE_API_SERVER=https://image-api.timesafari.app VITE_DEFAULT_PARTNER_API_SERVER=https://partner-api.endorser.ch # Platform Configuration VITE_PLATFORM=web|electron|capacitor VITE_APP_SERVER=https://timesafari.app # Feature Flags VITE_PASSKEYS_ENABLED=true ``` #### Build Output Structure **Web Build:** ``` dist/ ├── index.html # Main HTML file ├── assets/ # Bundled JavaScript/CSS ├── sw.js # Service worker (injected) ├── manifest.webmanifest # PWA manifest └── wasm/ # SQLite WASM files ``` **Electron Build:** ``` electron/ ├── app/ # Web assets ├── build/ # Compiled TypeScript ├── dist/ # Distribution packages │ ├── TimeSafari.exe # Windows executable │ ├── TimeSafari.dmg # macOS installer │ ├── TimeSafari.AppImage # Linux AppImage │ └── TimeSafari.deb # Debian package └── node_modules/ # Dependencies ``` #### Manual vs Automatic Steps **Manual Steps (Developer Responsibility):** - Database migration testing - Service worker script formatting (optional) - Version updates and changelog - Environment-specific builds **Automatic Steps (Build System):** - Code linting and formatting - Script combination - Asset optimization - Package creation - Service worker injection This architecture ensures consistent builds across all platforms while providing flexibility for platform-specific optimizations and manual quality assurance steps. --- ## Appendix A: Build Scripts Reference This appendix provides detailed documentation for all build scripts in the `scripts/` directory. ### A.1 build-web.sh **File**: `scripts/build-web.sh` **Author**: Matthew Raymer **Description**: Web build script for TimeSafari application **Purpose**: Handles the complete web build process including cleanup, environment setup, Vite build, and optional Docker containerization. **Usage**: ```bash # Direct script usage ./scripts/build-web.sh # Development build ./scripts/build-web.sh --dev # Development build (explicit) ./scripts/build-web.sh --test # Test environment build ./scripts/build-web.sh --prod # Production environment build ./scripts/build-web.sh --docker # Build with Docker containerization ./scripts/build-web.sh --docker:test # Test environment + Docker ./scripts/build-web.sh --docker:prod # Production environment + Docker ./scripts/build-web.sh --serve # Build and serve locally ./scripts/build-web.sh --help # Show help ./scripts/build-web.sh --verbose # Enable verbose logging # NPM Script Equivalents npm run build:web # Development build npm run build:web:test # Test environment build npm run build:web:prod # Production environment build npm run build:web:docker # Docker build npm run build:web:docker:test # Test Docker build npm run build:web:docker:prod # Production Docker build ``` **Build Modes**: - **Development**: Starts Vite dev server with hot reload (default) - **Test**: Optimized for testing with minimal minification - **Production**: Optimized for production with full minification **Script Features**: - **Environment Validation**: Checks for Node.js, npm, npx, package.json - **Environment Setup**: Loads `.env` files based on build mode - **Clean Build**: Removes previous `dist/` directory - **Vite Build**: Executes `npx vite build --config vite.config.web.mts` - **Docker Support**: Optional Docker containerization - **Local Serving**: Built-in HTTP server for testing builds **Exit Codes**: - `1` - Web cleanup failed - `2` - Environment setup failed - `3` - Vite build failed - `4` - Docker build failed - `5` - Serve command failed - `6` - Invalid build mode ### A.2 build-electron.sh **File**: `scripts/build-electron.sh` **Author**: Matthew Raymer **Description**: Clean, modular Electron build script for TimeSafari application **Purpose**: Handles Electron builds with proper separation of concerns and no command chaining, following DRY principles. **Usage**: ```bash # Direct script usage ./scripts/build-electron.sh # Development build (runs app) ./scripts/build-electron.sh --dev # Development build (runs app) ./scripts/build-electron.sh --test # Test environment build ./scripts/build-electron.sh --prod # Production environment build ./scripts/build-electron.sh --windows # Windows build ./scripts/build-electron.sh --mac # macOS build ./scripts/build-electron.sh --linux # Linux build ./scripts/build-electron.sh --appimage # Linux AppImage ./scripts/build-electron.sh --deb # Debian package ./scripts/build-electron.sh --dmg # macOS DMG ./scripts/build-electron.sh --help # Show help ./scripts/build-electron.sh --verbose # Enable verbose logging # Examples ./scripts/build-electron.sh --prod --windows # Windows production build ./scripts/build-electron.sh --test --appimage # Linux AppImage test build ./scripts/build-electron.sh --dev --mac # macOS development build ``` **Build Modes**: - **Development**: Development build (runs app) - **Test**: Test environment build - **Production**: Production environment build - **Clean**: Clean Electron build artifacts only **Platforms**: - **Windows**: Windows build - **macOS**: macOS build - **Linux**: Linux build **Packages**: - **AppImage**: Linux AppImage - **Deb**: Debian package - **DMG**: macOS DMG **Exit Codes**: - `1` - Invalid arguments - `2` - Electron cleanup failed - `3` - Web build failed - `4` - Capacitor sync failed - `5` - TypeScript compilation failed - `6` - Electron packaging failed - `7` - Asset generation failed - `8` - Electron app launch failed ### A.3 build-android.sh **File**: `scripts/build-android.sh` **Author**: Matthew Raymer **Date**: 2025-07-11 **Description**: Android build script for TimeSafari application **Purpose**: Handles the complete Android build process including cleanup, web build, Capacitor build, Gradle build, and Android Studio launch. **Usage**: ```bash # Direct script usage ./scripts/build-android.sh [options] # Options --dev, --development Build for development environment --test Build for testing environment --prod, --production Build for production environment --debug Build debug APK --release Build release APK --studio Open Android Studio after build --apk Build APK file --aab Build AAB (Android App Bundle) --clean Clean build artifacts only --sync Sync Capacitor only --assets Generate assets only --deploy Deploy APK to connected device -h, --help Show this help message -v, --verbose Enable verbose logging # Examples ./scripts/build-android.sh --dev --studio # Development build + open studio ./scripts/build-android.sh --prod --apk # Production APK build ./scripts/build-android.sh --test --aab # Testing AAB build ./scripts/build-android.sh --clean # Clean only ./scripts/build-android.sh --sync # Sync only ``` **Build Modes**: - **Development**: Build for development environment - **Test**: Build for testing environment - **Production**: Build for production environment **Build Types**: - **Debug**: Build debug APK (default) - **Release**: Build release APK **Exit Codes**: - `1` - Android cleanup failed - `2` - Web build failed - `3` - Capacitor build failed - `4` - Gradle clean failed - `5` - Gradle assemble failed - `6` - Capacitor sync failed - `7` - Asset generation failed - `8` - Android Studio launch failed - `9` - Resource check failed ### A.4 build-ios.sh **File**: `scripts/build-ios.sh` **Author**: Matthew Raymer **Date**: 2025-07-11 **Description**: iOS build script for TimeSafari application **Purpose**: Handles the complete iOS build process including cleanup, web build, Capacitor build, Xcode build, and iOS Simulator launch. **Usage**: ```bash # Direct script usage ./scripts/build-ios.sh [options] # Options --dev, --development Build for development environment --test Build for testing environment --prod, --production Build for production environment --debug Build debug app (default) --release Build release app --studio Open Xcode after build --ipa Build IPA file --app Build app bundle --clean Clean build artifacts only --sync Sync Capacitor only --assets Generate assets only --deploy Deploy app to connected device --auto-run Auto-run app after build -h, --help Show this help message -v, --verbose Enable verbose logging # Examples ./scripts/build-ios.sh --dev --studio # Development build + open Xcode ./scripts/build-ios.sh --prod --ipa # Production IPA build ./scripts/build-ios.sh --test --app # Testing app build ./scripts/build-ios.sh --clean # Clean only ./scripts/build-ios.sh --sync # Sync only ``` **Build Modes**: - **Development**: Build for development environment - **Test**: Build for testing environment - **Production**: Build for production environment **Build Types**: - **Debug**: Build debug app (default) - **Release**: Build release app **Key Features**: - **Environment Validation**: Checks for Xcode, iOS Simulator, Capacitor - **Resource Checking**: Validates app icons, splash screens, Info.plist - **Clean Build**: Removes Xcode build artifacts and DerivedData - **Asset Generation**: Creates platform-specific assets - **Simulator Support**: Launches iOS Simulator for testing ### A.5 common.sh **File**: `scripts/common.sh` **Author**: Matthew Raymer **Description**: Common utilities and functions for build scripts **Purpose**: Provides shared functionality, logging, environment setup, and utility functions used by all build scripts. **Key Functions**: **Logging Functions**: ```bash log_info "message" # Info level logging log_success "message" # Success level logging log_warning "message" # Warning level logging log_error "message" # Error level logging log_debug "message" # Debug level logging ``` **Environment Functions**: ```bash setup_build_env "platform" # Setup build environment for platform load_env_file "filename" # Load environment variables from file print_env_vars "prefix" # Print environment variables with prefix ``` **Utility Functions**: ```bash check_command "command" # Check if command is available check_file "filename" # Check if file exists safe_execute "description" "command" # Execute command with error handling clean_build_artifacts "dir" # Clean build artifacts directory ``` **Validation Functions**: ```bash validate_build_environment # Validate common build environment setup_app_directories # Setup application directories print_header "title" # Print formatted header ``` ## Appendix B: Vite Configuration Files Reference This appendix provides detailed documentation for all Vite configuration files. ### B.1 vite.config.common.mts **File**: `vite.config.common.mts` **Author**: Matthew Raymer **Description**: Common Vite configuration shared across all platforms **Purpose**: Provides base configuration that is extended by platform-specific configs. **Key Features**: - **Platform Detection**: Automatically detects and configures for web/capacitor/electron - **Environment Setup**: Loads environment variables and sets platform flags - **Path Aliases**: Configures TypeScript path resolution - **Build Optimization**: Platform-specific build optimizations - **Dependency Management**: Handles platform-specific dependencies **Configuration Structure**: ```typescript export async function createBuildConfig(platform: string): Promise { const appConfig = await loadAppConfig(); const isCapacitor = platform === "capacitor"; const isElectron = platform === "electron"; const isNative = isCapacitor || isElectron; return { base: "/", plugins: [vue()], server: { /* CORS and dev server config */ }, build: { /* Platform-specific build config */ }, worker: { /* Web worker configuration */ }, define: { /* Environment variables and flags */ }, resolve: { /* Path aliases and module resolution */ }, optimizeDeps: { /* Dependency optimization */ } }; } ``` **Environment Variables**: - `VITE_PLATFORM`: Set to platform name (web/capacitor/electron) - `__IS_MOBILE__`: Boolean flag for mobile platforms - `__IS_ELECTRON__`: Boolean flag for Electron platform - `__USE_QR_READER__`: Boolean flag for QR reader availability **Path Aliases**: - `@`: Points to `src/` directory - `@nostr/tools`: Nostr tools library - `path`, `fs`, `crypto`: Node.js polyfills for browser ### B.2 vite.config.web.mts **File**: `vite.config.web.mts` **Author**: Matthew Raymer **Description**: Vite configuration for web platform with PWA support **Purpose**: Configures Vite for web builds with environment-specific optimizations and PWA features. **Key Features**: - **Environment-Specific Configuration**: Different settings for dev/test/prod - **PWA Integration**: Progressive Web App support with service worker - **Build Optimization**: Manual chunk splitting for better caching - **Source Maps**: Environment-specific source map configuration - **Caching Strategies**: Production-specific API caching **Environment Configurations**: **Development Mode**: ```typescript { build: { minify: false, sourcemap: true, rollupOptions: { output: { manualChunks: undefined } } }, define: { __DEV__: true, __TEST__: false, __PROD__: false } } ``` **Test Mode**: ```typescript { build: { minify: false, sourcemap: true, rollupOptions: { output: { manualChunks: undefined } } }, define: { __DEV__: false, __TEST__: true, __PROD__: false } } ``` **Production Mode**: ```typescript { build: { minify: 'terser', sourcemap: false, rollupOptions: { output: { manualChunks: { vendor: ['vue', 'vue-router', 'pinia'], utils: ['luxon', 'ramda', 'zod'], crypto: ['@ethersproject/wallet', '@ethersproject/hdnode'], sql: ['@jlongster/sql.js', 'absurd-sql'] } } } }, define: { __DEV__: false, __TEST__: false, __PROD__: true } } ``` **PWA Configuration**: ```typescript VitePWA({ registerType: 'autoUpdate', manifest: appConfig.pwaConfig?.manifest, devOptions: { enabled: true, type: 'classic' }, workbox: { cleanupOutdatedCaches: true, skipWaiting: true, clientsClaim: true, sourcemap: mode !== 'production', maximumFileSizeToCacheInBytes: 10 * 1024 * 1024, runtimeCaching: mode === 'production' ? [/* API caching */] : [] } }) ``` ### B.3 vite.config.electron.mts **File**: `vite.config.electron.mts` **Author**: Matthew Raymer **Description**: Vite configuration for Electron desktop platform **Purpose**: Configures Vite for Electron builds with desktop-specific optimizations and native module support. **Key Features**: - **Electron-Specific Entry Point**: Uses `main.electron.ts` instead of `main.web.ts` - **Native Module Support**: Handles Electron-specific dependencies - **Desktop Optimizations**: Larger chunk sizes and desktop-specific settings - **Source Map Suppression**: Prevents DevTools warnings for external modules - **External Dependencies**: Properly handles Electron and native modules **Configuration Structure**: ```typescript export default defineConfig(async () => { const baseConfig = await createBuildConfig("electron"); return { ...baseConfig, plugins: [ // Electron entry point replacement // Source map suppression // External module handling ], build: { outDir: "dist", sourcemap: false, target: "node16", chunkSizeWarningLimit: 2000, rollupOptions: { external: ["electron", "@capacitor-community/electron"], output: { manualChunks: { vendor: ["vue", "vue-router", "@vueuse/core"], crypto: ["@nostr/tools", "crypto-js"], ui: ["@fortawesome/vue-fontawesome"] } } } }, define: { '__ELECTRON__': JSON.stringify(true), '__IS_DESKTOP__': JSON.stringify(true), '__USE_NATIVE_SQLITE__': JSON.stringify(true) } }; }); ``` **Plugins**: - **electron-entry-point**: Replaces main entry point for Electron - **electron-config**: Handles Electron-specific configurations - **suppress-source-maps**: Suppresses source map loading errors **External Dependencies**: - `electron`: Electron runtime - `@capacitor-community/electron`: Capacitor Electron plugin - `better-sqlite3-multiple-ciphers`: Native SQLite module ### B.4 vite.config.capacitor.mts **File**: `vite.config.capacitor.mts` **Author**: Matthew Raymer **Description**: Vite configuration for Capacitor mobile platform **Purpose**: Provides minimal configuration for Capacitor builds, inheriting from common config. **Configuration**: ```typescript import { defineConfig } from "vite"; import { createBuildConfig } from "./vite.config.common.mts"; export default defineConfig(async () => createBuildConfig('capacitor')); ``` **Key Features**: - **Minimal Configuration**: Inherits all settings from common config - **Mobile Platform**: Automatically configures for mobile-specific settings - **PWA Disabled**: Progressive Web App features disabled for native apps - **Native Dependencies**: Handles Capacitor-specific dependencies ### B.5 vite.config.utils.mts **File**: `vite.config.utils.mts` **Author**: Matthew Raymer **Description**: Utility functions for Vite configuration **Purpose**: Provides shared configuration loading and PWA manifest generation. **Key Functions**: **loadPackageJson()**: Loads and parses package.json for app configuration **loadAppConfig()**: Loads complete application configuration including PWA settings **PWA Configuration**: ```typescript interface PWAConfig { registerType: string; strategies: string; srcDir: string; filename: string; manifest: { name: string; short_name: string; theme_color: string; background_color: string; icons: ManifestIcon[]; share_target: ShareTarget; }; } ``` **Manifest Icons**: - Android Chrome 192x192 PNG - Android Chrome 512x512 PNG - Maskable icons for adaptive UI **Share Target Configuration**: ```typescript share_target: { action: "/share-target", method: "POST", enctype: "multipart/form-data", params: { files: [{ name: "photo", accept: ["image/*"] }] } } ``` **Alias Configuration**: - `@`: Source directory alias - `buffer`: Buffer polyfill - `dexie-export-import`: Database import/export utilities ### B.6 Additional Vite Configurations **vite.config.web.mts**: Web platform configuration (used by build-web.sh) **vite.config.electron.mts**: Electron platform configuration (used by build-electron.sh) **vite.config.capacitor.mts**: Capacitor mobile configuration (used by npm run build:capacitor) **vite.config.common.mts**: Shared configuration utilities **vite.config.utils.mts**: Configuration utility functions **vite.config.dev.mts**: Development-specific configuration **vite.config.optimized.mts**: Optimized build configuration ## Appendix C: Build Script Integration ### C.1 Script Dependencies All build scripts depend on `scripts/common.sh` for shared functionality: ```bash # Source common utilities in all build scripts source "$(dirname "$0")/common.sh" ``` ### C.2 Environment Variable Flow 1. **Script Level**: Build scripts set `BUILD_MODE` and `NODE_ENV` 2. **Vite Level**: Vite configs read environment variables and set `define` values 3. **Application Level**: Vue components access environment via `import.meta.env` ### C.3 Build Process Flow **Web Build**: ``` build-web.sh → vite.config.web.mts → dist/ ``` **Electron Build**: ``` build-electron.sh → vite.config.electron.mts → electron/app/ ``` **Mobile Build**: ``` build-android.sh/build-ios.sh → vite.config.capacitor.mts → android/ios/ ``` ### C.4 Error Handling All scripts use consistent error handling: - Exit codes for different failure types - Verbose logging with `--verbose` flag - Safe command execution with `safe_execute()` - Environment validation before builds ### C.5 Platform-Specific Considerations **Web Platform**: - PWA features enabled - Service worker injection - Browser-specific optimizations **Electron Platform**: - Native module support - Desktop-specific entry points - Source map suppression **Mobile Platform**: - Capacitor integration - Native asset generation - Platform-specific builds --- **Note**: This documentation is maintained alongside the build system. For the most up-to-date information, refer to the actual script files and Vite configuration files in the repository.