- You are inside this repo
- Bun installed
- Rust toolchain installed (
cargoavailable) - You are building a demo app under
examples/
bun run build-ffiWhat this does: compiles letui-ffi with cargo build --release.
Create examples/hello-world.ts:
import { COLORS, Column, Text, $, ff, onKey, run } from "../index.ts";
const count = $(0);
const countText = Text({
text: "count: 0",
foreground: COLORS.default.green,
});
ff(() => {
countText.setText(`count: ${count()}`);
});
const root = Column(
{
flexGrow: 1,
padding: "1 1",
gap: 1,
background: COLORS.default.bg,
border: { color: COLORS.default.bg_highlight, style: "rounded" },
},
[
Text({ text: "letui demo", foreground: COLORS.default.fg }),
countText,
Text({
text: "+/- update, r reset, q quit",
foreground: COLORS.default.grey,
}),
Text({
text: "starter uses gap/padding/flexGrow; wider layout API lives in StyleProps + BoxProps",
foreground: COLORS.default.grey,
}),
],
);
const app = run(root);
onKey("+", () => count(count() + 1));
onKey("-", () => count(count() - 1));
onKey("r", () => count(0));
onKey("q", () => app.quit());bun run examples/hello-world.ts+increment-decrementrresetqquit (custom handler)Ctrl+Qquit (default runtime handler)
- Replace static text with
Input+Button - Split UI into small builder functions (
buildHeader,buildBody,buildFooter) - Turn on metrics with
run(root, { debug: true })
bun run devrunsexamples/hello-world.tsafter building FFI- In
examples/, relative import from../index.tsis simplest starter path - Existing examples also use
@/...alias for modules insidesrc/ - The starter snippet above matches examples/hello-world.ts
- Current public props come from
StyleProps,BoxProps,TextProps,InputProps, andButtonPropsinsrc/types.ts - Keep node references stable across updates when you can; same-shape trees let runtime send deltas instead of rebuilding Rust tree state
run(root, { debug: true })writes phase timings todump/metrics.txt:serialize,textSync,rust,sync,flush