Skip to content
Cleft
Download

Founder dev log

Getting react-native-skia to build for Mac Catalyst

During an early React Native build of Cleft, react-native-skia would not compile for Mac Catalyst. I took a stalled community fix, brought it current against main, and got macOS Catalyst support merged upstream in v2.3.0.

Filed
Author
Justin Mitchell
Read
3 min
Updated

This came out of an early exploration into building Cleft 2.x on React Native, one codebase across iPhone, Mac, and Watch with a two-person team. That exploration is its own story, and I will get into where it led in a follow-up post. This one is about a single problem we hit along the way and the fix that ended up upstream because of it.

The recording screen used react-native-skia to draw the animated blob you watch while you talk. It is a Skia canvas with a morphing path, driven by Reanimated. It looks great and it runs on the GPU, which is exactly what you want for something that animates the whole time you are recording.

The problem: the Mac build went through Mac Catalyst, and react-native-skia would not compile for Catalyst. The Skia binaries were not built for that slice, so the moment I targeted the Mac, the build fell over. No blob on the Mac, and honestly no clean way around it inside our own app code, because the gap was down in how the native library itself gets built.

The stopgap, then the real fix

The first thing I did was the unglamorous thing. I built a patched tarball locally that made Catalyst compile and pointed our package.json at shopify-react-native-skia-0.0.0-new.tgz. It unblocked us, but a private tarball is not something you want to depend on. It is invisible to everyone else hitting the same wall, and it rots the moment upstream moves.

Digging through the issues, Samuel Scheit had already opened a PR with most of the Catalyst work. It had gone stale against main and never landed. The hard thinking was mostly done, it just needed to be brought current and pushed over the line. So I rebased his changes onto the latest main, sorted out the conflicts, and opened #3296, "adds support for macOS catalyst". Full credit to Samuel here. I take none of it for the original approach, I just carried it the last mile.

It was a small change in the end, around 149 lines across five files, and all additive:

  • packages/skia/scripts/skia-configuration.ts and build-skia.ts to produce the Catalyst-compatible Skia binaries.
  • A CI workflow addition so the Catalyst path keeps building and does not silently rot again.
  • An enable-catalyst.js helper in the example app to flip the Catalyst target on.

William Candillon merged it on October 1, 2025, and it shipped in react-native-skia v2.3.0. The release notes list it under fixes: "adds support for macOS catalyst (#3296)." A few days later I deleted our patched tarball and moved Cleft onto the official release. That part felt good. The hack came out and the real thing went in.

Why it was worth doing upstream

What I like about this particular thread is that the fix does not depend on where the React Native exploration ended up. That is the follow-up post. This part stands on its own: the Catalyst support is upstream now, so anyone building a React Native app that targets the Mac through Catalyst gets Skia working out of the box, and they never see the wall I hit.

That is the kind of contribution the dev log is here to hold: a concrete product constraint, a fix that was mostly already written by someone else, and a small push to get it merged where it helps everyone instead of just us. Most open-source work is exactly that, finishing the last mile on something good that stalled.