Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 126 additions & 4 deletions _artifacts/domain_map.yaml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# domain_map.yaml
# Generated by skill-domain-discovery
# Library: seitu
# Version: 0.15.1
# Version: 0.16.0
# Date: 2026-06-11
# Status: reviewed

library:
name: seitu
version: 0.15.1
version: 0.16.0
repository: https://github.com/letstri/seitu
description: Type-safe reactive primitives with a shared get/subscribe API for core, web, React, and Vue.
description: Type-safe reactive primitives with a shared get/subscribe API for core, web, React, Vue, Solid, and Svelte.
primary_framework: framework-agnostic
coverage:
ignored_packages:
Expand All @@ -26,7 +26,7 @@ domains:
description: Persistence, DOM APIs, and SSR-safe defaults for web environments.
- name: framework bindings
slug: framework-bindings
description: React and Vue hooks that subscribe to any Seitu primitive.
description: React, Vue, Solid, and Svelte bindings that subscribe to any Seitu primitive.
- name: library orientation
slug: orientation
description: Module map, mental model, and primitive selection for new adopters.
Expand Down Expand Up @@ -550,6 +550,125 @@ skills:
source: seitu/src/vue/index.ts
priority: CRITICAL
status: active
- name: use-subscription-solid
slug: use-subscription-solid
domain: framework-bindings
description: Solid primitive returning an Accessor for any Seitu primitive.
type: framework
packages:
- seitu
covers:
- useSubscription
tasks:
- subscribe to Seitu state in Solid
failure_modes:
- mistake: Reading the accessor without calling it
mechanism: useSubscription returns a Solid Accessor; it must be called to read and track.
wrong_pattern: |
const value = useSubscription(store)
return <div>{value}</div>
correct_pattern: |
const value = useSubscription(store)
return <div>{value()}</div>
source: seitu/src/solid/hooks.ts
priority: CRITICAL
status: active
- mistake: Passing reactive props directly instead of a getter
mechanism: Reading props outside a tracked scope loses reactivity; the getter form re-subscribes.
wrong_pattern: |
useSubscription(props.store)
correct_pattern: |
useSubscription(() => props.store)
source: seitu/src/solid/hooks.ts
priority: HIGH
status: active
- mistake: Importing from seitu/react in Solid
mechanism: Solid apps must use the seitu/solid primitive; the React hook relies on useSyncExternalStore.
wrong_pattern: |
import { useSubscription } from 'seitu/react'
correct_pattern: |
import { useSubscription } from 'seitu/solid'
source: seitu/src/solid/index.ts
priority: CRITICAL
status: active
- name: subscription-solid
slug: subscription-solid
domain: framework-bindings
description: Render-prop component alternative to useSubscription for Solid.
type: framework
packages:
- seitu
covers:
- Subscription
tasks:
- subscribe via component children render prop in Solid
failure_modes:
- mistake: Treating children's argument as a value, not an accessor
mechanism: The children function runs once and receives a Solid Accessor; call it inside JSX.
wrong_pattern: |
<Subscription value={store}>{value => <div>{value.count}</div>}</Subscription>
correct_pattern: |
<Subscription value={store}>{value => <div>{value().count}</div>}</Subscription>
source: seitu/src/solid/components.ts
priority: CRITICAL
status: active
- mistake: Preferring the component over the primitive without reason
mechanism: useSubscription is simpler for most cases; Subscription is for render-prop composition.
wrong_pattern: |
<Subscription value={s}>{v => <Child value={v()} />}</Subscription>
correct_pattern: |
const v = useSubscription(s); return <Child value={v()} />
source: docs/content/docs/solid/components.mdx
priority: LOW
status: active
- mistake: Importing from seitu/react in Solid
mechanism: The React component relies on React internals; Solid apps must use seitu/solid.
wrong_pattern: |
import { Subscription } from 'seitu/react'
correct_pattern: |
import { Subscription } from 'seitu/solid'
source: seitu/src/solid/index.ts
priority: CRITICAL
status: active
- name: use-subscription-svelte
slug: use-subscription-svelte
domain: framework-bindings
description: Svelte binding returning a Readable store for any Seitu primitive.
type: framework
packages:
- seitu
covers:
- useSubscription
tasks:
- subscribe to Seitu state in Svelte
failure_modes:
- mistake: Reading the store without the `$` prefix
mechanism: useSubscription returns a Svelte store; the $ prefix auto-subscribes and reads the value.
wrong_pattern: |
<div>{value}</div>
correct_pattern: |
<div>{$value}</div>
source: seitu/src/svelte/hooks.ts
priority: CRITICAL
status: active
- mistake: Passing a factory expecting reactivity to a changing source
mechanism: The factory is a one-time initializer; it does not re-run when external values change.
wrong_pattern: |
const value = useSubscription(() => createWebStorageValue({ key: `user:${id}`, ... }))
correct_pattern: |
const value = useSubscription(createWebStorageValue({ key: `user:${id}`, ... }))
source: seitu/src/svelte/hooks.ts
priority: MEDIUM
status: active
- mistake: Importing from seitu/react in Svelte
mechanism: The React hook relies on useSyncExternalStore; Svelte apps must use seitu/svelte.
wrong_pattern: |
import { useSubscription } from 'seitu/react'
correct_pattern: |
import { useSubscription } from 'seitu/svelte'
source: seitu/src/svelte/index.ts
priority: CRITICAL
status: active
- name: create-debounced
slug: create-debounced
domain: reactive-state
Expand Down Expand Up @@ -852,4 +971,7 @@ cross_references:
- from: use-subscription-react
to: create-scroll-state
reason: Scroll tracking requires factory + ref pattern in React.
- from: use-subscription-solid
to: create-scroll-state
reason: Scroll tracking uses the getter + ref pattern in Solid.
gaps: []
39 changes: 38 additions & 1 deletion _artifacts/skill_tree.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# skill_tree.yaml
library:
name: seitu
version: 0.15.1
version: 0.16.0
repository: https://github.com/letstri/seitu
description: Type-safe reactive primitives with shared get/subscribe API
generated_from:
Expand Down Expand Up @@ -236,6 +236,43 @@ skills:
sources:
- letstri/seitu:docs/content/docs/vue/composables.mdx
- letstri/seitu:seitu/src/vue/composables.ts
- name: use-subscription-solid
slug: use-subscription-solid
type: framework
domain: framework-bindings
path: seitu/skills/use-subscription-solid/SKILL.md
package: seitu
description: Solid primitive returning an Accessor for any Seitu primitive.
requires:
- seitu-overview
sources:
- letstri/seitu:docs/content/docs/solid/hooks.mdx
- letstri/seitu:seitu/src/solid/hooks.ts
- name: subscription-solid
slug: subscription-solid
type: framework
domain: framework-bindings
path: seitu/skills/subscription-solid/SKILL.md
package: seitu
description: Render-prop Subscription component for Solid.
requires:
- seitu-overview
- use-subscription-solid
sources:
- letstri/seitu:docs/content/docs/solid/components.mdx
- letstri/seitu:seitu/src/solid/components.ts
- name: use-subscription-svelte
slug: use-subscription-svelte
type: framework
domain: framework-bindings
path: seitu/skills/use-subscription-svelte/SKILL.md
package: seitu
description: Svelte binding returning a Readable store for any Seitu primitive.
requires:
- seitu-overview
sources:
- letstri/seitu:docs/content/docs/svelte/hooks.mdx
- letstri/seitu:seitu/src/svelte/hooks.ts

