@tooey/ui
v2.0.0
Published
Token-efficient UI library for LLMs
Downloads
314
Maintainers
Readme
tooey
token-efficient ui library for llm output
~39% fewer tokens than react | ~10kb minified | 0 depsinstall
npm install @tooey/uior via CDN:
<script src="https://unpkg.com/@tooey/ui/dist/tooey.js"></script>usage
tooey.render(document.getElementById('app'), {
s: {n: 0},
r: [vs,[[tx,{$:"n"}],[hs,[[bt,"-",{c:"n"}],[bt,"+",{c:"n"}]],{g:8}]],{g:8}]
});components
layout vs hs dv gr
text tx bt
input In ta sl cb rd
table tb th bd Tr Td tc
list ul ol li
media im ln svprops
spacing g p m w h mw mh
color bg fg o
border r bw bc bs
position pos z t l rt
type fs fw ff ta td lh ls
layout ai jc flw cols rows
misc cur ov sh tr pe us
element v ph type href src alt dis ch ro opts rw sp rsp cls id
layout shortcuts: c=center sb=space-between fe=flex-end fs=flex-start st=stretchevents
c click
x input/change
f focus
bl blur
k keydown
e mouseenter
lv mouseleave
sub submitstate ops
// array form
["state", "+"] // increment
["state", "-"] // decrement
["state", "!", val] // set
["state", "~"] // toggle
["state", "<", item] // append
["state", ">", item] // prepend
["state", "X", idx] // remove
["state", ".", [k,v]] // set prop
// string shorthand (for events)
"state+" // increment
"state-" // decrement
"state~" // toggle
"state!val" // set value
"state" // for inputs: set, for +/- buttons: infers opcontrol flow
// long form
{if: "show", then: [tx, "yes"], else: [tx, "no"]}
{map: "items", as: [li, "$item"]}
// short form (saves tokens)
{?: "show", t: [tx, "yes"], e: [tx, "no"]}
{m: "items", a: [li, "$item"]}
// equality check
{?: "step", is: 0, t: [tx, "step 1"]}function components
create reusable components with functions:
import { Component, vs, tx, hs, bt } from '@tooey/ui';
// simple component
const Card = (props, children) => [vs, children, { bg: '#fff', p: 16, r: 8, ...props }];
// component with props
const Alert = ({ type = 'info', message }) =>
[vs, [[tx, message]], { bg: type === 'error' ? '#fee' : '#eef', p: 12 }];
// usage
render(container, {
s: {},
r: [vs, [
[Card, [[tx, 'Hello']]],
[Alert, '', { type: 'error', message: 'Error!' }]
]]
});components receive (props, children) and return a NodeSpec.
api
const app = tooey.render(el, spec);
app.get("key") // read state
app.set("key", value) // write state
app.destroy() // cleanupexamples
/examples - counter, todo, form, converter, table, tabs, modal, cart, wizard
security
tooey includes several security features to protect against common vulnerabilities:
xss protection
- all text content is escaped using
textContentinstead ofinnerHTML - dynamic state values are sanitized before rendering
url validation
hrefandsrcprops are validated against safe protocols- blocked protocols:
javascript:,data:,vbscript: - allowed protocols:
http:,https:,mailto:,tel:,ftp: - relative urls and anchors are allowed
best practices
- content security policy: add csp headers to your deployment:
Content-Security-Policy: default-src 'self'; script-src 'self' https://unpkg.com/@tooey/ui- user input: always validate user input before passing to tooey specs
- state values: don't store sensitive data in state that gets rendered
reporting security issues
report security vulnerabilities via github issues with the security label.
llm reference
token efficiency
tested with gemini-3-flash-preview (2026-01-17):
| metric | tooey | react | savings | |--------|-------|-------|---------| | output tokens (8 components) | 435 | 1726 | 75% | | syntax valid | 100% | 100% | - | | structure correct | 100% | 100% | - |
break-even analysis: tooey becomes more efficient than react after ~6 generations in a sustained conversation due to prompt amortization.
| scenario | savings | |----------|---------| | 90% cache hit | 36% | | sustained (n=50) | 67% | | sustained (n=100) | 71% |
prompt
copy this into your system prompt for llms to generate tooey specs:
tooey: token-efficient UI lib. spec={s:{state},r:[component,content?,props?]}
components: vs(vstack) hs(hstack) dv(div) gr(grid) tx(text) bt(button) In(input) ta(textarea) sl(select) cb(checkbox) rd(radio) tb/th/bd/Tr/Td/tc(table) ul/ol/li(list) im(img) ln(a) sv(svg)
props: g(gap) p(padding) m(margin) w(width) h(height) mw mh bg(background) fg(color) o(opacity) r(radius) bw bc bs pos(position:rel/abs/fix) z t l rt b fs(font-size) fw ff ta td lh ls ai(align-items) jc(justify-content) flw cols rows cur ov sh tr pe us v(value) ph(placeholder) type href src alt dis(disabled) ch(checked) ro(readonly) opts cls id show(conditional display)
layout shortcuts: c=center sb=space-between fe=flex-end fs=flex-start st=stretch
events: c(click) x(input) f(focus) bl(blur) k(keydown) e(mouseenter) lv(mouseleave) sub(submit)
state ops: "key+"(inc) "key-"(dec) "key~"(toggle) "key!val"(set) or ["key","op",val?] where op=+/-/!/~/</>/X/.
control: {?:"key",t:[...],e:[...]} {?:"key",is:val,t:[...]} {m:"arr",a:[...]}
state ref: {$:"key"} | in map: $item $index $item.prop
function components: const Comp=(props,children)=>[vs,children,{...props}] | use: [Comp,content,props]
examples:
- counter: {s:{n:0},r:[vs,[[tx,{$:"n"}],[hs,[[bt,"-",{c:"n-"}],[bt,"+",{c:"n+"}]],{g:8}]],{g:8}]}
- toggle: {s:{v:false},r:[vs,[[tx,{$:"v"}],[bt,"Toggle",{c:"v~"}]],{g:8}]}
- input: {s:{t:""},r:[vs,[[In,"",{v:{$:"t"},x:"t"}],[tx,{$:"t"}]],{g:8}]}
- modal: {s:{o:false},r:[vs,[[bt,"Open",{c:"o~"}],[dv,[[vs,[[tx,"Title",{fw:700}],[tx,"Content"],[bt,"Close",{c:"o~"}]],{bg:"#fff",p:16,r:8,g:8}]],{show:"o",pos:"fix",w:"100vw",h:"100vh",bg:"#0008",jc:"c",ai:"c"}]],{g:8}]}claude code users
install the tooey plugin for claude code:
# add the marketplace
claude plugin marketplace add https://raw.githubusercontent.com/vijaypemmaraju/tooey/main/marketplace.json
# install the plugin
claude plugin install tooeythen use /tooey:ui to generate tooey specs directly. see @tooey/claude-plugin for more options.
license
mit
