RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Configs/Cursor rules/TechSquidTV/Hermes

Cursor rule

.cursor/rules/20-hermes-app-hooks.mdc
Cursor rules

Quality

73/100

Scores the file, not the repository.

Length

780 words

20 headings · 11 code blocks

Repository

45

— · pushed 3 days ago

Last changed

3 days ago

First indexed 3 days ago.
TechSquidTV/Hermes/.cursor/rules/20-hermes-app-hooks.mdcRawGitHub
1---
2globs:
3 - "packages/hermes-app/src/hooks/**/*.ts"
4 - "packages/hermes-app/src/hooks/**/*.tsx"
5---
6 
7# Hermes App - Custom Hooks Rules
8 
9## Hook Naming
10 
11- **MUST** start with `use` prefix: `useDownloadActions`, `useTheme`, `useApiKeys`
12- File name must match hook name: `useTheme.ts` exports `useTheme`
13- Export as named export, not default
14- Use descriptive names that indicate purpose
15 
16## Hook Structure
17 
18### Basic Template
19```typescript
20interface UseFeatureOptions {
21 initialValue?: string;
22 onSuccess?: (data: Data) => void;
23}
24 
25interface UseFeatureReturn {
26 data: Data | null;
27 isLoading: boolean;
28 error: Error | null;
29 actions: {
30 fetch: () => Promise<void>;
31 reset: () => void;
32 };
33}
34 
35/**
36 * @example
37 * const { data, isLoading, actions } = useFeature({ initialValue: 'test' });
38 */
39export function useFeature(options: UseFeatureOptions = {}): UseFeatureReturn {
40 const [data, setData] = useState<Data | null>(null);
41 const [isLoading, setIsLoading] = useState(false);
42 const [error, setError] = useState<Error | null>(null);
43 
44 return { data, isLoading, error, actions: { fetch, reset } };
45}
46```
47 
48### TypeScript Requirements
49- Define explicit return types
50- Create interfaces for options and return values
51- Avoid `any` type
52 
53## Hook Patterns
54 
55### Data Fetching (TanStack Query)
56```typescript
57export function useApiKeys() {
58 const queryClient = useQueryClient();
59 
60 const { data: apiKeys, isLoading, error } = useQuery({
61 queryKey: ["apiKeys"],
62 queryFn: fetchApiKeys,
63 });
64 
65 const createMutation = useMutation({
66 mutationFn: createApiKey,
67 onSuccess: () => {
68 queryClient.invalidateQueries({ queryKey: ["apiKeys"] });
69 },
70 });
71 
72 return {
73 apiKeys: apiKeys ?? [],
74 isLoading,
75 error,
76 createApiKey: createMutation.mutateAsync,
77 isCreating: createMutation.isPending,
78 };
79}
80```
81 
82### Action Hook
83```typescript
84export function useDownloadActions() {
85 const queryClient = useQueryClient();
86 
87 const pauseMutation = useMutation({
88 mutationFn: pauseDownload,
89 onSuccess: () => {
90 queryClient.invalidateQueries({ queryKey: ["downloads"] });
91 toast.success("Download paused");
92 },
93 onError: (error) => toast.error(`Failed: ${error.message}`),
94 });
95 
96 const pause = useCallback(
97 (id: string) => pauseMutation.mutateAsync(id),
98 [pauseMutation]
99 );
100 
101 return { pause, isPausing: pauseMutation.isPending };
102}
103```
104 
105### Utility Hook
106```typescript
107export function useDebounce<T>(value: T, delay: number = 500): T {
108 const [debouncedValue, setDebouncedValue] = useState<T>(value);
109 
110 useEffect(() => {
111 const handler = setTimeout(() => setDebouncedValue(value), delay);
112 return () => clearTimeout(handler);
113 }, [value, delay]);
114 
115 return debouncedValue;
116}
117```
118 
119### Context Hook
120```typescript
121export function useAuth() {
122 const context = useContext(AuthContext);
123 if (!context) {
124 throw new Error("useAuth must be used within AuthProvider");
125 }
126 return context;
127}
128```
129 
130## TanStack Query Integration
131 
132### Query Keys
133Use hierarchical, descriptive keys with parameters:
134 
135```typescript
136// ✅ Good
137queryKey: ["downloads", "list", { status: "active" }]
138queryKey: ["downloads", "detail", downloadId]
139 
140// ❌ Bad
141queryKey: ["data"]
142queryKey: ["downloads"] // Too generic
143```
144 
145### Mutations
146- Invalidate queries after successful mutations
147- Handle optimistic updates when appropriate
148- Show toast notifications for user feedback
149 
150```typescript
151const mutation = useMutation({
152 mutationFn: updateItem,
153 onMutate: async (newItem) => {
154 await queryClient.cancelQueries({ queryKey: ["items"] });
155 const prev = queryClient.getQueryData(["items"]);
156 queryClient.setQueryData(["items"], (old: Item[]) =>
157 old.map((item) => (item.id === newItem.id ? newItem : item))
158 );
159 return { prev };
160 },
161 onError: (err, newItem, context) => {
162 queryClient.setQueryData(["items"], context?.prev);
163 toast.error("Update failed");
164 },
165 onSettled: () => {
166 queryClient.invalidateQueries({ queryKey: ["items"] });
167 },
168});
169```
170 
171## Hook Composition
172 
173Compose smaller hooks into larger ones:
174 
175```typescript
176export function useQueueData() {
177 const { downloads, isLoading: isLoadingDownloads } = useDownloads();
178 const { stats, isLoading: isLoadingStats } = useStats();
179 const { pause, resume, cancel } = useDownloadActions();
180 const filters = useFilters();
181 
182 const filteredDownloads = useMemo(
183 () => applyFilters(downloads, filters.active),
184 [downloads, filters.active]
185 );
186 
187 return {
188 downloads: filteredDownloads,
189 stats,
190 isLoading: isLoadingDownloads || isLoadingStats,
191 actions: { pause, resume, cancel },
192 filters,
193 };
194}
195```
196 
197## Side Effects
198 
199### Dependencies
200- Always declare all dependencies
201- Use ESLint to catch missing dependencies
202- Extract stable references with `useCallback`
203 
204### Cleanup
205- Return cleanup function from effects
206- Cancel pending requests
207- Clear timers and subscriptions
208 
209```typescript
210useEffect(() => {
211 const controller = new AbortController();
212 
213 async function fetchData() {
214 try {
215 const data = await fetch(url, { signal: controller.signal });
216 setData(data);
217 } catch (error) {
218 if (error.name !== "AbortError") setError(error);
219 }
220 }
221 
222 fetchData();
223 return () => controller.abort();
224}, [url]);
225```
226 
227## Performance
228 
229### Memoization
230- Use `useCallback` for function references passed as props
231- Use `useMemo` for expensive computations
232- Don't over-optimize - profile first
233 
234```typescript
235export function useFilters() {
236 const [filters, setFilters] = useState<Filter[]>([]);
237 
238 const activeFilters = useMemo(
239 () => filters.filter((f) => f.active),
240 [filters]
241 );
242 
243 const addFilter = useCallback((filter: Filter) => {
244 setFilters((prev) => [...prev, filter]);
245 }, []);
246 
247 return { filters, activeFilters, addFilter };
248}
249```
250 
251## Error Handling
252 
253```typescript
254export function useVideoInfo(url: string) {
255 const [info, setInfo] = useState<VideoInfo | null>(null);
256 const [error, setError] = useState<Error | null>(null);
257 const [isLoading, setIsLoading] = useState(false);
258 
259 const fetchInfo = useCallback(async () => {
260 if (!url) return;
261 
262 setIsLoading(true);
263 setError(null);
264 
265 try {
266 const data = await api.getVideoInfo(url);
267 setInfo(data);
268 } catch (err) {
269 const error = err instanceof Error ? err : new Error("Unknown error");
270 setError(error);
271 toast.error(`Failed: ${error.message}`);
272 } finally {
273 setIsLoading(false);
274 }
275 }, [url]);
276 
277 useEffect(() => {
278 fetchInfo();
279 }, [fetchInfo]);
280 
281 return { info, error, isLoading, refetch: fetchInfo };
282}
283```
284 
285 

