oxycode-skills 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +143 -0
  3. package/index.js +17 -0
  4. package/package.json +49 -0
  5. package/skills/anti-slop/README.md +106 -0
  6. package/skills/anti-slop/SKILL.md +311 -0
  7. package/skills/anti-slop/examples/before-after.md +380 -0
  8. package/skills/anti-slop/references/quality-rubric.md +313 -0
  9. package/skills/anti-slop/references/slop-patterns.md +433 -0
  10. package/skills/component-architect/README.md +186 -0
  11. package/skills/component-architect/SKILL.md +644 -0
  12. package/skills/component-architect/examples/component-patterns.md +569 -0
  13. package/skills/component-architect/references/atomic-design.md +516 -0
  14. package/skills/design-audit/README.md +114 -0
  15. package/skills/design-audit/SKILL.md +305 -0
  16. package/skills/design-audit/examples/audit-report.md +424 -0
  17. package/skills/design-audit/references/scoring-rubric.md +498 -0
  18. package/skills/design-md/README.md +106 -0
  19. package/skills/design-md/SKILL.md +262 -0
  20. package/skills/design-md/examples/bad-design.md +195 -0
  21. package/skills/design-md/examples/good-design.md +250 -0
  22. package/skills/design-md/references/design-md-spec.md +267 -0
  23. package/skills/design-md/scripts/validate.sh +134 -0
  24. package/skills/ui-builder/README.md +169 -0
  25. package/skills/ui-builder/SKILL.md +357 -0
  26. package/skills/ui-builder/examples/dashboard.md +323 -0
  27. package/skills/ui-builder/examples/landing-page.md +396 -0
  28. package/skills/ui-builder/references/component-patterns.md +396 -0
  29. package/skills/ui-builder/references/layout-system.md +423 -0
  30. package/skills/ui-builder/references/polish-checklist.md +221 -0
