Tailor

Design it. Run it. Take the Rust.

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.

Download for macOS Read the tutorial brew install --cask wess/packages/tailor
CanvasSignInScreen
sign_in_screen.rsplain
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();
    }
}

The loop Interface Builder never closed

Drawing a screen is the easy half. The half that matters is what happens when it does not compile.

  1. Design

    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.

  2. Write the code behind it

    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.

  3. Run

    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.

What is in it

A builder, a compiler, and an editor that knows what the other two are doing.

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.

Errors point at components

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.

A real editor

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.

Your code, kept

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.

A component library is a plug-in

Tailor draws with guise and targets it through three traits. Another library is two crates and a line in main.

Drive it from an agent

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.

What it is not

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.

Documentation

Every page is written for someone using Tailor, not for someone selling it.