mcpField
S
solid-js-best-practices

solid-js-best-practices

github.com/richardcarlsDevelopment292 installsUpdated 4w ago
Repository

About solid-js-best-practices

solid-js-best-practices is a rule collection for AI-assisted coding, review, and refactoring of Solid.js applications. It organizes guidance by topic and task, and checks the project’s Solid.js version before applying examples.

Key features

  1. 01Version-aware rule selection
  2. 02Reactivity and component guidance
  3. 03State, DOM, and performance rules
  4. 04Accessibility and testing guidance
  5. 05Web Component integration rules

Use cases

  1. 01Drafting Solid.js components
  2. 02Reviewing Solid.js code
  3. 03Refactoring application state and reactivity
  4. 04Integrating custom elements with Solid.js

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/richardcarls/solid-js-best-practices --skill solid-js-best-practices

After installing, type/solid-js-best-practicesin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

LICENSE
.gitignore
AGENTS.md
README.md
CHANGELOG.md
docs/
version-support-plan.md
rules/
1-1-use-signals-correctly.md
1-4-avoid-signal-in-effect.md
1-2-use-memo-for-derived.md
1-3-effects-for-side-effects.md
1-6-batch-signal-updates.md
2-2-use-merge-props.md
1-5-use-untrack-when-needed.md
2-1-never-destructure-props.md
1-7-no-primitives-in-reactive-contexts.md
2-10-custom-element-typescript-declarations.md
2-3-use-split-props.md
2-5-component-composition.md
2-4-use-children-helper.md
2-6-components-return-once.md
3-1-use-show-for-conditionals.md
2-8-style-prop-conventions.md
2-9-never-call-components-as-functions.md
2-7-no-react-specific-props.md
3-3-use-index-for-primitives.md
3-6-stable-component-mount.md
3-5-provide-fallbacks.md
3-7-use-keyed-for-stateful-children.md
3-2-use-for-for-lists.md
3-4-use-switch-match.md

Details

From the project README

Solid.js Best Practices

Comprehensive best practices for building Solid.js applications and components, optimized for AI-assisted code generation, review, and refactoring.

Version Routing

Read the project's solid-js version from its manifest and lockfile before applying code examples. If the major is unknown, ask which major the project uses. The existing rule files are based on Solid 1.x; version_basis records the version behind a rule, without limiting its principle to that major. Do not copy a 1.x API example into a 2.x project without checking its current equivalent. Solid 2.x coverage is deferred until its official release. For a pre-release 2.x project, consult the official 1.x migration guide and documentation for the installed release candidate; do not treat these 1.x rules as verified 2.x guidance.

Rules by Category