@@ -0,0 +1,644 @@
1
+ # component-architect
2
+
3
+ ## Description
4
+
5
+ Design scalable component architectures using atomic design patterns, compound components, and composition over configuration. Prevents 800-line components and teaches proper structure.
6
+
7
+ ## Trigger
8
+
9
+ Use this skill when:
10
+ - User asks to design a component system
11
+ - User wants to refactor large components
12
+ - User says "architect this component" or "design a component library"
13
+ - Building a design system
14
+ - Components are getting too complex
15
+
16
+ ## Instructions
17
+
18
+ ### Step 1: Analyze Current State
19
+
20
+ Before designing, understand:
21
+ - Current component structure
22
+ - Pain points (too large, hard to maintain)
23
+ - Reuse patterns
24
+ - Dependencies
25
+
26
+ ### Step 2: Apply Atomic Design
27
+
28
+ Structure components using atomic design:
29
+
30
+ ```
31
+ src/
32
+ ├── components/
33
+ │ ├── atoms/ # Basic building blocks
34
+ │ │ ├── Button/
35
+ │ │ ├── Input/
36
+ │ │ ├── Badge/
37
+ │ │ └── Icon/
38
+ │ ├── molecules/ # Groups of atoms
39
+ │ │ ├── form-field/
40
+ │ │ ├── card/
41
+ │ │ └── nav-item/
42
+ │ ├── organisms/ # Complex components
43
+ │ │ ├── header/
44
+ │ │ ├── sidebar/
45
+ │ │ └── data-table/
46
+ │ ├── templates/ # Page layouts
47
+ │ │ ├── dashboard/
48
+ │ │ ├── landing/
49
+ │ │ └── auth/
50
+ │ └── pages/ # Specific instances
51
+ │ ├── home/
52
+ │ ├── settings/
53
+ │ └── profile/
54
+ ```
55
+
56
+ ### Step 3: Design Compound Components
57
+
58
+ Use compound components for complex UI:
59
+
60
+ ```tsx
61
+ // ❌ BAD: Configuration overload
62
+ <Select
63
+ options={options}
64
+ value={value}
65
+ onChange={onChange}
66
+ placeholder="Select..."
67
+ isSearchable
68
+ isClearable
69
+ isDisabled
70
+ isLoading
71
+ formatOptionLabel={formatLabel}
72
+ formatGroupLabel={formatGroup}
73
+ />
74
+
75
+ // ✅ GOOD: Compound components
76
+ <Select value={value} onChange={onChange}>
77
+ <Select.Trigger>
78
+ <Select.Value placeholder="Select..." />
79
+ <Select.Icon />
80
+ </Select.Trigger>
81
+ <Select.Content>
82
+ {options.map(option => (
83
+ <Select.Item key={option.value} value={option.value}>
84
+ {option.label}
85
+ </Select.Item>
86
+ ))}
87
+ </Select.Content>
88
+ </Select>
89
+ ```
90
+
91
+ ### Step 4: Use Composition Pattern
92
+
93
+ Compose components instead of configuring:
94
+
95
+ ```tsx
96
+ // ❌ BAD: One giant component
97
+ <Card
98
+ title="Title"
99
+ description="Description"
100
+ image="/image.jpg"
101
+ actions={<Button>Action</Button>}
102
+ footer={<div>Footer</div>}
103
+ header={<div>Header</div>}
104
+ variant="outlined"
105
+ size="large"
106
+ />
107
+
108
+ // ✅ GOOD: Composition
109
+ <Card>
110
+ <Card.Header>
111
+ <Card.Title>Title</Card.Title>
112
+ <Card.Description>Description</Card.Description>
113
+ </Card.Header>
114
+ <Card.Image src="/image.jpg" />
115
+ <Card.Content>
116
+ {/* Content here */}
117
+ </Card.Content>
118
+ <Card.Footer>
119
+ <Button>Action</Button>
120
+ </Card.Footer>
121
+ </Card>
122
+ ```
123
+
124
+ ### Step 5: Separate Concerns
125
+
126
+ Split components by concern:
127
+
128
+ ```tsx
129
+ // ❌ BAD: Mixed concerns
130
+ function UserCard({ user }) {
131
+ const [isEditing, setIsEditing] = useState(false)
132
+ const [formData, setFormData] = useState(user)
133
+
134
+ const handleSubmit = async () => {
135
+ await updateUser(formData)
136
+ setIsEditing(false)
137
+ }
138
+
139
+ return (
140
+ <div>
141
+ {isEditing ? (
142
+ <form onSubmit={handleSubmit}>
143
+ {/* Edit form */}
144
+ </form>
145
+ ) : (
146
+ <div>
147
+ {/* Display user */}
148
+ </div>
149
+ )}
150
+ </div>
151
+ )
152
+ }
153
+
154
+ // ✅ GOOD: Separated concerns
155
+ function UserCard({ user }) {
156
+ return (
157
+ <Card>
158
+ <Card.Content>
159
+ <UserInfo user={user} />
160
+ </Card.Content>
161
+ <Card.Footer>
162
+ <UserActions user={user} />
163
+ </Card.Footer>
164
+ </Card>
165
+ )
166
+ }
167
+
168
+ function UserInfo({ user }) {
169
+ return <div>{/* Display user */}</div>
170
+ }
171
+
172
+ function UserActions({ user }) {
173
+ const [isEditing, setIsEditing] = useState(false)
174
+ return <Button onClick={() => setIsEditing(true)}>Edit</Button>
175
+ }
176
+ ```
177
+
178
+ ### Step 6: Create Component Variants
179
+
180
+ Use variants instead of props:
181
+
182
+ ```tsx
183
+ // ❌ BAD: Too many props
184
+ <Button
185
+ primary
186
+ secondary
187
+ danger
188
+ outline
189
+ ghost
190
+ size="small"
191
+ size="medium"
192
+ size="large"
193
+ loading
194
+ disabled
195
+ icon={<Icon />}
196
+ />
197
+
198
+ // ✅ GOOD: Variants
199
+ <Button variant="primary">Primary</Button>
200
+ <Button variant="secondary">Secondary</Button>
201
+ <Button variant="danger">Danger</Button>
202
+ <Button variant="outline">Outline</Button>
203
+ <Button variant="ghost">Ghost</Button>
204
+ <Button size="sm">Small</Button>
205
+ <Button size="md">Medium</Button>
206
+ <Button size="lg">Large</Button>
207
+ ```
208
+
209
+ ### Step 7: Extract Custom Hooks
210
+
211
+ Extract logic into custom hooks:
212
+
213
+ ```tsx
214
+ // ❌ BAD: Logic in component
215
+ function DataTable({ data }) {
216
+ const [sort, setSort] = useState('name')
217
+ const [filter, setFilter] = useState('')
218
+ const [page, setPage] = useState(1)
219
+
220
+ const filteredData = data.filter(item =>
221
+ item.name.includes(filter)
222
+ )
223
+
224
+ const sortedData = filteredData.sort((a, b) =>
225
+ a[sort].localeCompare(b[sort])
226
+ )
227
+
228
+ const paginatedData = sortedData.slice(
229
+ (page - 1) * 10,
230
+ page * 10
231
+ )
232
+
233
+ return <Table data={paginatedData} />
234
+ }
235
+
236
+ // ✅ GOOD: Custom hook
237
+ function useDataTable(data) {
238
+ const [sort, setSort] = useState('name')
239
+ const [filter, setFilter] = useState('')
240
+ const [page, setPage] = useState(1)
241
+
242
+ const filteredData = data.filter(item =>
243
+ item.name.includes(filter)
244
+ )
245
+
246
+ const sortedData = filteredData.sort((a, b) =>
247
+ a[sort].localeCompare(b[sort])
248
+ )
249
+
250
+ const paginatedData = sortedData.slice(
251
+ (page - 1) * 10,
252
+ page * 10
253
+ )
254
+
255
+ return { data: paginatedData, sort, setSort, filter, setFilter, page, setPage }
256
+ }
257
+
258
+ function DataTable({ data }) {
259
+ const { data: tableData } = useDataTable(data)
260
+ return <Table data={tableData} />
261
+ }
262
+ ```
263
+
264
+ ### Step 8: Document Components
265
+
266
+ Create clear documentation:
267
+
268
+ ```tsx
269
+ /**
270
+ * Button component for user actions.
271
+ *
272
+ * @example
273
+ * <Button variant="primary" size="md">
274
+ * Click me
275
+ * </Button>
276
+ *
277
+ * @example
278
+ * <Button variant="outline" isLoading>
279
+ * Loading
280
+ * </Button>
281
+ */
282
+ interface ButtonProps {
283
+ /** Button variant */
284
+ variant?: 'primary' | 'secondary' | 'danger' | 'outline' | 'ghost'
285
+ /** Button size */
286
+ size?: 'sm' | 'md' | 'lg'
287
+ /** Loading state */
288
+ isLoading?: boolean
289
+ /** Disabled state */
290
+ disabled?: boolean
291
+ /** Button content */
292
+ children: React.ReactNode
293
+ /** Click handler */
294
+ onClick?: () => void
295
+ }
296
+ ```
297
+
298
+ ## Component Patterns
299
+
300
+ ### 1. Compound Components
301
+ ```tsx
302
+ <Tabs>
303
+ <Tabs.List>
304
+ <Tabs.Trigger value="tab1">Tab 1</Tabs.Trigger>
305
+ <Tabs.Trigger value="tab2">Tab 2</Tabs.Trigger>
306
+ </Tabs.List>
307
+ <Tabs.Content value="tab1">Content 1</Tabs.Content>
308
+ <Tabs.Content value="tab2">Content 2</Tabs.Content>
309
+ </Tabs>
310
+ ```
311
+
312
+ ### 2. Render Props
313
+ ```tsx
314
+ <DataList items={items}>
315
+ {(item) => (
316
+ <DataList.Item key={item.id}>
317
+ <DataList.Content>{item.name}</DataList.Content>
318
+ </DataList.Item>
319
+ )}
320
+ </DataList>
321
+ ```
322
+
323
+ ### 3. Higher-Order Components
324
+ ```tsx
325
+ const withLoading = (WrappedComponent) => {
326
+ return function WithLoadingComponent({ isLoading, ...props }) {
327
+ if (isLoading) return <Spinner />
328
+ return <WrappedComponent {...props} />
329
+ }
330
+ }
331
+
332
+ const UserCardWithLoading = withLoading(UserCard)
333
+ ```
334
+
335
+ ### 4. Custom Hooks
336
+ ```tsx
337
+ function useToggle(initialValue = false) {
338
+ const [value, setValue] = useState(initialValue)
339
+ const toggle = useCallback(() => setValue(v => !v), [])
340
+ return [value, toggle]
341
+ }
342
+ ```
343
+
344
+ ### 5. Context Providers
345
+ ```tsx
346
+ const ThemeContext = createContext()
347
+
348
+ function ThemeProvider({ children }) {
349
+ const [theme, setTheme] = useState('light')
350
+ return (
351
+ <ThemeContext.Provider value={{ theme, setTheme }}>
352
+ {children}
353
+ </ThemeContext.Provider>
354
+ )
355
+ }
356
+ ```
357
+
358
+ ## Anti-Patterns
359
+
360
+ ### ❌ 800-Line Components
361
+ ```tsx
362
+ // BAD: One giant component
363
+ function Dashboard() {
364
+ // 800 lines of code
365
+ }
366
+ ```
367
+
368
+ ### ✅ Split Into Smaller Components
369
+ ```tsx
370
+ // GOOD: Split by concern
371
+ function Dashboard() {
372
+ return (
373
+ <DashboardLayout>
374
+ <DashboardHeader />
375
+ <DashboardStats />
376
+ <DashboardTable />
377
+ <DashboardFooter />
378
+ </DashboardLayout>
379
+ )
380
+ }
381
+ ```
382
+
383
+ ### ❌ Configuration Overload
384
+ ```tsx
385
+ // BAD: Too many props
386
+ <Component
387
+ prop1={value1}
388
+ prop2={value2}
389
+ prop3={value3}
390
+ prop4={value4}
391
+ prop5={value5}
392
+ prop6={value6}
393
+ prop7={value7}
394
+ prop8={value8}
395
+ />
396
+ ```
397
+
398
+ ### ✅ Composition
399
+ ```tsx
400
+ // GOOD: Compose components
401
+ <Component>
402
+ <Component.Header>Header</Component.Header>
403
+ <Component.Content>Content</Component.Content>
404
+ <Component.Footer>Footer</Component.Footer>
405
+ </Component>
406
+ ```
407
+
408
+ ### ❌ Mixed Concerns
409
+ ```tsx
410
+ // BAD: UI + logic + data fetching
411
+ function UserCard() {
412
+ const [user, setUser] = useState(null)
413
+ const [loading, setLoading] = useState(true)
414
+
415
+ useEffect(() => {
416
+ fetchUser().then(setUser)
417
+ }, [])
418
+
419
+ if (loading) return <Spinner />
420
+
421
+ return (
422
+ <div>
423
+ {/* UI + logic + data */}
424
+ </div>
425
+ )
426
+ }
427
+ ```
428
+
429
+ ### ✅ Separated Concerns
430
+ ```tsx
431
+ // GOOD: Separate UI, logic, data
432
+ function UserCard({ user }) {
433
+ return (
434
+ <Card>
435
+ <UserInfo user={user} />
436
+ <UserActions user={user} />
437
+ </Card>
438
+ )
439
+ }
440
+
441
+ function useUser(id) {
442
+ const [user, setUser] = useState(null)
443
+ useEffect(() => {
444
+ fetchUser(id).then(setUser)
445
+ }, [id])
446
+ return user
447
+ }
448
+ ```
449
+
450
+ ## File Structure
451
+
452
+ ```
453
+ src/
454
+ ├── components/
455
+ │ ├── atoms/
456
+ │ │ ├── Button/
457
+ │ │ │ ├── Button.tsx
458
+ │ │ │ ├── Button.test.tsx
459
+ │ │ │ ├── Button.stories.tsx
460
+ │ │ │ └── index.ts
461
+ │ │ ├── Input/
462
+ │ │ └── Badge/
463
+ │ ├── molecules/
464
+ │ │ ├── form-field/
465
+ │ │ └── card/
466
+ │ ├── organisms/
467
+ │ │ ├── header/
468
+ │ │ └── sidebar/
469
+ │ ├── templates/
470
+ │ └── pages/
471
+ ├── hooks/
472
+ │ ├── useToggle.ts
473
+ │ ├── useDataTable.ts
474
+ │ └── useMediaQuery.ts
475
+ ├── lib/
476
+ │ ├── utils.ts
477
+ │ └── cn.ts
478
+ └── styles/
479
+ └── globals.css
480
+ ```
481
+
482
+ ## Examples
483
+
484
+ ### Example 1: Button Component
485
+
486
+ ```tsx
487
+ // atoms/Button/Button.tsx
488
+ import { cn } from '@/lib/utils'
489
+
490
+ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
491
+ variant?: 'primary' | 'secondary' | 'danger' | 'outline' | 'ghost'
492
+ size?: 'sm' | 'md' | 'lg'
493
+ isLoading?: boolean
494
+ }
495
+
496
+ const variants = {
497
+ primary: 'bg-zinc-900 text-white hover:bg-zinc-800',
498
+ secondary: 'bg-zinc-100 text-zinc-900 hover:bg-zinc-200',
499
+ danger: 'bg-red-600 text-white hover:bg-red-700',
500
+ outline: 'border border-zinc-300 text-zinc-700 hover:bg-zinc-50',
501
+ ghost: 'text-zinc-600 hover:text-zinc-900 hover:bg-zinc-100',
502
+ }
503
+
504
+ const sizes = {
505
+ sm: 'px-3 py-1.5 text-xs',
506
+ md: 'px-4 py-2 text-sm',
507
+ lg: 'px-6 py-3 text-base',
508
+ }
509
+
510
+ export function Button({
511
+ variant = 'primary',
512
+ size = 'md',
513
+ isLoading,
514
+ disabled,
515
+ className,
516
+ children,
517
+ ...props
518
+ }: ButtonProps) {
519
+ return (
520
+ <button
521
+ className={cn(
522
+ 'inline-flex items-center justify-center font-medium rounded-lg transition-colors',
523
+ 'disabled:opacity-50 disabled:cursor-not-allowed',
524
+ variants[variant],
525
+ sizes[size],
526
+ className
527
+ )}
528
+ disabled={disabled || isLoading}
529
+ {...props}
530
+ >
531
+ {isLoading && <Spinner className="mr-2" />}
532
+ {children}
533
+ </button>
534
+ )
535
+ }
536
+ ```
537
+
538
+ ### Example 2: Card Component
539
+
540
+ ```tsx
541
+ // molecules/Card/Card.tsx
542
+ import { cn } from '@/lib/utils'
543
+
544
+ interface CardProps extends React.HTMLAttributes<HTMLDivElement> {}
545
+
546
+ export function Card({ className, children, ...props }: CardProps) {
547
+ return (
548
+ <div
549
+ className={cn(
550
+ 'bg-white border border-zinc-200 rounded-lg',
551
+ className
552
+ )}
553
+ {...props}
554
+ >
555
+ {children}
556
+ </div>
557
+ )
558
+ }
559
+
560
+ Card.Header = function CardHeader({ className, children, ...props }) {
561
+ return (
562
+ <div
563
+ className={cn('px-6 py-4 border-b border-zinc-200', className)}
564
+ {...props}
565
+ >
566
+ {children}
567
+ </div>
568
+ )
569
+ }
570
+
571
+ Card.Title = function CardTitle({ className, children, ...props }) {
572
+ return (
573
+ <h3
574
+ className={cn('text-lg font-semibold text-zinc-900', className)}
575
+ {...props}
576
+ >
577
+ {children}
578
+ </h3>
579
+ )
580
+ }
581
+
582
+ Card.Content = function CardContent({ className, children, ...props }) {
583
+ return (
584
+ <div className={cn('px-6 py-4', className)} {...props}>
585
+ {children}
586
+ </div>
587
+ )
588
+ }
589
+
590
+ Card.Footer = function CardFooter({ className, children, ...props }) {
591
+ return (
592
+ <div
593
+ className={cn('px-6 py-4 border-t border-zinc-200', className)}
594
+ {...props}
595
+ >
596
+ {children}
597
+ </div>
598
+ )
599
+ }
600
+ ```
601
+
602
+ ### Example 3: Custom Hook
603
+
604
+ ```tsx
605
+ // hooks/useToggle.ts
606
+ import { useState, useCallback } from 'react'
607
+
608
+ export function useToggle(initialValue = false) {
609
+ const [value, setValue] = useState(initialValue)
610
+
611
+ const toggle = useCallback(() => {
612
+ setValue(v => !v)
613
+ }, [])
614
+
615
+ const setTrue = useCallback(() => {
616
+ setValue(true)
617
+ }, [])
618
+
619
+ const setFalse = useCallback(() => {
620
+ setValue(false)
621
+ }, [])
622
+
623
+ return { value, toggle, setTrue, setFalse }
624
+ }
625
+ ```
626
+
627
+ ## References
628
+
629
+ - [Atomic Design](https://atomicdesign.bradfrost.com/)
630
+ - [Compound Components](https://www.youtube.com/watch?v=v9ContrapKto)
631
+ - [React Patterns](https://reactpatterns.com/)
632
+ - [ui.shadcn.com](https://ui.shadcn.com/)
633
+
634
+ ## Validation Checklist
635
+
636
+ Before delivering component architecture:
637
+ - [ ] Components follow atomic design
638
+ - [ ] No 800+ line components
639
+ - [ ] Compound components used appropriately
640
+ - [ ] Composition over configuration
641
+ - [ ] Concerns separated
642
+ - [ ] Custom hooks extracted
643
+ - [ ] TypeScript types defined
644
+ - [ ] Documentation provided