Get Started
From an empty Rust project to a Glint component rendering on screen.
Glint is a set of .slint sources. The crate’s only job is to hand your build
script the directory they live in, so that @glint/... imports resolve the
same way @lucide does. Four dependencies, one build script, and the
components are yours.
This guide assumes a Rust toolchain and an empty project:
cargo new my-appcd my-appAdd the dependencies
Slint is a runtime dependency; the three that produce code — the Slint compiler, Glint, and Glint’s icon peer dependency — are build dependencies.
[dependencies]slint = "1.17"
[build-dependencies]slint-build = "1.17"# Glint is unreleased: nothing is on crates.io, so depend on the repository.glint-ui = { git = "https://github.com/thelipe7/glint-ui" }lucide-slint = "1.30"lucide-slint is a peer dependency rather than a bundled one: Glint’s public
API references its icon types, so your build has to know where they are. A
checkout works just as well as the git URL — glint-ui = { path = "../glint-ui" } — and is what to use while the repository is still private.
Register the libraries in build.rs
The Slint compiler resolves @glint/... and @lucide through library paths.
Register both, then compile your interface:
use std::{collections::HashMap, path::PathBuf};
fn main() { let libraries = HashMap::from([ ("glint".to_string(), glint_ui::lib()), ("lucide".to_string(), PathBuf::from(lucide_slint::lib())), ]);
let config = slint_build::CompilerConfiguration::new().with_library_paths(libraries);
slint_build::compile_with_config("ui/app-window.slint", config) .expect("failed to compile the Slint sources");}The name on the left of each pair is the alias an import writes. Register
glint under another name and @glint/components/button.slint stops
resolving.
Write the interface
Create ui/app-window.slint. Import the components you want and Tokens, the
semantic layer every Glint component reads — a window that paints itself
Tokens.color-background follows the theme along with everything in it.
The preview below is this exact file, running. Switch the theme or the palette in the header and it follows, because nothing in it names a color.
import { Button } from "@glint/components/button.slint";import { Input } from "@glint/components/input.slint";import { Tokens } from "@glint/theme/tokens.slint";
export component AppWindow inherits Window { title: "My app"; min-width: 420px; min-height: 220px; background: Tokens.color-background;
in-out property <string> username; in property <bool> signing-in: false; callback sign-in();
VerticalLayout { padding: 24px; spacing: 16px; alignment: center;
Text { text: "Sign in"; color: Tokens.color-foreground; font-size: Tokens.typography-h2-size; font-weight: Tokens.typography-weight-semibold; }
Input { placeholder: "Your username"; text <=> root.username; }
Button { text: "Sign in"; loading: root.signing-in; clicked => { root.sign-in(); } } }}Properties and callbacks declared on AppWindow are the seam between the
interface and your program, and the direction is in the declaration:
in-out property <string> username is state both sides touch,
in property <bool> signing-in is state Rust sets and the interface only
reads, and callback sign-in() is an event Rust handles. Glint’s components carry none
of your application’s state — a Button fires clicked, and what that means
is yours.
Import from the barrel instead if you prefer one line:
import { Button, Input, Tokens } from "@glint/glint.slint";Both resolve to the same sources. Per-component imports compile less, which is
worth having in a project with many small .slint files.
Run it
slint::include_modules!() brings in what the build script generated: one Rust
type per exported component, with a getter and setter per property and an
on_<callback> for each callback.
slint::include_modules!();
fn main() -> Result<(), slint::PlatformError> { let ui = AppWindow::new()?;
let handle = ui.as_weak(); ui.on_sign_in(move || { let ui = handle.unwrap(); println!("signing in as {}", ui.get_username()); });
ui.run()}cargo runThe window that opens is the preview above, in your own app.
Where to go next
- Theming — theme modes, the built-in palettes, and how to build one of your own.
- Components — one page per component, each with a live preview and a generated API reference.
Glint ships a handful of default strings — Continue, Cancel, Close,
Select…, Search… — through @tr(...), so they follow your application’s
translations when you set them up. Each one is also a property, so passing
already-translated text works without a catalog.