agents-md-kit 0.0.0-stage → 0.1.1
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 +162 -2
- package/bin/agent-kit.js +6 -0
- package/core/files/.claude/settings.json +16 -0
- package/core/files/.claude/skills/agent-memory-protocol/SKILL.md +117 -0
- package/core/files/.claude/skills/api-design-rest/SKILL.md +126 -0
- package/core/files/.claude/skills/backend-architecture-principles/SKILL.md +116 -0
- package/core/files/.claude/skills/backend-security/SKILL.md +117 -0
- package/core/files/.claude/skills/changelog-and-versioning/SKILL.md +169 -0
- package/core/files/.claude/skills/database-best-practices/SKILL.md +104 -0
- package/core/files/.claude/skills/git-commit-and-workflow/SKILL.md +140 -0
- package/core/files/.claude/skills/project-management-workflow/SKILL.md +181 -0
- package/core/files/CLAUDE.md +1 -0
- package/core/files/MEMORY.md +77 -0
- package/core/files/docs/adr/0000-template.md +21 -0
- package/core/fragments/agents-core.md +61 -0
- package/core/manifest.txt +21 -0
- package/docs/monorepo.md +72 -0
- package/package.json +50 -4
- package/packs/github/files/.github/ISSUE_TEMPLATE/bug_report.md +22 -0
- package/packs/github/files/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- package/packs/github/files/.github/pull_request_template.md +24 -0
- package/packs/github/files/.github/workflows/pr-title.yml +37 -0
- package/packs/github/manifest.txt +6 -0
- package/packs/web/files/.claude/skills/html-syntax-and-semantics/SKILL.md +127 -0
- package/packs/web/files/.claude/skills/seo-best-practices/SKILL.md +158 -0
- package/packs/web/fragments/agents-web.md +11 -0
- package/packs/web/manifest.txt +5 -0
- package/presets/node-backend/docs/node-backend.md +60 -0
- package/presets/node-backend/files/.editorconfig +12 -0
- package/presets/node-backend/files/.husky/commit-msg +1 -0
- package/presets/node-backend/files/.husky/pre-commit +1 -0
- package/presets/node-backend/files/.lintstagedrc.json +4 -0
- package/presets/node-backend/files/.prettierrc.json +7 -0
- package/presets/node-backend/files/.release-please-manifest.json +3 -0
- package/presets/node-backend/files/CHANGELOG.md +5 -0
- package/presets/node-backend/files/commitlint.config.mjs +12 -0
- package/presets/node-backend/files/eslint.config.mjs +38 -0
- package/presets/node-backend/files/release-please-config.json +25 -0
- package/presets/node-backend/fragments/agents-node-backend-github.md +7 -0
- package/presets/node-backend/fragments/agents-node-backend.md +13 -0
- package/presets/node-backend/fragments/gitignore.txt +19 -0
- package/presets/node-backend/fragments/prettierignore.txt +16 -0
- package/presets/node-backend/github/dependabot.yml +21 -0
- package/presets/node-backend/github/workflows/ci.yml +38 -0
- package/presets/node-backend/github/workflows/release-please.yml +21 -0
- package/presets/node-backend/manifest.txt +30 -0
- package/presets/python/docs/python.md +66 -0
- package/presets/python/files/.editorconfig +15 -0
- package/presets/python/files/.pre-commit-config.yaml +32 -0
- package/presets/python/files/.release-please-manifest.json +3 -0
- package/presets/python/files/CHANGELOG.md +5 -0
- package/presets/python/files/mypy.ini +5 -0
- package/presets/python/files/pytest.ini +6 -0
- package/presets/python/files/release-please-config.json +25 -0
- package/presets/python/files/ruff.toml +17 -0
- package/presets/python/fragments/agents-python-github.md +7 -0
- package/presets/python/fragments/agents-python.md +14 -0
- package/presets/python/fragments/gitignore.txt +25 -0
- package/presets/python/github/dependabot.yml +18 -0
- package/presets/python/github/workflows/ci.yml +37 -0
- package/presets/python/github/workflows/release-please.yml +21 -0
- package/presets/python/manifest.txt +25 -0
- package/presets/react-typescript/docs/react-typescript.md +71 -0
- package/presets/react-typescript/files/.claude/skills/react-principles/SKILL.md +264 -0
- package/presets/react-typescript/files/.editorconfig +12 -0
- package/presets/react-typescript/files/.husky/commit-msg +1 -0
- package/presets/react-typescript/files/.husky/pre-commit +1 -0
- package/presets/react-typescript/files/.lintstagedrc.json +4 -0
- package/presets/react-typescript/files/.prettierrc.json +7 -0
- package/presets/react-typescript/files/.release-please-manifest.json +3 -0
- package/presets/react-typescript/files/CHANGELOG.md +5 -0
- package/presets/react-typescript/files/commitlint.config.mjs +12 -0
- package/presets/react-typescript/files/eslint.config.mjs +55 -0
- package/presets/react-typescript/files/release-please-config.json +25 -0
- package/presets/react-typescript/fragments/agents-react-typescript-github.md +7 -0
- package/presets/react-typescript/fragments/agents-react-typescript.md +17 -0
- package/presets/react-typescript/fragments/gitignore.txt +22 -0
- package/presets/react-typescript/fragments/prettierignore.txt +17 -0
- package/presets/react-typescript/github/dependabot.yml +21 -0
- package/presets/react-typescript/github/workflows/ci.yml +38 -0
- package/presets/react-typescript/github/workflows/release-please.yml +21 -0
- package/presets/react-typescript/manifest.txt +32 -0
- package/src/blocks.js +132 -0
- package/src/cli.js +159 -0
- package/src/fsutil.js +123 -0
- package/src/install.js +223 -0
- package/src/manifest.js +187 -0
- package/src/validate.js +324 -0
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: react-principles
|
|
3
|
+
description: Principles and practices for writing React: SOLID, DRY/KISS/YAGNI, Hooks, state, effects, TypeScript and testing. Use when creating, refactoring or reviewing React components, Hooks, props or frontend structure.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# React Principles
|
|
7
|
+
|
|
8
|
+
Three parts: Part 1 structures components (SOLID), Part 2 keeps them simple (DRY, KISS, YAGNI), Part 3 covers everyday React practice. When Part 1 and Part 2 pull in different directions, choose the simpler solution that meets today's concrete requirements.
|
|
9
|
+
|
|
10
|
+
## Part 1: SOLID Principles
|
|
11
|
+
|
|
12
|
+
Use these principles to keep components small, composable and testable. When writing or reviewing React code, check each principle below. Apply them with judgment: a principle is a guide to better structure, not a reason to over-engineer (see Part 2, especially KISS and YAGNI).
|
|
13
|
+
|
|
14
|
+
### 1. Single Responsibility Principle (SRP)
|
|
15
|
+
|
|
16
|
+
**Rule:** A component or Hook has one reason to change.
|
|
17
|
+
|
|
18
|
+
**Do**
|
|
19
|
+
- Split components that fetch data, manage forms and render complex layouts into small UI components plus dedicated custom Hooks.
|
|
20
|
+
- Put data fetching, subscriptions and form logic in Hooks (`useUser`, `useCheckoutForm`).
|
|
21
|
+
- Keep presentational components free of side effects where possible.
|
|
22
|
+
|
|
23
|
+
**Don't**
|
|
24
|
+
- Build one component that fetches, validates, transforms and renders everything.
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
// Bad: fetching + state + rendering in one component
|
|
28
|
+
function UserProfile({ id }) {
|
|
29
|
+
const [user, setUser] = useState(null);
|
|
30
|
+
useEffect(() => { fetch(`/api/users/${id}`).then(r => r.json()).then(setUser); }, [id]);
|
|
31
|
+
return user ? <div>{/* 80 lines of layout */}</div> : <Spinner />;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Good: logic in a Hook, rendering in a UI component
|
|
35
|
+
function useUser(id: string) { /* fetching + state */ }
|
|
36
|
+
function UserProfile({ id }: { id: string }) {
|
|
37
|
+
const { user, isLoading } = useUser(id);
|
|
38
|
+
return isLoading ? <Spinner /> : <UserCard user={user} />;
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Smell check:** if you describe the component using "and" ("fetches users and renders the table and handles the form"), split it.
|
|
43
|
+
|
|
44
|
+
### 2. Open/Closed Principle (OCP)
|
|
45
|
+
|
|
46
|
+
**Rule:** Components are open for extension but closed for modification. Extend behavior from the outside instead of editing the component's source.
|
|
47
|
+
|
|
48
|
+
**Do**
|
|
49
|
+
- Accept `children`, render props, slots (`header`, `footer`) or `className`/`style` props.
|
|
50
|
+
- Use composition (compound components) for variants with different content.
|
|
51
|
+
|
|
52
|
+
**Don't**
|
|
53
|
+
- Add a new boolean flag or `if/else` branch every time a new variation is needed (`isCompact`, `isSpecial`, `showFooterV2`).
|
|
54
|
+
|
|
55
|
+
```tsx
|
|
56
|
+
// Bad: grows a new flag per use case
|
|
57
|
+
<Card showHeader showFooter isCompact withIcon />
|
|
58
|
+
|
|
59
|
+
// Good: extend through composition
|
|
60
|
+
<Card>
|
|
61
|
+
<Card.Header>Title</Card.Header>
|
|
62
|
+
<Card.Body>...</Card.Body>
|
|
63
|
+
<Card.Footer><Button>Save</Button></Card.Footer>
|
|
64
|
+
</Card>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 3. Liskov Substitution Principle (LSP)
|
|
68
|
+
|
|
69
|
+
**Rule:** A specialized component must be usable anywhere its base component is, without breaking behavior.
|
|
70
|
+
|
|
71
|
+
**Do**
|
|
72
|
+
- When wrapping a native element, extend its props type and forward them (`React.ComponentPropsWithoutRef<'button'>`).
|
|
73
|
+
- Forward `ref` (`forwardRef`, or the `ref` prop in React 19+) when the base element supports it.
|
|
74
|
+
- Spread remaining props onto the underlying element.
|
|
75
|
+
|
|
76
|
+
**Don't**
|
|
77
|
+
- Swallow or rename standard props (`onClick`, `disabled`, `type`, `aria-*`).
|
|
78
|
+
- Change the expected behavior of the base element (e.g. a "button" that ignores `disabled`).
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
type PrimaryButtonProps = React.ComponentPropsWithoutRef<'button'> & {
|
|
82
|
+
tone?: 'default' | 'danger';
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
function PrimaryButton({ tone = 'default', className, ...rest }: PrimaryButtonProps) {
|
|
86
|
+
return <button className={cx('btn-primary', tone, className)} {...rest} />;
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 4. Interface Segregation Principle (ISP)
|
|
91
|
+
|
|
92
|
+
**Rule:** Components should not depend on props they do not use. Props are the component's interface; keep it minimal.
|
|
93
|
+
|
|
94
|
+
**Do**
|
|
95
|
+
- Pass only the specific values a component needs.
|
|
96
|
+
- Define narrow prop types for each component.
|
|
97
|
+
|
|
98
|
+
**Don't**
|
|
99
|
+
- Pass whole objects (`user`, `order`, `config`) when only a few fields are used.
|
|
100
|
+
|
|
101
|
+
```tsx
|
|
102
|
+
// Bad: depends on a 20-field User type to show an image and a name
|
|
103
|
+
<Avatar user={user} />
|
|
104
|
+
|
|
105
|
+
// Good: depends only on what it renders
|
|
106
|
+
<Avatar imageUrl={user.imageUrl} username={user.username} />
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**Exception:** if a component genuinely represents the whole entity (e.g. `<UserCard user={user} />`), passing the object is fine. Keep that type as narrow as practical (`Pick<User, 'name' | 'imageUrl'>`).
|
|
110
|
+
|
|
111
|
+
### 5. Dependency Inversion Principle (DIP)
|
|
112
|
+
|
|
113
|
+
**Rule:** High-level UI components depend on abstractions, not on concrete low-level details such as a specific API client, `fetch`, `localStorage` or an analytics SDK.
|
|
114
|
+
|
|
115
|
+
**Do**
|
|
116
|
+
- Wrap external services in custom Hooks (`useTodos`, `useLocalPreference`) or Context providers.
|
|
117
|
+
- Inject dependencies through Context or props so tests can swap in mocks.
|
|
118
|
+
- Keep the Hook's returned shape independent of the underlying implementation.
|
|
119
|
+
|
|
120
|
+
**Don't**
|
|
121
|
+
- Call `fetch`, `axios`, `localStorage` or SDK clients directly inside presentational components.
|
|
122
|
+
|
|
123
|
+
```tsx
|
|
124
|
+
// Component depends on an abstraction (the Hook's contract)
|
|
125
|
+
function TodoList() {
|
|
126
|
+
const { todos, isLoading } = useTodos();
|
|
127
|
+
...
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Implementation can change (REST, GraphQL, mock) without touching TodoList
|
|
131
|
+
function useTodos() { /* uses api client from context */ }
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### SOLID Review Checklist
|
|
135
|
+
|
|
136
|
+
Before finishing a React change, confirm:
|
|
137
|
+
|
|
138
|
+
- [ ] Each component/Hook has one clear reason to change (SRP)
|
|
139
|
+
- [ ] New variations are added via `children`/render props/styling props, not new flags (OCP)
|
|
140
|
+
- [ ] Wrapper components accept and forward the base element's standard props (LSP)
|
|
141
|
+
- [ ] Components receive only the props they use (ISP)
|
|
142
|
+
- [ ] External services are behind Hooks or Context, and components are testable with mocks (DIP)
|
|
143
|
+
|
|
144
|
+
## Part 2: DRY, KISS, YAGNI
|
|
145
|
+
|
|
146
|
+
These rules keep React code simple and balanced. Use them alongside Part 1 (SOLID). When the two pull in different directions, prefer the simpler solution that meets today's concrete requirements.
|
|
147
|
+
|
|
148
|
+
### DRY: Don't Repeat Yourself
|
|
149
|
+
|
|
150
|
+
**Rule:** Extract repeated JSX into reusable components and duplicated stateful logic into custom Hooks.
|
|
151
|
+
|
|
152
|
+
**Do**
|
|
153
|
+
- Extract JSX that appears in several places into one component.
|
|
154
|
+
- Move repeated `useState` + `useEffect` patterns into a custom Hook (`useDebounce`, `useToggle`, `useFetch`).
|
|
155
|
+
- Share constants, types and validation rules from one place.
|
|
156
|
+
|
|
157
|
+
**Don't**
|
|
158
|
+
- Abstract after the first duplication. Wait until the same code appears about three times (the "rule of three") or the duplication is clearly the same concept.
|
|
159
|
+
- Merge code that looks alike but changes for different reasons. A wrong abstraction costs more than duplication.
|
|
160
|
+
|
|
161
|
+
```tsx
|
|
162
|
+
// Duplicated logic in several components
|
|
163
|
+
const [open, setOpen] = useState(false);
|
|
164
|
+
const toggle = () => setOpen(o => !o);
|
|
165
|
+
|
|
166
|
+
// Extracted once
|
|
167
|
+
function useToggle(initial = false) {
|
|
168
|
+
const [on, setOn] = useState(initial);
|
|
169
|
+
const toggle = useCallback(() => setOn(o => !o), []);
|
|
170
|
+
return [on, toggle] as const;
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### KISS: Keep It Simple, Stupid
|
|
175
|
+
|
|
176
|
+
**Rule:** Prefer the most straightforward solution that works.
|
|
177
|
+
|
|
178
|
+
**Do**
|
|
179
|
+
- Start with `useState`, `useReducer` and plain prop passing.
|
|
180
|
+
- Lift state up before reaching for Context; use Context before reaching for a state library.
|
|
181
|
+
- Add a state management library (Redux, Zustand, etc.) only when the app genuinely needs it: many distant components sharing complex state, or heavy cross-cutting updates.
|
|
182
|
+
- Write code a new teammate can read top to bottom.
|
|
183
|
+
|
|
184
|
+
**Don't**
|
|
185
|
+
- Introduce global stores, custom abstractions or deep indirection for state that a single component or parent owns.
|
|
186
|
+
- Use clever one-liners or patterns that hide intent.
|
|
187
|
+
|
|
188
|
+
### YAGNI: You Aren't Gonna Need It
|
|
189
|
+
|
|
190
|
+
**Rule:** Build only what is needed now.
|
|
191
|
+
|
|
192
|
+
**Do**
|
|
193
|
+
- Write the straightforward version first, then measure.
|
|
194
|
+
- Add `useMemo`, `useCallback` and `React.memo` only after profiling (React DevTools Profiler) shows a real bottleneck, or when referential stability is required for correctness (e.g. a stable dependency for an effect or a memoized child).
|
|
195
|
+
- Add props, config options and abstraction layers when a concrete use case exists.
|
|
196
|
+
|
|
197
|
+
**Don't**
|
|
198
|
+
- Wrap every function in `useCallback` or every value in `useMemo` by default.
|
|
199
|
+
- Add "just in case" props, generic wrapper components or plugin systems for imagined future needs.
|
|
200
|
+
|
|
201
|
+
### Quick Decision Guide
|
|
202
|
+
|
|
203
|
+
| Situation | Choose |
|
|
204
|
+
|---|---|
|
|
205
|
+
| Same JSX/logic copied 3+ times for the same reason | Extract (DRY) |
|
|
206
|
+
| Two snippets look similar but change for different reasons | Leave duplicated |
|
|
207
|
+
| State used by one component or its parent | `useState` / prop passing (KISS) |
|
|
208
|
+
| Slow render observed in the profiler | Add memoization (YAGNI satisfied) |
|
|
209
|
+
| "We might need this later" | Don't build it yet |
|
|
210
|
+
|
|
211
|
+
### DRY/KISS/YAGNI Review Checklist
|
|
212
|
+
|
|
213
|
+
- [ ] Repeated JSX/logic extracted only where it is truly the same concept (DRY)
|
|
214
|
+
- [ ] State handled with the simplest tool that fits (KISS)
|
|
215
|
+
- [ ] No premature `useMemo`/`useCallback`/abstractions without a measured need (YAGNI)
|
|
216
|
+
|
|
217
|
+
## Part 3: React Practices
|
|
218
|
+
|
|
219
|
+
### Hooks
|
|
220
|
+
- Call Hooks only at the top level of components and custom Hooks, never inside conditions, loops or nested functions. Custom Hooks start with `use`.
|
|
221
|
+
- Keep the `react-hooks/exhaustive-deps` lint rule on. Fix dependency arrays instead of suppressing the warning.
|
|
222
|
+
|
|
223
|
+
### State
|
|
224
|
+
- Keep state as local as possible. Lift it up only when siblings need it.
|
|
225
|
+
- Don't store derived data in state. Compute it during render.
|
|
226
|
+
- Server data: use a data-fetching library (TanStack Query, SWR, framework loaders) instead of hand-rolled `useEffect` + `useState`. Always handle loading, error and empty states.
|
|
227
|
+
- Use `useReducer` for related transitions. Replace piles of boolean flags with a status union (`'idle' | 'loading' | 'success' | 'error'`).
|
|
228
|
+
- Never mutate state or props. Create new objects and arrays.
|
|
229
|
+
- Large forms: use a form library (React Hook Form) and validate with the same schema as the backend where possible.
|
|
230
|
+
|
|
231
|
+
### Effects
|
|
232
|
+
- Effects synchronize with external systems (subscriptions, timers, DOM APIs). They are not for transforming data, handling events (use handlers) or resetting state on prop change (use `key`).
|
|
233
|
+
- Always clean up subscriptions, timers, listeners and in-flight requests (`AbortController`). Effects must survive Strict Mode's double invocation.
|
|
234
|
+
|
|
235
|
+
### Rendering and Keys
|
|
236
|
+
- Render is pure: no side effects, no randomness, no mutation.
|
|
237
|
+
- Stable, unique `key` for list items. Don't use the array index for lists that reorder or change.
|
|
238
|
+
- Never define a component inside another component.
|
|
239
|
+
- Code-split routes (`React.lazy` + `Suspense`), virtualize very long lists, and measure before memoizing (YAGNI).
|
|
240
|
+
|
|
241
|
+
### TypeScript
|
|
242
|
+
- Use `strict` mode. Type props explicitly, avoid `any`, and model variants with discriminated unions.
|
|
243
|
+
- Wrapper components extend native props (`React.ComponentPropsWithoutRef<'button'>`).
|
|
244
|
+
- Prefer `unknown` over `any` for untrusted data, then narrow it. Parse API responses with a schema (Zod) at the boundary.
|
|
245
|
+
|
|
246
|
+
### Structure and Naming
|
|
247
|
+
- Organize by feature and colocate the component, hooks, styles and tests. Components are PascalCase, Hooks are `useX`, and each file has one main component.
|
|
248
|
+
- Use barrel files sparingly. They hurt tree-shaking and create import cycles.
|
|
249
|
+
|
|
250
|
+
### Accessibility, SEO and Security
|
|
251
|
+
- Follow `html-syntax-and-semantics`. Keep `eslint-plugin-jsx-a11y` enabled. Public pages use SSR/SSG per `seo-best-practices`.
|
|
252
|
+
- Never render unsanitized HTML with `dangerouslySetInnerHTML`. Validate URLs placed in `href`/`src` (block `javascript:`). Anything in a client bundle is public (`VITE_*`, `NEXT_PUBLIC_*`), so never put secrets there. See `backend-security`.
|
|
253
|
+
|
|
254
|
+
### Testing
|
|
255
|
+
- Vitest or Jest with React Testing Library: query by role, label and text, and test behavior, not implementation details.
|
|
256
|
+
- Mock the network with MSW. Test Hooks through components or `renderHook`. Add axe checks for accessibility.
|
|
257
|
+
- Playwright for a few critical end-to-end flows.
|
|
258
|
+
|
|
259
|
+
### React Practices Checklist
|
|
260
|
+
- [ ] Hooks rules and exhaustive-deps satisfied; effects clean up
|
|
261
|
+
- [ ] No derived state; server data handled by a data library with loading/error/empty states
|
|
262
|
+
- [ ] Stable keys; no components defined inside components
|
|
263
|
+
- [ ] Strict TypeScript, no `any`, narrow prop types
|
|
264
|
+
- [ ] Tests assert user-visible behavior; a11y lint and axe pass
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
npx --no -- commitlint --edit "$1"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
npx lint-staged
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Enforces Conventional Commits. See the git-commit-and-workflow skill.
|
|
2
|
+
export default {
|
|
3
|
+
extends: ['@commitlint/config-conventional'],
|
|
4
|
+
rules: {
|
|
5
|
+
// Subject line (header) at most 72 characters.
|
|
6
|
+
'header-max-length': [2, 'always', 72],
|
|
7
|
+
// Body lines: warn above 100 chars (URLs and stack traces can be long).
|
|
8
|
+
'body-max-line-length': [1, 'always', 100],
|
|
9
|
+
// Uncomment to restrict scopes to your project's modules:
|
|
10
|
+
// 'scope-enum': [2, 'always', ['auth', 'checkout', 'api', 'db', 'ui', 'deps', 'release']],
|
|
11
|
+
},
|
|
12
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// ESLint flat config for React + TypeScript.
|
|
2
|
+
// Rules here back up the react-principles and html-syntax-and-semantics skills.
|
|
3
|
+
import js from '@eslint/js';
|
|
4
|
+
import globals from 'globals';
|
|
5
|
+
import tseslint from 'typescript-eslint';
|
|
6
|
+
import react from 'eslint-plugin-react';
|
|
7
|
+
import reactHooks from 'eslint-plugin-react-hooks';
|
|
8
|
+
import jsxA11y from 'eslint-plugin-jsx-a11y';
|
|
9
|
+
import prettier from 'eslint-config-prettier';
|
|
10
|
+
|
|
11
|
+
export default [
|
|
12
|
+
{ ignores: ['dist', 'build', 'coverage', '.next', 'node_modules', 'CHANGELOG.md'] },
|
|
13
|
+
|
|
14
|
+
js.configs.recommended,
|
|
15
|
+
...tseslint.configs.recommended,
|
|
16
|
+
|
|
17
|
+
react.configs.flat.recommended,
|
|
18
|
+
react.configs.flat['jsx-runtime'],
|
|
19
|
+
jsxA11y.flatConfigs.recommended,
|
|
20
|
+
|
|
21
|
+
{
|
|
22
|
+
files: ['**/*.{js,jsx,mjs,cjs,ts,tsx}'],
|
|
23
|
+
languageOptions: {
|
|
24
|
+
globals: { ...globals.browser, ...globals.node },
|
|
25
|
+
},
|
|
26
|
+
settings: { react: { version: 'detect' } },
|
|
27
|
+
plugins: { 'react-hooks': reactHooks },
|
|
28
|
+
rules: {
|
|
29
|
+
// Hooks (react-principles, Part 3)
|
|
30
|
+
'react-hooks/rules-of-hooks': 'error',
|
|
31
|
+
'react-hooks/exhaustive-deps': 'warn',
|
|
32
|
+
|
|
33
|
+
// React
|
|
34
|
+
'react/jsx-key': 'error',
|
|
35
|
+
'react/no-danger': 'warn',
|
|
36
|
+
'react/self-closing-comp': 'warn',
|
|
37
|
+
'react/prop-types': 'off', // TypeScript types replace prop-types
|
|
38
|
+
'react/jsx-no-target-blank': 'error',
|
|
39
|
+
|
|
40
|
+
// TypeScript
|
|
41
|
+
'@typescript-eslint/no-explicit-any': 'warn',
|
|
42
|
+
'@typescript-eslint/no-unused-vars': [
|
|
43
|
+
'error',
|
|
44
|
+
{ argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
|
|
45
|
+
],
|
|
46
|
+
|
|
47
|
+
// General
|
|
48
|
+
eqeqeq: ['error', 'always'],
|
|
49
|
+
'no-console': ['warn', { allow: ['warn', 'error'] }],
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
// Must stay last: turns off rules that conflict with Prettier.
|
|
54
|
+
prettier,
|
|
55
|
+
];
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
|
|
3
|
+
"release-type": "node",
|
|
4
|
+
"include-component-in-tag": false,
|
|
5
|
+
"bump-minor-pre-major": true,
|
|
6
|
+
"bump-patch-for-minor-pre-major": false,
|
|
7
|
+
"packages": {
|
|
8
|
+
".": {
|
|
9
|
+
"changelog-path": "CHANGELOG.md"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"changelog-sections": [
|
|
13
|
+
{ "type": "feat", "section": "Added" },
|
|
14
|
+
{ "type": "fix", "section": "Fixed" },
|
|
15
|
+
{ "type": "perf", "section": "Changed" },
|
|
16
|
+
{ "type": "revert", "section": "Changed" },
|
|
17
|
+
{ "type": "docs", "section": "Documentation", "hidden": true },
|
|
18
|
+
{ "type": "style", "section": "Styles", "hidden": true },
|
|
19
|
+
{ "type": "refactor", "section": "Refactoring", "hidden": true },
|
|
20
|
+
{ "type": "test", "section": "Tests", "hidden": true },
|
|
21
|
+
{ "type": "build", "section": "Build", "hidden": true },
|
|
22
|
+
{ "type": "ci", "section": "CI", "hidden": true },
|
|
23
|
+
{ "type": "chore", "section": "Chores", "hidden": true }
|
|
24
|
+
]
|
|
25
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
### GitHub automation (react-typescript preset + github pack)
|
|
2
|
+
|
|
3
|
+
| Tool | Config | Enforces |
|
|
4
|
+
|---|---|---|
|
|
5
|
+
| CI | `.github/workflows/ci.yml` | Lint, format check, typecheck, test, build, dependency audit |
|
|
6
|
+
| release-please | `release-please-config.json`, `.release-please-manifest.json`, `.github/workflows/release-please.yml` | Version bumps, `CHANGELOG.md`, tags. Don't hand-edit `CHANGELOG.md` or version fields |
|
|
7
|
+
| Dependabot | `.github/dependabot.yml` | Weekly npm and GitHub Actions updates with Conventional Commit messages |
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
## React + TypeScript
|
|
2
|
+
|
|
3
|
+
| Area | Skill | Load when |
|
|
4
|
+
|---|---|---|
|
|
5
|
+
| React | `react-principles` | Creating/refactoring components and Hooks, props, state, effects, abstractions, memoization |
|
|
6
|
+
|
|
7
|
+
### Tooling (installed by the react-typescript preset; don't work around it)
|
|
8
|
+
|
|
9
|
+
| Tool | Config | Enforces |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| commitlint + husky `commit-msg` | `commitlint.config.mjs`, `.husky/commit-msg` | Conventional Commit format on every commit |
|
|
12
|
+
| lint-staged + husky `pre-commit` | `.lintstagedrc.json`, `.husky/pre-commit` | ESLint and Prettier on staged files |
|
|
13
|
+
| ESLint | `eslint.config.mjs` | TypeScript, React, Hooks and jsx-a11y rules |
|
|
14
|
+
| Prettier | `.prettierrc.json`, `.prettierignore` | Formatting |
|
|
15
|
+
| EditorConfig | `.editorconfig` | Charset, line endings, indentation |
|
|
16
|
+
|
|
17
|
+
Never bypass these (`--no-verify`, disabling rules to make a check pass). Fix the underlying issue. Setup and versions: `docs/agent-kit/react-typescript.md`.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
node_modules/
|
|
3
|
+
|
|
4
|
+
# Build output
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
coverage/
|
|
8
|
+
.next/
|
|
9
|
+
.vite/
|
|
10
|
+
.turbo/
|
|
11
|
+
|
|
12
|
+
# Environment and secrets (keep .env.example)
|
|
13
|
+
.env
|
|
14
|
+
.env.*
|
|
15
|
+
!.env.example
|
|
16
|
+
|
|
17
|
+
# Logs and OS/editor files
|
|
18
|
+
*.log
|
|
19
|
+
.DS_Store
|
|
20
|
+
.idea/
|
|
21
|
+
.vscode/*
|
|
22
|
+
!.vscode/extensions.json
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
node_modules
|
|
2
|
+
dist
|
|
3
|
+
build
|
|
4
|
+
coverage
|
|
5
|
+
.next
|
|
6
|
+
package-lock.json
|
|
7
|
+
pnpm-lock.yaml
|
|
8
|
+
yarn.lock
|
|
9
|
+
CHANGELOG.md
|
|
10
|
+
.release-please-manifest.json
|
|
11
|
+
# Files agent-kit owns and compares on every install (formatting them would cause .new conflicts)
|
|
12
|
+
AGENTS.md
|
|
13
|
+
CLAUDE.md
|
|
14
|
+
.claude/
|
|
15
|
+
docs/agent-kit/
|
|
16
|
+
.github/ISSUE_TEMPLATE/
|
|
17
|
+
.github/pull_request_template.md
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: npm
|
|
4
|
+
directory: /
|
|
5
|
+
schedule:
|
|
6
|
+
interval: weekly
|
|
7
|
+
open-pull-requests-limit: 5
|
|
8
|
+
commit-message:
|
|
9
|
+
prefix: build
|
|
10
|
+
include: scope # produces "build(deps): bump ..."
|
|
11
|
+
groups:
|
|
12
|
+
dev-dependencies:
|
|
13
|
+
dependency-type: development
|
|
14
|
+
|
|
15
|
+
- package-ecosystem: github-actions
|
|
16
|
+
directory: /
|
|
17
|
+
schedule:
|
|
18
|
+
interval: weekly
|
|
19
|
+
commit-message:
|
|
20
|
+
prefix: ci
|
|
21
|
+
include: scope
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
|
|
8
|
+
concurrency:
|
|
9
|
+
group: ci-${{ github.ref }}
|
|
10
|
+
cancel-in-progress: true
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
checks:
|
|
17
|
+
name: checks
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
|
|
22
|
+
- uses: actions/setup-node@v4
|
|
23
|
+
with:
|
|
24
|
+
node-version: 24 # adjust to your project's supported Node version
|
|
25
|
+
cache: npm
|
|
26
|
+
|
|
27
|
+
- run: npm ci
|
|
28
|
+
|
|
29
|
+
# Scripts are skipped if not defined (--if-present). Remove the flag once
|
|
30
|
+
# your project defines them, so a missing script fails the build.
|
|
31
|
+
- run: npm run lint --if-present
|
|
32
|
+
- run: npm run format:check --if-present
|
|
33
|
+
- run: npm run typecheck --if-present
|
|
34
|
+
- run: npm test --if-present
|
|
35
|
+
- run: npm run build --if-present
|
|
36
|
+
|
|
37
|
+
- name: Audit production dependencies
|
|
38
|
+
run: npm audit --omit=dev --audit-level=high
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: release-please
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: write
|
|
9
|
+
pull-requests: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
release-please:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: googleapis/release-please-action@v4
|
|
16
|
+
with:
|
|
17
|
+
config-file: release-please-config.json
|
|
18
|
+
manifest-file: .release-please-manifest.json
|
|
19
|
+
# PRs opened with the default GITHUB_TOKEN do not trigger other workflows (e.g. CI).
|
|
20
|
+
# If you want CI to run on the release PR, create a PAT or GitHub App token
|
|
21
|
+
# and pass it here: token: ${{ secrets.RELEASE_PLEASE_TOKEN }}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# description: React + TypeScript tooling: ESLint 9 (TS, React, Hooks, jsx-a11y), Prettier, commitlint + husky + lint-staged, react-principles skill. With --pack github: CI, release-please, Dependabot.
|
|
2
|
+
|
|
3
|
+
# Commands the installer prints for the user (it never edits package.json / pyproject.toml):
|
|
4
|
+
# run: npm install -D eslint@9 @eslint/js@9 typescript typescript-eslint globals eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-jsx-a11y eslint-config-prettier prettier husky lint-staged @commitlint/cli @commitlint/config-conventional
|
|
5
|
+
# run: npm pkg set scripts.prepare="husky" scripts.lint="eslint ." scripts.format="prettier --write ." scripts.format:check="prettier --check ." scripts.typecheck="tsc --noEmit"
|
|
6
|
+
# run: npm run prepare
|
|
7
|
+
|
|
8
|
+
implies web
|
|
9
|
+
|
|
10
|
+
block react-typescript AGENTS.md agents-react-typescript.md
|
|
11
|
+
copy .claude/skills/react-principles/SKILL.md
|
|
12
|
+
copy eslint.config.mjs
|
|
13
|
+
copy .prettierrc.json
|
|
14
|
+
block react-typescript .prettierignore prettierignore.txt style=hash
|
|
15
|
+
copy .editorconfig
|
|
16
|
+
block react-typescript .gitignore gitignore.txt style=hash
|
|
17
|
+
copy .lintstagedrc.json
|
|
18
|
+
copy .husky/pre-commit
|
|
19
|
+
copy .husky/commit-msg
|
|
20
|
+
copy commitlint.config.mjs
|
|
21
|
+
copy docs/agent-kit/react-typescript.md from=docs/react-typescript.md
|
|
22
|
+
|
|
23
|
+
# GitHub-only: CI, Dependabot and release-please (release-please runs as a GitHub Action,
|
|
24
|
+
# so its config and the generated CHANGELOG.md come with it; without GitHub, the
|
|
25
|
+
# changelog-and-versioning skill uses manual mode).
|
|
26
|
+
block react-typescript-github AGENTS.md agents-react-typescript-github.md requires=github
|
|
27
|
+
copy .github/workflows/ci.yml requires=github from=github/workflows/ci.yml
|
|
28
|
+
copy .github/workflows/release-please.yml requires=github from=github/workflows/release-please.yml
|
|
29
|
+
copy .github/dependabot.yml requires=github from=github/dependabot.yml
|
|
30
|
+
copy release-please-config.json requires=github
|
|
31
|
+
copy .release-please-manifest.json requires=github
|
|
32
|
+
copy-once CHANGELOG.md requires=github
|