You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

16 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

Package Management

TimeSafari uses a mixed package management approach, combining npm and JSR (JavaScript Registry) for optimal dependency management.

JSR Integration

Some packages are installed via JSR for better ESM support and modern TypeScript compatibility:

# Install JSR packages
npx jsr add @nostr/tools

Package Migration History

nostr-tools → @nostr/tools

Date: June 2025
Reason: Resolved Vite/Rollup build issues with deep imports

Before (npm):

import { finalizeEvent } from "nostr-tools/lib/cjs/index.js";
import { accountFromExtendedKey } from "nostr-tools/lib/cjs/nip06.js";

After (JSR):

import { finalizeEvent } from "@nostr/tools";
import { accountFromExtendedKey } from "@nostr/tools/nip06";

Benefits:

  • Proper ESM support
  • No deep import issues with Vite/Rollup
  • Better TypeScript compatibility
  • Modern package structure

Current Package Strategy

  • npm: Primary package manager for most dependencies
  • JSR: Used for packages with better ESM support or modern alternatives
  • Mixed approach: Allows using the best package for each dependency

When to Use JSR

Consider using JSR for:

  • Packages with ESM/CJS compatibility issues in npm
  • Modern TypeScript-first packages
  • Packages that work better with modern bundlers
  • New dependencies where JSR has a better alternative

Vite Configuration

The build system is configured to handle both npm and JSR packages:

// vite.config.common.mts
resolve: {
  alias: {
    '@nostr/tools': path.resolve(__dirname, 'node_modules/@nostr/tools'),
    '@nostr/tools/nip06': path.resolve(__dirname, 'node_modules/@nostr/tools/nip06'),
  }
}

Troubleshooting Package Issues

  1. Build failures with deep imports

    • Check if package has ESM/CJS compatibility issues
    • Consider JSR alternative if available
    • Update Vite configuration if needed
  2. TypeScript errors

    • Ensure proper type definitions are available
    • Check package exports in package.json
    • Verify import paths match package structure
  3. Mixed package manager issues

    • Keep package.json and node_modules in sync
    • Use npm install after JSR package additions
    • Check for conflicting package versions

Web Development

Local Development

npm run dev

Web Build for Server

  1. Run the production build:

    npm run build:web
    

    The built files will be in the dist directory.

  2. 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:

  1. 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
    
  2. 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
      
  • 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:

./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:

    npm run build:web
    npm run build:capacitor
    
  2. Update Android project:

    npx cap sync android
    
  3. Generate assets:

    npx capacitor-assets generate --android
    
  4. 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:

  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:
    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:

    npm run build:web
    npm run build:capacitor
    npx cap sync ios
    
  2. 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
    
  3. 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 -
    
  4. Open in Xcode:

    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:

./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

  1. Build the Docker image:

    docker build -t timesafari:latest .
    
  2. For development builds with specific environment variables:

    docker build --build-arg NODE_ENV=development -t timesafari:dev .
    

Running the Container

  1. Run the container:

    docker run -d -p 80:80 timesafari:latest
    
  2. 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:

  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:

# 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 <container_id>
    • 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

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:

  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)