solid
Skill59 starsChanged 16 days agoMITView on GitHub
Write, refactor, review, or test Solid 2 UI in OpenClaw (Control UI, plugin views, Canvas hosts), including state ownership, native custom elements, overlays, testing, performance, and lessons learned.
We split this skill into the rules it gives an agent
2 rules. 0 are common, 1 is distinctive, and 1 is very specific to this project.
0
Common
Most of the 13 edited versions we read keep these.
1
Distinctive
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 22
Replace controller lifecycles at their owner: Follow the controller-to-Solid recipe, including its worked example.
- Very specific: line 49
Use jsxImportSource: "@solidjs/web" and its JSX types, not Solid 1's solid-js/web.
“Common” is measured: kept by at least 6 in 10 of the 13 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Solid 2 in OpenClaw
The Control UI and plugin views (extensions/x, extensions/workboard) render with Solid 2 (solid-js, @solidjs/web, @solidjs/signals, compiled by @solidjs/vite-plugin/@solidjs/compiler). Lit and Web Awesome are removed from these surfaces; new code is Solid only. The Canvas hosts also use Solid, but the sandboxed upstream A2UI v0.8 catalog retains its separate @a2ui/lit dependency.
Read ui/AGENTS.md first; its state-ownership rules apply to Solid unchanged. Use the exact installed Solid pins from the owning package.json: the runtime and compiler are 2.0.0-rc.14, and @solidjs/vite-plugin is 3.0.0-next.49. solid-js and @solidjs/* are exempt from the repository's seven-day release-age gate (Peter, 2026-10-11); third-party Solid ecosystem packages remain subject to it.
Rules that keep the UI correct
Before your first edit, read the installed ui/node_modules/solid-js/CHEATSHEET.md, especially its "What changed from 1.x" list. It is the rc.14 API contract, written as a guard against React and Solid 1 priors, the two dominant bug sources. For new code or a Solid audit, then read idioms and lessons; to refactor or review existing code, also use the refactor checklist. Check solid-js/types/client/flow.d.ts and the installed @solidjs/signals / @solidjs/web types when choosing an API. rc.14 has no createAsync: asynchronous values are ordinary computations returning promises or async iterables.
- Domain owners stay plain TypeScript. The Gateway store, capabilities,
lib/sessions/*, caches, persistence, and mutation authority keep synchronous mutate-then-read semantics. Solid 2 writes become visible only after a microtask flush, so authoritative state never lives in a signal. → state and ownership - Components consume projections from
ui/src/lib/reactive/(one per owner and scope, never a second store) anduseApplication()for the application context. Add a thin adapter only with its first production caller; subscribe to ordered events directly. - Host tags and classes survive. A component renders its existing
openclaw-*tag as a plain host element in light DOM; CSS and E2E select it. Never rename a tag or a class. → components - One implementation per registered tag. Native custom elements and Solid callers share one renderer through
defineSolidBridgeinui/src/lib/solid-bridge.ts. Use its returned component in JSX so the host has one lifecycle owner. → components - One renderer per DOM region, and one lifecycle owner per overlay surface. → overlays
- Derive, don't synchronize.
createMemobeforecreateSignal; no copies of owner state; no defensive guards for states the owner already excludes. Prefer smaller code with fewer owners. - Replace controller lifecycles at their owner. Follow the controller-to-Solid recipe, including its worked example. Delete the class and host adapter wiring together; do not wrap a controller in revision signals as the final design.
Component skeleton
An illustrative component (the tag is an example): it renders its host tag, reads an owner through a projection, and derives instead of copying state.
import { createMemo, Show } from "solid-js";
import { useApplication } from "../lib/reactive/context.ts";
import { projectAgents } from "../lib/reactive/domain-capabilities.ts";
export function AgentCount(props: { compact?: boolean }) {
const app = useApplication();
// Reads through to the synchronous owner; disposed with this component's owner.
const agents = projectAgents(app.agents);
// Never destructure props: reads must stay reactive.
const count = createMemo(() => agents.read().agentsList?.agents.length ?? 0);
return (
<openclaw-agent-count class={["agent-count", { "agent-count--compact": props.compact }]}>
<Show when={count() > 0} fallback={<span class="muted">—</span>}>
<span>{count()}</span>
</Show>
</openclaw-agent-count>
);
}Use jsxImportSource: "@solidjs/web" and its JSX types, not Solid 1's solid-js/web.
Traps that compile but break
on:x,attr:x,bool:x,classList, anduse:are gone in Solid 2; they compile to literal attributes or no-ops (lint flags them).prop:is the only namespace left.- Events are camelCase (
onClick). Dashed custom events need the exact dash, such asonSession-change, or alisten(...)ref factory. - Native event bindings bind once: dispatch through a stable callback that reads the current handler prop. Runtime spreads, including dynamic elements, can update handlers.
- A read right after a write sees the old value until
flush(). Don't write-then-read in handlers; derive. - Reactive reads after the first
awaitin an async memo are untracked, and async memos get noAbortSignal. - Ref callbacks run unowned:
onCleanupinside them does nothing. - ARIA enumerations are typed strings:
aria-pressed={pressed() ? "true" : "false"}, never a boolean. - Solid 1 APIs (
createResource,onMount,mergeProps,Context.Provider) don't carry over: use async computations,onSettled,merge, and the context component itself. - Writing a signal or store from a memo, an effect compute phase, or a component body throws in dev.
untrackdoesn't exempt it (the guard checks the owner); derive instead, or write from a handler,onSettled, or effect apply. - Class strings built with template literals or
.filter(Boolean).join(" ")lose composable reactivity: useclass={["base", { active: active() }]}. createRenderEffectis for render-phase runtime bindings, andflush()in production code usually hides a write-then-read: feature code usescreateEffectand derivations.
More, each with its root cause: lessons learned.
Testing
mountSolid, waitForSolid/flush, renderSolidRef, and the Solid application-context provider live in ui/src/test-helpers/. .test.tsx files are discovered. Keep assertions when you replace a harness. Visual changes need inspected, sanitized before/after screenshots. Follow the assigned campaign's compute budget. → testing
References
| Topic | Read when |
| idioms | choosing a primitive, derivations, props, lifecycle, stores, keys, async, context, diagnostics |
| refactor checklist | refactoring or reviewing existing Solid: measurable smells, replacements, before/after |
| components | writing components, native custom-element hosts, JSX bindings, events, refs, styles |
| state and ownership | touching owners, projections, async reads, lifetimes, parking, chat render lifecycle |
| overlays | menus, popovers, tooltips, dialogs, focus, positioning, the platform floor |
| testing | unit, browser, E2E, WebKit, parity, retention suites |
| performance | startup bundle, lazy loading, render budgets |
| plugins | building a plugin's Control UI view in Solid |
| lessons learned | before a new kind of change; most entries cost a failed CI run to learn |
Trending
Surging: 3 new projects took it in the last 4 weeks, none the 4 weeks before.thin data
Other versions14 projects use a version of this.
Word for word · 0
None found.
Edited · 6
- steipete/warelay★ 394k64% same
- moltbot/clawdbot★ 394k64% same
- moltbot/moltbot★ 394k64% same
- clawdbot/clawdbot★ 394k64% same
- steipete/clawdis★ 394k64% same
- openclaw/openclaw★ 394k64% same
Wrote their own version · 8
- vercel-labs/json-render★ 19ksame name
- ramziddin/solid-skills★ 591same name
- nank1ro/solid★ 165same name
- DGouron/review-flow★ 42same name
- JordanCoin/codingskills★ 10same name
- Gusen1453/creed★ 3same name
- vladcheck/skills★ 1same name
- ramybarsoum/claude-skills★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
Used alongsideProjects with it also use openclaw-performance.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
clawdbotSkillopenclaw-performance
Performance work in OpenClaw: a slow or heavy flow (latency, CPU, memory, SQL, RPC, renders), writing or reviewing a perf PR, or adding a cache. Count the work, delete waste first, cache last.
Also in 6 projects that use this
In this repository107 other files it gives its agents.
- AGENTS.mdAGENTS.md
- docs/AGENTS.mdAGENTS.md
- extensions/AGENTS.mdAGENTS.md
- scripts/AGENTS.mdAGENTS.md
- test/AGENTS.mdAGENTS.md
- ui/AGENTS.mdAGENTS.md
- agent-transcriptSkill
- auto-qaSkill
- autoreviewSkill
- channel-message-flowsSkill
- clawdtributorSkill
- claw-scoreSkill
- clawsweeperSkill
- control-ui-e2eSkill
- crabboxSkill
- discord-clawdSkill
- discord-e2eSkill
- discord-user-postSkill
- discrawlSkill
- gitcrawlSkill
- graincrawlSkill
- notcrawlSkill
- openclaw-changelog-updateSkill
- openclaw-ci-limitsSkill
- openclaw-debuggingSkill
- openclaw-docker-e2e-authoringSkill
- openclaw-ghsa-maintainerSkill
- openclaw-live-updaterSkill
- openclaw-parallels-smokeSkill
- openclaw-pr-maintainerSkill
- openclaw-qa-testingSkill
- openclaw-refactor-docsSkill
- openclaw-release-validationSkill
- openclaw-repair-sweepSkill
- openclaw-secret-scanning-maintainerSkill
- openclaw-test-heap-leaksSkill
- openclaw-testingSkill
- openclaw-test-performanceSkill
- openclaw-updateSkill
- parallels-discord-roundtripSkill
- plugin-sdk-impactSkill
- proof-videoSkill
- prototype-openclaw-tuiSkill
- pr-simplifySkill
- release-openclaw-announcementSkill
- release-openclaw-ciSkill
- release-openclaw-macSkill
- release-openclaw-maintainerSkill
- release-openclaw-plugin-testingSkill
- security-triageSkill
- slack-e2eSkill
- slacrawlSkill
- tag-duplicate-prs-issuesSkill
- technical-documentationSkill
- telegram-e2e-userbotSkill
- test-auditSkill
- update-team-serverSkill
- verify-releaseSkill
- 1passwordSkill
- apple-notesSkill
- The first 60 shown.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

