Back to skills
SkillHub ClubShip Full StackFull StackFrontend
solidjs-patterns
SolidJS reactivity + UI state patterns for OpenWork
Packaged view
This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.
Stars
11,961
Hot score
99
Updated
March 20, 2026
Overall rating
C5.0
Composite score
5.0
Best-practice grade
B81.2
Install command
npx @skill-hub/cli install different-ai-openwork-solidjs-patterns
Repository
different-ai/openwork
Skill path: .opencode/skill/solidjs-patterns
SolidJS reactivity + UI state patterns for OpenWork
Open repositoryBest for
Primary workflow: Ship Full Stack.
Technical facets: Full Stack, Frontend.
Target audience: everyone.
License: Unknown.
Original source
Catalog source: SkillHub Club.
Repository owner: different-ai.
This is still a mirrored public skill entry. Review the repository before installing into production workflows.
What it helps with
- Install solidjs-patterns into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
- Review https://github.com/different-ai/openwork before adding solidjs-patterns to shared team environments
- Use solidjs-patterns for development workflows
Works across
Claude CodeCodex CLIGemini CLIOpenCode
Favorites: 0.
Sub-skills: 0.
Aggregator: No.
Original source / Raw SKILL.md
---
name: solidjs-patterns
description: SolidJS reactivity + UI state patterns for OpenWork
---
## 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?
## 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