# Building TimeSafari This guide explains how to build TimeSafari for different platforms. ## Prerequisites For a quick dev environment setup, use [pkgx](https://pkgx.dev). - Node.js (LTS version recommended) - npm (comes with Node.js) - Git - For Android builds: Android Studio with SDK installed - For iOS builds: macOS with Xcode and ruby gems & bundle - 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 ``` - 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 Dev Locally ```bash npm run dev ``` ## Web Build for Server 1. Run the production build: ```bash npm run build ``` 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 ``` ### 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. * `npx prettier --write ./sw_scripts/` * Update the ClickUp tasks & CHANGELOG.md & the version in package.json, run `npm install`. * 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 later). * Tag with the new version, [online](https://gitea.anomalistdesign.com/trent_larson/crowd-funder-for-time-pwa/releases) or `git tag 0.3.55 && git push origin 0.3.55`. * 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_PASSKEYS_ENABLED=true npm run build ``` ... 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.staging 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 0.3.55 && npm install && npm run build && cd -` (The plain `npm run build` uses the .env.production file.) * Back up the time-safari/dist folder & deploy: `mv time-safari/dist time-safari-dist-prev.0 && 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`, and commit. 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 ``` ### 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) ### Linux Build 1. Build the electron app in production mode: ```bash npm run build:electron-prod ``` 2. Package the Electron app for Linux: ```bash # For AppImage (recommended) npm run electron:build-linux # For .deb package npm run electron:build-linux-deb ``` 3. 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` ### Running the Packaged App - 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 ``` ### Development Testing For testing the Electron build before packaging: ```bash # Build and run in development mode (includes DevTools) npm run electron:dev # Build in production mode and test npm run build:electron-prod && npm run electron:start ``` ## Mobile Builds (Capacitor) ### iOS Build Prerequisites: macOS with Xcode installed 1. Build the web assets: ```bash npm run build:capacitor ``` 2. Update iOS project with latest build: ```bash npx cap sync ios ``` 3. Copy the assets: ```bash mkdir -p ios/App/App/Assets.xcassets/AppIcon.appiconset npx capacitor-assets generate --ios ``` 3. Open the project in Xcode: ```bash npx cap open ios ``` 4. Use Xcode to build and run on simulator or device. #### First-time iOS Configuration - Generate certificates inside XCode. - Right-click on App and under Signing & Capabilities set the Team. ### Android Build Prerequisites: Android Studio with SDK installed 1. Build the web assets: ```bash rm -rf dist npm run build:web npm run build:capacitor cd android ./gradlew clean ./gradlew assembleDebug ``` 2. Update Android project with latest build: ```bash npx cap sync android ``` 3. Copy the assets ```bash npx capacitor-assets generate --android ``` 4. Open the project in Android Studio: ```bash npx cap open android ``` 5. 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 .. npx cap run android ``` ... or, to create the `aab` file, `bundle` instead of `build`: ```bash ./gradlew bundleDebug -Dlint.baselines.continue=true ``` ... or, to create a signed release, add the app/gradle.properties.secrets file (see properties at top of app/build.gradle) and the app/time-safari-upload-key-pkcs12.jks file, then `bundleRelease`: ```bash ./gradlew bundleRelease -Dlint.baselines.continue=true ``` ## First-time Android Configuration for deep links You must add the following intent filter to the `android/app/src/main/AndroidManifest.xml` file: ```xml ```