Standards Detection
Search for ESLint config (.eslintrc.*, eslint.config.*, package.json). If found, merge with baseline (ESLint takes precedence). Otherwise use baseline only.
Baseline Standards
Types & Imports
- Use
type(notinterface) - Use
import typefor type-only imports - Naming:
ComponentNameProps,UseHookNameOptions - Order: types → libraries → components → utilities → styles
Naming
| Element | Convention | Example |
|---|---|---|
| Components | PascalCase | UserProfile |
| Variables/functions | camelCase | getUserData |
| Constants | UPPER_SNAKE_CASE | MAX_RETRY_COUNT |
| Event handlers | on* | onClick |
| Hooks | use* | useAuth |
Components
- Functional components with arrow functions
- Destructure props with defaults
- Named exports preferred
- Set
displayName - Memoize:
useCallbackfor callbacks,useMemofor computations - Early returns for guards
- Conditional rendering with
&&
Custom Components
type ComponentNameProps = {}
export const ComponentName: FC<ComponentNameProps> = props => {
const {} = props
}
ComponentName.displayName = 'ComponentName'
Custom Hooks
export function useHookName(options: UseHookNameOptions) {
const { a, b } = options
// a, b
return {}
}
Code Style
- TypeScript strict mode
- Avoid
any→ useunknownor specific types - Prefer
constoverlet - Single responsibility functions
Directory Organization
When this skill creates or reorganizes React files, it must follow this directory organization. First identify the existing app/module root (src/, src/apps/<app>/, packages/<name>/src/, framework route directory, etc.), then apply these rules inside that root.
- Put reusable code in shared
hooks/andcomponents/. - Put page-only code inside the page module's
hooks/,components/, andapi.ts. - Do not create ad hoc sibling folders for hooks, components, page APIs, or page-private code.
- Preserve clearly established equivalent project naming only when the shared vs page-private boundaries stay the same.
Shared Hooks
hooks/
├── index.ts # re-exports all shared hooks (single import entry)
└── useXxx.ts # one hook per file, named useXxx
Shared Components
components/
├── index.ts # re-exports all shared components
├── Button/
│ ├── index.tsx # exports Button component
│ └── index.module.less
└── XxxCard/
├── index.tsx # exports XxxCard component
└── index.module.less
Page Modules
<Name>/ # <Name> = main component name (e.g., UserProfile)
├── index.tsx # exports the page's main component
├── index.module.less
├── api.ts # page API requests only; no business logic
├── components/ # page-private components (optional)
│ ├── index.ts # re-exports this page's components
│ └── ...
└── hooks/ # page-private hooks (optional)
├── index.ts # re-exports this page's hooks
└── ...
Conventions:
index.tsfor unified exports — keeps imports clean:import { Button } from '@/components'- Named exports only — avoid default exports from shared components
- Directory name = Component name —
UserProfile/index.tsxexportsUserProfile - Page
api.tsis request-only — keep page API calls there; do not put data transformation, state updates, or business branching there
Import examples:
// Good
import { Button } from '@/components'
import { useAuth } from '@/hooks'
import { UserProfile } from '@/pages/UserProfile' // or the project's existing page/module path
// Avoid
import Button from '@/components/Button' // inconsistent with index.ts pattern