letstri/seitu/seitu-setup
Claude Code and agent skill by letstri/seitu
- community
Checking that the SKILL.md file is still in the repository.
Adopt Seitu across an existing project: install it, find hand-rolled reactive state and browser subscriptions (localStorage/sessionStorage/cookie hooks, matchMedia, online status, scroll listeners, debounce/throttle helpers, small global stores), and replace them with Seitu primitives without losing persisted user data. Use when asked to set up Seitu, migrate a codebase to Seitu, or replace existing state or storage code with Seitu.
Install
npx vskill@latest install letstri/seitu/seitu-setupSKILL.md
Seitu setup and migration
Moves an existing app onto Seitu in reviewable steps. Read seitu-overview first for the mental model. For the exact options of each primitive, read the matching file in the seitu skill's references/ folder before you write the replacement.
The goal is less code with the same behavior. A replacement that changes what a user sees, or drops data they already stored, is a regression.
Workflow
- Detect the stack. Do this before you change anything.
- Install
seituand, when needed, a schema library. - Inventory the candidates with the searches below.
- Classify each candidate as replace, keep or ask.
- Show the plan to the user and wait for approval.
- Migrate one category at a time. Verify after each category.
- Delete the code and dependencies that nothing uses anymore.
Do not rewrite the whole project in one pass. A category is one row of the replacement table, for example "all localStorage hooks".
1. Detect the stack
Read package.json and the lockfile, and record:
| Question | Where to look | Why it matters | |
|---|---|---|---|
| Package manager | pnpm-lock.yaml, yarn.lock, bun.lock, package-lock.json | Install command | |
| Framework | react, vue, solid-js, svelte in dependencies | Binding import: seitu/react, seitu/vue, seitu/solid, seitu/svelte | |
| Framework version | same | Seitu needs React >= 19, Vue >= 3.5, Solid >= 1.9, Svelte >= 5. Stop and tell the user if the project is older. | |
| SSR | next, nuxt, @tanstack/react-start, @sveltejs/kit, @solidjs/start, astro, remix, react-router (framework mode) | defaultMatches, createCookieValue with getServerCookies | |
| Schema library | zod, valibot, arktype | Storage primitives need a Standard Schema validator | |
| Module format and Node | "type", engines | Seitu is ESM-only and needs Node >= 22 |
A monorepo can use more than one framework. Pick the binding for each package, not for the whole repository.
2. Install
The framework bindings ship inside seitu, so there are no extra packages. The storage primitives need a Standard Schema validator. Reuse the project's validator. If there is none, ask the user before you add one. Zod is the default suggestion.
3. Inventory
Search source files only. Exclude node_modules, build output and generated files.
For each hit, record the file, what the code does, who reads the value and who writes it. Group the hits into categories from the table below.
4. Classify
Replace
| Existing code | Seitu primitive | Reference | |
|---|---|---|---|
useLocalStorage / useSessionStorage hook, useStorage from VueUse, writable + localStorage.setItem in Svelte | createWebStorageValue (one key), createWebStorage (several related keys) | create-web-storage-value.md, create-web-storage.md | |
| Cookie read in SSR and written in the browser (theme, language, consent) | createCookieValue with getServerCookies | create-cookie-value.md | |
useMediaQuery, matchMedia(...).addEventListener('change', ...) | createMediaQuery | create-media-query.md | |
navigator.onLine with online/offline listeners | createIsOnline | create-is-online.md | |
| Scroll listener that computes "at top", "at bottom" or distance to an edge | createScrollState | create-scroll-state.md | |
ResizeObserver in an effect that stores width/height, useElementSize, useResizeObserver | createElementSize | create-element-size.md | |
Module-level variable plus a listener set, EventEmitter or mitt used as a store | createStore | create-store.md | |
Small global store (zustand, nanostores, jotai atom, Svelte writable) with no middleware | createStore, or createSchemaStore when the value is validated | create-store.md, create-schema-store.md | |
| React context that only shares one value and its setter | createStore at module scope + useSubscription | react.md | |
useMemo / computed / derived over values that are now Seitu handles | createComputed | create-computed.md | |
lodash.debounce, lodash.throttle or a hand-written timer whose result is shown in the UI | createDebouncedFn, createThrottledFn | create-debounced-fn.md, create-throttled-fn.md | |
| Debounced copy of another reactive value (for example search input) | createDebounced, createThrottled | create-debounced.md, create-throttled.md | |
idb-keyval, localforage or raw indexedDB used as a key/value store | createIndexedDb + createIndexedDbStorage | create-indexed-db.md, create-indexed-db-storage.md | |
Raw indexedDB object stores with indexes and queries | createIndexedDb + createIndexedDbTable | create-indexed-db-table.md | |
| Custom browser subscription (visibility, resize, clipboard, geolocation) | createSubscription + createReadableSubscription | create-subscription.md, create-readable-subscription.md |
Keep
Do not replace these. List them in the plan with the reason.
- Server state: TanStack Query, SWR, Apollo, tRPC and RTK Query caches. Seitu does not fetch, cache or revalidate.
- Form state: React Hook Form, TanStack Form, Formik, VeeValidate.
- Router state: search params, route params.
- Local UI state:
useState/ref/$statethat only one component reads, such as an open menu or an input draft. - Stores with middleware or devtools in use (Redux, zustand
persistwith migrations,immer, time travel). Replacing them changes behavior, so ask first. - `HttpOnly` cookies: JavaScript cannot read or write them.
- Debounce or throttle inside a library that you do not own.
Ask
Ask the user before you replace:
- A dependency that other packages in a monorepo also use.
- A store with more than about ten consumers.
- Any storage key whose stored shape you cannot prove from the code.
- A change that removes a public export of a package.
5. Show the plan
Before you edit files, give the user a short plan:
Wait for approval. Then migrate one category at a time.
6. Migrate
Rules for every replacement
- Create shared handles once, at module scope. Put them next to the feature that owns them, for example
src/stores/theme.ts. Do not create a handle inside a component body. When a handle depends on props, pass a factory touseSubscriptionwithdeps. - Keep the storage key. Use the same
keyas the old code, so returning users keep their data. - Write a schema that accepts the stored data. Seitu parses the stored string with
JSON.parse. A value that is not valid JSON is read as a plain string. If validation fails,get()returnsdefaultValueand the stored value is overwritten on the nextset(). - Match the old default. Use the same fallback value the old code used.
- Keep the SSR output. If the old code rendered a value on the server, the new code must render the same value. Use
defaultMatchesfor media queries. UsecreateCookieValuewithgetServerCookiesfor values the server must show. - Return new objects from updaters.
set()does not notify when the new value is the same reference. - Import the binding for the file's framework. Do not import
seitu/reactin Vue, Solid or Svelte code.
Stored data compatibility
Check the old write path for each key before you choose the schema:
| Old write | Stored string | Seitu reads | Schema | |
|---|---|---|---|---|
setItem('theme', 'dark') | dark | 'dark' | z.enum(['light', 'dark']) | |
setItem('theme', JSON.stringify('dark')) | "dark" | 'dark' | same | |
setItem('count', String(5)) | 5 | 5 (number) | z.number(), not z.string() | |
setItem('id', '123') where the id is a string | 123 | 123 (number) | z.coerce.string() or a union | |
setItem('user', JSON.stringify(user)) | JSON object | object | object schema with the real shape |
When the stored shape changed between app versions, use onValidationError to repair the value, or repairValueObjectWithDefault from seitu/utils for objects that gained fields. Do not silently reset user data that you can repair.
Before and after
localStorage hook (React)
Before:
After:
The old hook read localStorage during render, so it failed on the server and did not sync across tabs. The new handle does both.
Media query hook
Before:
After:
Consumers change from useIsDesktop() to useSubscription(isDesktop).
Global store with a listener set
Before:
After:
Vue: VueUse `useStorage`
Before:
After:
Code that wrote token.value = x now calls token.set(x).
Svelte: `writable` persisted by hand
Before:
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingseitu/skills/seitu-setup/SKILL.md
Popularity
- 7-day trend score
- 5
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/letstri/seitu/seitu-setup)