Sections

  • Hermes App - Custom Hooks Rules
  • Hook Naming
  • Hook Structure
  • Basic Template
  • TypeScript Requirements
  • Hook Patterns
  • Data Fetching (TanStack Query)
  • Action Hook
  • Utility Hook
  • Context Hook
  • TanStack Query Integration
  • Query Keys
  • Mutations
  • Hook Composition
  • Side Effects
  • Dependencies
  • Cleanup
  • Performance
  • Memoization
  • Error Handling

What it covers

lint-formatcode-stylearchitecturetypesdependenciesperformancedo-not

Stack — with the evidence

typescript

(1.00)

node

(0.70)

react

(0.70)

fastapi

(0.70)

redis

(0.70)

tailwind

(0.70)

vite

(0.70)

vitest

(0.70)

pytest

(0.70)

eslint

(0.70)

ruff

(0.70)

javascript

(0.60)

monorepo

(0.60)

pnpm

(0.60)

docker

(0.60)

github-actions

(0.60)

python

(0.50)

Glob targeting

  • packages/hermes-app/src/hooks/**/*.ts
  • packages/hermes-app/src/hooks/**/*.tsx

Format

Cursor rules

The most expressive format here. Many small .mdc files, each with frontmatter declaring when it should load, so a rule about migrations only enters context when a migration is open. Costs the most to maintain and only one editor reads it.

