Show HN: Skip – Build native iOS and Android apps from a single Swift codebase (skip.tools)

322 points by marcprux ↗ HN
Hello Hacker News. I'm Marc, one half of the team that created skip.tools. Skip is a tool that transpiles your SwiftUI iOS app into a Kotlin Jetpack Compose app, and enables you to use a single language to create a complete app that reaches the entire mobile marketplace.

What it is: Skip stands in contrast to other cross-platform development tools like Flutter, React Native, and Xamarin, in that it enables the creation of genuinely native applications for both of the dominant mobile platforms. It doesn't embed a separate engine or runtime into your app, but instead lets you use pure Swift and SwiftUI to create the iOS side of the app (as per Apple's recommended best practices for creating iOS apps), and transpiles it into a pure Kotlin and Jetpack Compose app for the Android side (which is Google's recommendation for building Android apps). So your application will use platform-native controls and will automatically have all the affordances provided by the platform vendor: animations, accessibility, and future-proof evolution alongside OS updates.

How it works: you build a Skip app using the same tools that you use to create a standard iOS app: Xcode, Swift, and SwiftUI. Skip augments this workflow with a Swift Package Manager plugin called "skipstone", which transpiles your Swift into Kotlin each time you build your app, and launches the Android app side-by-side with the iOS app each time you run the app. The transpilation works not just on your primary app module, but also transitively processes all your dependent SwiftPM modules, so you can break complex projects down into individually testable sub-modules containing business logic or UI code. In fact, this is how our own adaptor modules for the standard frameworks are structured: SkipFoundation adapts the Foundation framework and SkipUI adapts the SwiftUI framework, so the same familiar API can be used when building the app. And there's a GitHub ecosystem of open-source modules supporting popular frameworks, including SQLite, Firebase, Lottie, and many other common building blocks of modern apps.

Over the past year Skip has evolved into a fully-capable solution for creating best-in-class apps for both iOS and Android. And today we are delighted to announce the release of version 1.0, meaning that it is ready for production use.

We have a wealth of videos and documentation available at https://skip.tools, and I'll be around to field any questions that any of you might have. Thanks in advance for taking a look!

Home: https://skip.tools

FAQ: https://skip.tools/docs/faq/

GitHub: https://github.com/skiptools/

120 comments

[ 3.2 ms ] story [ 173 ms ] thread
Looks very cool!

Looking at the docs gives a good overview of how it works.

Regarding transpilation and the tradeoffs (https://skip.tools/topic/transpilation-tradeoffs/), does the limitation of certain Swift features cause any significant friction with using parts of SwiftUI or other core libraries?

Wondering how much those (understandable) limitations on the transpilation limit what a random iOS dev might be able to do compared to what they can do in iOS land.

Also, using SwiftUI cross-platform makes me think that many android libraries would be a no-go.

One of the reasons that Xamarin development was painful (other than the numerous bugs in trying to target 2 foreign platforms) was that you couldn't _really_ utilize the large native ecosystems of either platform, and you would end up spending a lot of time "rewriting" libraries in dotnet.

Thanks for the positive words! Any limitations in the transpiler (such as some advanced generics) will only be limitations on the Android side – the iOS side can still do anything that is support in Swift. We discuss this a bit at https://skip.tools/docs/platformcustomization/

> Also, using SwiftUI cross-platform makes me think that many android libraries would be a no-go.

A unique feature of Skip is that the Kotlin/Android side is free to integrate with whatever gradle libraries it wants (see https://skip.tools/docs/dependencies/). Similarly, the Swift side can have any SwiftPM dependencies it wants.

Only your own transpiled modules, and the core Skip modules, will need to support transpilation. You can then include any native dependencies via your app's transpiled code that branches based on which platform/language you are targeting. So, for example, the Swift/SwiftUI side of the project can depend on the SwiftPM "https://github.com/firebase/firebase-ios-sdk.git" dependency, and the Kotlin/Compose side can depend on the Gradle "com.google.firebase:firebase-bom" dependency. This is what we ourselves do in the various integration modules we have (such as SkipFirebase, for this particular example).

Can vouch- been using this tool the last couple months and it's been magic. It's new so there is definitely a learning curve, but once you get things working it solves the cross-platform problem completely.
why is this better than RN or Flutter? Does it make styling easier? like android app can have a material design.
I would guess the apps are much lighter and less buggy.
Maybe? The docs say you have to build the swift app in a weird way (meaning you can't just convert your existing code to the new framework).

Doing something non-standard hints bugs to me.

Nothing non-standard about it, and you can certainly convert existing code. But if you want to convert an app - as opposed to a framework - you should start with our template and move your code over. The Xcode app project file format is opaque, making it very hard to migrate, and we rely on it being set up in a certain way to be able to build for Android
Does it really? The layouts on Android seem very iOS-y unless you apply "platform customisation" but that seems to defeat the purpose of this framework. I think it's a nice toy experiment to cross-compile things but not really transformative enough to be a viable option. Also becoming dependant on a for-profit company to build your app on top of the platform, I think there are others who have tried this as well.
I am curious, are you building your app on a non-profit company platform? If so, do you mind sharing it?
Are there showcase apps? A "Built with Skip" list?
We do have a showcase app, literally called "Showcase": https://skip.tools/docs/samples/skipapp-showcase/. It is available on both the Apple App Store and Google Play Store, so you can compare the two experiences side-by-side, if you have both an iOS and Android device.

No "built with" list yet, but coming soon…

tbh this is the main thing I was looking for on the webpage. It's hard for me to jump ship from my existing workflows unless I see a professional and highly sophisticated app example. I am sure it works for simple cases but I am concerned about limitations that one hits as one does more complex things
Out of curiosity, what are your existing workflows?

Note that Skip doesn't put any constraints on the iOS side of your app at all: if it can be expressed with SwiftUI or UIKit, then you can do anything. If there are bits that SkipUI doesn't translate to your liking (or at all), you can always drop down directly into Kotlin and Jetpack Compose to implement those any way you want. See https://skip.tools/docs/platformcustomization/ for details.

How does it work in practice?

In other words the Swift app will keep developing, requiring constant Android app generation via transpilation.

Does it keep track of generated and manually edited parts or will that step on each other?

The Skip transpiler runs locally on every build. It is implemented as an Xcode build plugin, so it is transparent and instantaneous. Every change you make to the Swift code is immediately converted into Kotlin, so each time you launch the app in the iPhone Simulator, the Android app will launch next to it in the Android Emulator. For a good overview of this process, take a look at: https://skip.tools/tour/skip-showreel/
That I had understood, I was looking for what @abewhite replied.
To answer the other part of your question: you don’t manually edit the generated Kotlin. Instead there are mechanisms for writing Kotlin inline in your Swift, dropping Kotlin files into the project, and other platform customization options: https://skip.tools/docs/platformcustomization/
Damn, this sounds too good to be true. Really nothing to add here except than keep pushing!

This fixes the big painpoint that nowadays' cross-platform frameworks come with performance tradeoffs as they have a unified presentation layer!

> first-class development environment (Xcode)

Are you sure

Also giggled at calling Xcode “an Idyllic IDE“.

I guess one ugly mobile app IDE is better than two.

Android studio is miles ahead from xcode this days - I'm envious ios dev. Wouldn't call android studio crappy
This looks great! Thanks for sharing here.
Good to see Skip on the home page! We were evaluating Skip just a couple weeks ago for a side project.

The issue we ran into is that we've already built a native iOS app with SwiftUI + a bit of UIKit. Integrating Skip with an existing app seemed like a significant task

Does that hold true in your experiences? Do you have any examples of small- or medium-sized existing apps that have migrated to Skip?

Yes, the docs even say that integrating into an existing app is way harder than starting with a new one!

https://skip.tools/docs/gettingstarted/#existing_development

Have not read the docs, but what’s the reason for that?

Is it not just a transpiler, since then it should work at any stage. No?

It’s missing things that are harder to work around if you already have code relying on those missing bits or done in an architecture it can’t transpile
Loving this so far, I've been working with it for a week now. I have a personal app, DownPay for iOS, that is built with SwiftUI that I want to bring to Android. I tried going the React Native route to build an android-only version but the context switching between SwiftUI, React Native, and then my day job made it challenging. I also tried Ionic and Ignite and wasn't successful with those either.

After testing the feasibility of other cross-platform frameworks, I landed on Skip. I LOVE that I don't have to break out of the "Swift" mental context, I just have to focus on writing an app in 1 language.

So before I commit fully I've been testing it out (building a demo app this week) and so far I am very impressed. The syntax to write platform-specific code (#if !SKIP #endif) is very easy to use once you get the hang of it.

It's amazing I don't have to learn Android to get something up and running at this speed with Skip. Hitting run in xcode and watching both emulators open feels like magic. I want to put this to the test so I plan to build a complete App with it from start to finish, ship it to both App Stores, and if all that goes smoothly I will proceed to migrate my main app using Skip.

> It's amazing I don't have to learn Android to get something up and running at this speed with Skip

Any thoughts on how you would debug issues on Android that don’t show up on iOS?

Skip generates native code, so you can open it in Android Studio and use all the native debugging tools
If you know how given the point of this is not having to learn android
None of the alternatives like RN or Flutter will allow you to skip learning about a specific platform if you have a platform-specific bug or issue.
> given the point of this is not having to learn android

We wouldn't say that is the point of using Skip. The benefit you get from using Skip is that you can use a single language and a single framework for building your app, and you can iterate on your app's development without needing to constantly context-swift between different worlds.

But there is no denying that at some point, you will need to interact with the Android universe: you will need to run the app on an Android emulator or device to test it, you will need to use Android Studio (or IntelliJ) to run the app in a debugger, you will need to grapple with the Android-specific nuances of deploying you app to the Play Store.

So every version you release you'll have to go back and fix the same bugs?

Or re-patch them in some way?

You don’t manually edit the generated Kotlin. You change the Swift. And if there are things you can't or don't want to do in Swift, there are mechanisms for writing Kotlin inline in your Swift, dropping Kotlin files into the project, and other platform customization options: https://skip.tools/docs/platformcustomization/
Sounds amazing. From a career point of view it is good for a dev as they click up native skills instead of some abstraction layer, while being able to do cross platform.

Been a long time since I worked on mobile (pre Kotlin!) but how does it handle differences in the UIs. Do you need "is android" directives. Are there Swift objects in your library that are android specific.

Since both SwiftUI and Jetpack Compose are declarative and semantic user-interface frameworks, components are generally presented in what the system believes to be the "correct" layout. So if you have a `SwiftUI.VStack` (which translates to a Compose `Column`) of buttons and text fields, then they will generally be presented with the "correct" spacing and alignment for the platform.

That being said, there is often plenty of need for customization with any but the most trivial app. So Skip has a lot of options for that, which is covered in the Platform Customization guide at https://skip.tools/docs/platformcustomization/.

Skip is definitely a great way to ease into the Android dev world.

Lots of options for adding platform-specific code - including being able to directly call Kotlin/Java APIs from your Swift, move back and forth between SwiftUI and Compose, etc.

https://skip.tools/docs/platformcustomization/

How can I load a library in C or c++ with this in a way that will work in both Android and iOS?
Glad you asked! We have an FFI framework (https://skip.tools/docs/modules/skip-ffi/) that enables you to use the same native code on both iOS and Android. I wrote a blog post about it at: https://skip.tools/blog/sharing-c-between-swift-and-kotlin/ . It is what powers some of our own frameworks like SkipSQL (https://skip.tools/docs/modules/skip-sql/).

On the Swift/iOS side, it simply uses Swift's excellent C integration; on the Java/Android side, it uses the venerable JNA library to handle loading and calling into embedded native libraries.

Will this work seemlesly with C only or C++ as well? I know swift this days have good c++ interop but not sure about jni/jna
You are correct that JNA's C++ integration – while possible – is not exactly seamless. It is an area that we are actively researching better solutions for.
[flagged]
I am not into mobile dev and was just having a look and don't have anything to say on the project itself.

The website is very slow to scroll on phone for some reason. Feels like scrolling has smoothing effect applied on it which does not work well everywhere and ends up slowing down scrolling (feels like 10 fps or something).

It's fast for me my on my iPhone 12 Mini (Safari) and Pixel 6 (Chrome). What device and browser are you using? Are any particular pages slower than others?
Given that this is now production ready, any limitations one needs to be aware of?

Please feel free to point to a doc that may already answer that.

To put the question in context, I'll preface by saying that Skip is unique among cross-platform app development solutions in that it isn't imposing an "alien" language or runtime on your app. It uses Swift on iOS, and Kotlin on Android, which are both the first-class recommended development languages for the respective devices. Any translation limitations can always be overcome by branching on the platform/language you are using, and just writing custom code for the platform in question.

That being said, while we have good translation coverage at both the lower levels (Foundation to the Android SDK) and higher levels (SwiftUI to Jetpack Compose), there are many Apple frameworks that we simply don't have any compatibility frameworks for yet. One commonly-request example is maps: we don't have anything that takes the MapKit API and converts into the Google Maps equivalent. However, this doesn't prevent you from implementing it yourself. For a simple example, see the Travel Bookings sample demo at 2:15 at https://skip.tools/tour/skip-showreel/, where you can see how you can drop MapKit and Compose Maps inline into your code.

As time goes on, Skip's community ecosystem of compatibility frameworks will grow and expand. But until then, there aren't any barriers to simply implementing them yourself.

Makes sense.. so any limitations are going to be on Android side, which if I understand correctly can just be implemented directly in Kotlin.
Our Jetpack Compose app is almost done, while our iOS app written in SwiftUI was released earlier this year. I would love to try this but I'm afraid it is too late in the development cycle.

I would just like to ask, what Material version are you using?

It looks like 3.0 from the screenshots? But I'm not sure.
Material 3
Thanks for making Skip! I will try to contribute to your repo. I lead the mobile team so definitely will evaluate this.
So far all looks interesting. The only thing that I’m still wrapping my head around is the pricing/licensing for “indie”

If I may suggest, instead of 6 month audit and machine locked license, perhaps something like where license is needed IFF the app is launched. This will reduce friction for individuals and pre-funding startups. I believe Unity and Unreal use this kind of licensing.

For me for "Indie" pricing is not clear what it means "members with less than 30K USD related annual revenue" Does it mean less than 30k revenue from app using Skip? Or any revenue such developer has? If the latter then any freelancer or indie will not qualify if have monthly salaries >2500usd doing any IT stuff or app dev using different frameworks.
Yes, their pricing/licensing is not ideal at the moment, IMHO of course.

They need to build critical mass and hence initial tinkering should be as friction free as possible. Landscape is full of alternatives so people need to get started as quickly as possible.

They seem to have a valuable product, but this initial friction might reduce traction, again IMHO.

If I learned anything from expo -- get signed up so you can get grandfathered in to future plans. They're almost gonna certainly increase prices.
First they have to gain critical mass. Not sure what was Expo’s initial pricing like.
Excellent development in the direction of reducing the browser+JS/TS apps! Congratulations!
This is magical. Almost too good to be true. I hope this is indeed production ready.
Looks interesting. Does it support things like the device camera?
How do you handle the minimum denominator issue that is invariably present in all cross platform tools? In other words, what are the sacrifices you made in each platform to make it all work? And why each of these specifically?
Skip isn't a minimum denominator framework. With Skip, you write normal iOS code. So you legitimately make zero sacrifices to your iOS app.

Now of course Skip can't have complete Android coverage for every iOS framework - far from it. So if you use something on the iOS side that has no Android coverage, you have to create a separate code path for Android, where typically you'll utilize an equivalent Android framework/function. Skip has several mechanisms for integrating Android code, including being able to call Kotlin and Java API directly from your Swift. These mechanisms are also how you can differentiate parts of your Android app as desired, and how we create our own cross-platform libraries.

I was just looking through everything and didn't see much when it came to scale. Having been the founder of a devtool platform in the past, one common question we had was what would happen to the platform if someone built the next Flappy Bird. Would we be able to keep up with the insanely fast growth?

Have you addressed that with Skip?

Looks incredible, btw. :)

Skip is a locally installed and run dev tool. It is infinitely scalable! :)
One big advantage here is you can “eject” at any point and have two functioning, normal native apps. If you’re talking about scaling a team then you can simply eject and hire for each platform if you outgrow the tool.
Great work. Cool to see this here, I’ve been meaning to try it. We have two large Swift apps at work that wouldn’t be a good fit but I’ll check it out for a side project. The bulk of our Swift code is actually non-ui code as we have a somewhat complicated data and offline sync layer. We’re actually more interested in the Swift on Android and Wasm developments for this reason which (I saw you’ve also been contributing to the Android Swift toolchain Marc).
How does it handle cases like Material You Dynamic Colors?

I am thinking about making an app, and we want to support the best offerings from each OS. So the dynamic colors is important on the Android side

We’ve been thinking about KMP til I read about this, which sounds promising!

Skip translates your SwiftUI into Compose, so it uses your Material theme just like any other native Compose app would
I was wondering a while back if a tool like this existed. Good job!
This is really really awesome. The only thing is I feel like it would be heavily reliant on SwiftUI/Jetpack Compose and so breaking changes would break the entire codebase until the tool is updated since there is no 'runtime'. I'm also curious how hacky workarounds would be transpiled over to Compose, since in my experience SwiftUI can involve lots of hacks in order to get something more unconventional working properly.
Yeah, we still leverage UICollectionView a lot even in SwiftUI as there’s no suitable replacement, grids have a bunch of downsides still right now.
As others, from the videos, I really like the tight Xcode integration. Reading the FAQ I do have few concerns,

1. Open-source, it mentions GPL forms, is there a reason MIT not mentioned? is that not considered open-source (especially with many iOS/Swift using MIT to be compliant with store distribution).

2. Packages, how does it handled packages? or the cases when you need to have branching for iOS/Android? the FAQ does not address this.

3. How Apple service APIs being handled on Android? I didn't look at the example weather app, but as an example, Apple got WeatherKit. or in my case case I use the built-in geolocation APIs.

My concrete example, I have a small app I've made. It uses geolocation from Apple (to detect country city, etc), It uses AdMob and Apple's built-in In-App / Subscription services.

I think this is a fair example of simple commercial product, and it'll be nice if you have some example for ads and in-app/subscription which might be important for closed/paid monetized projects...

- The LGPL license for Skip's libraries is the same license used in projects like WebKit. It does not interfere with using Skip in commercial, closed-source apps.

- Skip is based on Swift Package Manager and fully both dual-platform and iOS and Android-specific dependencies.

- Skip has a suite of dual-platform libraries, and for anything that isn't covered, multiple techniques for integrating platform-specific code and libraries. These include being able to use Kotlin right inline with your Swift and mix Compose code in with your SwiftUI.

https://skip.tools/docs/platformcustomization/

https://skip.tools/docs/dependencies/#implementation