POROROCA OTA
Over-the-air updates for native SwiftUI apps
The problem: a copy fix shouldn't need a review cycle
A price display is wrong, a paywall headline needs a rewrite, an onboarding step confuses new users — and the fix is sitting on your machine while App Store review runs its course. For a fully native SwiftUI app, there has been no equivalent of the code-push tools React Native and Flutter teams take for granted.
App Store 2.5.2, satisfied by shipping data, not code
Pororoca's SwiftUI runtime targets iOS 17+, and the update it downloads is a signed, data-only screen document — never executable code. The runtime keeps a managed crash-safe store and a compiled embedded fallback, so a bad or unreachable update never leaves a user stuck: the app always has something safe to render.
The workflow in four steps
1. Validate the documents you authored against the iOS platform schema before anything is signed — this step catches an unrecognized field or a document that doesn't match the platform you intend to ship it to, so treat a clean validate as your gate before touching the private key.
swift run pororoca validate .pororoca/documents --platform ios2. Export a signed, immutable update bundle from those documents. The update ID you choose here is permanent and unique within the app, so a descriptive, dated ID makes it easier to match a bundle back to the change that produced it later.
swift run pororoca export .pororoca/documents \
--output .pororoca/update --update-id paywall-1 \
--private-key .pororoca/keys/private.key3. Publish it to a channel at a conservative rollout percentage. Starting at 10% means only a small, deterministic slice of installs by install ID is exposed while you watch for problems, rather than every user at once.
POROROCA_API_TOKEN=pororoca_live_... swift run pororoca publish .pororoca/update \
--server https://pororoca-ota.fly.dev --app your-app-slug \
--channel production --rollout 10 \
--public-key .pororoca/keys/public.key4. Confirm an eligible install actually resolves the update before trusting it further. A 200 means this install receives the signed update, a 204 means it's outside the current 10% cohort (expected, not a failure), and a 401 means the runtime token is missing, revoked, or wrong for this app — check that before assuming the publish itself failed.
curl -i \
-H "Authorization: Bearer $POROROCA_RUNTIME_TOKEN" \
"https://pororoca-ota.fly.dev/api/v1/apps/your-app-slug/channels/production/resolve?install_id=docs-smoke-0001"Rollout is deterministic by install ID, so the same devices stay in the same cohort as you widen it, and `applied` telemetry shows up in the dashboard once a device actually renders the update successfully. If something looks wrong, one command rolls the channel back to the previous known-good update, and the next device check picks that rollback up on its next launch.
Limits and the trial
Not yet available: team members and role-based access control, usage-based limits, automated alerts, cross-platform expression parity with Android, and a hosted MCP transport (the MCP server runs locally today).
There is one Pro plan, with a card-required 21-day trial, billed in BRL or USD.