Pups (components)
A pup is any .rat file under pups/. Its filename becomes a tag (pups/greeting.rat becomes the greeting tag). Its > server block defines defaults that callers can override via attrs, and its > page block is the markup. Attributes on the call site become local variables inside the pup body.
Define a pup
pups/greeting.rat
tagline is a server var with a default — any caller can override it by passing the attribute. Inside the body it reads like any other identifier.
> server
tagline: 'hello'
> page
<p class['greeting']> [tagline], friend. Use the pup
Pass props as attrs
Call sites look like HTML tags. The attribute becomes the local variable inside the pup — tagline['nice to meet you'] inside the call seeds the pup's tagline for that instance.
> page
<greeting>
<greeting tagline['nice to meet you']>
<greeting tagline['welcome back, Ada']> hello, friend.
nice to meet you, friend.
welcome back, Ada, friend.
Children slot
<children> inlines caller markup
A pup that wraps content uses the children tag to splice in whatever the caller wrote between the open and close tags. The children evaluate in the caller's scope, so any [name] reads in there resolve against the page that invoked the pup — not the pup's own state.
# pups/card.rat
> page
<div class['card']>
<header> Card
<div class['card-body']>
<children>
# somewhere in a page
<card>
<h2> Hello
<p> Anything goes here. Pup with its own state
Reactive counter as a component
Pups can declare their own page-tier state and handlers — the framework rebinds each instance separately, so two counter tags on one page keep independent counts.
# pups/counter.rat
> page
count: 0
<button on_click[count++]> clicked [count] times
# in a page
<counter>
<counter> Next: Services — singletons with state and methods you call as auth.login(u, p) from any page.