Scott Idem b3f59b7bf5 docs: add onsite deployment guide and device reference table
- Step-by-step SSH deployment instructions (build, copy .app, write seed.json)
- Multi-laptop deployment loop example
- Device reference table: all 19 laptops with IPs and event_device_ids
- Clarify seed.json location, format, and per-event API key workflow
- Document architecture detection (x64 vs arm64) and SSH key setup
2026-04-20 14:26:54 -04:00

Aether Native Launcher (Electron)

The Aether Native Launcher is a specialized Electron-based shell for the Aether Platform. It provides a secure bridge between the SvelteKit web UI and the local operating system, enabling features restricted by browser sandboxing.

🚀 Overview

This application serves as the "Native Mode" runtime for Aether podiums and devices. It handles:

  • Local File Orchestration: Managed cache for presentation files (PPTx, Keynote, PDF).
  • Automation: Specialized AppleScript handlers for PowerPoint and Keynote.
  • Hardware Telemetry: Direct access to CPU, RAM, and Network interface data.
  • Remote Control: Slide navigation and application control via WebSocket intents.

🖥️ Onsite Deployment

Current hardware: MacBook Air 2018 — Intel x64. All current deployments use aether_launcher-darwin-x64. Future hardware: Apple Silicon Macs use aether_launcher-darwin-arm64. Windows and Linux builds are planned.

SSH user on all laptops: speaker ready IP pattern: 192.168.32.1XX (XX = zero-padded laptop number, e.g. 03 → .103). Find/replace this prefix for other onsite environments.

Step 1 — Build the app (workstation)

cd ~/OSIT_dev/aether_app_native_electron
npm run package:mac
# Produces builds/aether_launcher-darwin-x64/aether_launcher.app  ← the one to deploy

Only rebuild if source code has changed. The .app bundle is identical for all Intel laptops — only ~/seed.json differs per device.

Step 2 — Determine target architecture and copy the .app

Check the target Mac's CPU if unsure:

ssh "speaker ready"@192.168.32.103 "uname -m"
# x86_64  → use aether_launcher-darwin-x64    (MacBook Air 2018 and all current Intel Macs)
# arm64   → use aether_launcher-darwin-arm64   (Apple Silicon M1/M2/M3/M4)

Copy from the workstation (replace 103 with the target IP last octet):

# Intel (current hardware):
scp -r builds/aether_launcher-darwin-x64/aether_launcher.app \
    "speaker ready"@192.168.32.103:/Applications/aether_launcher.app

# Apple Silicon (future hardware):
scp -r builds/aether_launcher-darwin-arm64/aether_launcher.app \
    "speaker ready"@192.168.32.103:/Applications/aether_launcher.app

If /Applications/aether_launcher.app already exists, scp -r overwrites it. No need to remove the old version first.

Step 3 — Write seed.json on the target laptop

The seed file lives at ~/seed.json (/Users/speaker ready/seed.json) on each Mac. It is intentionally outside the app bundle so it can be updated without redeploying.

ssh "speaker ready"@192.168.32.103 "cat > ~/seed.json" << 'EOF'
{
  "event_device_id": "DEVICE_ID_FOR_THIS_LAPTOP",
  "aether_api_key": "YOUR_API_KEY",
  "primary_api_base_url": "https://api.oneskyit.com",
  "backup_api_base_url": "https://bak-api.oneskyit.com",
  "onsite_api_base_url": null
}
EOF

event_device_id values by laptop — see the Device Reference table below.

Step 4 — Verify

# Confirm seed.json landed correctly
ssh "speaker ready"@192.168.32.103 "cat ~/seed.json"

# Confirm the .app is present
ssh "speaker ready"@192.168.32.103 "ls /Applications/aether_launcher.app"

Then launch the app on the laptop and confirm it connects and shows the correct device name in the Launcher UI.

Updating seed.json only (no app reinstall)

If only the device config needs updating (e.g. changing event_device_id or onsite_api_base_url):

ssh "speaker ready"@192.168.32.103 "cat > ~/seed.json" << 'EOF'
{ ... }
EOF

No need to re-copy the .app. Restart the Electron app after writing the new seed.

Deploy to multiple laptops at once

Repeat Steps 23 for each laptop, or use a loop:

