npx skills add ...
npx skills add lynx-community/skills --skill reactlynx-best-practices
Reviews, writes, and refactors ReactLynx code and component libraries for Lynx dual-thread best practices. Applies when writing ReactLynx components, or handling background-only, useLayoutEffect, bindtap/catchtap, main-thread:*, runOnMainThread/runOnBackground, lazy/Suspense, globalPropsMode/__globalProps, component-library publishing (preserved JSX vs React.createElement), or render/diff/commit performance traces. Excludes vanilla Lynx Element PAPI without ReactLynx JSX (use vanilla-lynx), running-app debugging via DevTool/CDP (use lynx-devtool), or Rspeedy/tsconfig config (use lynx-typescript).
npx skills add lynx-community/skills --skill reactlynx-best-practices
Use this skill when writing, reviewing, or refactoring ReactLynx code. ReactLynx follows the React programming model, but Lynx's dual-thread runtime changes how side effects, lifecycle timing, event handlers, and main-thread scripts should be reasoned about.
This skill intentionally does not require @ast-grep/napi or any native parser at runtime. The bundled scanner is a lightweight heuristic helper for common issues. The agent must still read the code and apply the rule documents in rules/*.md.
lynx.getJSModule, NativeModules, runOnMainThread, runOnBackground, lazy, Suspense, or useLayoutEffect.React.createElement support: https://github.com/lynx-family/lynx-stack/blob/main/packages/react/CHANGELOG.md#01210Use one of these modes:
| Mode | Use when |
|---|---|
writing | The user asks for new ReactLynx code or best-practice guidance |
review | The user asks to check, audit, explain, or validate existing code |
refactor | The user asks to fix or rewrite existing code |
If the mode is not explicit, infer it from the user's wording. Prefer review before refactor when code has not been inspected yet.
For repository work, search before editing:
Read nearby components, custom hooks, custom components that forward event handlers, Rspeedy config, and performance-related code before making changes.
The scanner catches common background-only and lifecycle issues. It is not a complete parser and must not replace code review.
Always combine scanner output with these manual checks:
'background only' directive.useLayoutEffect is unsupported; use useEffect for background side effects or main-thread layout events/refs for layout reads.bind*/catch* handlers run on the background thread; main-thread:* handlers require 'main thread' and have stricter limitations.runOnMainThread() or runOnBackground().with { runtime: 'shared' } only for code sharing, not state sharing.dist ESM with authored JSX preserved in JSX-bearing .jsx files and matching declarations; export the actual .js or .jsx entry that the build emits. Expose TS/TSX source only through an explicit source field or supported condition. Check Rslib, TypeScript, Babel, and SWC output for classic, automatic, or custom-factory JSX lowering. Treat intentional React.createElement according to the @lynx-js/react peer range instead of assuming every call is incompatible.lynx.__globalProps: Host-injected cross-page/global data updated through updateGlobalProps.globalPropsMode: 'reactive' triggers root forceUpdate; 'event' requires explicit updates with useGlobalPropsChanged. When migrating to 'event', scan direct lynx.__globalProps reads because root forceUpdate no longer applies.Suspense, CSS scope awareness, and error handling for important boundaries.displayName values to identify hot render/diff/update paths before optimizing.For refactor mode:
Use auto-fixes only as suggestions. The current auto-fixes are designed for detect-background-only diagnostics and should be reviewed before applying.
| Rule | Impact | Use for |
|---|---|---|
| detect-background-only | CRITICAL | lynx.getJSModule, NativeModules, 'background only', custom event/hook boundaries |
| avoid-use-layout-effect | MEDIUM | Lifecycle and layout reads |
| proper-event-handlers | MEDIUM | bindtap, catchtap, propagation, dataset, custom prop handlers |
| main-thread-scripts-guide | MEDIUM | main-thread:*, useMainThreadRef, cross-thread calls, shared modules |
| component-library-packaging | HIGH | ReactLynx component-library exports, type-erased ESM, preserved JSX, Rslib, tsc |
| global-props-mode | MEDIUM | globalPropsMode config, direct lynx.__globalProps reads, useGlobalPropsChanged migration |
| code-splitting | MEDIUM | lazy, Suspense, standalone lazy bundles, CSS bundle scope |
| performance-profiling | MEDIUM | ReactLynx trace events, flow IDs, displayName |
| hoist-static-jsx | LOW | Static JSX and render cost |
node -e "
import fs from 'fs';
import { ReactLynxWorkflow, formatFixPlan } from '<path_to_skill>/scripts/index.mjs';
const input = '<sourceCodeOrFilePath>';
const sourceCode = fs.existsSync(input) ? fs.readFileSync(input, 'utf-8') : input;
const workflow = new ReactLynxWorkflow('refactor');
workflow.reviewCode(sourceCode);
const plan = workflow.generateFixPlan();
if (plan) {
console.log(formatFixPlan(plan));
}
"function runSkill(source: string): Diagnostic[];
function runSkillWithFixes(source: string): DiagnosticWithFix[];
function analyzeBackgroundOnlyUsage(source: string): Diagnostic[];
function analyzeLifecycleUsage(source: string): Diagnostic[];
function generateFixes(source: string, diagnostic: Diagnostic): Fix[];
function applyFix(source: string, fix: Fix): string;
function applyFixes(source: string, fixes: Fix[]): string;
function formatScanReport(summary: ScanSummary): string;
function formatFixPlan(plan: FixPlan): string;class ReactLynxWorkflow {
constructor(mode: WorkflowMode);
reviewCode(source: string): ScanSummary;
generateFixPlan(): FixPlan | null;
applyAutoFixes(source: string): { fixed: string; appliedFixes: Fix[] };
}