Run, Build, Stop
No setup: a project you have never exported gets its own build directory. Debug or release. The console tags the compiler's output apart from your app's, and the app runs with backtraces on.
Tailor is a visual interface builder for gpui — Interface Builder for Rust. Lay out a screen from real components, write the code behind the controls, press Run, and leave with a crate that has no dependency on Tailor in it.
impl Render for SignInScreen {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div()
.flex()
.flex_col()
.gap(px(16.))
.child(Title::new("Welcome back").order(2))
.child(TextInput::bind(&self.email, cx))
.child(
Button::new("submit", "Sign in")
.variant(Variant::Filled)
.full_width(true)
.on_click(cx.listener(|this, _window, cx| this.submit(cx))),
)
}
}
impl SignInScreen {
/// Sign the user in.
pub fn submit(&mut self, cx: &mut Context<Self>) {
let who = crate::accounts::current();
self.email.set(cx, who);
cx.notify();
}
}Drawing a screen is the easy half. The half that matters is what happens when it does not compile.
Drag real components onto a canvas. A Button on it is a
real one, reading the same theme — there is no second rendering path to
keep in step.
Wire a click to an action, then write the method, with completion over what is actually in scope. Your code lives in the project file, so regenerating writes around it.
Press ⌘R. Tailor writes the crate, cargo builds it, your app opens. A compiler error comes back as a row you can click — and it selects the component that caused it.
A builder, a compiler, and an editor that knows what the other two are doing.
No setup: a project you have never exported gets its own build directory. Debug or release. The console tags the compiler's output apart from your app's, and the app runs with backtraces on.
Codegen tags every node with the line it generated. A type error at
main_screen.rs:41 resolves back to the button that produced
it, in the gutter and in Problems.
Every file a build compiles, parsed by tree-sitter, with line numbers, inline diagnostics and ⌘F. ⌥⌘O hands the file to Zed, VS Code, or whatever you use.
Action bodies live in the .tailor file. Modules you add
are declared by main.rs and written once — an export reports
them as kept, never replaced.
Tailor draws with guise and
targets it through three traits. Another library is two crates
and a line in main.
An MCP server over the same document model. It saves after every change and the app watches the file, so a screen built by an agent appears on the canvas as it is built.
Not a runtime. The .tailor file is a design
document, not something your app loads. What ships is a Rust file you own,
and the ending Tailor is built for is the one where you take that file and
stop opening the builder.
Not cross-platform, yet. gpui targets the desktop, so Tailor does too — one artboard size, which is the window your app opens at. A wasm backend is the point at which a second one would mean something.
Every page is written for someone using Tailor, not for someone selling it.