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.

Read the docs
$ pnpm add seitu
Createin-memory
const value = createStore(0)
Get · setwritable

value.get() → 0

Module scope · no component needed

Subscribelast notify

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.

const query = createStore('')const debouncedQuery = createDebounced(query, 300)// Re-renders 300 ms after typing stopsconst value = useSubscription(debouncedQuery)

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
terminal

$ 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

  1. 1Add the package

    One dependency. Bindings ship inside it.

    $ pnpm add seitu
  2. 2Create a handle

    At module scope, so any file can import it.

    const counter = createStore(0)
  3. 3Read it in a component

    From seitu/react, /vue, /solid or /svelte.

    useSubscription(counter)