coverage:
ignored_packages:
Expand Down
2 changes: 1 addition & 1 deletion docs/content/docs/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ So I created a library based on shadcn/cli and called it Hookas. But it was Reac

## Solution

That's why I built **Seitu** _(word "utils" reversed, with the letter L replaced by E)_. It's a type-safe, framework-agnostic library for working with familiar hooks. I brought together my experience with TypeScript and different frameworks, so you can use Seitu with React or without any framework at all.
That's why I built **Seitu** _(word "utils" reversed, with the letter L replaced by E)_. It's a type-safe, framework-agnostic library for working with familiar hooks. I brought together my experience with TypeScript and different frameworks, so you can use Seitu with React, Vue, Solid, Svelte, or without any framework at all.

## Examples

Expand Down
58 changes: 58 additions & 0 deletions docs/content/docs/solid/components.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
title: Components
---

## Subscription()
Declarative component that subscribes to a reactive value and passes an accessor to a render function.
Unlike React, the children function runs once and receives a Solid `Accessor<R>` — call it (`value()`)
inside the returned JSX so updates stay fine-grained. Use when you prefer a component API over the
useSubscription primitive.

### Examples

#### Basic usage

```tsx
import { createWebStorage } from 'seitu/web'
import { Subscription } from 'seitu/solid'
import * as z from 'zod'

const sessionStorage = createWebStorage({
type: 'sessionStorage',
schemas: { count: z.number(), name: z.string() },
defaultValues: { count: 0, name: '' },
})

function Page() {
return (
<Subscription value={sessionStorage}>
{value => <div>{value().count}</div>}
</Subscription>
)
}
```

#### With selector

```tsx
import { createWebStorage } from 'seitu/web'
import { Subscription } from 'seitu/solid'
import * as z from 'zod'

const sessionStorage = createWebStorage({
type: 'sessionStorage',
schemas: { count: z.number(), name: z.string() },
defaultValues: { count: 0, name: '' },
})

function Page() {
return (
<Subscription value={sessionStorage} selector={v => v.count}>
{count => <div>{count()}</div>}
</Subscription>
)
}
```

* * *

Loading
Loading