What the corpus says about it

Repository

Owner
TechSquidTV
Language
—
License
—
Archived
no

All configs in this repo

Also in TechSquidTV/Hermes

Diff this repo’s formats

One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?

The other instruction files in this repository
RepositoryFormatStackCoversScoreChanged
TechSquidTV/Hermes.cursor/rules/00-project.mdc · 45Cursor rulestypescriptmonorepo+15setuplint-formatstylearch+489/1003 days ago
TechSquidTV/Hermes.cursor/rules/10-hermes-api.mdc · 45Cursor rulestypescriptpytest+15testlint-formatstylearch+5100/1003 days ago
TechSquidTV/Hermes.cursor/rules/10-hermes-app.mdc · 45Cursor rulestypescriptnode+15lint-formatstylearchtypes+588/1003 days ago
TechSquidTV/Hermes.cursor/rules/20-hermes-api-api.mdc · 45Cursor rulestypescriptnode+15stylearchdependenciesapi+277/1003 days ago
TechSquidTV/Hermes.cursor/rules/20-hermes-api-db.mdc · 45Cursor rulestypescriptnode+15teststylearchtesting-strategy+373/1003 days ago
TechSquidTV/Hermes.cursor/rules/20-hermes-api-tests.mdc · 45Cursor rulestypescriptpytest+15teststyletesting-strategysecurity+397/1003 days ago
TechSquidTV/Hermes.cursor/rules/20-hermes-app-components.mdc · 45Cursor rulestypescriptnode+15archtypesuiperformance+165/1003 days ago
TechSquidTV/Hermes.cursor/rules/20-hermes-app-routes.mdc · 45Cursor rulestypescriptnode+15archapiuido-not65/1003 days ago
TechSquidTV/Hermes.cursor/rules/30-docker.mdc · 45Cursor rulestypescriptnode+15setupbuildstylesecurity+484/1003 days ago
TechSquidTV/Hermes.cursor/rules/30-docs.mdc · 45Cursor rulestypescriptnode+15setuplint-formatstylearch+381/1003 days ago
TechSquidTV/Hermes.cursor/rules/30-tests.mdc · 45Cursor rulestypescriptpytest+15buildteststylearch+485/1003 days ago
Diff against .cursor/rules/00-project.mdc Diff against .cursor/rules/10-hermes-api.mdc Diff against .cursor/rules/10-hermes-app.mdc Diff against .cursor/rules/20-hermes-api-api.mdc Diff against .cursor/rules/20-hermes-api-db.mdc Diff against .cursor/rules/20-hermes-api-tests.mdc Diff against .cursor/rules/20-hermes-app-components.mdc Diff against .cursor/rules/20-hermes-app-routes.mdc Diff against .cursor/rules/30-docker.mdc Diff against .cursor/rules/30-docs.mdc Diff against .cursor/rules/30-tests.mdc

Similar configs

Same format, overlapping stack, ranked by quality.

Same format, overlapping stack, ranked by quality
RepositoryFormatStackCoversScoreChanged
hiromaily/go-crypto-wallet.cursor/rules/typescript.mdc · 126Cursor rulesgobun+5setupbuildtestlint-format+6100/1003 days ago
TechSquidTV/Hermes.cursor/rules/10-hermes-api.mdc · 45Cursor rulestypescriptpytest+15testlint-formatstylearch+5100/1003 days ago
dodgecfr/combatfilms-webapp.cursor/rules/frontend.mdc · 0Cursor rulestypescriptturborepo+15setuptestlint-formatstyle+799/1003 days ago
deifos/clipmira-subtitles.cursor/rules/frontend.mdc · 1Cursor rulestypescriptnextjs+5setuptestlint-formatstyle+799/1003 days ago
markstev/mark-starter.cursor/rules/frontend.mdc · 0Cursor rulestypescriptturborepo+14setuptestlint-formatstyle+699/1003 days ago
Allymahmoud/case-intake-platform.cursor/rules/frontend.mdc · 0Cursor rulestypescriptturborepo+13setuptestlint-formatstyle+799/1003 days ago
langflow-ai/langflow.cursor/rules/docs_development.mdc · 153kCursor rulespythonnode+16setupbuildtestlint-format+797/1003 days ago
TechSquidTV/Hermes.cursor/rules/20-hermes-api-tests.mdc · 45Cursor rulestypescriptpytest+15teststyletesting-strategysecurity+397/1003 days ago
RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack