Built with Kittine — this page is compiled Kittine (.kitty) source, not hand-written HTML or a JavaScript framework.

Language & CLI reference

Every construct Kittine ships today

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 — components

A component is a func that returns JSX-like markup: func Hello() { return (<div>"Hi"</div>) }. Props are plain typed values, not signals.

purr — functions

A plain, non-view function: purr add(a, b) #n { return (a + b) }. Callable anywhere an expression is — same-file or imported.

<{name}> >> value — signals

One construct declares and mutates reactive state. First occurrence declares; every later one mutates. A bare <{name}> reads it.

event — an on<Event> handler's value

onInput={<{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 bindings

hold 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 — loops

spin<{item}> in list }{ .. }{ — the }{ fence delimits the body. Inside return ( ... ) it becomes a reactive Leptos <For>, keyed by an optional key(expr) clause.

Comparisons & logic

< <= > >= != && || — usable generally, not just in conditions: purr returns, craft<...> arguments, JSX interpolations.

craft / warn / error — logging

Three 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 operator

Renders 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 tags

Optional, 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 — structs

litter 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, .. } — maps

A 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 — enums

breed Shape { Circle(#n), Idle } declares a closed set of variants. Circle(5) builds one, a bare Idle references a unit variant.

pounce> — pattern matching

Matches 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 structs

A 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 — closures

A 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.

Generics

One type parameter per litter/breed: litter Holder<#t> { value #t }. Optionally bounded by a claw: <#t: Named>.

claw / bare .. for .. — traits

claw Named { describe() #w } declares a trait; bare Named for Point { purr describe() #w { .. } } implements it, with an implicit self.

import / export / private

import { 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.

Routing

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.

Two render targets, one compiler

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.