func — components
A component is a func that returns JSX-like markup: func Hello() { return (<div>"Hi"</div>) }. Props are plain typed values, not signals.
Language & CLI reference
Search or filter by topic below — real, current syntax only. Nothing planned or removed is listed here; see the Roadmap for what's not built yet.
func — componentsA component is a func that returns JSX-like markup: func Hello() { return (<div>"Hi"</div>) }. Props are plain typed values, not signals.
purr — functionsA plain, non-view function: purr add(a, b) #n { return (a + b) }. Callable anywhere an expression is — same-file or imported.
<{name}> >> value — signalsOne construct declares and mutates reactive state. First occurrence declares; every later one mutates. A bare <{name}> reads it.
event — an on<Event> handler's valueonInput={<{name}> >> event} reads what was actually typed, not just a fixed literal — the handler binds ev and lowers event to event_target_value(&ev). Try it: →
hold — plain bindingshold navigate >> use_navigate() — a non-reactive local, evaluated once. For hooks that need to run eagerly at setup, not lazily in an event handler.
if> / orif> / else>Indentation-delimited control flow. >> inside a condition is always equality, never assignment: if><{status}> >> "active".
spin — loopsspin<{item}> in list }{ .. }{ — the }{ fence delimits the body. Inside return ( ... ) it becomes a reactive Leptos <For>, keyed by an optional key(expr) clause.
< <= > >= != && || — usable generally, not just in conditions: purr returns, craft<...> arguments, JSX interpolations.
craft / warn / error — loggingThree levels of the same statement — craft<expr>, warn<expr>, error<expr> — mapping to leptos::logging::log!/warn!/error!. Arrays, litters, breeds, and stashes format with {:?} instead of {}.
&expr — reference operatorRenders a real Rust & reference, for calling any API that needs one: serde_json::to_string(&value). Binds like unary -. An interop escape hatch — Kittine values are otherwise always owned.
#n / #w / #f — type tagsOptional, two-character sigils — shorter than f64/String/bool. Omit one on a prop or purr param/return and it's inferred from the body.
litter — structslitter Point { x #n, y #n } declares a real Rust struct. Point { x: 3, y: 4 } constructs one; .x reads a field, no parens. Every litter/breed derives serde::Serialize/Deserialize too — serde_json::to_string(&p) just works.
stash{ key: expr, .. } — mapsA real String-keyed map, lowering to HashMap::from([..]). Typed like an array — #n{} / #w{} / #f{} — mirroring #n[] / #w[] / #f[]. Read/mutate like anything else: .get(k) to read, <{m}> >> stash{..} to replace.
breed — enumsbreed Shape { Circle(#n), Idle } declares a closed set of variants. Circle(5) builds one, a bare Idle references a unit variant.
pounce> — pattern matchingMatches a breed value, arm by arm: Circle(r) >> craft<r>. else> catches the rest. Works as a statement (branch and act) and now as an expression (branch and compute): return (pounce> result Ok(v) >> v Err(e) >> 0) unwraps a Result-shaped value and returns it in one step.
litter[] / breed[] — arrays of structsA litter/breed name is a real prop/purr param or return type now, optionally []-suffixed: purr matching(DocEntry[] entries, query) DocEntry[] { .. } — a real Vec<DocEntry> once generated, the same way #n[] / #w[] / #f[] already work for scalars.
|param| expr — closuresA closure literal, lowering verbatim to a real Rust closure — the missing piece a real iterator method needs: entries.iter().filter(|e| e.title.contains(&query)).cloned().collect(). The zero-param form || expr works too. This very search box is built from exactly this — try it below.
One type parameter per litter/breed: litter Holder<#t> { value #t }. Optionally bounded by a claw: <#t: Named>.
claw / bare .. for .. — traitsclaw Named { describe() #w } declares a trait; bare Named for Point { purr describe() #w { .. } } implements it, with an implicit self.
import / export / privateimport { Nav } from './Nav.kitty' brings a component into scope. private opts an item out of being importable; export import re-exports one through a barrel file.
leptos_router is in scope everywhere, zero new syntax — <Route path={StaticSegment("about")} view={About}/>. Dynamic segments and programmatic navigation both work.
kittine-compiler build <input>Compiles <input> and every import it reaches, recursively, into sibling .rs files. Only rewrites a file whose output actually changed. --output <path> overrides the default.
The exact same compiler output feeds vite-plugin-kittine (CSR) or cargo-leptos + Axum (SSR) — zero compiler changes either way. Full commands on the Install page.