brainstorming
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or planning anything new, in software or out of it (a talk, a business, a renovation).
audit-code-qualityDetect and fix repo-wide anti-patterns and consistency drift (naming, organisation, repeated smells). Use when "code smell", "anti-pattern", "technical debt", or "standardize the codebase". This PR/diff review → audit-code-review.
Independent GitHub snapshot · Automated classification · Original documentation governs
Degree of freedom: MIXED — Parts 1–2 judgment [HIGH freedom]; convention
greps and Validation [LOW freedom — run exactly].
Audit-and-fix exception. Detect and then fix. Not present-then-stop.
Fix the findings you reported, in the files you named; a repo-wide restyle or rename pass the report did not list is a different session. Edit surgically — the offending hook, key, or import — rather than rewriting whole files. Pre-existing bugs met on the way go in the report as follow-ups. Add or change tests only where the task asks or the repo already keeps them for that surface; one-off greps and scratch scripts stay out of the commit.
Repo-wide React/TypeScript anti-patterns plus naming, organisation, and
pattern consistency. A named PR/diff → audit-code-review.
file:line) and whether git blame / CONTRIBUTING marks it intentionaluseEffect = High; naming-only = LowObserve:
components/PaymentForm.tsxhas'use server'and auseEffectthat fetches invoices; four sortable lists usekey={i}. Interpret: server action lives in UI; fetch refires on remount; reorder remounts rows. Classify: organisation +useEffect-for-data + index-as-key. Severity: High (actions-in-components); Medium (keys). Finding:PaymentForm.tsx| High | move action tofeatures/*/server/; replace fetch effect with TanStack Query
cat CONTRIBUTING.md .cursor/rules/*.md 2>/dev/null | head -100 # existing conventions
git log --oneline -20 | grep -i "convention\|pattern\|style" # recent decisions
Verify the "inconsistency" isn't intentional. Check git blame before touching working code.
// Bad: prop drilled through 5+ levels
<Layout user={user}><Sidebar user={user}><UserMenu user={user}><Avatar user={user} />
// Fix: context for global state
const UserContext = createContext<User | null>(null)
const useUser = () => useContext(UserContext)
// Fix: composition for UI concerns
<Layout><Layout.Sidebar><UserMenu /></Layout.Sidebar></Layout>
useState → useMemo// Bad
const [items, setItems] = useState([])
const [filtered, setFiltered] = useState([])
useEffect(() => { setFiltered(items.filter(i => i.active)) }, [items])
// Fix
const filtered = useMemo(() => items.filter(i => i.active), [items])
useEffect for data fetching → Server Components or TanStack Query// Fix (Next.js 16 Server Component)
async function DataDisplay() {
const data = await db.getData()
return <div>{data.name}</div>
}
// Fix (client with TanStack Query)
const { data, isLoading } = useQuery({ queryKey: ['data'], queryFn: fetchData })
// Bad: new object every render → infinite loop
useEffect(() => { doSomething(options) }, [options])
// Fix
const options = useMemo(() => ({ page, limit }), [page, limit])
useEffect(() => { doSomething(options) }, [options])
// Bad
{items.map((item, i) => <Item key={i} />)}
// Fix
{items.map(item => <Item key={item.id} />)}
// Split by responsibility
export function UserDashboard() {
const user = useUser()
return (
<DashboardLayout>
<UserHeader user={user} />
<UserStats userId={user.id} />
<RecentActivity userId={user.id} />
</DashboardLayout>
)
}
// Bad: any
function processData(data: any) { return data.items.map((i: any) => i.name) }
// Fix: proper types + Zod validation
const DataSchema = z.object({ items: z.array(z.object({ id: z.string(), name: z.string() })) })
function processData(data: z.infer<typeof DataSchema>) { return data.items.map(i => i.name) }
// Bad: enums (runtime object, not tree-shakeable)
enum Status { Pending = 'pending', Active = 'active' }
// Fix: union types
type Status = 'pending' | 'active'
// Fix: exhaustive switch
function handle(s: Status): string {
switch (s) {
case 'pending': return 'Waiting'
case 'active': return 'Running'
default:
const _: never = s
throw new Error(`Unknown: ${_}`)
}
}
// Rule of thumb:
// URL state (nuqs) → shareable, bookmarkable
// Global state (Zustand) → cross-component, persisted
// Local state (useState) → component-specific, ephemeral
// Stale closure fix
useEffect(() => {
const id = setInterval(() => setCount(c => c + 1), 1000) // functional update
return () => clearInterval(id)
}, [])
// Circular deps → extract shared code / dependency inversion
// Business logic in components → move to lib/feature/calculations.ts
// God files → feature-based organisation:
lib/
date/format.ts
currency/format.ts
validation/schemas.ts
| Element | Expected | Check |
|---|---|---|
| Components | PascalCase | userCard vs UserCard |
| Hooks | use prefix | fetchData vs useFetchData |
| Utils | camelCase | format_date vs formatDate |
| Constants | SCREAMING_SNAKE | apiUrl vs API_URL |
| Files | kebab-case | UserCard.tsx vs user-card.tsx |
| Boolean props | is/has/should | loading vs isLoading |
rg "export (function|const|class) [a-z]" --type tsx # lowercase component exports
rg "use[A-Z]" --type ts # hook patterns
rg "export default" --type tsx -l | head -20 # mixed default/named exports
src/
features/{name}/
components/ # UI only
hooks/ # custom hooks
server/ # server actions
types.ts
schemas.ts
components/ui/ # shared primitives
lib/ # global utilities
Red flags:
/lib or /utilsrg "z\.object" --glob "*/components/*" # inline schemas
rg "'use server'" --glob "*/components/*" # actions in wrong place
rg "from '\.\." --type tsx | head -20 # relative imports instead of @/
| Concern | Check |
|---|---|
| Server state | All TanStack Query, or mixed with useEffect? |
| Forms | All React Hook Form, or controlled inputs too? |
| Error handling | Consistent ActionResult shape? |
| Styling | cn() used everywhere? Dark mode via CSS vars? |
| Tests | *.test.ts vs __tests__/? Consistent mocking? |
# Code Quality Audit
## Summary
- Verdict: [one line — what blocks, what is drift]
- Critical findings: X
## Anti-patterns found
| Pattern | Files | Severity |
|---------|-------|----------|
| useEffect for data | 3 files | High |
| Index as key | 2 files | Medium |
## Naming convention findings
| Element | Expected | Actual | Files |
|---------|----------|--------|-------|
| Components | PascalCase | Mixed | 4 |
## Organisation findings
- Server actions found in: components/PaymentForm.tsx
- Types scattered in: 6 component files
## Priority fixes
1. Move server actions to features/*/server/
2. Replace useEffect data fetching with TanStack Query
3. Standardise component naming to PascalCase
## Conventions to document
1. Decision on default vs named exports
2. Where Zod schemas live
useEffect for derived stateany (use unknown + validation)file:line or rg hit, not "the codebase feels messy"audit-code-reviewgit blame checked; working intentional code left alonepackage.json → typecheck, else tsc --noEmit)eslint src/CONTRIBUTING.md or .cursor/rules/