1. Reactivity (7 rules)
#RulePriorityDescription
1-1Use Signals CorrectlyCRITICALAlways call signals as functions count() not count
1-2Use Memo for Derived ValuesHIGHUse createMemo for computed values, not createEffect
1-3Effects for Side Effects OnlyHIGHUse createEffect only for side effects, not derivations
1-7No Primitives in Reactive ContextsHIGHDon't call hooks or create reactive primitives inside effects or memos
1-4Avoid Setting Signals in EffectsMEDIUMSetting signals in effects can cause infinite loops
1-5Use Untrack When NeededMEDIUMUse untrack() to prevent unwanted reactive subscriptions
1-6Batch Signal UpdatesLOWUse batch() for multiple synchronous signal updates
2. Components (10 rules)
#RulePriorityDescription
2-1Never Destructure PropsCRITICALDestructuring props breaks reactivity
2-6Components Return OnceCRITICALNever use early returns; use <Show>, <Switch>, etc. in JSX
2-9Never Call Components as FunctionsCRITICALAlways use JSX or createComponent(); direct calls leak reactive scope
2-2Use mergePropsHIGHUse mergeProps for default prop values
2-3Use splitPropsHIGHUse splitProps to separate prop groups safely
2-7No React-Specific PropsHIGHUse class not className, for not htmlFor
2-10Custom Element TypeScript DeclarationsHIGHDeclare custom element tags in JSX namespace; augment DOM types for newer attributes
2-4Use children HelperMEDIUMUse children() helper for safe children access
2-5Prefer CompositionMEDIUMPrefer composition and context over prop drilling
2-8Style Prop ConventionsMEDIUMUse object syntax with kebab-case properties for style
3. Control Flow (7 rules)
#RulePriorityDescription
3-1Use Show for ConditionalsHIGHUse <Show> for conditional rendering and its function child when callers need a narrowed value
3-2Use For for ListsHIGHUse <For> for referentially keyed list rendering
3-7Use keyed for Stateful ChildrenHIGHAdd keyed when child has internal state and value identity (not just truthiness) matters
3-3Use Index for PrimitivesMEDIUMUse <Index> when array index matters more than identity
3-4Use Switch/MatchMEDIUMUse <Switch>/<Match> for multiple conditions; narrowed accessors throw once their branch deactivates
3-6Stable Component MountMEDIUMAvoid rendering the same component in multiple Switch/Show branches
3-5Provide FallbacksLOWAlways provide fallback props for loading states
4. State Management (7 rules)
#RulePriorityDescription
4-1Signals vs StoresHIGHUse signals for primitives, stores for nested objects
4-2Use Store Path SyntaxHIGHUse path syntax for granular, efficient store updates
4-3Use produce for MutationsMEDIUMUse produce for complex mutable-style store updates
4-4Use reconcile for Server DataMEDIUMUse reconcile when integrating server/external data
4-5Use Context for Global StateMEDIUMUse Context API for cross-component shared state
4-6Store Functions with a WrapperHIGHWrap function values so setStore does not invoke them as updater functions
4-7Cleanup at the Page Ownership BoundaryHIGHUse per-page cleanup when multiple routed panes remain mounted; audit every context field when splitting a shared context
5. Refs & DOM (10 rules)
#RulePriorityDescription
5-1Use Refs CorrectlyHIGHUse callback refs for conditional elements
5-2Access DOM in onMountHIGHAccess DOM elements in onMount, not during render
5-3Cleanup with onCleanupHIGHAlways clean up subscriptions and timers
5-5Avoid innerHTMLHIGHAvoid innerHTML to prevent XSS; use JSX or textContent
5-7Web Component Controlled StateHIGHUse prop:* properties and on:wc-* events for modern custom elements; reserve refs/effects for native or legacy APIs
5-8Wrap Signal Mutation in View TransitionHIGHCall the Solid setter inside startViewTransition() so the browser captures the old DOM before applying the new reactive state
5-9Two-Way Scroll SyncHIGHReport only settled scroll positions and skip re-scrolling for your own echo
5-10Possibly Missing progress/meter valueHIGHvalue is always a property and throws on undefined; use attr:value
5-4Use DirectivesMEDIUMUse use: directives for reusable element behaviors
5-6Event Handler PatternsMEDIUMUse on:/oncapture: namespaces and array handler syntax correctly
6. Performance (6 rules)
#RulePriorityDescription
6-1Avoid Unnecessary TrackingHIGHDon't access signals outside reactive contexts
6-2Use Lazy ComponentsMEDIUMUse lazy() for code splitting large components
6-3Use SuspenseMEDIUMUse <Suspense> for async loading boundaries
6-6Web Component CSS and Bundle StrategyMEDIUMImport components individually; place ::part() overrides in a global stylesheet
6-4Optimize Store AccessLOWAccess only the store properties you need
6-5Prefer classListLOWUse classList prop for conditional class toggling
7. Accessibility (4 rules)
#RulePriorityDescription
7-1Use Semantic HTMLHIGHUse appropriate semantic HTML elements
7-2Use ARIA AttributesMEDIUMApply appropriate ARIA attributes for custom controls
7-3Support Keyboard NavigationMEDIUMEnsure all interactive elements are keyboard accessible
7-4End-Match Root Router LinksHIGHAdd end matching so the root link is not current on every route
8. Testing (12 rules)
#RulePriorityDescription
8-1Configure Vitest for SolidCRITICALConfigure Vitest with Solid-specific resolve conditions and plugin
8-2Wrap Render in Arrow FunctionsCRITICALAlways use render(() => <C />) not render(<C />)
8-3Test Primitives in a RootHIGHWrap signal/effect/memo tests in createRoot or renderHook
8-4Handle Async in TestsHIGHUse findBy queries and proper timer config for async behavior
8-5Use Accessible QueriesMEDIUMPrefer role and label queries over test IDs
8-6Separate Logic from UI TestsMEDIUMTest primitives/hooks independently from component rendering
8-7Browser Mode for Browser-Dependent BehaviorHIGHUse a real browser for layout, focus, native APIs, and custom-element behavior jsdom cannot model faithfully
8-8Testing Headless UI Libraries with Non-Standard ARIAMEDIUMHeadless UI libraries use non-obvious ARIA structures and portals; inspect the actual tree before querying
8-9Browser-Native API Test IsolationHIGHClear IndexedDB and localStorage between tests; close connection before deleteDatabase
8-10Router Integration TestingHIGHUse MemoryRouter root prop to provide router context to layout providers
8-11TanStack Query Test SetupHIGHCreate a fresh QueryClient per test with retry and caching disabled
8-12Deproxy Before Structured CloneHIGHRemove every reactive proxy before writing data to IndexedDB
9. Web Component Integration (8 rules)
#RulePriorityDescription
9-1Register Custom Elements at App EntryHIGHImport /define side-effects before any SolidJS reactive context
9-2Handle slotchange After Slot AssignmentHIGHslotchange is delivered in a microtask; defer only work that needs a later lifecycle or rendering phase
9-3Treat Custom Element and SolidJS Reactivity as DecoupledMEDIUMUse one-way data flow (SolidJS -> attributes/props -> events -> SolidJS); never read custom element internal state from SolidJS reactive contexts
9-4Thin Web Component WrappersHIGHWrappers own labels, layout, type adaptation, and form glue; custom elements own timing and native sync
9-5Property vs Attribute BindingHIGHDynamic props on custom elements are already properties; use prop:* for intent and attr:* for data-*, ID-reference ARIA, and CSS-visible attributes
9-6Register Custom Fields with Form LibrariesHIGHEnsure property-bound custom fields enter lazy form-library registries
9-7Store State for Web-Component-Heavy FormsMEDIUMPrefer a Solid store when custom elements already own field interaction
9-8Wrapper Signal for Controlled-Only WCHIGHWhen a WC has no defaultValue, use createSignal in the wrapper to own the uncontrolled → controlled bridge

