Reactive primitives for TypeScript
One contract for every value
Stores, localStorage, cookies, IndexedDB and media queries all share get and subscribe, plus set wherever a value is writable. Learn it once. So does your AI agent.
$ pnpm add seituvalue.get() → 0
Module scope · no component needed
waiting for notify()…
- Validated by your schema
- Zod, Valibot or ArkType — any Standard Schema. Bad stored data falls back to your defaults.
- SSR-safe by default
- Browser APIs are touched only on the client. Servers render your defaults, so hydration matches.
- Import only what you use
- No framework in core. Entry points per area and per primitive keep bundles small.
Debouncing is one more handle
Wrap any source with createDebounced and read it like the original. No effects, timers or cleanup in your components.
query.get()""
debouncedQuery.get()""
Predictable for people. Obvious to agents.
Coding agents get small, uniform APIs right. Seitu ships skills with the package and every docs page as Markdown, so your agent reads the API of the version you installed.
Set up your agent$ npx skills add letstri/seitu
# what your agent can read
seitu-overviewmodule map, mental model, SSR
seituper-primitive API, common mistakes
seitu-setupmigrate an existing project
/llms.txtindex of every docs page
/docs/<page>.mdxany page as plain Markdown
From install to a live value in three steps
1Add the package
One dependency. Bindings ship inside it.
$ pnpm add seitu2Create a handle
At module scope, so any file can import it.
const counter = createStore(0)3Read it in a component
From seitu/react, /vue, /solid or /svelte.
useSubscription(counter)