Writing/Native modules
Shipping a component library into production
Building one is easy. Using your own library in an app real people rely on is where you find out what's wrong with it.
Building a component library is easy. You pick a problem, you solve it in isolation, you write a demo app that shows it working, and everything behaves, because nothing is asking anything difficult of it.
Using your own library inside an app that real people rely on is where you find out what is actually wrong with it. Liquid Glass went into TeamTipOut about four weeks after I started it. The first week broke two things I would never have found in a preview.
The bugs you cannot find alone
The first was a crash on the New Architecture. A slider passed a fractional value across the bridge as a double, where the Swift side expected a quantised step. In the demo app the slider only ever moved between clean stops, because I was the only person who had ever touched it.
“A preview app never holds a value from a real user, and never renders under real layout pressure.”
The second was a segmented control that measured its own width on first paint, before the font had loaded and the labels had settled. On a warm simulator with a cached font it never happened once. On a real phone from a cold start, it happened most of the time.
Optional by default
Both fixes were small. The structural lesson was not. If a library ships native modules, every one of them has to be an optional peer, because the failure you are designing for is not a bug in your code. It is a consumer who installed the JavaScript package and never linked the native side.
// never let a missing peer throw at importexport function optionalRequire(id: string) { try { return require(id) } catch { return null }} const Native = optionalRequire('…/glass-native')const tier = Native ? 'native' : 'fallback'That one decision turned a class of crash-at-import failures into a class of quiet degradations. The component still renders. It just renders the tier below, and the app author never has to think about it.
What I would do differently
I would put it in a real app much earlier: week one, not week four. The demo app was reassuring and almost entirely useless. The only honest test of a tool is something that breaks when the tool breaks.
