13 KiB
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.
- 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:
# 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.
npx cap add android
npx cap add ios
You'll also want to edit the deep link configuration (see below).
Initial Setup
Install dependencies:
npm install
Web Development
Local Development
npm run dev
Web Build for Server
-
Run the production build:
npm run build:web
The built files will be in the
dist
directory. -
To test the production build locally:
npm run serve
Environment Configuration
For different environments, create .env
files:
# .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:
./scripts/electron-dev.sh
Production Build
For production builds with automatic environment setup:
./scripts/build-electron.sh
Linux Packaging
# 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
# 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:
-
Set up environment variables in
.env
file: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
-
Build with signing:
./scripts/build-electron-mac.sh
Running the Packaged App
-
Linux:
- AppImage: Make executable and run
chmod +x dist-electron-packages/TimeSafari-*.AppImage ./dist-electron-packages/TimeSafari-*.AppImage
- DEB: Install and run
sudo dpkg -i dist-electron-packages/timesafari_*_amd64.deb timesafari
- AppImage: Make executable and run
-
macOS:
.app
bundle: Double-clickTimeSafari.app
in Finder.dmg
installer:- Double-click the
.dmg
file - Drag the app to your Applications folder
- Launch from Applications
- Double-click the
.zip
archive:- Extract the
.zip
file - Move
TimeSafari.app
to your Applications folder - Launch from Applications
- Extract the
Note: If you get a security warning when running the app:
- Right-click the app
- Select "Open"
- 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:
./scripts/build-android.sh
This script automatically:
- Sets up environment variables for Capacitor
- Cleans previous builds
- Builds web assets
- Builds Capacitor version
- Cleans and builds Gradle project
- Syncs with Capacitor
- Generates assets
- Opens Android Studio
Manual Steps (if needed)
If you need to run individual steps:
-
Build the web assets:
npm run build:web npm run build:capacitor
-
Update Android project:
npx cap sync android
-
Generate assets:
npx capacitor-assets generate --android
-
Open in Android Studio:
npx cap open android
Console Build
For building from the console:
cd android
./gradlew clean
./gradlew build -Dlint.baselines.continue=true
cd -
For creating an aab
file:
cd android
./gradlew bundleDebug -Dlint.baselines.continue=true
cd -
For creating a signed release:
- Setup signing configuration in
app/gradle.properties.secrets
- Add signing key file
app/time-safari-upload-key-pkcs12.jks
- Update version in
app/build.gradle
- Build release:
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
-
Build the web assets & update iOS:
npm run build:web npm run build:capacitor npx cap sync ios
-
Generate assets:
# 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
-
Update 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 -
-
Open in Xcode:
npx cap open ios
-
Build and run on simulator or device using Xcode
Release Process
- Choose Product -> Destination -> Any iOS Device
- Choose Product -> Archive
- Click Distribute -> App Store Connect
- In App Store Connect, add the build to the distribution
Testing
Complete Test Suite
Run all tests with automatic environment setup:
./scripts/test-all.sh
Mobile Tests
Run mobile-specific tests:
./scripts/test-mobile.sh
Environment Testing
Test environment variable handling:
./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
-
Build the Docker image:
docker build -t timesafari:latest .
-
For development builds with specific environment variables:
docker build --build-arg NODE_ENV=development -t timesafari:dev .
Running the Container
-
Run the container:
docker run -d -p 80:80 timesafari:latest
-
For development with hot-reloading:
docker run -d -p 80:80 -v $(pwd):/app timesafari:dev
Using Docker Compose
Create a docker-compose.yml
file:
version: '3.8'
services:
timesafari:
build: .
ports:
- "80:80"
environment:
- NODE_ENV=production
restart: unless-stopped
Run with Docker Compose:
docker-compose up -d
Production Deployment
For production deployment, consider the following:
- Use specific version tags instead of 'latest'
- Implement health checks
- Configure proper logging
- Set up reverse proxy with SSL termination
- Use Docker secrets for sensitive data
Example production deployment:
# 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
-
Container fails to start
- Check logs:
docker logs <container_id>
- Verify port availability
- Check environment variables
- Check logs:
-
Build fails
- Ensure all dependencies are in package.json
- Check Dockerfile syntax
- Verify build context
-
Performance issues
- Monitor container resources:
docker stats
- Check nginx configuration
- Verify caching settings
- Monitor container resources:
Configuration
Deep Links
Android Configuration
You must add the following intent filter to the android/app/src/main/AndroidManifest.xml
file:
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="timesafari" />
</intent-filter>
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:
- Open the project in Xcode
- Select your app target
- Go to Info tab
- Add URL Types with scheme
timesafari
Troubleshooting
Common Issues
-
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
- Use
-
Build Failures
- Use
--verbose
flag for detailed logging:./scripts/build-electron.sh --verbose
- Check prerequisites are installed
- Verify all dependencies are installed:
npm install
- Use
-
Permission Issues
- Make scripts executable:
chmod +x scripts/*.sh
- Check file permissions on build directories
- Make scripts executable:
-
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) |