A half-duplex communication application specialized for paragliding, using Apple's iOS 16+ PushToTalk framework with a Cloudflare Workers backend. A hybrid system designed to complement traditional VHF/UHF radios.
Based on the Vite 7 + HeroUI (v2) + Auth0 with Turborepo and Yarn 4 workspaces template.
If you appreciate my work, please consider giving it a star! 🤩
ParaWave PTT is a Push‑to‑Talk (PTT) half‑duplex communication system built for paragliding clubs and pilots. It combines an iOS client (native Swift app) using Apple's PushToTalk framework with a Cloudflare Workers backend for low‑latency audio chunk ingestion and session management.
This repository contains multiple workspaces:
ios/ParaWavePTT/ParaWavePTT(iOS app) — Swift app using Apple's PushToTalk, AVFoundation and AVAudioEngine for audio capture and AAC encoding.apps/cloudflare-worker— Cloudflare Workers backend and Durable Objects that handle PTT sessions and audio chunk ingestion.apps/backend-admin— Admin web UI and API documentation for server operators.docs/— Design notes, API analysis and OpenAPI spec.
- Provide a reliable, low‑latency group voice channel optimized for paragliding use cases (site channels, emergency channel, geo‑local channels).
- Use AAC‑LC for energy‑efficient hardware accelerated encoding on iOS.
- Integrate Apple PushToTalk framework for best UX on iOS 16+ devices.
- Support server‑side session management, push token handling and real‑time distribution via WebSockets/Durable Objects.
- iOS client with PushToTalk integration (channel join/leave, transmit/stop, ephemeral PTT push tokens).
- Audio capture with AVAudioEngine and conversion to AAC‑LC before upload.
- Chunked audio upload endpoint for streaming audio to the backend.
- Cloudflare Workers backend with API endpoints for transmission lifecycle (start, chunk, end) and optional WebSocket/Durable Object relay.
- Admin UI for channel management and telemetry.
ios/ParaWavePTT/ParaWavePTT— Main iOS app projectapps/cloudflare-worker— Worker code, tests and migrationsapps/backend-admin— Admin web app and OpenAPI clientdocs/openapi.json— API specification used by the apps
- Target iOS 16.0 or later. PushToTalk framework is only available on real devices.
- Make sure the app has the following entitlements and capabilities:
- Push‑to‑Talk capability (
com.apple.developer.push-to-talk) - App Group configured if you share data between extensions
- Background audio modes including
push-to-talkinUIBackgroundModes - Remote notifications (for PTT push flow)
- Push‑to‑Talk capability (
- Microphone permission required (
AVAudioSessionrequestRecordPermission). - Audio capture: app uses
AVAudioEngineinput node and installs a tap to obtainAVAudioPCMBuffer. The buffer is encoded to AAC‑LC before being base64 encoded and sent to the backend chunk endpoint.
- The backend accepts chunked audio via
POST /api/v1/transmissions/{session_id}/chunkand expects base64‑encoded payloads. - AudioFormat supported:
aac-lc,opus,pcm. The iOS client should sendaac-lcby default. - Durable Objects / WebSocket relay used for delivering real‑time audio to channel participants when available.
- Open
ios/ParaWavePTT/ParaWavePTT.xcodeprojin Xcode 14+. - Select a physical device (PushToTalk is not supported in Simulator).
- Ensure provisioning profile includes PushToTalk capability and App Group if configured.
- Build & run.
- Install Node 18+ and Wrangler (per Cloudflare docs).
- From repo root:
yarn install
yarn dev:env- Located at
apps/backend-admin. Uses Vite. See that app's README for dev commands.
- The repository includes an OpenAPI description in
docs/openapi.jsonused by the admin UI and backend tests. - Unit and integration tests for the Cloudflare Worker are in
apps/cloudflare-worker/test.
- AAC encoding on iOS should use
AVAudioConverter/AudioToolboxto produce AAC‑LC frames. Be careful to produce proper ADTS/ADIF headers if the backend expects raw AAC frames or packaged containers. The current implementation encodes to MPEG‑4 AAC frames and the backend expects base64 of that stream. - For production, tune audio bitrate and packet sizing for network conditions (e.g., 24–64 kbps typical for voice).
- Always test end‑to‑end on physical devices across network conditions.
- Open issues or PRs for features and fixes. Follow the repo's code style and run tests for the affected parts.
- See top‑level
LICENSEfile. Some files are AGPL‑3.0‑or‑later (noted in file headers). Other parts of the monorepo may use MIT.
- Repo owner / maintainer: highcanfly-club
- For security issues please open an issue labelled
security. To use the authentication system in your application, wrap your components with theAuthenticationProvider:
To use Auth0, follow these steps:
-
Create an Auth0 Account:
- Go to Auth0 and sign up for a free account.
-
Create a New Application:
- In the Auth0 dashboard, navigate to the "Applications" section.
- Click on "Create Application".
- Choose a name for your application.
- Select "Single Page Web Applications" as the application type.
- Click "Create".
-
Configure Application Settings:
- In the application settings, you will find your
Client IDandDomain. - Set the "Allowed Callback URLs" to
http://localhost:5173(or your development URL). - Set the "Allowed Logout URLs" to
http://localhost:5173(or your development URL). - Set the "Allowed Web Origins" to
http://localhost:5173(or your development URL).
- In the application settings, you will find your
-
Sample settings:
- The settings used by the demo deployment on GitHub Pages are:
- Allowed Callback URLs:
https://sctg-development.github.io/vite-react-heroui-auth0-template - Allowed Logout URLs:
https://sctg-development.github.io/vite-react-heroui-auth0-template - Allowed Web Origins:
https://sctg-development.github.io - On Github repository settings, the
AUTH0_CLIENT_IDsecret is set to the Auth0 client ID and theAUTH0_DOMAINsecret is set to the Auth0 domain. - The full Auth0 configuration screenshot is available here.
- Allowed Callback URLs:
- The settings used by the demo deployment on GitHub Pages are:
-
Configure API in Auth0:
- Navigate to "APIs" section in the Auth0 dashboard
- Click "Create API"
- Provide a descriptive name (e.g., "My Application API")
- Set the identifier (audience) - typically a URL or URI (e.g.,
https://api.myapp.com) - Configure the signing algorithm (RS256 recommended)
-
Configure API Settings:
- Enable RBAC (Role-Based Access Control) if you need granular permission management
- Define permissions (scopes) that represent specific actions (e.g.,
read:api,write:api) - Configure token settings as needed (expiration, etc.)
- Include permissions in the access token
-
Set Environment Variables (example - anonymized): The repository uses a number of environment variables. Below is an anonymized example that mirrors the keys in the project's
.envfile — values are masked and must be replaced with your real credentials/URLs.# --- Local .env and GitHub Secrets (anonymized examples) --- # Replace placeholders with real values. NEVER commit real secrets. # App bundle identifier (used by iOS builds) APPLE_APP_BUNDLE_ID=club.highcanfly.parawave-ptt # Cloudflare (used for publishing workers and optional dev tunnels) CLOUDFLARE_ACCOUNT_ID=xxxxxxxxxxxxxxxxxxxxxxxxxxxx CLOUDFLARE_API_TOKEN=REDACTED_CLOUDFLARE_TOKEN CLOUDFLARE_TUNNEL_TOKEN=REDACTED_TUNNEL_TOKEN CLOUDFLARE_TUNNEL_FRONTEND_TOKEN=REDACTED_FRONTEND_TOKEN # Encryption key for storing/restoring encrypted development artifacts # (used only by the repository's helper scripts) CRYPTOKEN=REDACTED # Authentication provider selection AUTHENTICATION_PROVIDER_TYPE=auth0 # Auth0 tenant credentials (replace with your tenant values) AUTH0_CLIENT_ID=REDACTED_CLIENT_ID AUTH0_CLIENT_SECRET=REDACTED_CLIENT_SECRET AUTH0_DOMAIN=REDACTED_AUTH0_DOMAIN AUTH0_SCOPE="openid profile email read:api write:api admin:api" AUTH0_AUDIENCE=http://localhost:5173 # Optional: pre-fetched token for local tests ONLY (do not use in CI or prod) AUTH0_TOKEN=REDACTED # API endpoints and CORS origins API_BASE_URL=https://parawave-ptt.example/api CORS_ORIGIN=https://parawave-ptt-admin.example,http://localhost:5173 # Permissions / application flags READ_PERMISSION=read:api WRITE_PERMISSION=write:api ADMIN_PERMISSION=admin:api ACCESS_PERMISSION_PREFIX=access TENANT_ADMIN_PERMISSION=tenant:admin # Auth0 management (M2M) used by backend services AUTH0_MANAGEMENT_AUDIENCE=https://your-auth0-tenant/api/v2/ AUTH0_MANAGEMENT_CLIENT_ID=REDACTED_M2M_CLIENT_ID AUTH0_MANAGEMENT_CLIENT_SECRET=REDACTED_M2M_CLIENT_SECRET # Misc API_VERSION="1.0.0" ENVIRONMENT=development DEX_JWKS_ENDPOINT= # SECURITY NOTE: # - Keep all real tokens/credentials out of the repository. Use GitHub Secrets or # your CI/CD secret store for deployment keys. # - .env files should be added to .gitignore. Treat AUTH0_TOKEN, CLOUDFLARE_API_TOKEN, # and all CLIENT_SECRET values as high‑sensitivity secrets.
-
Sample Configuration: For reference, view the Auth0 API configuration used in the demo deployment.