Work
Live2026

Kickstart Exchange for Expo

A Swift-only banner SDK, installable from npm.

Kickstart Exchange for Expo: A Swift-only banner SDK, installable from npm.

Kickstart Exchange is a free cross-promotion network for indie Apple apps: your app shows other people's banners and they show yours. The official SDK is SwiftUI and Swift Package Manager only, so React Native and Expo apps couldn't touch it. This hosts the real SwiftUI view inside your React tree instead of reimplementing it.

The thing I wanted to avoid was reimplementing the banner. Redraw it in JS and I own every bug in it forever and I'm permanently behind whatever upstream ships next. So the package hosts the actual view through Expo's SwiftUI host and passes props straight down. Anything you don't set falls through to the SDK's own defaults rather than to something I picked.

Most of the work was plumbing. CocoaPods won't let a dynamic pod depend on a static one, and ExpoModulesCore hard-codes itself static, so the one piece that has to be dynamic, the Swift Package Manager dependency, lives in its own pod and the Expo pod depends on that. The bridge itself is a single line: an `@_exported import` of the upstream module.

The bug I would never have guessed: hosting with content matching on both axes applies `fixedSize` horizontally, SwiftUI throws away the width React Native proposed and lays out at its ideal width instead, and Yoga writes that back into the tree. Any ad with a long enough title and the banner hangs off the side of the phone. Matching vertically only fixed it.

On Android it installs and does nothing, on purpose. The exchange only serves Apple platforms, so the Kotlin module is empty with a comment explaining why. That beats a build that breaks because the package is in the tree.

What it does

  • Hosts the official SwiftUI view, so upstream's fixes are your fixes
  • Unset props fall through to the SDK's own defaults, not mine
  • Split into two podspecs to get around CocoaPods' static linkage rule
  • Android and web install cleanly and render nothing, deliberately