for OCTET in 103 104 105 106; do
  echo "=== Deploying to 192.168.32.$OCTET ==="
  scp -r builds/aether_launcher-darwin-x64/aether_launcher.app \
      "speaker ready"@192.168.32.$OCTET:/Applications/aether_launcher.app
done

seed.json must still be written per-device (each has a unique event_device_id).

Adding SSH key to a new laptop (first time only)

ssh-copy-id "speaker ready"@192.168.32.1XX

Run once per laptop before attempting any of the deploy steps above.


📋 Device Reference

Laptop IP Address event_device_id Notes
01 192.168.32.101 tFLL1fLQfnk
02 192.168.32.102 rpbfunVPEzw
03 192.168.32.103 1EPfPX8kfw8
04 192.168.32.104 zvgyLM5yieU
05 192.168.32.105 QOc046GoeSc
06 192.168.32.106 2o8j6eb0L6s
07 192.168.32.107 Oa1tlxPEVSQ
08 192.168.32.108 fY4yznpUZ48
09 192.168.32.109 YlgGCyjo9bY
10 192.168.32.110 GcTnFsp1mHI
11 192.168.32.111 6z88m9oEZio
12 192.168.32.112 EggJqL2kWkA
13 192.168.32.113 O11eckHFdVE
14 192.168.32.114 reI0SecUEhI
15 192.168.32.115 crozxT8mA44
16 192.168.32.116 0nP4VZsvr2Q
17 192.168.32.117 Gm2gNqPGzLA
19 192.168.32.119 6tpukvRVugU (no laptop 18)
x20 192.168.32.120 rwLYnKUNd1M old 04, spare/retired

aether_api_key: all laptops share a single key per event deployment. The key is created in the Aether admin panel before the show and deleted after. Check builds/seed.json for the current key, or create a new one in Aether (Core → Accounts or Events → Devices API key section) before each deployment.


⚙️ Configuration

The application requires a seed.json file to identify the device and connect to the Aether API.

1. Seed Configuration

Location: ~/seed.json (user's home directory — external to the app bundle by design)

This file is intentionally kept outside the application bundle so it can be edited per-device without re-signing or repackaging the app. On macOS this is /Users/speaker ready/seed.json.

Seed file format:

{
  "event_device_id": "tFLL1fLQfnk",
  "aether_api_key": "YOUR_API_KEY",
  "primary_api_base_url": "https://api.oneskyit.com",
  "backup_api_base_url": "https://bak-api.oneskyit.com",
  "onsite_api_base_url": null
}

event_device_id is the id_random from the Aether event_device record for that physical laptop — see the Device Reference table above. aether_api_key is a shared key created per event deployment and deleted after the show.

2. Development Setup

npm install
npm start        # Compiles TypeScript (tsc) then launches Electron

3. File Cache Layout

Presentation files are cached locally under hash_prefix_length-char subdirectories (default: 2):

[local_file_cache_path]/
  4a/
    4a228ef8ac1a...sha256hash...file
  1d/
    1d720916a831...sha256hash...file

Important: hash_prefix_length must be consistent. If it changes, files in old directories become orphaned and will be re-downloaded. The default is 2 and should not be changed unless explicitly coordinated across all devices.

🌉 The Native Bridge (aetherNative)

The bridge is exposed to the renderer via contextBridge. It can be accessed in the web UI via window.aetherNative.

Core Methods

Method Description
list_tools() Returns a JSON manifest of all available native functions.
launch_presentation({path, app}) Launches a presentation with auto-focus and slideshow start.
control_presentation({app, action}) Sends next, prev, start, or stop to active decks.
open_folder(path) Opens a local directory in the OS file explorer.
get_device_info() Returns hardware metadata (RAM, IPs, Hostname).

Example Usage (UI Relay)

import * as native from '$lib/electron/electron_relay';

// Launch a file from local cache
await native.launch_presentation({ 
    path: '[tmp]/my_deck.pptx', 
    app: 'powerpoint' 
});

// Navigate slides
await native.control_presentation({ 
    app: 'powerpoint', 
    action: 'next' 
});

🛠️ Development

  • Preload: Logic defined in src/preload/index.ts.
  • Handlers: OS-level logic in src/main/shell_handlers.ts and src/main/file_handlers.ts.
  • Types: Shared TypeScript interfaces in src/shared/types.ts.
Description
No description provided
Readme 4.3 MiB
Languages
CSS 44.2%
JavaScript 40.4%
HTML 15.4%