swe-workflow-skills 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/LICENSE +21 -0
- package/README.md +144 -0
- package/VERSION +1 -0
- package/bin/cli.mjs +44 -0
- package/catalog.json +225 -0
- package/commands/role.md +34 -0
- package/hooks/session-start.mjs +118 -0
- package/install.mjs +318 -0
- package/package.json +47 -0
- package/roles.json +194 -0
- package/scripts/resolve.mjs +296 -0
- package/skills/accessibility-design/SKILL.md +128 -0
- package/skills/accessibility-design/evals/evals.json +51 -0
- package/skills/accessibility-design/references/accessibility-patterns.md +321 -0
- package/skills/api-design/SKILL.md +144 -0
- package/skills/api-design/evals/evals.json +48 -0
- package/skills/api-design/references/rest-conventions.md +147 -0
- package/skills/api-design/templates/api-spec.md +156 -0
- package/skills/architecture-design/SKILL.md +86 -0
- package/skills/architecture-design/evals/evals.json +44 -0
- package/skills/architecture-design/references/clean-architecture.md +147 -0
- package/skills/architecture-design/references/component-principles.md +129 -0
- package/skills/architecture-design/references/principles.md +81 -0
- package/skills/architecture-design/references/solid-principles.md +106 -0
- package/skills/architecture-design/templates/adr.md +63 -0
- package/skills/architecture-documentation/SKILL.md +126 -0
- package/skills/architecture-documentation/evals/evals.json +44 -0
- package/skills/architecture-documentation/references/abstraction-levels.md +91 -0
- package/skills/architecture-documentation/references/diagram-tooling.md +141 -0
- package/skills/architecture-documentation/templates/architecture-doc.md +171 -0
- package/skills/bug-investigating/SKILL.md +133 -0
- package/skills/bug-investigating/evals/evals.json +56 -0
- package/skills/bug-investigating/references/common-bugs.md +62 -0
- package/skills/bug-investigating/references/debugging-patterns.md +94 -0
- package/skills/cicd-pipeline/SKILL.md +87 -0
- package/skills/cicd-pipeline/evals/evals.json +34 -0
- package/skills/cicd-pipeline/references/pipeline-patterns.md +206 -0
- package/skills/cicd-pipeline/templates/github-actions.md +206 -0
- package/skills/code-reviewing/SKILL.md +92 -0
- package/skills/code-reviewing/evals/evals.json +62 -0
- package/skills/code-reviewing/references/error-handling.md +108 -0
- package/skills/code-reviewing/references/review-checklist.md +144 -0
- package/skills/configuration-strategy/SKILL.md +109 -0
- package/skills/configuration-strategy/evals/evals.json +41 -0
- package/skills/configuration-strategy/references/config-patterns.md +161 -0
- package/skills/containerization/SKILL.md +90 -0
- package/skills/containerization/evals/evals.json +36 -0
- package/skills/containerization/references/dockerfile-patterns.md +168 -0
- package/skills/containerization/templates/dockerfile.md +154 -0
- package/skills/data-modeling/SKILL.md +83 -0
- package/skills/data-modeling/evals/evals.json +43 -0
- package/skills/data-modeling/references/conventions.md +57 -0
- package/skills/data-modeling/templates/schema.md +120 -0
- package/skills/dependency-impact-analysis/SKILL.md +113 -0
- package/skills/dependency-impact-analysis/evals/evals.json +41 -0
- package/skills/dependency-impact-analysis/references/impact-patterns.md +150 -0
- package/skills/dependency-management/SKILL.md +161 -0
- package/skills/dependency-management/evals/evals.json +48 -0
- package/skills/dependency-management/references/evaluation-checklist.md +127 -0
- package/skills/deployment-checklist/SKILL.md +132 -0
- package/skills/deployment-checklist/evals/evals.json +58 -0
- package/skills/deployment-checklist/references/pre-deploy-gates.md +91 -0
- package/skills/deployment-repo/SKILL.md +190 -0
- package/skills/deployment-repo/evals/evals.json +44 -0
- package/skills/deployment-repo/references/deployment-repo-patterns.md +258 -0
- package/skills/deployment-repo/references/version-compatibility.md +227 -0
- package/skills/deployment-repo/templates/deployment-repo-structure.md +226 -0
- package/skills/effort-estimation/SKILL.md +95 -0
- package/skills/effort-estimation/evals/evals.json +32 -0
- package/skills/effort-estimation/references/estimation-methods.md +154 -0
- package/skills/feature-planning/SKILL.md +84 -0
- package/skills/feature-planning/evals/evals.json +44 -0
- package/skills/feature-planning/templates/plan.md +55 -0
- package/skills/feature-planning/templates/task.md +26 -0
- package/skills/frontend-architecture/SKILL.md +154 -0
- package/skills/frontend-architecture/evals/evals.json +34 -0
- package/skills/frontend-architecture/references/component-patterns.md +264 -0
- package/skills/frontend-architecture/templates/folder-structure.md +203 -0
- package/skills/git-workflow/SKILL.md +127 -0
- package/skills/git-workflow/evals/evals.json +44 -0
- package/skills/git-workflow/references/conventions.md +142 -0
- package/skills/git-workflow/templates/pull-request.md +57 -0
- package/skills/gitops-delivery/SKILL.md +319 -0
- package/skills/gitops-delivery/evals/evals.json +44 -0
- package/skills/gitops-delivery/references/gitops-patterns.md +478 -0
- package/skills/gitops-delivery/templates/gitops-config.md +196 -0
- package/skills/incident-response/SKILL.md +130 -0
- package/skills/incident-response/evals/evals.json +55 -0
- package/skills/incident-response/references/communication-templates.md +134 -0
- package/skills/incident-response/references/severity-levels.md +77 -0
- package/skills/incident-response/templates/incident-timeline.md +57 -0
- package/skills/infrastructure-as-code/SKILL.md +86 -0
- package/skills/infrastructure-as-code/evals/evals.json +33 -0
- package/skills/infrastructure-as-code/references/iac-patterns.md +179 -0
- package/skills/infrastructure-as-code/templates/terraform-module.md +158 -0
- package/skills/metrics-and-okrs/SKILL.md +113 -0
- package/skills/metrics-and-okrs/evals/evals.json +33 -0
- package/skills/metrics-and-okrs/references/metric-catalog.md +90 -0
- package/skills/metrics-and-okrs/templates/okr-document.md +61 -0
- package/skills/ml-experiment-tracking/SKILL.md +96 -0
- package/skills/ml-experiment-tracking/evals/evals.json +32 -0
- package/skills/ml-experiment-tracking/references/tracking-tools.md +127 -0
- package/skills/ml-model-deployment/SKILL.md +106 -0
- package/skills/ml-model-deployment/evals/evals.json +34 -0
- package/skills/ml-model-deployment/references/serving-patterns.md +162 -0
- package/skills/ml-pipeline-design/SKILL.md +162 -0
- package/skills/ml-pipeline-design/evals/evals.json +34 -0
- package/skills/ml-pipeline-design/references/pipeline-components.md +174 -0
- package/skills/observability-design/SKILL.md +162 -0
- package/skills/observability-design/evals/evals.json +52 -0
- package/skills/observability-design/references/logging-patterns.md +229 -0
- package/skills/observability-design/references/slo-framework.md +151 -0
- package/skills/observability-design/templates/slo-document.md +80 -0
- package/skills/performance-optimization/SKILL.md +83 -0
- package/skills/performance-optimization/evals/evals.json +47 -0
- package/skills/performance-optimization/references/bottleneck-patterns.md +256 -0
- package/skills/performance-optimization/references/concurrency.md +101 -0
- package/skills/prd-writing/SKILL.md +109 -0
- package/skills/prd-writing/evals/evals.json +33 -0
- package/skills/prd-writing/references/prd-examples.md +132 -0
- package/skills/prd-writing/templates/prd.md +71 -0
- package/skills/prd-writing/templates/rfc.md +79 -0
- package/skills/project-documentation/SKILL.md +104 -0
- package/skills/project-documentation/evals/evals.json +48 -0
- package/skills/project-documentation/references/contributing-guide.md +100 -0
- package/skills/project-documentation/templates/changelog.md +59 -0
- package/skills/project-documentation/templates/readme.md +121 -0
- package/skills/project-proposal/SKILL.md +90 -0
- package/skills/project-proposal/evals/evals.json +31 -0
- package/skills/project-proposal/references/proposal-examples.md +140 -0
- package/skills/project-proposal/templates/proposal.md +76 -0
- package/skills/project-review/SKILL.md +111 -0
- package/skills/project-review/evals/evals.json +42 -0
- package/skills/refactoring/SKILL.md +90 -0
- package/skills/refactoring/evals/evals.json +44 -0
- package/skills/refactoring/references/transformations.md +132 -0
- package/skills/retrospective/SKILL.md +157 -0
- package/skills/retrospective/evals/evals.json +34 -0
- package/skills/retrospective/references/facilitation-guide.md +130 -0
- package/skills/retrospective/templates/post-mortem.md +121 -0
- package/skills/rollback-strategy/SKILL.md +116 -0
- package/skills/rollback-strategy/evals/evals.json +55 -0
- package/skills/rollback-strategy/references/rollback-patterns.md +125 -0
- package/skills/rollback-strategy/templates/rollback-plan.md +69 -0
- package/skills/security-audit/SKILL.md +146 -0
- package/skills/security-audit/evals/evals.json +66 -0
- package/skills/security-audit/references/owasp-top-10.md +167 -0
- package/skills/security-audit/templates/security-report.md +79 -0
- package/skills/skill-router/SKILL.md +171 -0
- package/skills/skill-router/evals/evals.json +39 -0
- package/skills/strategic-review/SKILL.md +106 -0
- package/skills/strategic-review/evals/evals.json +42 -0
- package/skills/strategic-review/templates/full-review-prompt.md +84 -0
- package/skills/tdd-workflow/SKILL.md +147 -0
- package/skills/tdd-workflow/evals/evals.json +58 -0
- package/skills/tdd-workflow/references/test-quality.md +71 -0
- package/skills/technical-debt-review/SKILL.md +113 -0
- package/skills/technical-debt-review/evals/evals.json +41 -0
- package/skills/technical-debt-review/references/debt-taxonomy.md +124 -0
- package/skills/technical-debt-review/templates/debt-audit.md +85 -0
- package/skills/test-data-strategy/SKILL.md +129 -0
- package/skills/test-data-strategy/evals/evals.json +49 -0
- package/skills/test-data-strategy/references/data-generation-patterns.md +341 -0
- package/skills/test-suite-design/SKILL.md +137 -0
- package/skills/test-suite-design/evals/evals.json +69 -0
- package/skills/test-suite-design/references/test-infrastructure.md +175 -0
- package/skills/test-suite-design/references/testing-pyramid.md +140 -0
- package/skills/ui-ux-design/SKILL.md +117 -0
- package/skills/ui-ux-design/evals/evals.json +35 -0
- package/skills/ui-ux-design/references/interaction-patterns.md +145 -0
- package/skills/ui-ux-design/templates/screen-spec.md +97 -0
- package/skills/verification-before-completion/SKILL.md +85 -0
- package/skills/verification-before-completion/evals/evals.json +53 -0
- package/skills/writing-skills/SKILL.md +87 -0
- package/skills/writing-skills/evals/evals.json +41 -0
- package/skills/writing-skills/references/pressure-testing.md +69 -0
- package/uninstall.mjs +182 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill_name": "frontend-architecture",
|
|
3
|
+
"evals": [
|
|
4
|
+
{
|
|
5
|
+
"id": 1,
|
|
6
|
+
"prompt": "I'm starting a new React app (Next.js) for a project management tool. It has projects, tasks, team members, and a dashboard. Users can filter, sort, and search tasks. There's real-time collaboration. Help me design the frontend architecture.",
|
|
7
|
+
"expected_output": "Should design component hierarchy, choose state management strategy (server state vs client state), define data fetching patterns, propose folder structure, and address real-time needs.",
|
|
8
|
+
"assertions": [
|
|
9
|
+
"Decomposes UI into page, feature, UI, and layout component categories",
|
|
10
|
+
"Separates server state (TanStack Query) from client state (useState/Zustand)",
|
|
11
|
+
"Addresses real-time data with WebSocket + cache invalidation strategy",
|
|
12
|
+
"Proposes feature-based folder structure (not type-based)",
|
|
13
|
+
"Defines design tokens for visual consistency",
|
|
14
|
+
"Addresses code splitting at route level",
|
|
15
|
+
"Error boundary strategy at feature boundaries",
|
|
16
|
+
"URL state for filters, sort, and search (shareable links)"
|
|
17
|
+
]
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"id": 2,
|
|
21
|
+
"prompt": "Our React app has grown to 200+ components and state management is a mess — we have Redux, Context, local state, and even some global variables. Some components re-render 50+ times when you type in a search box. How do we untangle this?",
|
|
22
|
+
"expected_output": "Should diagnose the root causes (mixed state paradigms, no separation of server vs client state, over-connected Redux), and propose an incremental migration strategy.",
|
|
23
|
+
"assertions": [
|
|
24
|
+
"Diagnoses the re-render problem as likely unnecessary Redux subscriptions",
|
|
25
|
+
"Recommends migrating server data OUT of Redux into TanStack Query / SWR",
|
|
26
|
+
"Recommends keeping Redux only for genuinely global client state",
|
|
27
|
+
"Suggests an incremental migration (one feature at a time, not big-bang)",
|
|
28
|
+
"Applies the state placement ladder (useState first, then up)",
|
|
29
|
+
"Does NOT recommend adding yet another state management library on top",
|
|
30
|
+
"Addresses the performance issue specifically (memoization, selector optimization)"
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
# Component Patterns
|
|
2
|
+
|
|
3
|
+
## Contents
|
|
4
|
+
- Component API design
|
|
5
|
+
- Composition patterns
|
|
6
|
+
- State management decision guide
|
|
7
|
+
- Data fetching patterns
|
|
8
|
+
- Error boundary strategy
|
|
9
|
+
- Performance patterns
|
|
10
|
+
|
|
11
|
+
## Component API Design
|
|
12
|
+
|
|
13
|
+
### Props design rules
|
|
14
|
+
|
|
15
|
+
1. **Prefer fewer, focused props** over many configurational ones.
|
|
16
|
+
Bad: `<Button size="lg" variant="primary" isLoading isDisabled rounded fullWidth />`
|
|
17
|
+
Better: Compose smaller components or use variants.
|
|
18
|
+
|
|
19
|
+
2. **Use TypeScript interfaces** with explicit optional markers.
|
|
20
|
+
```typescript
|
|
21
|
+
interface ButtonProps {
|
|
22
|
+
children: React.ReactNode;
|
|
23
|
+
variant?: 'primary' | 'secondary' | 'ghost';
|
|
24
|
+
size?: 'sm' | 'md' | 'lg';
|
|
25
|
+
disabled?: boolean;
|
|
26
|
+
loading?: boolean;
|
|
27
|
+
onClick?: () => void;
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
3. **Extend native HTML elements** for wrapper components.
|
|
32
|
+
```typescript
|
|
33
|
+
interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
|
34
|
+
label: string;
|
|
35
|
+
error?: string;
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
This automatically supports all native input props without listing them.
|
|
39
|
+
|
|
40
|
+
4. **Use `children` for content, not props.**
|
|
41
|
+
Bad: `<Card title="Hello" description="World" />`
|
|
42
|
+
Better: `<Card><Card.Title>Hello</Card.Title><Card.Body>World</Card.Body></Card>`
|
|
43
|
+
|
|
44
|
+
5. **Don't pass components as string names.**
|
|
45
|
+
Bad: `<Icon name="arrow-right" />`
|
|
46
|
+
Better: `<Icon as={ArrowRightIcon} />` or `<ArrowRightIcon />`
|
|
47
|
+
|
|
48
|
+
## Composition Patterns
|
|
49
|
+
|
|
50
|
+
### Compound Components
|
|
51
|
+
Components that work together, sharing implicit state through Context:
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
const Tabs = ({ children, defaultValue }) => {
|
|
55
|
+
const [active, setActive] = useState(defaultValue);
|
|
56
|
+
return (
|
|
57
|
+
<TabsContext.Provider value={{ active, setActive }}>
|
|
58
|
+
{children}
|
|
59
|
+
</TabsContext.Provider>
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
Tabs.List = ({ children }) => <div role="tablist">{children}</div>;
|
|
64
|
+
Tabs.Tab = ({ value, children }) => {
|
|
65
|
+
const { active, setActive } = useTabsContext();
|
|
66
|
+
return (
|
|
67
|
+
<button role="tab" aria-selected={active === value} onClick={() => setActive(value)}>
|
|
68
|
+
{children}
|
|
69
|
+
</button>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
Tabs.Panel = ({ value, children }) => {
|
|
73
|
+
const { active } = useTabsContext();
|
|
74
|
+
return active === value ? <div role="tabpanel">{children}</div> : null;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// Usage — clean, readable, flexible
|
|
78
|
+
<Tabs defaultValue="general">
|
|
79
|
+
<Tabs.List>
|
|
80
|
+
<Tabs.Tab value="general">General</Tabs.Tab>
|
|
81
|
+
<Tabs.Tab value="security">Security</Tabs.Tab>
|
|
82
|
+
</Tabs.List>
|
|
83
|
+
<Tabs.Panel value="general">General settings...</Tabs.Panel>
|
|
84
|
+
<Tabs.Panel value="security">Security settings...</Tabs.Panel>
|
|
85
|
+
</Tabs>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Use compound components for: tabs, accordions, menus, selects, form groups.
|
|
89
|
+
|
|
90
|
+
### Render Props / Children as Function
|
|
91
|
+
When a component needs to share computed state with its children:
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
<Fetch url="/api/users">
|
|
95
|
+
{({ data, loading, error }) => {
|
|
96
|
+
if (loading) return <Skeleton />;
|
|
97
|
+
if (error) return <ErrorMessage error={error} />;
|
|
98
|
+
return <UserList users={data} />;
|
|
99
|
+
}}
|
|
100
|
+
</Fetch>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Modern alternative: Custom hooks usually replace render props:
|
|
104
|
+
```typescript
|
|
105
|
+
const { data, loading, error } = useFetch('/api/users');
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Slot Pattern (Layout Components)
|
|
109
|
+
```typescript
|
|
110
|
+
function PageLayout({ header, sidebar, children, footer }) {
|
|
111
|
+
return (
|
|
112
|
+
<div className="grid grid-cols-[250px_1fr] grid-rows-[auto_1fr_auto]">
|
|
113
|
+
<header className="col-span-2">{header}</header>
|
|
114
|
+
<aside>{sidebar}</aside>
|
|
115
|
+
<main>{children}</main>
|
|
116
|
+
<footer className="col-span-2">{footer}</footer>
|
|
117
|
+
</div>
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## State Management Decision Guide
|
|
123
|
+
|
|
124
|
+
### When to use what
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
Is the state only used in one component?
|
|
128
|
+
→ YES: useState
|
|
129
|
+
|
|
130
|
+
Is the state shared between parent and 1-2 children?
|
|
131
|
+
→ YES: Lift state to parent, pass via props
|
|
132
|
+
|
|
133
|
+
Is it being drilled through 3+ levels?
|
|
134
|
+
→ Is it rarely changing (theme, locale, auth)?
|
|
135
|
+
→ YES: React Context
|
|
136
|
+
→ Is it frequently changing?
|
|
137
|
+
→ Is it server data (from an API)?
|
|
138
|
+
→ YES: TanStack Query / SWR
|
|
139
|
+
→ Is it form data?
|
|
140
|
+
→ YES: React Hook Form (local to form)
|
|
141
|
+
→ Is it shared client state?
|
|
142
|
+
→ YES: Zustand (simple) or Redux Toolkit (complex/team)
|
|
143
|
+
|
|
144
|
+
Should it survive page navigation?
|
|
145
|
+
→ YES: URL search params (filters, pagination, sort)
|
|
146
|
+
|
|
147
|
+
Should it survive page refresh?
|
|
148
|
+
→ YES: URL params (shareable) or localStorage (personal preferences)
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Server state vs client state
|
|
152
|
+
|
|
153
|
+
This is the most important distinction. **Don't put server data in Redux/Zustand.**
|
|
154
|
+
|
|
155
|
+
**Server state** (data from your API):
|
|
156
|
+
- Has a source of truth on the server
|
|
157
|
+
- Can become stale
|
|
158
|
+
- Needs refetching, caching, and invalidation
|
|
159
|
+
- Examples: user profile, order list, product catalog
|
|
160
|
+
- Tool: TanStack Query, SWR, RTK Query
|
|
161
|
+
|
|
162
|
+
**Client state** (exists only in the browser):
|
|
163
|
+
- Has no server counterpart
|
|
164
|
+
- Is always "fresh" by definition
|
|
165
|
+
- Examples: sidebar open/closed, selected tab, modal visibility, dark mode
|
|
166
|
+
- Tool: useState, Context, Zustand
|
|
167
|
+
|
|
168
|
+
## Data Fetching Patterns
|
|
169
|
+
|
|
170
|
+
### TanStack Query (recommended for most apps)
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
// Define the query
|
|
174
|
+
function useProjects() {
|
|
175
|
+
return useQuery({
|
|
176
|
+
queryKey: ['projects'],
|
|
177
|
+
queryFn: () => api.get('/projects'),
|
|
178
|
+
staleTime: 5 * 60 * 1000, // Consider data fresh for 5 minutes
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Use in component — loading/error/data handled automatically
|
|
183
|
+
function ProjectList() {
|
|
184
|
+
const { data: projects, isLoading, error } = useProjects();
|
|
185
|
+
if (isLoading) return <Skeleton />;
|
|
186
|
+
if (error) return <ErrorMessage error={error} />;
|
|
187
|
+
return <List items={projects} />;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Mutations with optimistic updates
|
|
191
|
+
function useDeleteProject() {
|
|
192
|
+
const queryClient = useQueryClient();
|
|
193
|
+
return useMutation({
|
|
194
|
+
mutationFn: (id) => api.delete(`/projects/${id}`),
|
|
195
|
+
onMutate: async (id) => {
|
|
196
|
+
await queryClient.cancelQueries(['projects']);
|
|
197
|
+
const previous = queryClient.getQueryData(['projects']);
|
|
198
|
+
queryClient.setQueryData(['projects'], old => old.filter(p => p.id !== id));
|
|
199
|
+
return { previous };
|
|
200
|
+
},
|
|
201
|
+
onError: (err, id, context) => {
|
|
202
|
+
queryClient.setQueryData(['projects'], context.previous); // Rollback
|
|
203
|
+
},
|
|
204
|
+
onSettled: () => queryClient.invalidateQueries(['projects']),
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Error Boundary Strategy
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
// Generic error boundary
|
|
213
|
+
function ErrorBoundary({ children, fallback }) {
|
|
214
|
+
return (
|
|
215
|
+
<ReactErrorBoundary
|
|
216
|
+
fallbackRender={({ error, resetErrorBoundary }) => (
|
|
217
|
+
fallback || (
|
|
218
|
+
<ErrorPanel
|
|
219
|
+
message="Something went wrong"
|
|
220
|
+
error={error}
|
|
221
|
+
onRetry={resetErrorBoundary}
|
|
222
|
+
/>
|
|
223
|
+
)
|
|
224
|
+
)}
|
|
225
|
+
>
|
|
226
|
+
{children}
|
|
227
|
+
</ReactErrorBoundary>
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Strategy: wrap at feature boundaries, not at the app root
|
|
232
|
+
<ErrorBoundary> {/* Page-level: catches route errors */}
|
|
233
|
+
<Header /> {/* Not wrapped: if header breaks, show error */}
|
|
234
|
+
<ErrorBoundary> {/* Feature-level: isolates sidebar failures */}
|
|
235
|
+
<Sidebar />
|
|
236
|
+
</ErrorBoundary>
|
|
237
|
+
<ErrorBoundary> {/* Feature-level: isolates main content failures */}
|
|
238
|
+
<MainContent />
|
|
239
|
+
</ErrorBoundary>
|
|
240
|
+
</ErrorBoundary>
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Place error boundaries at **feature boundaries**, not around every component. The goal: a sidebar crash doesn't take down the whole page.
|
|
244
|
+
|
|
245
|
+
## Performance Patterns
|
|
246
|
+
|
|
247
|
+
### Memoization rules
|
|
248
|
+
- `React.memo()`: Wrap components that receive the same props frequently but re-render anyway. Don't wrap everything — it has overhead.
|
|
249
|
+
- `useMemo()`: Cache expensive computations. Not needed for simple operations.
|
|
250
|
+
- `useCallback()`: Stabilize function references passed as props to memoized children.
|
|
251
|
+
- **Rule of thumb**: Don't optimize until you measure a problem. Then optimize surgically.
|
|
252
|
+
|
|
253
|
+
### Code splitting
|
|
254
|
+
```typescript
|
|
255
|
+
// Route-level splitting (always do this)
|
|
256
|
+
const ProjectPage = React.lazy(() => import('./features/projects/ProjectPage'));
|
|
257
|
+
const SettingsPage = React.lazy(() => import('./features/settings/SettingsPage'));
|
|
258
|
+
|
|
259
|
+
// Component-level splitting (for large, rarely-used components)
|
|
260
|
+
const HeavyChart = React.lazy(() => import('./components/HeavyChart'));
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### List virtualization
|
|
264
|
+
For lists over 100 items, use virtualization (react-window or TanStack Virtual) to render only visible items. Don't render 10,000 DOM nodes.
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# Frontend Architecture Templates
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## Recommended `src/` Folder Structure
|
|
6
|
+
|
|
7
|
+
Feature-based layout with a shared component library. Copy this structure and delete the directories you don't need yet.
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
src/
|
|
11
|
+
├── app/ # App-level wiring (not business logic)
|
|
12
|
+
│ ├── providers.tsx # All context providers composed in one place
|
|
13
|
+
│ ├── router.tsx # Route definitions
|
|
14
|
+
│ └── layout.tsx # Root layout (nav, sidebar, footer)
|
|
15
|
+
│
|
|
16
|
+
├── features/ # One directory per business feature
|
|
17
|
+
│ ├── auth/
|
|
18
|
+
│ │ ├── components/ # Components used only in this feature
|
|
19
|
+
│ │ │ └── LoginForm/
|
|
20
|
+
│ │ │ ├── LoginForm.tsx
|
|
21
|
+
│ │ │ ├── LoginForm.test.tsx
|
|
22
|
+
│ │ │ └── LoginForm.types.ts
|
|
23
|
+
│ │ ├── hooks/ # Feature-specific hooks
|
|
24
|
+
│ │ │ └── useLogin.ts
|
|
25
|
+
│ │ ├── api.ts # API calls for this feature (React Query queries/mutations)
|
|
26
|
+
│ │ ├── types.ts # Types scoped to this feature
|
|
27
|
+
│ │ └── index.ts # Public API — only export what other modules need
|
|
28
|
+
│ ├── projects/
|
|
29
|
+
│ └── settings/
|
|
30
|
+
│
|
|
31
|
+
├── components/ # Shared, reusable UI components (no business logic)
|
|
32
|
+
│ ├── ui/ # Atomic primitives: Button, Input, Modal, Badge
|
|
33
|
+
│ └── layout/ # Layout components: Stack, Grid, Container, Sidebar
|
|
34
|
+
│
|
|
35
|
+
├── hooks/ # Shared hooks: useDebounce, useMediaQuery, useLocalStorage
|
|
36
|
+
├── lib/ # Shared infrastructure
|
|
37
|
+
│ ├── api-client.ts # Configured axios/fetch instance
|
|
38
|
+
│ ├── tokens.ts # Design tokens (see below)
|
|
39
|
+
│ └── utils.ts # Pure utility functions
|
|
40
|
+
└── types/ # Shared TypeScript types and interfaces
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
> **Rules:** Features import from `components/` and `lib/`. Features never import from other features. Circular imports mean a responsibility boundary is wrong — move the shared code to `lib/` or `components/`.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Component File Template
|
|
48
|
+
|
|
49
|
+
Co-locate everything for a component in one folder. Avoids hunting across the filesystem for related files.
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
components/ui/Button/
|
|
53
|
+
├── Button.tsx # Component implementation
|
|
54
|
+
├── Button.test.tsx # Tests
|
|
55
|
+
├── Button.types.ts # Props interface
|
|
56
|
+
└── index.ts # Re-export (allows: import { Button } from '@/components/ui/Button')
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Button.types.ts**
|
|
60
|
+
```typescript
|
|
61
|
+
export interface ButtonProps {
|
|
62
|
+
variant?: 'primary' | 'secondary' | 'ghost' | 'danger';
|
|
63
|
+
size?: 'sm' | 'md' | 'lg';
|
|
64
|
+
disabled?: boolean;
|
|
65
|
+
loading?: boolean;
|
|
66
|
+
onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
|
|
67
|
+
children: React.ReactNode;
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**Button.tsx**
|
|
72
|
+
```tsx
|
|
73
|
+
import type { ButtonProps } from './Button.types';
|
|
74
|
+
|
|
75
|
+
export function Button({
|
|
76
|
+
variant = 'primary',
|
|
77
|
+
size = 'md',
|
|
78
|
+
disabled = false,
|
|
79
|
+
loading = false,
|
|
80
|
+
onClick,
|
|
81
|
+
children,
|
|
82
|
+
}: ButtonProps) {
|
|
83
|
+
return (
|
|
84
|
+
<button
|
|
85
|
+
className={`btn btn--${variant} btn--${size}`}
|
|
86
|
+
disabled={disabled || loading}
|
|
87
|
+
onClick={onClick}
|
|
88
|
+
>
|
|
89
|
+
{loading ? <span className="spinner" aria-hidden /> : null}
|
|
90
|
+
{children}
|
|
91
|
+
</button>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Design Tokens — `lib/tokens.ts`
|
|
99
|
+
|
|
100
|
+
Define all visual constants here. Never hardcode colors, spacing, or typography values in components.
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
export const tokens = {
|
|
104
|
+
color: {
|
|
105
|
+
primary: {
|
|
106
|
+
50: '#eff6ff',
|
|
107
|
+
100: '#dbeafe',
|
|
108
|
+
500: '#3b82f6',
|
|
109
|
+
700: '#1d4ed8',
|
|
110
|
+
900: '#1e3a8a',
|
|
111
|
+
},
|
|
112
|
+
neutral: {
|
|
113
|
+
50: '#f9fafb',
|
|
114
|
+
100: '#f3f4f6',
|
|
115
|
+
200: '#e5e7eb',
|
|
116
|
+
500: '#6b7280',
|
|
117
|
+
800: '#1f2937',
|
|
118
|
+
900: '#111827',
|
|
119
|
+
},
|
|
120
|
+
semantic: {
|
|
121
|
+
success: '#10b981',
|
|
122
|
+
warning: '#f59e0b',
|
|
123
|
+
error: '#ef4444',
|
|
124
|
+
info: '#3b82f6',
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
spacing: {
|
|
128
|
+
xs: '0.25rem', // 4px
|
|
129
|
+
sm: '0.5rem', // 8px
|
|
130
|
+
md: '1rem', // 16px
|
|
131
|
+
lg: '1.5rem', // 24px
|
|
132
|
+
xl: '2rem', // 32px
|
|
133
|
+
'2xl': '3rem', // 48px
|
|
134
|
+
},
|
|
135
|
+
radius: {
|
|
136
|
+
sm: '0.25rem',
|
|
137
|
+
md: '0.5rem',
|
|
138
|
+
lg: '1rem',
|
|
139
|
+
full: '9999px',
|
|
140
|
+
},
|
|
141
|
+
fontSize: {
|
|
142
|
+
xs: '0.75rem',
|
|
143
|
+
sm: '0.875rem',
|
|
144
|
+
base: '1rem',
|
|
145
|
+
lg: '1.125rem',
|
|
146
|
+
xl: '1.25rem',
|
|
147
|
+
'2xl': '1.5rem',
|
|
148
|
+
},
|
|
149
|
+
shadow: {
|
|
150
|
+
sm: '0 1px 2px rgba(0,0,0,0.05)',
|
|
151
|
+
md: '0 4px 6px rgba(0,0,0,0.1)',
|
|
152
|
+
lg: '0 10px 15px rgba(0,0,0,0.1)',
|
|
153
|
+
},
|
|
154
|
+
} as const;
|
|
155
|
+
|
|
156
|
+
// Type helpers for token-safe props
|
|
157
|
+
export type ColorToken = typeof tokens.color;
|
|
158
|
+
export type SpacingToken = keyof typeof tokens.spacing;
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Custom Hook Template — `hooks/useResource.ts`
|
|
164
|
+
|
|
165
|
+
Standard pattern for data-fetching hooks (wraps React Query; adapt for SWR or raw fetch).
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
169
|
+
import { fetchResource, updateResource } from '@/features/resource/api';
|
|
170
|
+
import type { Resource } from '@/features/resource/types';
|
|
171
|
+
|
|
172
|
+
// Query key factory — keeps cache keys consistent across the app
|
|
173
|
+
export const resourceKeys = {
|
|
174
|
+
all: () => ['resources'] as const,
|
|
175
|
+
list: (filters: Record<string, unknown>) => [...resourceKeys.all(), 'list', filters] as const,
|
|
176
|
+
detail: (id: string) => [...resourceKeys.all(), 'detail', id] as const,
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
// Fetch hook — returns { data, isLoading, error }
|
|
180
|
+
export function useResource(id: string) {
|
|
181
|
+
return useQuery({
|
|
182
|
+
queryKey: resourceKeys.detail(id),
|
|
183
|
+
queryFn: () => fetchResource(id),
|
|
184
|
+
enabled: Boolean(id),
|
|
185
|
+
staleTime: 5 * 60 * 1000, // 5 minutes
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Mutation hook — returns { mutate, isPending, error }
|
|
190
|
+
export function useUpdateResource() {
|
|
191
|
+
const queryClient = useQueryClient();
|
|
192
|
+
|
|
193
|
+
return useMutation({
|
|
194
|
+
mutationFn: ({ id, data }: { id: string; data: Partial<Resource> }) =>
|
|
195
|
+
updateResource(id, data),
|
|
196
|
+
onSuccess: (_, { id }) => {
|
|
197
|
+
// Invalidate affected queries so UI stays fresh
|
|
198
|
+
queryClient.invalidateQueries({ queryKey: resourceKeys.detail(id) });
|
|
199
|
+
queryClient.invalidateQueries({ queryKey: resourceKeys.all() });
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
```
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: git-workflow
|
|
3
|
+
description: "Write commit messages, PR descriptions, and manage branching strategy following conventional commits. Triggers: write a commit message, commit this, PR description, pull request, branching strategy, git workflow, squash commits, rebase, conventional commits, how should I commit this, review staged changes."
|
|
4
|
+
model: haiku
|
|
5
|
+
allowed-tools: Read, Grep, Glob, Write, Edit
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Git Workflow
|
|
9
|
+
|
|
10
|
+
Help write clear commit messages, structured PR descriptions, and manage branching conventions. Good git history is documentation — it tells the story of why the codebase evolved the way it did.
|
|
11
|
+
|
|
12
|
+
## Workflow: Commit Messages
|
|
13
|
+
|
|
14
|
+
### Step 1: Analyze the Changes
|
|
15
|
+
|
|
16
|
+
Read the staged changes to understand what was done:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
git diff --staged
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Identify:
|
|
23
|
+
- **What changed?** (files modified, functions added/removed, logic altered)
|
|
24
|
+
- **Why did it change?** (feature, bugfix, refactor, dependency update)
|
|
25
|
+
- **Is this one logical change or multiple?** If multiple, suggest splitting into separate commits.
|
|
26
|
+
|
|
27
|
+
### Step 2: Write the Commit Message
|
|
28
|
+
|
|
29
|
+
Use the Conventional Commits format — see [references/conventions.md](references/conventions.md):
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
<type>(<scope>): <short description>
|
|
33
|
+
|
|
34
|
+
<body — explain WHY, not WHAT>
|
|
35
|
+
|
|
36
|
+
<footer — references, breaking changes>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**The subject line** (first line):
|
|
40
|
+
- Type: `feat`, `fix`, `refactor`, `test`, `docs`, `chore`, `perf`, `ci`, `build`
|
|
41
|
+
- Scope: The module, component, or area affected (optional but recommended)
|
|
42
|
+
- Description: Present tense, lowercase, no period, under 50 characters
|
|
43
|
+
- It should complete the sentence: "If applied, this commit will..."
|
|
44
|
+
|
|
45
|
+
**The body** (optional but valuable for non-trivial changes):
|
|
46
|
+
- Explain WHY this change was made, not WHAT changed (the diff shows what)
|
|
47
|
+
- Include context that isn't obvious from the code
|
|
48
|
+
- Wrap at 72 characters
|
|
49
|
+
|
|
50
|
+
**The footer** (optional):
|
|
51
|
+
- Reference issues: `Closes #123`, `Fixes #456`
|
|
52
|
+
- Breaking changes: `BREAKING CHANGE: description`
|
|
53
|
+
- Co-authors: `Co-authored-by: Name <email>`
|
|
54
|
+
|
|
55
|
+
### Step 3: Validate
|
|
56
|
+
|
|
57
|
+
Before committing, check:
|
|
58
|
+
- [ ] Is this a single logical change? (If not, split it)
|
|
59
|
+
- [ ] Does the subject line describe the behavior change, not the implementation?
|
|
60
|
+
- [ ] Would someone understand why this commit exists 6 months from now?
|
|
61
|
+
- [ ] Are related issue numbers referenced?
|
|
62
|
+
|
|
63
|
+
## Workflow: PR Descriptions
|
|
64
|
+
|
|
65
|
+
### Step 1: Analyze the Branch
|
|
66
|
+
|
|
67
|
+
Read the changes in the branch:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
git log main..HEAD --oneline
|
|
71
|
+
git diff main...HEAD --stat
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Understand the full scope of changes across all commits.
|
|
75
|
+
|
|
76
|
+
### Step 2: Write the PR Description
|
|
77
|
+
|
|
78
|
+
Use the template at [templates/pull-request.md](templates/pull-request.md). Key sections:
|
|
79
|
+
|
|
80
|
+
- **What**: What this PR does (1-2 sentences)
|
|
81
|
+
- **Why**: Why this change is needed (link to issue/task)
|
|
82
|
+
- **How**: Brief description of the approach taken and key decisions
|
|
83
|
+
- **Testing**: How the changes were tested
|
|
84
|
+
- **Screenshots**: For UI changes (before/after)
|
|
85
|
+
- **Checklist**: Standard items (tests pass, docs updated, etc.)
|
|
86
|
+
|
|
87
|
+
The PR description should let a reviewer understand the change without reading every line of code first.
|
|
88
|
+
|
|
89
|
+
### Step 3: Self-Review
|
|
90
|
+
|
|
91
|
+
Before requesting review:
|
|
92
|
+
- [ ] Read through the entire diff one more time
|
|
93
|
+
- [ ] Are there any debugging leftovers?
|
|
94
|
+
- [ ] Are there any changes that don't belong in this PR?
|
|
95
|
+
- [ ] Is the PR a reasonable size? (Under 400 lines changed is ideal. Over 800 is a red flag.)
|
|
96
|
+
|
|
97
|
+
If the PR is too large, suggest splitting it into stacked PRs or smaller logical units.
|
|
98
|
+
|
|
99
|
+
## Workflow: Branching Strategy
|
|
100
|
+
|
|
101
|
+
Help set up or improve branching conventions. Ask about team size and release cadence, then recommend:
|
|
102
|
+
|
|
103
|
+
**For small teams (1-5 devs) or continuous deployment:**
|
|
104
|
+
- `main` — always deployable
|
|
105
|
+
- `feat/description` — feature branches, short-lived (1-3 days)
|
|
106
|
+
- `fix/description` — bug fix branches
|
|
107
|
+
- Merge to main via PR, deploy from main
|
|
108
|
+
|
|
109
|
+
**For medium teams (5-15 devs) or scheduled releases:**
|
|
110
|
+
- `main` — production
|
|
111
|
+
- `develop` — integration branch
|
|
112
|
+
- `feat/description`, `fix/description` — branch from develop
|
|
113
|
+
- `release/x.y.z` — stabilization branch before release
|
|
114
|
+
- `hotfix/description` — urgent fixes branching from main
|
|
115
|
+
|
|
116
|
+
**For large teams or complex release cycles:**
|
|
117
|
+
- Consider trunk-based development with feature flags
|
|
118
|
+
- Short-lived branches (< 1 day) merged to main
|
|
119
|
+
- Feature flags control what's visible to users
|
|
120
|
+
|
|
121
|
+
See [references/conventions.md](references/conventions.md) for branch naming conventions.
|
|
122
|
+
|
|
123
|
+
## Principles Applied
|
|
124
|
+
|
|
125
|
+
- **KISS**: One commit = one logical change. Don't bundle unrelated changes.
|
|
126
|
+
- **DRY**: If you're writing the same commit message pattern repeatedly, you might be making commits too granular or too broad.
|
|
127
|
+
- **Functional Independence**: Each PR should be independently deployable when possible. Avoid PRs that depend on other unmerged PRs.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill_name": "git-workflow",
|
|
3
|
+
"evals": [
|
|
4
|
+
{
|
|
5
|
+
"id": 1,
|
|
6
|
+
"prompt": "I just finished implementing a user notification feature. I've staged all changes. Write a good commit message for me.",
|
|
7
|
+
"expected_output": "Should read the staged diff first, then write a Conventional Commits formatted message with type, scope, subject, and body explaining why.",
|
|
8
|
+
"assertions": [
|
|
9
|
+
"Runs git diff --staged to read the actual changes",
|
|
10
|
+
"Uses Conventional Commits format (type(scope): description)",
|
|
11
|
+
"Subject line is under 50 characters",
|
|
12
|
+
"Body explains WHY, not just WHAT",
|
|
13
|
+
"Checks if the staged changes are a single logical unit",
|
|
14
|
+
"If multiple logical changes, suggests splitting into separate commits"
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"id": 2,
|
|
19
|
+
"prompt": "I need to write a PR description for a branch that adds Stripe payment integration. The branch has 12 commits including some WIP and fix-typo commits. We're using a standard PR template.",
|
|
20
|
+
"expected_output": "Should read the branch diff and commit log, suggest squashing the WIP commits, then write a structured PR description.",
|
|
21
|
+
"assertions": [
|
|
22
|
+
"Reads git log and diff for the branch",
|
|
23
|
+
"Suggests cleaning up the 'WIP' and 'fix-typo' commits via rebase/squash",
|
|
24
|
+
"Writes a complete PR description with What/Why/How/Testing sections",
|
|
25
|
+
"Links to the relevant issue or task",
|
|
26
|
+
"Includes a checklist with relevant items (especially security for payments)",
|
|
27
|
+
"Notes for reviewers highlights the payment-related security considerations"
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"id": 3,
|
|
32
|
+
"prompt": "We're a team of 4 starting a new project. What branching strategy should we use? We deploy to production multiple times a day.",
|
|
33
|
+
"expected_output": "Should recommend a simple strategy (main + short-lived feature branches) given small team and continuous deployment. Should NOT suggest GitFlow or other complex models.",
|
|
34
|
+
"assertions": [
|
|
35
|
+
"Recommends simple branching (main + feature branches)",
|
|
36
|
+
"Does NOT recommend GitFlow (too heavy for 4 devs + continuous deployment)",
|
|
37
|
+
"Recommends short-lived branches (1-3 days max)",
|
|
38
|
+
"Suggests squash-merge as default merge strategy",
|
|
39
|
+
"Includes branch naming conventions",
|
|
40
|
+
"Mentions PR review requirements appropriate for team size"
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
}
|