Skip to main content

code

Use when writing TypeScript/React code - covers type safety, component patterns, and file organization

소스 정보

저장소
trycompai/comp
최근 소스 활동
2026년 4월 27일 13:37
감지된 SKILL.md 언어
영어
스타
2,035
포크
433

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
code
description
Use when writing TypeScript/React code - covers type safety, component patterns, and file organization
Source Cursor rule: `.cursor/rules/code.mdc`. Original Cursor alwaysApply: `false`. # Code Standards ## TypeScript ### No `any`, No Unsafe Casts ```tsx // ✅ Validate with zod const TaskSchema = z.object({ id: z.string(), title: z.string() }); const task = TaskSchema.parse(response.data); // ✅ Use unknown and narrow const parseResponse = (data: unknown): Task => { if (!isTask(data)) throw new Error('Invalid'); return data; }; // ❌ Never const data: any = fetchData(); const task = response as Task; const name = user!.name; // @ts-ignore ``` ### Generics Over Any ```tsx // ✅ Generic const first = <T>(items: T[]): T | undefined => items[0]; // ❌ Any const first = (items: any[]): any => items[0]; ``` ## React Patterns ### Named Exports, PascalCase ```tsx // ✅ Named export, PascalCase file // TaskCard.tsx export function TaskCard({ task }: TaskCardProps) { ... } // ❌ Default export, lowercase export default function taskCard() { ... } ``` ### Derive State, Avoid useEffect ```tsx // ✅ Derived const completedCount = tasks.filter(t => t.completed).length; // ❌ Synced state const [count, setCount] = useState(0); useEffect(() => { setCount(tasks.filter(t => t.completed).length); }, [tasks]); ``` ### When useEffect IS Appropriate ```tsx // External subscriptions useEffect(() => { const sub = eventSource.subscribe(handler); return () => sub.unsubscribe(); }, []); // DOM measurements useEffect(() => { setHeight(ref.current?.getBoundingClientRect().height); }, []); ``` ### Toasts with Sonner ```tsx import { toast } from 'sonner'; toast.success('Task created'); toast.error('Failed to save'); toast.promise(saveTask(), { loading: 'Saving...', success: 'Saved!', error: 'Failed', }); ``` ## File Structure ### Colocate at Route Level ``` app/(app)/[orgId]/tasks/ ├── page.tsx # Server component ├── components/ │ └── TaskList.tsx # Client component ├── hooks/ │ └── useTasks.ts # SWR hook └── data/ └── queries.ts # Server queries ``` ### Share Only When Reused 3+ Times ``` src/components/shared/ # Cross-page components src/hooks/ # Shared hooks (useApiSWR, useDebounce) ``` ## Code Quality ### File Size Limit: 300 Lines Split large files into focused components. ### Named Parameters for 2+ Args ```tsx // ✅ Named const createTask = ({ title, assigneeId }: CreateTaskParams) => { ... }; createTask({ title: 'Review PR', assigneeId: user.id }); // ❌ Positional const createTask = (title: string, assigneeId: string) => { ... }; createTask('Review PR', user.id); // What's the 2nd param? ``` ### Early Returns ```tsx // ✅ Early return function processTask(task: Task | null) { if (!task) return null; if (task.deleted) return null; return <TaskCard task={task} />; } // ❌ Nested function processTask(task) { if (task) { if (!task.deleted) { return <TaskCard task={task} />; } } return null; } ``` ### Event Handler Naming ```tsx // ✅ Prefix with "handle" const handleClick = () => { ... }; const handleSubmit = (e: FormEvent) => { ... }; const handleTaskCreate = (task: Task) => { ... }; ``` ## Accessibility ```tsx // Interactive elements need keyboard support <div role="button" tabIndex={0} onClick={handleClick} onKeyDown={(e) => e.key === 'Enter' && handleClick()} aria-label="Delete task" > <TrashIcon /> </div> // Form inputs need labels <label htmlFor="task-name">Task Name</label> <input id="task-name" type="text" /> ```
GitHub에서 보기