RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Configs/Cursor rules/VictorGoic0/Math-Tutoring-App

Cursor rule

.cursor/rules/react-patterns.mdc

React webapp conventions (Math Tutoring App)

Cursor rules

Quality

69/100

Scores the file, not the repository.

Length

712 words

6 headings · 2 code blocks

Repository

0

— · pushed 112 days ago

Last changed

3 days ago

First indexed 3 days ago.
VictorGoic0/Math-Tutoring-App/.cursor/rules/react-patterns.mdcRawGitHub
1---
2description: React webapp conventions (Math Tutoring App)
3globs: webapp/**/*.{tsx,ts}
4alwaysApply: false
5---
6 
7# React Patterns — `webapp/`
8 
9Stack: **React 19**, **Vite**, **React Router**, **Firebase** (client SDK).
10 
11## useEffect rules (read first)
12 
13- **Computed values → plain vars, not state.** Never use `useEffect` to sync props into state. Derive inline.
14- **Router-driven resets → `key`, not `useEffect`.** When a screen must reinitialize from a route param (or equivalent identity), let the parent set `key={…}` to remount instead of mirroring props into state in an effect.
15- **Callbacks in deps → `useEffectEvent`.** Never put a parent-supplied callback directly in a `useEffect` dependency array — it may not be stable. Wrap it with `useEffectEvent`. Prefer `useEffectEvent` over `useCallback` for this.
16- **“Latest value” reads → `useEffectEvent`.** If you need a value inside an effect but don’t want it to re-trigger the effect, read it inside a `useEffectEvent` wrapper.
17- **Fetching / async load → custom hooks only.** Never perform data loading (Firestore queries, `fetch` to the Express API, etc.) directly inside `useEffect` in a route or feature component. Use a `useXxx` hook in `src/hooks/` that encapsulates loading (e.g. TanStack Query, or a dedicated hook that wraps your service calls). Components call hooks; they don’t inline async load effects.
18- **Expensive calculations → `useMemo`.** Don’t compute inside an effect and write to state unless it’s truly an external sync; derive or memoize.
19 
20**Exceptions:** Long-lived **subscriptions** (e.g. Firebase `onAuthStateChanged` in `AuthProvider`) belong in an effect with a proper cleanup return — that is not “fetching”; keep listeners from leaking.
21 
22```tsx
23// Rules 4 & 3 — useEffectEvent for latest values and unstable callbacks
24import { useEffect, useEffectEvent, useState } from 'react';
25 
26function TypingIndicator({ conversationId, onTick }: Props) {
27 const [dots, setDots] = useState(1);
28 
29 const fireTick = useEffectEvent(() => {
30 setDots((d) => (d % 3) + 1);
31 onTick(); // parent callback — not listed in useEffect deps
32 });
33 
34 useEffect(() => {
35 const id = setInterval(fireTick, 500);
36 return () => clearInterval(id);
37 }, [conversationId]); // only remount interval when conversation changes
38}
39 
40// Rules 2 & 1 — key for remount; derived strings, not effect-synced state
41// Parent (e.g. route wrapper)
42<Chat key={conversationId ?? 'new'} />
43 
44// Inside Chat — no useEffect to copy props into state
45function Chat({ conversationId }: { conversationId: string | null }) {
46 const { data } = useConversationHistory(); // Rule 5 — load via hook
47 const title = conversationId ? `Thread ${conversationId.slice(0, 8)}` : 'New chat'; // Rule 1
48 const sortedMessages = useMemo(
49 () => [...(data?.messages ?? [])].sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime()),
50 [data?.messages]
51 ); // Rule 6
52}
53```
54 
55## Custom hooks per resource
56 
57- Each **distinct data domain** gets its own hook in `src/hooks/`, named after that domain (`useAuth`, `useConversationHistory`, etc.).
58- **One hook per resource shape** where it helps clarity: e.g. conversation list/history vs. auth session vs. a single upload flow — don’t stuff unrelated async into one mega-hook.
59- **Services stay in `src/services/`** (`chatService`, `api`, `storageService`); hooks orchestrate those (and caching libraries if you add them). Screen components should not import `chatService` / call `fetch` directly for load paths that belong in a hook.
60 
61```ts
62// ✅ GOOD — names reflect resources / concerns
63useAuth();
64useConversationHistory();
65 
66// ❌ BAD — Chat.tsx importing loadConversationHistory and wiring useEffect inline for the main load path
67```
68 
69## Layout
70 
71| Area | Path |
72|------|------|
73| App shell & routes | `webapp/src/App.tsx`, `webapp/src/main.tsx` |
74| Screens / features | `webapp/src/components/` (e.g. `Chat.tsx`, `Login.tsx`, `SignUp.tsx`) |
75| Design system | `webapp/src/components/design-system/` |
76| Hooks | `webapp/src/hooks/` |
77| Context | `webapp/src/contexts/` |
78| Client API / streaming | `webapp/src/services/api.ts` |
79| Firestore / persistence | `webapp/src/services/chatService.ts`, `storageService.ts` |
80| Global styles / tokens | `webapp/src/styles/tokens.ts` |
81 
82There is no `src/pages/` tree; route-level views live under `src/components/`.
83 
84## Data & side effects
85 
86- **Firestore reads/writes** run in the **webapp** via the Firebase client SDK — not from the Express API for normal chat persistence.
87- **LLM / OpenAI** runs only **server-side** (`api/`). The webapp uses Express for chat streaming (`api.ts` / SSE) and sends **Firebase ID tokens**; never embed provider API keys in the client.
88- Prefer **custom hooks** (`useAuth`, resource hooks above) for shared data and UI coordination.
89 
90## Components
91 
92- Prefer **focused components** under `src/components/` over single huge files; shared primitives live in `design-system/`.
93- Keep **accessibility** in mind for interactive controls (buttons, forms, chat input).
94 

Sections

  • React Patterns — `webapp/`
  • useEffect rules (read first)
  • Custom hooks per resource
  • Layout
  • Data & side effects
  • Components

What it covers

code-stylearchitecturedo-not

Stack — with the evidence

typescript

(1.00)

node

(0.70)

react

(0.70)

express

(0.70)

vite

(0.70)

javascript

(0.50)

Glob targeting

  • webapp/**/*.{tsx
  • ts}

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
VictorGoic0
Language
—
License
—
Archived
no

All configs in this repo

Also in VictorGoic0/Math-Tutoring-App

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
VictorGoic0/Math-Tutoring-App.cursor/rules/api-patterns.mdc · 0Cursor rulestypescriptnode+4setupstylearchsecurity+273/1003 days ago
VictorGoic0/Math-Tutoring-App.cursor/rules/linting.mdc · 0Cursor rulestypescriptnode+4lint-formatstyledo-notagent-behaviour68/1003 days ago
VictorGoic0/Math-Tutoring-App.cursor/rules/one-pr-at-a-time.mdc · 0Cursor rulestypescriptnode+4git16/1003 days ago
VictorGoic0/Math-Tutoring-App.cursor/rules/react-readability.mdc · 0Cursor rulestypescriptnode+4styleuido-not57/1003 days ago
Diff against .cursor/rules/api-patterns.mdc Diff against .cursor/rules/linting.mdc Diff against .cursor/rules/one-pr-at-a-time.mdc Diff against .cursor/rules/react-readability.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
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
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
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