macOS
AppKit
macos-appkitThe Mac’s native toolkit: the same NSButton, NSTableView, and menu bar that Finder and Mail are made of. Packs as a signed, notarized .dmg.
Building for macOSDay is a Rust framework that builds your app for Android, iOS, HarmonyOS, Windows, macOS, Linux, and the web — with each platform’s own native controls. Your product looks and works the way each platform’s users expect.
cargo install day-cliInstalls the day CLI from crates.io. Requires a stable Rust toolchain (rustup).
Runs natively on
macOS
macos-appkitThe Mac’s native toolkit: the same NSButton, NSTableView, and menu bar that Finder and Mail are made of. Packs as a signed, notarized .dmg.
Building for macOSiOS & iPadOS
ios-uikitApple’s UI framework for iPhone and iPad: real navigation pushes, tab bars, and system text handling. Ships as a normal .ipa.
Building for iOS & iPadOSAndroid
android-mdcGoogle’s native widgets over android.view, on phones, tablets, and foldables, themed by the OS and packaged as .apk or .aab.
Building for AndroidLinux
linux-gtkGNOME’s toolkit, styled by libadwaita. It is the desktop Ubuntu, Fedora, and Debian install by default. Ships as a flatpak.
Building for LinuxLinux
linux-qtThe toolkit beneath KDE Plasma: the desktop of Kubuntu, openSUSE, and the Steam Deck. Portable enough that it is also a Day target on macOS and Windows.
Building for LinuxWindows
windows-xamlWindows 11’s native controls, hosted in a Win32 window with no framework runtime to install. Packs as .msix plus an installer.
Building for WindowsHarmonyOS
harmony-arkuiHarmonyOS Next’s native UI framework, driven through its C node API on Huawei phones and tablets. Packs as a .hap.
Building for HarmonyOSWeb
web-domThe browser’s own widgets: the same Rust compiled to WebAssembly, driving real <button> and <dialog> elements. Hosts as static files. Open the live build.
What native means here
A Day app is made of the platform's own controls. The button you write in Rust becomes an NSButton on macOS, a UIButton on iOS, and aMaterialButton on Android — the same objects an app written in Swift, Kotlin, or ArkTS creates. Attach Accessibility Inspector or Xcode's view debugger to a running Day app and those are the classes you find. Because those are the platform's controls, text input, scrolling physics, and screen-reader support are the platform's too, and they improve with every OS update.
day pack produces a signed and notarized .dmg, an .ipa, an .aab, an .msix, a flatpak, or a .hap — whatever that platform's users install.One codebase, every platform
This is a complete, working counter, the whole thing. The same function becomes a real AppKit control on macOS, UIKit on iOS, Material on Android, and native GTK, Qt, XAML, and ArkUI widgets everywhere else. Those are the screenshots in the carousel above: real platform components, from this exact kind of code.
use day::prelude::*;
fn counter() -> impl Piece {
let count = Signal::new(0i64);
column((
label(move || format!("{} clicks", count.get())),
row((
button("–").action(move || count.update(|c| *c -= 1)),
button("+").action(move || count.update(|c| *c += 1)),
)).spacing(8.0),
))
.spacing(12.0)
.padding(16.0)
}One function, a native counter on all twelve targets.
Why Day
Cross-platform tools usually make you choose between apps that feel native and a codebase you only write once. Day keeps both.
Every control is the platform’s own: a real Mac button on macOS, real Material on Android. Text, scrolling, shortcuts, and dark mode behave the way each platform’s users already expect, and keep improving with OS updates you never have to ship.
Day apps are compact native binaries that link the toolkit the operating system already has, so they start in milliseconds and install in megabytes.
Six operating systems and the web from a single Rust program. A feature lands once and ships everywhere at the same time.
Screen-reader support uses each platform’s own accessibility tree, and every user-facing string is localized with Mozilla Fluent. Both are in the framework from the first build.
Each commit builds a full demo app on all twelve targets, drives it end to end, and captures screenshots. The gallery on this site is those exact artifacts.
One command line creates, runs, tests, and packages signed installers for every platform: dmg, App Store, Android, flatpak, Windows. The same automation scripts drive the app everywhere, for CI and for AI-assisted development.
Menu bar, keyboard shortcuts, a preferences window, toolbars, and multi-window are part of the framework, and the Window menu on macOS assembles itself.
When you need the platform’s own UI framework, use it: SwiftUI views embed in the Day tree on Apple platforms with typed Rust constructors, and per-platform tweaks reach any native widget’s API, so the platform’s full toolkit stays within reach.
One dayscript walkthrough is an end-to-end test, an accessibility pass, and your screenshot shoot — per locale and theme. The captures feed the store listings in store/ and a generated app website, so shipping collateral stays as current as the build.
Agents & automation
Every Day app embeds dayscript, the same automation engine that drives Day's own release pipeline. A YAML script, an agent over MCP, or your CI taps buttons, types text, asserts what's on screen by stable element ids, and captures screenshots, identically on every platform.
Evaluating your options
Electron, Tauri
Your interface is a web app, so a web team is productive from the first day and the npm UI ecosystem is available.
Flutter, Iced
The framework draws every pixel itself, so screens are identical on every platform and a design system carries over exactly.
Swift + Kotlin + C++ teams
Each app uses its platform’s full toolkit directly, with one codebase and one team per platform.
Just a Mac app? Just Linux?
A Day app on one platform is a native app on that platform, with native packaging and scriptable testing. A second platform later is one command, day app add-toolkit.
Day keeps the platform's own components and the single codebase. It is young, it relaunches rather than hot-reloads, and it leaves pixel-level branding to the platform.
Read the comparison →How it works
Day builds your interface from real platform components once, then keeps each one connected to your application's state. A change runs only the closures that read it and ends in one native setter call. Day apps perform like hand-written platform code because, at runtime, that's what they are.
let section = Signal::new(String::new());
selector(section)
.style(SelectorStyle::Sidebar) // native split view / tabs / pushing list
.item("home", "Home", home_page)
.item("settings", "Settings", settings_page)