Describe
Start with your app idea in the AI assistant.
Native Apple UI, live in Lua
Build polished macOS and iOS interfaces with declarative Lua, real AppKit/UIKit controls, and no compile cycle between edits.
⌘ Edit. Run. See it immediately.
A real native window, rendered from Lua
The lua-objc film
A short film about building native Apple apps in Lua, from the first edit to a running interface.
Lua Studio for iPad
Describe the iPhone app you want. Lua Studio turns the idea into an editable project, shows the changed files, and runs it in a native iPhone preview right on your iPad.
Build on iPad today iPhone app coming soon
Start with your app idea in the AI assistant.
Review and edit the project files as they are created.
See your iPhone app in a live native preview.
The short version
SwiftUI is elegant. The compile-and-preview loop around it can be anything but. lua-objc keeps the expressive part and removes the ceremony between an edit and the thing you are building.
AppKit and UIKit controls do the real work: selection, keyboard behavior, accessibility, focus, and platform metrics.
Edit a Lua controller or etlua view, run it directly, and get a fresh native window without an Xcode build step.
Headless tests, screenshots, and native layout dumps make behavior and geometry inspectable by people and agents.
A small proof
One app. A real network request, native loading state, a location sidebar, and a seven-day forecast that scrolls when it needs to.

Stable structure belongs in etlua. State, network boundaries, and actions stay in Lua. The result is simple to read, simple to test, and still feels at home on the platform.
Read the weather walkthroughStart with a folder
Keep the shape familiar: a model for data, a controller for actions, and views for declarative structure. The framework instantiates the controller returned by init.lua and calls its createWindow() method. Reusable view components return view trees.
The workflow is familiar: a controller prepares model data and passes it to a template. Here, Controller.lua renders views/*.etlua into real AppKit/UIKit controls. Partials, layouts, and reusable Lua view components keep presentation organized.
The key difference is lifetime. Controllers and native widgets stay alive across clicks, typing, and asynchronous results. Native callbacks invoke actions, and controllers explicitly update the views. Model changes do not yet trigger automatic reconciliation.
Use Laravel as a guide for separating responsibilities: models own queries and mutations, controllers coordinate actions, and views own presentation. This is an architectural comparison; the models are ordinary Lua code, with no Eloquent-style ORM implied.
Read the Laravel comparison<% if #city.forecast > 0 then -%>
<Divider />
<Label text="7-day forecast"
size="14"
weight="semibold"
/>
<ScrollView contentWidth="772"
contentHeight="188"
fixedHeight="200"
fillWidth="true"
horizontal="true"
>
<HStack spacing="12"
alignment="top"
fixedWidth="772"
>
<% for _, day in ipairs(city.forecast) do -%>
<VStack spacing="4"
alignment="center"
fixedWidth="100"
>
<Label text="<%= day.date %>"
size="11"
color="secondary"
/>
<Image src="<%= day.icon %>"
fixedWidth="28"
fixedHeight="28"
label="<%= day.desc %>"
/>
<Label text="<%= day.tempMax or "--" %>°"
size="16"
weight="medium"
/>
<Label text="<%= day.precipProbability or "--" %>% rain"
size="10"
color="secondary"
/>
</VStack>
<% end -%>
</HStack>
</ScrollView>
<% end -%><VStack flexGrow="1"
padding="24"
spacing="12"
alignment="leading"
>
<Label text="Hello from Lua"
size="24"
weight="bold"
/>
<Label text="A SwiftUI-like API backed by native AppKit controls."
size="14"
/>
<SystemImage name="swift"
size="64"
label="Swift"
/>
</VStack>local ns = require("AppKit"
)
local xml = require("ui.xml"
)
function Controller:createWindow()
local cfg = xml.renderFile(VIEWS .. "Window.etlua"
)
return ns.Window(cfg)
endBuilt with lua-objc
A native Mac app that turns storage into a visual map, with the context to review cleanup before anything moves.
Explore Diskmap
Open source, Apple-shaped
Contributors are very welcome. Bring a widget, an example, a test, a design idea, or simply a sharp question.