You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs: enforce coding standards in AGENTS.md (ban useEffect, as any, effect-based patterns)
- Document Choose Your Bug framing for useEffect misuse
- Add Rules 1–6: useMountEffect-only, ban as any, derive state,
data-fetching libs, event handlers over effect flags, keys for reset
- Cross-reference from ANTI-PATTERNS
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Leo <leoisadev1@users.noreply.github.com>
Copy file name to clipboardExpand all lines: AGENTS.md
+35Lines changed: 35 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -51,7 +51,42 @@ openchat/
51
51
- Assume dev servers are already running; do not start `bun dev*` unless explicitly requested.
52
52
- Prefer build/typecheck/test verification when runtime validation is needed.
53
53
54
+
## Coding Standards & Banned Patterns
55
+
56
+
These rules apply to all AI agents and human contributors working in this repository.
57
+
58
+
### Choose Your Bug — Why We Ban useEffect Misuse
59
+
60
+
Misusing `useEffect` doesn't help you avoid bugs — it just lets you choose which bug you get. Every effect that syncs state, fetches data, or reacts to user actions is a latent race condition, stale closure, or infinite loop waiting to happen. The rules below eliminate this entire class of bugs.
61
+
62
+
### Rules
63
+
64
+
**Rule 1 — BAN direct use of `useEffect`**
65
+
66
+
Do not use `useEffect` directly. Use `useMountEffect()` only for rare, justified external side-effect syncs (e.g. third-party SDK initialization). Any other use must be approved and documented with a comment explaining why no alternative works.
67
+
68
+
**Rule 2 — BAN `as any` casts**
69
+
70
+
Do not use TypeScript `as any` casts. Use proper types, generics, or type guards. If you cannot type something, use `unknown` and narrow it explicitly. `as any` silences the compiler and hides real bugs.
71
+
72
+
**Rule 3 — Derive state inline, never sync it with effects**
73
+
74
+
Do not use `useEffect` + `useState` to sync or transform other state. Derive computed values inline during render, or use `useMemo` if the computation is expensive. Effect-based state sync always has at least one render where the derived state is stale.
75
+
76
+
**Rule 4 — Use data-fetching libraries instead of fetch-in-effect**
77
+
78
+
Do not fetch data inside `useEffect`. Use `useQuery` (TanStack Query) or an equivalent data-fetching library. These libraries handle caching, deduplication, background refetching, loading states, and error states correctly. Effect-based fetching is a manual reimplementation of these features, done worse.
79
+
80
+
**Rule 5 — Use event handlers for user actions, not effect flags**
81
+
82
+
Do not use `useEffect` to react to user interactions by watching a flag or state change. Put the logic directly in the event handler. Effects that watch for 'action triggers' fire one render late and make code impossible to follow.
83
+
84
+
**Rule 6 — Reset components with keys, not dependency choreography**
85
+
86
+
Do not use complex `useEffect` dependency arrays to reset or reinitialize component state when an ID or key prop changes. Instead, pass the relevant value as the `key` prop to the component — React will fully remount it, resetting all state cleanly with zero effect logic.
87
+
54
88
## ANTI-PATTERNS (THIS PROJECT)
89
+
- Follow **Coding Standards & Banned Patterns** above for enforced React and TypeScript rules (`useEffect` misuse, `as any`, and related patterns).
55
90
- Do not use `NEXT_PUBLIC_*` env vars in web code.
56
91
- Do not treat `docs-site/` like a regular workspace; it is a git subtree.
57
92
- Do not introduce new logic against deprecated message fields when `chainOfThoughtParts` exists.
0 commit comments