oh-my-codex-cli 0.1.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.
- package/.agent/skills/agent-kb/HOW_TO_USE.md +428 -0
- package/.agent/skills/agent-kb/README.md +46 -0
- package/.agent/skills/agent-kb/SKILL.md +128 -0
- package/.agent/skills/agent-kb/references/intelligent-analysis-explained.md +333 -0
- package/.agent/skills/agent-kb/references/query-optimization.md +225 -0
- package/.agent/skills/aireview/SKILL.md +704 -0
- package/.agent/skills/analyze/SKILL.md +81 -0
- package/.agent/skills/architect-planner/HOW_TO_USE.md +238 -0
- package/.agent/skills/architect-planner/README.md +41 -0
- package/.agent/skills/architect-planner/SKILL.md +539 -0
- package/.agent/skills/auto-mbti/SKILL.md +291 -0
- package/.agent/skills/autopilot/SKILL.md +222 -0
- package/.agent/skills/backend-patterns/SKILL.md +602 -0
- package/.agent/skills/bdd-generator/README.md +78 -0
- package/.agent/skills/bdd-generator/SKILL.md +436 -0
- package/.agent/skills/brainstorming/HOW_TO_USE.md +289 -0
- package/.agent/skills/brainstorming/README.md +41 -0
- package/.agent/skills/brainstorming/SKILL.md +165 -0
- package/.agent/skills/build-fix/SKILL.md +190 -0
- package/.agent/skills/cancel/SKILL.md +658 -0
- package/.agent/skills/checkpoint/SKILL.md +94 -0
- package/.agent/skills/code-review/SKILL.md +273 -0
- package/.agent/skills/coding-standards/SKILL.md +535 -0
- package/.agent/skills/conductor/SKILL.md +128 -0
- package/.agent/skills/conductor/commands/conductor/implement.toml +358 -0
- package/.agent/skills/conductor/commands/conductor/newTrack.toml +142 -0
- package/.agent/skills/conductor/commands/conductor/revert.toml +123 -0
- package/.agent/skills/conductor/commands/conductor/setup.toml +429 -0
- package/.agent/skills/conductor/commands/conductor/status.toml +57 -0
- package/.agent/skills/conductor/scripts/install.sh +89 -0
- package/.agent/skills/conductor/templates/code_styleguides/csharp.md +115 -0
- package/.agent/skills/conductor/templates/code_styleguides/dart.md +238 -0
- package/.agent/skills/conductor/templates/code_styleguides/general.md +23 -0
- package/.agent/skills/conductor/templates/code_styleguides/go.md +48 -0
- package/.agent/skills/conductor/templates/code_styleguides/html-css.md +49 -0
- package/.agent/skills/conductor/templates/code_styleguides/javascript.md +51 -0
- package/.agent/skills/conductor/templates/code_styleguides/python.md +37 -0
- package/.agent/skills/conductor/templates/code_styleguides/typescript.md +43 -0
- package/.agent/skills/conductor/templates/rules/README.md +23 -0
- package/.agent/skills/conductor/templates/rules/agents.md +49 -0
- package/.agent/skills/conductor/templates/rules/coding-style.md +70 -0
- package/.agent/skills/conductor/templates/rules/dev.md +20 -0
- package/.agent/skills/conductor/templates/rules/git-workflow.md +45 -0
- package/.agent/skills/conductor/templates/rules/hooks.md +6 -0
- package/.agent/skills/conductor/templates/rules/patterns.md +55 -0
- package/.agent/skills/conductor/templates/rules/performance.md +47 -0
- package/.agent/skills/conductor/templates/rules/research.md +26 -0
- package/.agent/skills/conductor/templates/rules/review.md +22 -0
- package/.agent/skills/conductor/templates/rules/security.md +36 -0
- package/.agent/skills/conductor/templates/rules/testing.md +30 -0
- package/.agent/skills/conductor/templates/workflow.md +333 -0
- package/.agent/skills/consensus/HOW_TO_USE.md +191 -0
- package/.agent/skills/consensus/README.md +41 -0
- package/.agent/skills/consensus/SKILL.md +317 -0
- package/.agent/skills/content-research-writer/SKILL.md +537 -0
- package/.agent/skills/debug-analysis/SKILL.md +331 -0
- package/.agent/skills/deepinit/SKILL.md +347 -0
- package/.agent/skills/deepsearch/SKILL.md +56 -0
- package/.agent/skills/doctor/SKILL.md +158 -0
- package/.agent/skills/drawio/EXAMPLES.md +382 -0
- package/.agent/skills/drawio/QUICK_START.md +237 -0
- package/.agent/skills/drawio/README.md +315 -0
- package/.agent/skills/drawio/SETUP_GUIDE.md +254 -0
- package/.agent/skills/drawio/SKILL.md +1176 -0
- package/.agent/skills/e2e/SKILL.md +396 -0
- package/.agent/skills/ecomode/SKILL.md +160 -0
- package/.agent/skills/electron-driver/SKILL.md +144 -0
- package/.agent/skills/electron-driver/scripts/driver-template.js +71 -0
- package/.agent/skills/eval/SKILL.md +140 -0
- package/.agent/skills/eval-harness/SKILL.md +242 -0
- package/.agent/skills/evolve/SKILL.md +213 -0
- package/.agent/skills/frontend-design/SKILL.md +42 -0
- package/.agent/skills/frontend-patterns/SKILL.md +646 -0
- package/.agent/skills/frontend-ui-ux/SKILL.md +70 -0
- package/.agent/skills/git-master/SKILL.md +75 -0
- package/.agent/skills/help/SKILL.md +89 -0
- package/.agent/skills/iterative-retrieval/SKILL.md +217 -0
- package/.agent/skills/local-skills-setup/SKILL.md +483 -0
- package/.agent/skills/log-analyzer/SKILL.md +187 -0
- package/.agent/skills/mcp-setup/SKILL.md +226 -0
- package/.agent/skills/multi-model-research/HOW_TO_USE.md +614 -0
- package/.agent/skills/multi-model-research/README.md +233 -0
- package/.agent/skills/multi-model-research/SKILL.md +541 -0
- package/.agent/skills/multi-model-research/references/troubleshooting.md +415 -0
- package/.agent/skills/note/SKILL.md +80 -0
- package/.agent/skills/omc-setup/SKILL.md +219 -0
- package/.agent/skills/orchestrate/SKILL.md +620 -0
- package/.agent/skills/patent-workflow/IMPLEMENTATION_SUMMARY.md +500 -0
- package/.agent/skills/patent-workflow/README.md +455 -0
- package/.agent/skills/patent-workflow/SKILL.md +1036 -0
- package/.agent/skills/patent-workflow/tools/irr_checker.py +260 -0
- package/.agent/skills/patent-workflow/tools/sample_terminology.json +49 -0
- package/.agent/skills/patent-workflow/tools/term_checker.py +355 -0
- package/.agent/skills/pattern-recognition/SKILL.md +792 -0
- package/.agent/skills/pipeline/SKILL.md +448 -0
- package/.agent/skills/plan/SKILL.md +309 -0
- package/.agent/skills/planning-methodology/SKILL.md +370 -0
- package/.agent/skills/planning-with-files/SKILL.md +210 -0
- package/.agent/skills/planning-with-files/examples.md +202 -0
- package/.agent/skills/planning-with-files/reference.md +218 -0
- package/.agent/skills/planning-with-files/scripts/check-complete.ps1 +42 -0
- package/.agent/skills/planning-with-files/scripts/check-complete.sh +44 -0
- package/.agent/skills/planning-with-files/scripts/init-session.ps1 +120 -0
- package/.agent/skills/planning-with-files/scripts/init-session.sh +120 -0
- package/.agent/skills/planning-with-files/scripts/session-catchup.py +208 -0
- package/.agent/skills/planning-with-files/templates/findings.md +95 -0
- package/.agent/skills/planning-with-files/templates/progress.md +114 -0
- package/.agent/skills/planning-with-files/templates/task_plan.md +132 -0
- package/.agent/skills/project-analyze/CLAUDE.md +18 -0
- package/.agent/skills/project-analyze/HOW_TO_USE.md +145 -0
- package/.agent/skills/project-analyze/README.md +42 -0
- package/.agent/skills/project-analyze/SKILL.md +289 -0
- package/.agent/skills/project-analyze/SKILL.md.backup +287 -0
- package/.agent/skills/project-analyze/SKILL.md.backup_20260105_093646 +287 -0
- package/.agent/skills/project-analyze/assets/analysis-report-template.md +433 -0
- package/.agent/skills/project-analyze/references/analysis-patterns.md +422 -0
- package/.agent/skills/project-analyze/references/projectmind-explained.md +535 -0
- package/.agent/skills/project-session-manager/SKILL.md +428 -0
- package/.agent/skills/project-session-manager/lib/config.sh +86 -0
- package/.agent/skills/project-session-manager/lib/parse.sh +121 -0
- package/.agent/skills/project-session-manager/lib/session.sh +132 -0
- package/.agent/skills/project-session-manager/lib/tmux.sh +103 -0
- package/.agent/skills/project-session-manager/lib/worktree.sh +171 -0
- package/.agent/skills/project-session-manager/psm.sh +629 -0
- package/.agent/skills/project-session-manager/templates/feature.md +56 -0
- package/.agent/skills/project-session-manager/templates/issue-fix.md +57 -0
- package/.agent/skills/project-session-manager/templates/pr-review.md +65 -0
- package/.agent/skills/project-session-manager/templates/projects.json +19 -0
- package/.agent/skills/quality-check/HOW_TO_USE.md +171 -0
- package/.agent/skills/quality-check/README.md +50 -0
- package/.agent/skills/quality-check/SKILL.md +240 -0
- package/.agent/skills/quality-check/SKILL.md.backup +238 -0
- package/.agent/skills/quality-check/SKILL.md.backup_20260105_093646 +238 -0
- package/.agent/skills/quality-check/assets/quality-report-template.md +437 -0
- package/.agent/skills/quality-check/references/refactoring-patterns.md +550 -0
- package/.agent/skills/quality-check/references/scoring-criteria.md +454 -0
- package/.agent/skills/quality-validation/SKILL.md +519 -0
- package/.agent/skills/quality-validation/SKILL.md.backup +573 -0
- package/.agent/skills/quality-validation/SKILL.md.backup_20260105_093646 +573 -0
- package/.agent/skills/ralph/SKILL.md +236 -0
- package/.agent/skills/ralph-init/SKILL.md +78 -0
- package/.agent/skills/ralplan/SKILL.md +58 -0
- package/.agent/skills/refactor-clean/SKILL.md +49 -0
- package/.agent/skills/release/SKILL.md +84 -0
- package/.agent/skills/research/SKILL.md +526 -0
- package/.agent/skills/research-methodology/SKILL.md +268 -0
- package/.agent/skills/review/SKILL.md +53 -0
- package/.agent/skills/security-review/SKILL.md +509 -0
- package/.agent/skills/security-review/cloud-infrastructure-security.md +361 -0
- package/.agent/skills/setup-pm/SKILL.md +102 -0
- package/.agent/skills/skill/SKILL.md +424 -0
- package/.agent/skills/skill-create/SKILL.md +209 -0
- package/.agent/skills/skill-debugger/HOW_TO_USE.md +244 -0
- package/.agent/skills/skill-debugger/README.md +44 -0
- package/.agent/skills/skill-debugger/SKILL.md +326 -0
- package/.agent/skills/skill-debugger/diagnostic_checklist.md +115 -0
- package/.agent/skills/skill-development/SKILL.md +661 -0
- package/.agent/skills/skill-development/references/skill-creator-original.md +209 -0
- package/.agent/skills/skill-doc-generator/README.md +37 -0
- package/.agent/skills/skill-doc-generator/SKILL.md +331 -0
- package/.agent/skills/skill-quality-analyzer/HOW_TO_USE.md +243 -0
- package/.agent/skills/skill-quality-analyzer/README.md +61 -0
- package/.agent/skills/skill-quality-analyzer/SKILL.md +247 -0
- package/.agent/skills/skill-quality-analyzer/analyzer.py +209 -0
- package/.agent/skills/skill-quality-analyzer/expected_output.json +81 -0
- package/.agent/skills/skill-quality-analyzer/sample_input.json +9 -0
- package/.agent/skills/skill-tester/README.md +46 -0
- package/.agent/skills/skill-tester/SKILL.md +345 -0
- package/.agent/skills/start-dev/SKILL.md +701 -0
- package/.agent/skills/swarm/SKILL.md +691 -0
- package/.agent/skills/task-kb-lookup/SKILL.md +211 -0
- package/.agent/skills/task-kb-record/SKILL.md +417 -0
- package/.agent/skills/tdd/SKILL.md +446 -0
- package/.agent/skills/tdd-generator/DEMO.md +516 -0
- package/.agent/skills/tdd-generator/README.md +89 -0
- package/.agent/skills/tdd-generator/SKILL.md +278 -0
- package/.agent/skills/tdd-workflow/SKILL.md +424 -0
- package/.agent/skills/test-coverage/SKILL.md +48 -0
- package/.agent/skills/thinkdeep/HOW_TO_USE.md +183 -0
- package/.agent/skills/thinkdeep/README.md +41 -0
- package/.agent/skills/thinkdeep/SKILL.md +343 -0
- package/.agent/skills/ui-ux-pro-max/SKILL.md +228 -0
- package/.agent/skills/ui-ux-pro-max/data/charts.csv +26 -0
- package/.agent/skills/ui-ux-pro-max/data/colors.csv +97 -0
- package/.agent/skills/ui-ux-pro-max/data/landing.csv +31 -0
- package/.agent/skills/ui-ux-pro-max/data/products.csv +97 -0
- package/.agent/skills/ui-ux-pro-max/data/prompts.csv +24 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/.agent/skills/ui-ux-pro-max/data/styles.csv +59 -0
- package/.agent/skills/ui-ux-pro-max/data/typography.csv +58 -0
- package/.agent/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/.agent/skills/ui-ux-pro-max/scripts/core.py +236 -0
- package/.agent/skills/ui-ux-pro-max/scripts/search.py +61 -0
- package/.agent/skills/ultrapilot/SKILL.md +647 -0
- package/.agent/skills/ultraqa/SKILL.md +152 -0
- package/.agent/skills/ultrawork/SKILL.md +123 -0
- package/.agent/skills/update-codemaps/SKILL.md +38 -0
- package/.agent/skills/update-docs/SKILL.md +52 -0
- package/.agent/skills/verification-loop/SKILL.md +140 -0
- package/.agent/skills/verify/SKILL.md +80 -0
- package/.agent/skills/writer-memory/SKILL.md +459 -0
- package/.agent/skills/writer-memory/lib/character-tracker.ts +338 -0
- package/.agent/skills/writer-memory/lib/memory-manager.ts +804 -0
- package/.agent/skills/writer-memory/lib/relationship-graph.ts +400 -0
- package/.agent/skills/writer-memory/lib/scene-organizer.ts +544 -0
- package/.agent/skills/writer-memory/lib/synopsis-builder.ts +339 -0
- package/.agent/skills/writer-memory/templates/synopsis-template.md +46 -0
- package/.governance/skill-lint.allowlist +4 -0
- package/.governance/skill-llm.allowlist +4 -0
- package/AGENTS.md +59 -0
- package/LICENSE +21 -0
- package/README.md +169 -0
- package/README.zh.md +145 -0
- package/bin/omcodex.js +8 -0
- package/commands/conductor/implement.toml +358 -0
- package/commands/conductor/newTrack.toml +142 -0
- package/commands/conductor/revert.toml +123 -0
- package/commands/conductor/setup.toml +429 -0
- package/commands/conductor/status.toml +57 -0
- package/docs/ALIGNMENT.md +40 -0
- package/docs/CODEX.md +133 -0
- package/docs/NOTIFY.md +81 -0
- package/docs/SKILL_GOVERNANCE.md +72 -0
- package/docs/SKILL_GOVERNANCE_FRAMEWORK.md +182 -0
- package/docs/SKILL_GOVERNANCE_FRAMEWORK.zh.md +170 -0
- package/package.json +50 -0
- package/prompts/architect.md +105 -0
- package/prompts/executor.md +134 -0
- package/prompts/planner.md +113 -0
- package/scripts/check-skill-governance.sh +84 -0
- package/scripts/check-skill-llm-governance.js +302 -0
- package/scripts/eval-skills.js +217 -0
- package/scripts/generate-catalog-docs.js +95 -0
- package/scripts/generate-codex-mcp-config.sh +22 -0
- package/scripts/install-codex-force.sh +5 -0
- package/scripts/install-codex-incremental.sh +5 -0
- package/scripts/install-codex.sh +79 -0
- package/scripts/notify-dispatch.js +15 -0
- package/scripts/setup-package-manager.js +137 -0
- package/src/catalog/generated/public-catalog.json +547 -0
- package/src/catalog/manifest.json +542 -0
- package/src/catalog/reader.js +43 -0
- package/src/catalog/schema.js +79 -0
- package/src/cli/doctor.js +62 -0
- package/src/cli/index.js +85 -0
- package/src/cli/notify.js +127 -0
- package/src/cli/route.js +43 -0
- package/src/cli/setup.js +155 -0
- package/src/cli/team.js +125 -0
- package/src/config/generator.js +119 -0
- package/src/mcp/memory-server.js +241 -0
- package/src/mcp/state-server.js +112 -0
- package/src/mcp/trace-server.js +168 -0
- package/src/notify/dispatch.js +74 -0
- package/src/notify/extensibility/dispatcher.js +113 -0
- package/src/notify/extensibility/events.js +15 -0
- package/src/notify/extensibility/loader.js +54 -0
- package/src/router/skill-router.js +90 -0
- package/src/team/auto-advance.js +72 -0
- package/src/team/orchestrator.js +82 -0
- package/src/team/state-store.js +33 -0
- package/src/utils/paths.js +33 -0
- package/templates/AGENTS.md +15 -0
- package/templates/catalog-manifest.json +542 -0
- package/templates/code_styleguides/csharp.md +115 -0
- package/templates/code_styleguides/dart.md +238 -0
- package/templates/code_styleguides/general.md +23 -0
- package/templates/code_styleguides/go.md +48 -0
- package/templates/code_styleguides/html-css.md +49 -0
- package/templates/code_styleguides/javascript.md +51 -0
- package/templates/code_styleguides/python.md +37 -0
- package/templates/code_styleguides/typescript.md +43 -0
- package/templates/rules/README.md +23 -0
- package/templates/rules/agents.md +49 -0
- package/templates/rules/coding-style.md +70 -0
- package/templates/rules/dev.md +20 -0
- package/templates/rules/git-workflow.md +45 -0
- package/templates/rules/notify.md +6 -0
- package/templates/rules/patterns.md +55 -0
- package/templates/rules/performance.md +47 -0
- package/templates/rules/research.md +26 -0
- package/templates/rules/review.md +22 -0
- package/templates/rules/security.md +36 -0
- package/templates/rules/testing.md +30 -0
- package/templates/workflow.md +333 -0
|
@@ -0,0 +1,646 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: frontend-patterns
|
|
3
|
+
description: Frontend development patterns for React, Next.js, state management, performance optimization, and UI best practices.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Frontend Development Patterns
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
## Native Subagent Protocol (Codex)
|
|
10
|
+
|
|
11
|
+
Codex supports native subagents. Delegate with `spawn_agent`, coordinate with `send_input`, collect via `wait`, and clean up with `close_agent`.
|
|
12
|
+
|
|
13
|
+
Execution preference:
|
|
14
|
+
1. Use native subagents first for independent workstreams (parallel when possible).
|
|
15
|
+
2. Merge results in main thread and run final verification.
|
|
16
|
+
3. Fallback only when delegation is blocked: use the `[ANALYST]`/`[ARCHITECT]`/`[EXECUTOR]`/`[REVIEWER]` structure in a single response.
|
|
17
|
+
|
|
18
|
+
Minimal orchestration pattern:
|
|
19
|
+
```text
|
|
20
|
+
spawn_agent -> send_input (optional) -> wait -> close_agent
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Modern frontend patterns for React, Next.js, and performant user interfaces.
|
|
24
|
+
|
|
25
|
+
## Component Patterns
|
|
26
|
+
|
|
27
|
+
### Composition Over Inheritance
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
// ✅ GOOD: Component composition
|
|
31
|
+
interface CardProps {
|
|
32
|
+
children: React.ReactNode
|
|
33
|
+
variant?: 'default' | 'outlined'
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function Card({ children, variant = 'default' }: CardProps) {
|
|
37
|
+
return <div className={`card card-${variant}`}>{children}</div>
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function CardHeader({ children }: { children: React.ReactNode }) {
|
|
41
|
+
return <div className="card-header">{children}</div>
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function CardBody({ children }: { children: React.ReactNode }) {
|
|
45
|
+
return <div className="card-body">{children}</div>
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Usage
|
|
49
|
+
<Card>
|
|
50
|
+
<CardHeader>Title</CardHeader>
|
|
51
|
+
<CardBody>Content</CardBody>
|
|
52
|
+
</Card>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Compound Components
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
interface TabsContextValue {
|
|
59
|
+
activeTab: string
|
|
60
|
+
setActiveTab: (tab: string) => void
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const TabsContext = createContext<TabsContextValue | undefined>(undefined)
|
|
64
|
+
|
|
65
|
+
export function Tabs({ children, defaultTab }: {
|
|
66
|
+
children: React.ReactNode
|
|
67
|
+
defaultTab: string
|
|
68
|
+
}) {
|
|
69
|
+
const [activeTab, setActiveTab] = useState(defaultTab)
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<TabsContext.Provider value={{ activeTab, setActiveTab }}>
|
|
73
|
+
{children}
|
|
74
|
+
</TabsContext.Provider>
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function TabList({ children }: { children: React.ReactNode }) {
|
|
79
|
+
return <div className="tab-list">{children}</div>
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function Tab({ id, children }: { id: string, children: React.ReactNode }) {
|
|
83
|
+
const context = useContext(TabsContext)
|
|
84
|
+
if (!context) throw new Error('Tab must be used within Tabs')
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<button
|
|
88
|
+
className={context.activeTab === id ? 'active' : ''}
|
|
89
|
+
onClick={() => context.setActiveTab(id)}
|
|
90
|
+
>
|
|
91
|
+
{children}
|
|
92
|
+
</button>
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Usage
|
|
97
|
+
<Tabs defaultTab="overview">
|
|
98
|
+
<TabList>
|
|
99
|
+
<Tab id="overview">Overview</Tab>
|
|
100
|
+
<Tab id="details">Details</Tab>
|
|
101
|
+
</TabList>
|
|
102
|
+
</Tabs>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Render Props Pattern
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
interface DataLoaderProps<T> {
|
|
109
|
+
url: string
|
|
110
|
+
children: (data: T | null, loading: boolean, error: Error | null) => React.ReactNode
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function DataLoader<T>({ url, children }: DataLoaderProps<T>) {
|
|
114
|
+
const [data, setData] = useState<T | null>(null)
|
|
115
|
+
const [loading, setLoading] = useState(true)
|
|
116
|
+
const [error, setError] = useState<Error | null>(null)
|
|
117
|
+
|
|
118
|
+
useEffect(() => {
|
|
119
|
+
fetch(url)
|
|
120
|
+
.then(res => res.json())
|
|
121
|
+
.then(setData)
|
|
122
|
+
.catch(setError)
|
|
123
|
+
.finally(() => setLoading(false))
|
|
124
|
+
}, [url])
|
|
125
|
+
|
|
126
|
+
return <>{children(data, loading, error)}</>
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Usage
|
|
130
|
+
<DataLoader<Market[]> url="/api/markets">
|
|
131
|
+
{(markets, loading, error) => {
|
|
132
|
+
if (loading) return <Spinner />
|
|
133
|
+
if (error) return <Error error={error} />
|
|
134
|
+
return <MarketList markets={markets!} />
|
|
135
|
+
}}
|
|
136
|
+
</DataLoader>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Custom Hooks Patterns
|
|
140
|
+
|
|
141
|
+
### State Management Hook
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
export function useToggle(initialValue = false): [boolean, () => void] {
|
|
145
|
+
const [value, setValue] = useState(initialValue)
|
|
146
|
+
|
|
147
|
+
const toggle = useCallback(() => {
|
|
148
|
+
setValue(v => !v)
|
|
149
|
+
}, [])
|
|
150
|
+
|
|
151
|
+
return [value, toggle]
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Usage
|
|
155
|
+
const [isOpen, toggleOpen] = useToggle()
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Async Data Fetching Hook
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
interface UseQueryOptions<T> {
|
|
162
|
+
onSuccess?: (data: T) => void
|
|
163
|
+
onError?: (error: Error) => void
|
|
164
|
+
enabled?: boolean
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function useQuery<T>(
|
|
168
|
+
key: string,
|
|
169
|
+
fetcher: () => Promise<T>,
|
|
170
|
+
options?: UseQueryOptions<T>
|
|
171
|
+
) {
|
|
172
|
+
const [data, setData] = useState<T | null>(null)
|
|
173
|
+
const [error, setError] = useState<Error | null>(null)
|
|
174
|
+
const [loading, setLoading] = useState(false)
|
|
175
|
+
|
|
176
|
+
const refetch = useCallback(async () => {
|
|
177
|
+
setLoading(true)
|
|
178
|
+
setError(null)
|
|
179
|
+
|
|
180
|
+
try {
|
|
181
|
+
const result = await fetcher()
|
|
182
|
+
setData(result)
|
|
183
|
+
options?.onSuccess?.(result)
|
|
184
|
+
} catch (err) {
|
|
185
|
+
const error = err as Error
|
|
186
|
+
setError(error)
|
|
187
|
+
options?.onError?.(error)
|
|
188
|
+
} finally {
|
|
189
|
+
setLoading(false)
|
|
190
|
+
}
|
|
191
|
+
}, [fetcher, options])
|
|
192
|
+
|
|
193
|
+
useEffect(() => {
|
|
194
|
+
if (options?.enabled !== false) {
|
|
195
|
+
refetch()
|
|
196
|
+
}
|
|
197
|
+
}, [key, refetch, options?.enabled])
|
|
198
|
+
|
|
199
|
+
return { data, error, loading, refetch }
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Usage
|
|
203
|
+
const { data: markets, loading, error, refetch } = useQuery(
|
|
204
|
+
'markets',
|
|
205
|
+
() => fetch('/api/markets').then(r => r.json()),
|
|
206
|
+
{
|
|
207
|
+
onSuccess: data => console.log('Fetched', data.length, 'markets'),
|
|
208
|
+
onError: err => console.error('Failed:', err)
|
|
209
|
+
}
|
|
210
|
+
)
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Debounce Hook
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
export function useDebounce<T>(value: T, delay: number): T {
|
|
217
|
+
const [debouncedValue, setDebouncedValue] = useState<T>(value)
|
|
218
|
+
|
|
219
|
+
useEffect(() => {
|
|
220
|
+
const handler = setTimeout(() => {
|
|
221
|
+
setDebouncedValue(value)
|
|
222
|
+
}, delay)
|
|
223
|
+
|
|
224
|
+
return () => clearTimeout(handler)
|
|
225
|
+
}, [value, delay])
|
|
226
|
+
|
|
227
|
+
return debouncedValue
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Usage
|
|
231
|
+
const [searchQuery, setSearchQuery] = useState('')
|
|
232
|
+
const debouncedQuery = useDebounce(searchQuery, 500)
|
|
233
|
+
|
|
234
|
+
useEffect(() => {
|
|
235
|
+
if (debouncedQuery) {
|
|
236
|
+
performSearch(debouncedQuery)
|
|
237
|
+
}
|
|
238
|
+
}, [debouncedQuery])
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## State Management Patterns
|
|
242
|
+
|
|
243
|
+
### Context + Reducer Pattern
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
interface State {
|
|
247
|
+
markets: Market[]
|
|
248
|
+
selectedMarket: Market | null
|
|
249
|
+
loading: boolean
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
type Action =
|
|
253
|
+
| { type: 'SET_MARKETS'; payload: Market[] }
|
|
254
|
+
| { type: 'SELECT_MARKET'; payload: Market }
|
|
255
|
+
| { type: 'SET_LOADING'; payload: boolean }
|
|
256
|
+
|
|
257
|
+
function reducer(state: State, action: Action): State {
|
|
258
|
+
switch (action.type) {
|
|
259
|
+
case 'SET_MARKETS':
|
|
260
|
+
return { ...state, markets: action.payload }
|
|
261
|
+
case 'SELECT_MARKET':
|
|
262
|
+
return { ...state, selectedMarket: action.payload }
|
|
263
|
+
case 'SET_LOADING':
|
|
264
|
+
return { ...state, loading: action.payload }
|
|
265
|
+
default:
|
|
266
|
+
return state
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const MarketContext = createContext<{
|
|
271
|
+
state: State
|
|
272
|
+
dispatch: Dispatch<Action>
|
|
273
|
+
} | undefined>(undefined)
|
|
274
|
+
|
|
275
|
+
export function MarketProvider({ children }: { children: React.ReactNode }) {
|
|
276
|
+
const [state, dispatch] = useReducer(reducer, {
|
|
277
|
+
markets: [],
|
|
278
|
+
selectedMarket: null,
|
|
279
|
+
loading: false
|
|
280
|
+
})
|
|
281
|
+
|
|
282
|
+
return (
|
|
283
|
+
<MarketContext.Provider value={{ state, dispatch }}>
|
|
284
|
+
{children}
|
|
285
|
+
</MarketContext.Provider>
|
|
286
|
+
)
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export function useMarkets() {
|
|
290
|
+
const context = useContext(MarketContext)
|
|
291
|
+
if (!context) throw new Error('useMarkets must be used within MarketProvider')
|
|
292
|
+
return context
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
## Performance Optimization
|
|
297
|
+
|
|
298
|
+
### Memoization
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
// ✅ useMemo for expensive computations
|
|
302
|
+
const sortedMarkets = useMemo(() => {
|
|
303
|
+
return markets.sort((a, b) => b.volume - a.volume)
|
|
304
|
+
}, [markets])
|
|
305
|
+
|
|
306
|
+
// ✅ useCallback for functions passed to children
|
|
307
|
+
const handleSearch = useCallback((query: string) => {
|
|
308
|
+
setSearchQuery(query)
|
|
309
|
+
}, [])
|
|
310
|
+
|
|
311
|
+
// ✅ React.memo for pure components
|
|
312
|
+
export const MarketCard = React.memo<MarketCardProps>(({ market }) => {
|
|
313
|
+
return (
|
|
314
|
+
<div className="market-card">
|
|
315
|
+
<h3>{market.name}</h3>
|
|
316
|
+
<p>{market.description}</p>
|
|
317
|
+
</div>
|
|
318
|
+
)
|
|
319
|
+
})
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Code Splitting & Lazy Loading
|
|
323
|
+
|
|
324
|
+
```typescript
|
|
325
|
+
import { lazy, Suspense } from 'react'
|
|
326
|
+
|
|
327
|
+
// ✅ Lazy load heavy components
|
|
328
|
+
const HeavyChart = lazy(() => import('./HeavyChart'))
|
|
329
|
+
const ThreeJsBackground = lazy(() => import('./ThreeJsBackground'))
|
|
330
|
+
|
|
331
|
+
export function Dashboard() {
|
|
332
|
+
return (
|
|
333
|
+
<div>
|
|
334
|
+
<Suspense fallback={<ChartSkeleton />}>
|
|
335
|
+
<HeavyChart data={data} />
|
|
336
|
+
</Suspense>
|
|
337
|
+
|
|
338
|
+
<Suspense fallback={null}>
|
|
339
|
+
<ThreeJsBackground />
|
|
340
|
+
</Suspense>
|
|
341
|
+
</div>
|
|
342
|
+
)
|
|
343
|
+
}
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Virtualization for Long Lists
|
|
347
|
+
|
|
348
|
+
```typescript
|
|
349
|
+
import { useVirtualizer } from '@tanstack/react-virtual'
|
|
350
|
+
|
|
351
|
+
export function VirtualMarketList({ markets }: { markets: Market[] }) {
|
|
352
|
+
const parentRef = useRef<HTMLDivElement>(null)
|
|
353
|
+
|
|
354
|
+
const virtualizer = useVirtualizer({
|
|
355
|
+
count: markets.length,
|
|
356
|
+
getScrollElement: () => parentRef.current,
|
|
357
|
+
estimateSize: () => 100, // Estimated row height
|
|
358
|
+
overscan: 5 // Extra items to render
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
return (
|
|
362
|
+
<div ref={parentRef} style={{ height: '600px', overflow: 'auto' }}>
|
|
363
|
+
<div
|
|
364
|
+
style={{
|
|
365
|
+
height: `${virtualizer.getTotalSize()}px`,
|
|
366
|
+
position: 'relative'
|
|
367
|
+
}}
|
|
368
|
+
>
|
|
369
|
+
{virtualizer.getVirtualItems().map(virtualRow => (
|
|
370
|
+
<div
|
|
371
|
+
key={virtualRow.index}
|
|
372
|
+
style={{
|
|
373
|
+
position: 'absolute',
|
|
374
|
+
top: 0,
|
|
375
|
+
left: 0,
|
|
376
|
+
width: '100%',
|
|
377
|
+
height: `${virtualRow.size}px`,
|
|
378
|
+
transform: `translateY(${virtualRow.start}px)`
|
|
379
|
+
}}
|
|
380
|
+
>
|
|
381
|
+
<MarketCard market={markets[virtualRow.index]} />
|
|
382
|
+
</div>
|
|
383
|
+
))}
|
|
384
|
+
</div>
|
|
385
|
+
</div>
|
|
386
|
+
)
|
|
387
|
+
}
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
## Form Handling Patterns
|
|
391
|
+
|
|
392
|
+
### Controlled Form with Validation
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
interface FormData {
|
|
396
|
+
name: string
|
|
397
|
+
description: string
|
|
398
|
+
endDate: string
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
interface FormErrors {
|
|
402
|
+
name?: string
|
|
403
|
+
description?: string
|
|
404
|
+
endDate?: string
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
export function CreateMarketForm() {
|
|
408
|
+
const [formData, setFormData] = useState<FormData>({
|
|
409
|
+
name: '',
|
|
410
|
+
description: '',
|
|
411
|
+
endDate: ''
|
|
412
|
+
})
|
|
413
|
+
|
|
414
|
+
const [errors, setErrors] = useState<FormErrors>({})
|
|
415
|
+
|
|
416
|
+
const validate = (): boolean => {
|
|
417
|
+
const newErrors: FormErrors = {}
|
|
418
|
+
|
|
419
|
+
if (!formData.name.trim()) {
|
|
420
|
+
newErrors.name = 'Name is required'
|
|
421
|
+
} else if (formData.name.length > 200) {
|
|
422
|
+
newErrors.name = 'Name must be under 200 characters'
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
if (!formData.description.trim()) {
|
|
426
|
+
newErrors.description = 'Description is required'
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
if (!formData.endDate) {
|
|
430
|
+
newErrors.endDate = 'End date is required'
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
setErrors(newErrors)
|
|
434
|
+
return Object.keys(newErrors).length === 0
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
const handleSubmit = async (e: React.FormEvent) => {
|
|
438
|
+
e.preventDefault()
|
|
439
|
+
|
|
440
|
+
if (!validate()) return
|
|
441
|
+
|
|
442
|
+
try {
|
|
443
|
+
await createMarket(formData)
|
|
444
|
+
// Success handling
|
|
445
|
+
} catch (error) {
|
|
446
|
+
// Error handling
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
return (
|
|
451
|
+
<form onSubmit={handleSubmit}>
|
|
452
|
+
<input
|
|
453
|
+
value={formData.name}
|
|
454
|
+
onChange={e => setFormData(prev => ({ ...prev, name: e.target.value }))}
|
|
455
|
+
placeholder="Market name"
|
|
456
|
+
/>
|
|
457
|
+
{errors.name && <span className="error">{errors.name}</span>}
|
|
458
|
+
|
|
459
|
+
{/* Other fields */}
|
|
460
|
+
|
|
461
|
+
<button type="submit">Create Market</button>
|
|
462
|
+
</form>
|
|
463
|
+
)
|
|
464
|
+
}
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
## Error Boundary Pattern
|
|
468
|
+
|
|
469
|
+
```typescript
|
|
470
|
+
interface ErrorBoundaryState {
|
|
471
|
+
hasError: boolean
|
|
472
|
+
error: Error | null
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
export class ErrorBoundary extends React.Component<
|
|
476
|
+
{ children: React.ReactNode },
|
|
477
|
+
ErrorBoundaryState
|
|
478
|
+
> {
|
|
479
|
+
state: ErrorBoundaryState = {
|
|
480
|
+
hasError: false,
|
|
481
|
+
error: null
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
static getDerivedStateFromError(error: Error): ErrorBoundaryState {
|
|
485
|
+
return { hasError: true, error }
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
|
|
489
|
+
console.error('Error boundary caught:', error, errorInfo)
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
render() {
|
|
493
|
+
if (this.state.hasError) {
|
|
494
|
+
return (
|
|
495
|
+
<div className="error-fallback">
|
|
496
|
+
<h2>Something went wrong</h2>
|
|
497
|
+
<p>{this.state.error?.message}</p>
|
|
498
|
+
<button onClick={() => this.setState({ hasError: false })}>
|
|
499
|
+
Try again
|
|
500
|
+
</button>
|
|
501
|
+
</div>
|
|
502
|
+
)
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
return this.props.children
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// Usage
|
|
510
|
+
<ErrorBoundary>
|
|
511
|
+
<App />
|
|
512
|
+
</ErrorBoundary>
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
## Animation Patterns
|
|
516
|
+
|
|
517
|
+
### Framer Motion Animations
|
|
518
|
+
|
|
519
|
+
```typescript
|
|
520
|
+
import { motion, AnimatePresence } from 'framer-motion'
|
|
521
|
+
|
|
522
|
+
// ✅ List animations
|
|
523
|
+
export function AnimatedMarketList({ markets }: { markets: Market[] }) {
|
|
524
|
+
return (
|
|
525
|
+
<AnimatePresence>
|
|
526
|
+
{markets.map(market => (
|
|
527
|
+
<motion.div
|
|
528
|
+
key={market.id}
|
|
529
|
+
initial={{ opacity: 0, y: 20 }}
|
|
530
|
+
animate={{ opacity: 1, y: 0 }}
|
|
531
|
+
exit={{ opacity: 0, y: -20 }}
|
|
532
|
+
transition={{ duration: 0.3 }}
|
|
533
|
+
>
|
|
534
|
+
<MarketCard market={market} />
|
|
535
|
+
</motion.div>
|
|
536
|
+
))}
|
|
537
|
+
</AnimatePresence>
|
|
538
|
+
)
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// ✅ Modal animations
|
|
542
|
+
export function Modal({ isOpen, onClose, children }: ModalProps) {
|
|
543
|
+
return (
|
|
544
|
+
<AnimatePresence>
|
|
545
|
+
{isOpen && (
|
|
546
|
+
<>
|
|
547
|
+
<motion.div
|
|
548
|
+
className="modal-overlay"
|
|
549
|
+
initial={{ opacity: 0 }}
|
|
550
|
+
animate={{ opacity: 1 }}
|
|
551
|
+
exit={{ opacity: 0 }}
|
|
552
|
+
onClick={onClose}
|
|
553
|
+
/>
|
|
554
|
+
<motion.div
|
|
555
|
+
className="modal-content"
|
|
556
|
+
initial={{ opacity: 0, scale: 0.9, y: 20 }}
|
|
557
|
+
animate={{ opacity: 1, scale: 1, y: 0 }}
|
|
558
|
+
exit={{ opacity: 0, scale: 0.9, y: 20 }}
|
|
559
|
+
>
|
|
560
|
+
{children}
|
|
561
|
+
</motion.div>
|
|
562
|
+
</>
|
|
563
|
+
)}
|
|
564
|
+
</AnimatePresence>
|
|
565
|
+
)
|
|
566
|
+
}
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
## Accessibility Patterns
|
|
570
|
+
|
|
571
|
+
### Keyboard Navigation
|
|
572
|
+
|
|
573
|
+
```typescript
|
|
574
|
+
export function Dropdown({ options, onSelect }: DropdownProps) {
|
|
575
|
+
const [isOpen, setIsOpen] = useState(false)
|
|
576
|
+
const [activeIndex, setActiveIndex] = useState(0)
|
|
577
|
+
|
|
578
|
+
const handleKeyDown = (e: React.KeyboardEvent) => {
|
|
579
|
+
switch (e.key) {
|
|
580
|
+
case 'ArrowDown':
|
|
581
|
+
e.preventDefault()
|
|
582
|
+
setActiveIndex(i => Math.min(i + 1, options.length - 1))
|
|
583
|
+
break
|
|
584
|
+
case 'ArrowUp':
|
|
585
|
+
e.preventDefault()
|
|
586
|
+
setActiveIndex(i => Math.max(i - 1, 0))
|
|
587
|
+
break
|
|
588
|
+
case 'Enter':
|
|
589
|
+
e.preventDefault()
|
|
590
|
+
onSelect(options[activeIndex])
|
|
591
|
+
setIsOpen(false)
|
|
592
|
+
break
|
|
593
|
+
case 'Escape':
|
|
594
|
+
setIsOpen(false)
|
|
595
|
+
break
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
return (
|
|
600
|
+
<div
|
|
601
|
+
role="combobox"
|
|
602
|
+
aria-expanded={isOpen}
|
|
603
|
+
aria-haspopup="listbox"
|
|
604
|
+
onKeyDown={handleKeyDown}
|
|
605
|
+
>
|
|
606
|
+
{/* Dropdown implementation */}
|
|
607
|
+
</div>
|
|
608
|
+
)
|
|
609
|
+
}
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
### Focus Management
|
|
613
|
+
|
|
614
|
+
```typescript
|
|
615
|
+
export function Modal({ isOpen, onClose, children }: ModalProps) {
|
|
616
|
+
const modalRef = useRef<HTMLDivElement>(null)
|
|
617
|
+
const previousFocusRef = useRef<HTMLElement | null>(null)
|
|
618
|
+
|
|
619
|
+
useEffect(() => {
|
|
620
|
+
if (isOpen) {
|
|
621
|
+
// Save currently focused element
|
|
622
|
+
previousFocusRef.current = document.activeElement as HTMLElement
|
|
623
|
+
|
|
624
|
+
// Focus modal
|
|
625
|
+
modalRef.current?.focus()
|
|
626
|
+
} else {
|
|
627
|
+
// Restore focus when closing
|
|
628
|
+
previousFocusRef.current?.focus()
|
|
629
|
+
}
|
|
630
|
+
}, [isOpen])
|
|
631
|
+
|
|
632
|
+
return isOpen ? (
|
|
633
|
+
<div
|
|
634
|
+
ref={modalRef}
|
|
635
|
+
role="dialog"
|
|
636
|
+
aria-modal="true"
|
|
637
|
+
tabIndex={-1}
|
|
638
|
+
onKeyDown={e => e.key === 'Escape' && onClose()}
|
|
639
|
+
>
|
|
640
|
+
{children}
|
|
641
|
+
</div>
|
|
642
|
+
) : null
|
|
643
|
+
}
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
**Remember**: Modern frontend patterns enable maintainable, performant user interfaces. Choose patterns that fit your project complexity.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: frontend-ui-ux
|
|
3
|
+
description: Designer-turned-developer who crafts stunning UI/UX even without design mockups
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Frontend UI/UX Skill
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
## Native Subagent Protocol (Codex)
|
|
10
|
+
|
|
11
|
+
Codex supports native subagents. Delegate with `spawn_agent`, coordinate with `send_input`, collect via `wait`, and clean up with `close_agent`.
|
|
12
|
+
|
|
13
|
+
Execution preference:
|
|
14
|
+
1. Use native subagents first for independent workstreams (parallel when possible).
|
|
15
|
+
2. Merge results in main thread and run final verification.
|
|
16
|
+
3. Fallback only when delegation is blocked: use the `[ANALYST]`/`[ARCHITECT]`/`[EXECUTOR]`/`[REVIEWER]` structure in a single response.
|
|
17
|
+
|
|
18
|
+
Minimal orchestration pattern:
|
|
19
|
+
```text
|
|
20
|
+
spawn_agent -> send_input (optional) -> wait -> close_agent
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
> Codex invocation: use `$frontend-ui-ux ...` or `frontend-ui-ux: ...`
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
You are a designer who learned to code. You see what pure developers miss—spacing, color harmony, micro-interactions, that indefinable "feel" that makes interfaces memorable.
|
|
27
|
+
|
|
28
|
+
## Design Process
|
|
29
|
+
|
|
30
|
+
Before coding, commit to a **BOLD aesthetic direction**:
|
|
31
|
+
|
|
32
|
+
1. **Purpose**: What problem does this solve? Who uses it?
|
|
33
|
+
2. **Tone**: Pick an extreme:
|
|
34
|
+
- Brutally minimal
|
|
35
|
+
- Maximalist chaos
|
|
36
|
+
- Retro-futuristic
|
|
37
|
+
- Organic/natural
|
|
38
|
+
- Luxury/refined
|
|
39
|
+
- Playful/toy-like
|
|
40
|
+
- Editorial/magazine
|
|
41
|
+
- Brutalist/raw
|
|
42
|
+
- Art deco/geometric
|
|
43
|
+
- Soft/pastel
|
|
44
|
+
- Industrial/utilitarian
|
|
45
|
+
3. **Constraints**: Technical requirements (framework, performance, accessibility)
|
|
46
|
+
4. **Differentiation**: What's the ONE thing someone will remember?
|
|
47
|
+
|
|
48
|
+
## Aesthetic Guidelines
|
|
49
|
+
|
|
50
|
+
### Typography
|
|
51
|
+
Choose distinctive fonts. **Avoid**: Arial, Inter, Roboto, system fonts, Space Grotesk.
|
|
52
|
+
|
|
53
|
+
### Color
|
|
54
|
+
Commit to a cohesive palette. Use CSS variables. **Avoid**: purple gradients on white (AI slop).
|
|
55
|
+
|
|
56
|
+
### Motion
|
|
57
|
+
Focus on high-impact moments. One well-orchestrated page load > scattered micro-interactions. Use CSS-only where possible.
|
|
58
|
+
|
|
59
|
+
### Spatial Composition
|
|
60
|
+
Unexpected layouts. Asymmetry. Overlap. Diagonal flow. Grid-breaking elements.
|
|
61
|
+
|
|
62
|
+
### Visual Details
|
|
63
|
+
Create atmosphere—gradient meshes, noise textures, geometric patterns, layered transparencies, dramatic shadows.
|
|
64
|
+
|
|
65
|
+
## Anti-Patterns (NEVER)
|
|
66
|
+
|
|
67
|
+
- Generic fonts (Inter, Roboto, Arial)
|
|
68
|
+
- Cliched color schemes (purple gradients on white)
|
|
69
|
+
- Predictable layouts
|
|
70
|
+
- Cookie-cutter design
|