Task-Based Rule Selection

Writing New Components

Load these rules when creating new Solid.js components:

RuleWhy
1-1Ensure signals are called as functions
2-1Prevent reactivity breakage
2-6No early returns; use control flow in JSX
2-9Never call components as plain functions
2-2Handle default props correctly
2-3Separate local and forwarded props
3-1Proper conditional rendering
3-7keyed for forms and stateful children
3-2Efficient list rendering
5-3Prevent memory leaks
Web Component Integration

Load these rules when integrating Lit or other custom elements with SolidJS:

RuleWhy
9-1Register before any SolidJS context mounts
9-2Handle assigned nodes after the browser delivers slotchange
9-3One-way data flow design
9-4Keep wrappers focused on app concerns
9-5prop:* for properties, attr:* for attributes CSS or ARIA must see
9-6Property-bound fields in form-library registries
9-7Store state for custom-element-heavy forms
5-6Use on: namespace for custom element events
Code Review

Focus on these rules during code review:

PriorityRules
CRITICAL1-1, 2-1, 2-6, 2-9
HIGH1-2, 1-3, 1-7, 2-7, 5-2, 5-3, 5-5
Performance Optimization

Load these rules when optimizing performance:

RuleFocus
1-2Prevent unnecessary recomputation
1-6Reduce update cycles
4-2Granular store updates
6-1Prevent unwanted subscriptions
6-2Code splitting
6-4Efficient store access
State Management

Load these rules when working with application state:

RuleFocus
4-1Choose the right primitive
4-2Efficient updates
4-3Complex mutations
4-4External data integration
4-5Cross-component state
4-6Function values in stores
4-7Several mounted panes sharing context
Accessibility Audit

Load these rules when auditing accessibility:

RuleFocus
7-1Semantic structure
7-2Screen reader support
7-3Keyboard users
7-4Current-page state on router links
Writing Tests

Load these rules when writing or reviewing tests:

RuleFocus
8-1Correct Vitest configuration
8-2Reactive render scope
8-3Reactive ownership for primitives
8-4Async queries and timers
8-5Accessible query selection
8-6Test architecture
8-7When to use browser mode vs jsdom
8-8Portals and non-standard ARIA structures
8-9IDB and localStorage cleanup patterns
8-10MemoryRouter setup for integration tests
8-11QueryClient configuration for tests
8-12Store proxies written to IndexedDB
Integrating Web Components / Custom Elements

Load these rules when using any custom element library (Shoelace, FAST, Lion, Material Web Components, etc.) or native browser APIs like <dialog> and the Popover API:

RuleWhy
2-10Declare custom element tags in JSX namespace; type newer HTML attributes and experimental CSS properties
5-6Use on: for all custom element events; type CustomEvent payloads correctly
5-7Prefer declarative prop:*/on:wc-*; use refs for native or legacy APIs only
6-6Per-component imports for tree-shaking; ::part() overrides in global CSS only
9-8When the WC has no defaultValue, own the uncontrolled → controlled bridge with createSignal
5-8Keep Solid's DOM update inside the View Transition snapshot callback
5-10value on native <progress>/<meter> throws on undefined
Carousels and Scroll-Synced Components

Load 5-9 when an index is both driven into a scroll container and reported back out of it.

Migrating From React

Load signals, component execution, reactive props, HTML prop names, style syntax, control flow, list rendering, and event handlers.

Tooling

For automated linting alongside these best practices, use eslint-plugin-solid. The plugin catches many of the same issues this skill covers (destructured props, early returns, React-specific props, innerHTML usage, style prop format, etc.) and provides auto-fixable rules.

Resources

Comments

Markdown supported