
Solidjs Patterns
Apply OpenWork-style SolidJS signal patterns so agent UIs stay responsive and permission flows never deadlock on a global busy flag.
Overview
solidjs-patterns is an agent skill for the Build phase that teaches SolidJS signal, memo, and scoped-async patterns to prevent UI deadlocks in OpenWork-style apps.
Install
npx skills add https://github.com/different-ai/openwork --skill solidjs-patternsWhat is this skill?
- Fine-grained signals instead of shared global busy flags
- Scoped pending state per async action with guard-and-finally cleanup
- Derived UI via createMemo() to avoid duplicated booleans
- Immutable updates for arrays/objects stored in signals
- Permission prompts disabled only by permission-specific pending—not global busy
Adoption & trust: 571 installs on skills.sh; 15.9k GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your SolidJS UI freezes or blocks permission buttons because unrelated async work shares one global busy flag.
Who is it for?
Builders maintaining SolidJS agent or desktop UIs where multiple async operations and permission prompts can overlap.
Skip if: Greenfield React or Vue apps, or teams that only need generic Solid tutorial content without OpenWork-style async/permission coupling.
When should I use this skill?
SolidJS UI bugs, new async actions, or permission flows in OpenWork-style codebases where global busy() might couple unrelated controls.
What do I get? / Deliverables
After applying these patterns, each action owns its pending state, derived UI stays in sync via memos, and permission flows remain clickable while other work runs.
- Refactored handlers with per-action pending signals
- Memo-derived UI state instead of duplicated flags
Recommended Skills
Journey fit
SolidJS UI architecture belongs in Build because you implement and fix reactive frontend state while shipping the product surface. Frontend is the canonical shelf: signals, memos, and scoped async actions are all client UI state concerns.
How it compares
Use structured signal-scoping rules instead of copying React mental models or ad-hoc boolean flags for every button.
Common Questions / FAQ
Who is solidjs-patterns for?
Solo and indie developers building SolidJS frontends—especially OpenWork or similar agent shells—who want consistent reactivity patterns inside AI coding agents.
When should I use solidjs-patterns?
During Build when adding async handlers, permission UI, or overlapping background tasks; whenever buttons stay disabled after a long job or memos drift from duplicated booleans.
Is solidjs-patterns safe to install?
It is procedural frontend guidance only—review the Security Audits panel on this Prism page before trusting any third-party skill package in your repo.
SKILL.md
READMESKILL.md - Solidjs Patterns
## Why this skill exists OpenWork’s UI is SolidJS: it updates via **signals**, not React-style rerenders. Most “UI stuck” bugs are actually **state coupling** bugs (e.g. one global `busy()` disabling an unrelated action), not rerender issues. This skill captures the patterns we want to consistently use in OpenWork. ## Core rules - Prefer **fine-grained signals** over shared global flags. - Keep async actions **scoped** (each action gets its own `pending` state). - Derive UI state via `createMemo()` instead of duplicating booleans. - Avoid mutating arrays/objects stored in signals; always create new values. ## Scoped async actions (recommended) When an operation can overlap with others (permissions, installs, background refresh), don’t reuse a global `busy()`. Use a dedicated signal per action: ```ts const [replying, setReplying] = createSignal(false); async function respond() { if (replying()) return; setReplying(true); try { await doTheThing(); } finally { setReplying(false); } } ``` ### Why A single `busy()` boolean creates deadlocks: - Long-running task sets `busy(true)` - A permission prompt appears and its buttons are disabled by `busy()` - The task can’t continue until permission is answered - The user can’t answer because buttons are disabled Fix: permission UI must be disabled only by a **permission-specific** pending state. ## Signal snapshots in async handlers If you read signals inside an async function and you need stable values, snapshot early: ```ts const request = activePermission(); if (!request) return; const requestID = request.id; await respondPermission(requestID, "always"); ``` ## Derived UI state Prefer `createMemo()` for computed disabled states: ```ts const canSend = createMemo(() => prompt().trim().length > 0 && !busy()); ``` ## Lists - Use setter callbacks for derived updates: ```ts setItems((current) => current.filter((x) => x.id !== id)); ``` - Don’t mutate `current` in-place. ## Practical checklist (SolidJS UI changes) - Does any button depend on a global flag that could be true during long-running work? - Could two async actions overlap and fight over one boolean? - Is any UI state duplicated (can be derived instead)? - Do event handlers read signals after an `await` where values might have changed? - If you refactor props/types, did you update all intermediate component signatures and call sites? ## References - SolidJS: https://www.solidjs.com/docs/latest - SolidJS signals: https://www.solidjs.com/docs/latest/api#createsignal - SolidJS memos: https://www.solidjs.com/docs/latest/api#creatememo