# Building TimeSafari This guide explains how to build TimeSafari for different platforms using our unified build scripts. ## Prerequisites For a quick dev environment setup, use [pkgx](https://pkgx.dev). - Node.js (LTS version recommended) - npm (comes with Node.js) - Git - For desktop builds: Additional build tools based on your OS ## Unified Build Scripts TimeSafari now uses unified build scripts that automatically handle environment variables, logging, error handling, and timing. All scripts are located in the `scripts/` directory and use a common utilities library. ### Script Features - **Automatic Environment Setup**: Each script sets the correct environment variables for its build type - **Rich Logging**: Colored, timestamped output with different log levels - **Error Handling**: Proper exit codes and graceful failure recovery - **Timing**: Automatic execution time tracking for each step - **Validation**: Checks for required dependencies and files - **CLI Options**: `--help`, `--verbose`, `--env` flags for all scripts ### Available Scripts | Script | Purpose | Command | |--------|---------|---------| | `electron-dev.sh` | Electron development | `./scripts/electron-dev.sh` | | `electron-build.sh` | Electron build | `./scripts/build-electron.sh` | | `capacitor-dev.sh` | Capacitor development | `./scripts/capacitor-dev.sh` | | `capacitor-build.sh` | Capacitor build | `./scripts/build-capacitor.sh` | | `web-dev.sh` | Web development | `./scripts/web-dev.sh` | | `web-build.sh` | Web build | `./scripts/build-web.sh` | ### Environment Variables All scripts automatically set the correct environment variables for their build type: | Build Type | VITE_PLATFORM | VITE_PWA_ENABLED | VITE_DISABLE_PWA | NODE_ENV | |------------|---------------|------------------|------------------|----------| | `electron` | electron | false | true | production* | | `capacitor` | capacitor | false | true | - | | `web` | web | true | false | - | *NODE_ENV=production only set when production mode is enabled ### CLI Options All scripts support these options: ```bash # Show help ./scripts/build-electron.sh --help # Enable verbose logging ./scripts/build-electron.sh --verbose # Show environment variables ./scripts/build-electron.sh --env ``` ## 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 npm run build:web ``` The built files will be in the `dist` directory. 2. To test the production build locally: ```bash npm run serve ``` ### Environment Configuration For different environments, create `.env` files: ```bash # .env.development VITE_APP_SERVER=https://dev.timesafari.app VITE_DEFAULT_ENDORSER_API_SERVER=https://dev-api.endorser.ch VITE_DEFAULT_IMAGE_API_SERVER=https://dev-image-api.timesafari.app VITE_DEFAULT_PARTNER_API_SERVER=https://dev-partner-api.endorser.ch VITE_DEFAULT_PUSH_SERVER=https://dev.timesafari.app VITE_PASSKEYS_ENABLED=true # .env.production VITE_APP_SERVER=https://timesafari.app 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 VITE_DEFAULT_PUSH_SERVER=https://timesafari.app VITE_PASSKEYS_ENABLED=true ``` ## Desktop Build (Electron) ### Development For development with automatic environment setup: ```bash ./scripts/electron-dev.sh ``` ### Production Build For production builds with automatic environment setup: ```bash ./scripts/build-electron.sh ``` ### Linux Packaging ```bash # Build AppImage (recommended) ./scripts/build-electron-linux.sh # Build .deb package ./scripts/build-electron-linux.sh deb # Build production AppImage ./scripts/build-electron-linux.sh prod ``` The packaged applications will be in `dist-electron-packages/`: - AppImage: `dist-electron-packages/TimeSafari-x.x.x.AppImage` - DEB: `dist-electron-packages/timesafari_x.x.x_amd64.deb` ### macOS Packaging ```bash # Build standard Mac package ./scripts/build-electron-mac.sh # Build universal package (Intel + Apple Silicon) ./scripts/build-electron-mac.sh universal ``` The packaged applications will be in `dist-electron-packages/`: - `.app` bundle: `TimeSafari.app` - `.dmg` installer: `TimeSafari-x.x.x.dmg` - `.zip` archive: `TimeSafari-x.x.x-mac.zip` ### Code Signing and Notarization (macOS) For public distribution on macOS, you need to code sign and notarize your app: 1. Set up environment variables in `.env` file: ```bash CSC_LINK=/path/to/your/certificate.p12 CSC_KEY_PASSWORD=your_certificate_password APPLE_ID=your_apple_id APPLE_ID_PASSWORD=your_app_specific_password ``` 2. Build with signing: ```bash ./scripts/build-electron-mac.sh ``` ### Running the Packaged App - **Linux**: - AppImage: Make executable and run ```bash chmod +x dist-electron-packages/TimeSafari-*.AppImage ./dist-electron-packages/TimeSafari-*.AppImage ``` - DEB: Install and run ```bash sudo dpkg -i dist-electron-packages/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 - `.zip` archive: 1. Extract the `.zip` file 2. Move `TimeSafari.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 ## Mobile Builds (Capacitor) ### Android Build Prerequisites: Android Studio with Java SDK installed #### Complete Build Process Use the unified Android build script: ```bash ./scripts/build-android.sh ``` This script automatically: 1. Sets up environment variables for Capacitor 2. Cleans previous builds 3. Builds web assets 4. Builds Capacitor version 5. Cleans and builds Gradle project 6. Syncs with Capacitor 7. Generates assets 8. Opens Android Studio #### Manual Steps (if needed) If you need to run individual steps: 1. Build the web assets: ```bash npm run build:web npm run build:capacitor ``` 2. Update Android project: ```bash npx cap sync android ``` 3. Generate assets: ```bash npx capacitor-assets generate --android ``` 4. Open in Android Studio: ```bash npx cap open android ``` #### Console Build For building from the console: ```bash cd android ./gradlew clean ./gradlew build -Dlint.baselines.continue=true cd - ``` For creating an `aab` file: ```bash cd android ./gradlew bundleDebug -Dlint.baselines.continue=true cd - ``` For creating a signed release: 1. Setup signing configuration in `app/gradle.properties.secrets` 2. Add signing key file `app/time-safari-upload-key-pkcs12.jks` 3. Update version in `app/build.gradle` 4. Build release: ```bash cd android ./gradlew bundleRelease -Dlint.baselines.continue=true cd - ``` The `aab` file will be at `app/build/outputs/bundle/release`. ### iOS Build Prerequisites: macOS with Xcode installed #### First-time iOS Configuration - Generate certificates inside Xcode - Right-click on App and under Signing & Capabilities set the Team #### Build Process 1. Build the web assets & update iOS: ```bash npm run build:web npm run build:capacitor npx cap sync ios ``` 2. Generate assets: ```bash # Create required directories 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 # Generate assets npx capacitor-assets generate --ios ``` 3. Update version to match Android & package.json: ```bash 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 - ``` 4. Open in Xcode: ```bash npx cap open ios ``` 5. Build and run on simulator or device using Xcode #### Release Process 1. Choose Product -> Destination -> Any iOS Device 2. Choose Product -> Archive 3. Click Distribute -> App Store Connect 4. In App Store Connect, add the build to the distribution ## Testing ### Complete Test Suite Run all tests with automatic environment setup: ```bash ./scripts/test-all.sh ``` ### Mobile Tests Run mobile-specific tests: ```bash ./scripts/test-mobile.sh ``` ### Environment Testing Test environment variable handling: ```bash ./scripts/test-env.sh ``` ## 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 ``` ### 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 ## Configuration ### Deep Links #### Android Configuration You must add the following intent filter to the `android/app/src/main/AndroidManifest.xml` file: ```xml ``` Note: When using `timesafari://` scheme, you may encounter build errors about missing http(s) scheme and host attributes. This is expected for custom URL schemes. #### iOS Configuration For iOS deep links, configure the URL scheme in Xcode: 1. Open the project in Xcode 2. Select your app target 3. Go to Info tab 4. Add URL Types with scheme `timesafari` ## Troubleshooting ### Common Issues 1. **Environment Variables Not Set** - Use `--env` flag to check current environment: `./scripts/build-electron.sh --env` - Verify `.env` file exists and is properly formatted - Check script output for environment setup messages 2. **Build Failures** - Use `--verbose` flag for detailed logging: `./scripts/build-electron.sh --verbose` - Check prerequisites are installed - Verify all dependencies are installed: `npm install` 3. **Permission Issues** - Make scripts executable: `chmod +x scripts/*.sh` - Check file permissions on build directories 4. **Platform-Specific Issues** - **Linux**: Ensure AppImage dependencies are installed - **macOS**: Check code signing certificates and entitlements - **Android**: Verify Android Studio and SDK are properly configured - **iOS**: Ensure Xcode and certificates are set up correctly ### Getting Help - Check script help: `./scripts/build-electron.sh --help` - Review script documentation in `scripts/README.md` - Test environment setup: `./scripts/test-env.sh` - Test common utilities: `./scripts/test-common.sh` ### Platform Support Matrix | Platform | Mode | PWA Enabled | Native Features | Notes | |----------|------|-------------|-----------------|-------| | `web` | web | true | false | Standard web browser | | `capacitor` | capacitor | false | true | Mobile app (iOS/Android) | | `electron` | electron | false | true | Desktop app (Windows/macOS/Linux) |