What SkeleKit Is

The scope, principles, and programming model of SkeleKit.

SkeleKit [pronounced /ˈskel.ə.kit/] is a C# UI framework built directly on top of UIKit. It gives .NET for iOS apps a layout system, controls, bindings, navigation, and the usual application services without trying to hide the platform underneath.

It is not a cross-platform renderer and it does not draw its own imitation of an iOS interface. A SkeleKit app is still a fully native iOS app. It uses real UIKit controls, follows UIKit's behavior, and can drop down to the native APIs whenever the framework does not cover something.

UIKit underneath

SkeleKit controls wrap the corresponding UIKit types. SkeleKit handles their composition and layout, while UIKit remains responsible for rendering and interaction. A button looks and behaves like an iOS button because, underneath, that is exactly what it is.

This also means that features such as Dynamic Type, safe areas, dark mode, accessibility, and the keyboard are not afterthoughts added to a platform-neutral UI. They are part of the platform SkeleKit is built around. The framework handles the annoying part of UIKit, but it does not replace it.

Of course, wrapping UIKit does not mean that every native API suddenly has a nice SkeleKit abstraction. UIKit is enormous, and SkeleKit is still young. When something is missing, the native control is available through View.Native, any UIView can be hosted with NativeView, and the underlying view controller is reachable via ContentView.Controller.

UI written in C#

SkeleKit view trees are plain C# object initializers:

Content = new StackPanel
{
    Spacing = 12,
    Padding = new Thickness(20),
    Children =
    {
        new Label { Text = "Hello, iOS" },
        new Button { Text = "Continue" }
    }
};

There is no XAML parser, no storyboard, and no Auto Layout constraint graph to maintain. Layouts such as Grid, StackPanel, and Overlay describe the view tree, while SkeleKit measures and arranges it. The result is somewhat familiar if you have used WPF or UWP, but it is still normal C#: helper methods, conditions, loops, and the compiler all work as expected.

I don't think writing UI in code is automatically better than XAML. XAML can be very nice, especially with good tooling. It was simply a much larger problem than the one I wanted to solve. Object initializers get surprisingly close to the syntax I wanted without adding another language and toolchain to the framework.

A familiar application model

The view syntax is only one part of SkeleKit. It also provides the structure around it: pages, navigation, dependency injection, bindings, commands, and application setup. A small app can start with a single ContentView; a larger one can use tab and navigation stacks without managing UIViewController instances anywhere.

MVVM is 100% supported, while not forcing it on every application. Bindings work with regular INotifyPropertyChanged objects and commands use ICommand. There is no required base ViewModel, so something such as CommunityToolkit.Mvvm fits naturally, but plain classes work too.

Because iOS device builds use full AOT and trimming, bindings avoid reflection, expression-tree compilation, and runtime code generation. That restriction affects some of the design, but I would rather make AOT part of the framework from the beginning than discover much later that a convenient API only works in the simulator.

Focused on Apple platforms

SkeleKit currently targets .NET 10 for iOS 18 and later, with iPhone and iPad as the actual focus. tvOS may follow later, but SkeleKit is not intended to become a write-once UI for every platform - so even then it would require two different code bases.

That limited scope is intended. Supporting each platform properly is a very different goal from making one interface run everywhere. SkeleKit can make stronger assumptions about iOS because it does not also have to pretend that the same control is an Android view, a Windows control and an HTML element.

What it is not

SkeleKit borrows ideas from WPF and UWP, but it is not a reimplementation of either one. It is also not SwiftUI translated into C#, a complete wrapper for every UIKit API, or an attempt to make the native platform disappear.

The basic idea is much smaller: keep UIKit and the native iOS experience, then remove the parts that make building an app in raw UIKit unnecessarily repetitive. You still build an iOS app, just with C# and a more convenient layout model.