We've written about templating one app idea across the four Legi & Amenzi apps — this is the layer underneath that made it possible. Every app in our portfolio pulls from one internal Swift package: shared components, design tokens, and screen scaffolding that don't get rebuilt from scratch each time. It's the single biggest reason a new, simple app can go from idea to submission in weeks instead of months. It's also the single easiest way to ship the same bug to nineteen apps at once if we're not careful about it.
What actually lives in the shared package
The boring, high-leverage stuff: color and spacing tokens for light and dark mode, a settings screen scaffold, an onboarding carousel component, empty-state and error-state views, a paywall shell for our subscription apps, and a handful of list-row and card components tuned for the diffing behavior we wrote about in SwiftUI in production. None of it is glamorous. All of it is the code every new app needs on day one, and none of it should have anything to do with what makes a given app distinct.
What deliberately stays out of it
Brand color, iconography, copy voice, and any screen that expresses the actual idea of the app — a quiz engine for Civio, a maintenance log for My Mustang, a fasting timer for Easy Fasting — is written per app, on purpose. The test we use: if putting something in the shared kit would make two apps look more alike to a user than the product reason for them being separate apps justifies, it doesn't go in. The kit exists to remove the boring 20%, not to homogenize the 80% that's supposed to be different.
Versioning is the actual discipline, not the code
The risk with a shared package isn't writing it — it's that a "small" change to a shared component can silently ripple into apps you're not actively looking at. We pin each app to a specific version of the internal package instead of always building against the latest, and we bump that pin deliberately, app by app, verified with that app's own testing pass — never as a side effect of working on a different app entirely. It's slower than letting every app auto-update, which is exactly the point: a shared kit should never let a bug travel faster than our attention does.
Where it pays off most
Not on the flagship apps — on the small, fast-to-validate ones. When testing a new idea means the settings screen, onboarding, and paywall shell are already solid on day one, the only thing left to build is the part of the app that's actually new. That's what let us treat app ideas as small, testable bets instead of each one being a multi-month commitment before we know if the idea has legs.
A shared UI kit is an accelerant, not a shortcut — it still has to be maintained like any other piece of production code, arguably more carefully, because its blast radius is every app we ship instead of just one.