openstory / rules
Cursor rule678 starsChanged 2 months agoMITView on GitHub
React best practices and conventions for UI code
We split this react-rules.mdc into the rules it gives an agent
32 rules. About 0 are common, 31 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈31
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 8
Keep components small - less than 100 lines
- Distinctive: line 10
Remove as much logic as possible from components and views
- Distinctive: line 16
Avoid using useEffect to fetch data or initialise state
- Very specific: line 17
Use hooks, tanstack query, or the new use feature in react 19
- Distinctive: line 18
use useEffect to update state when something else changes
- Distinctive: line 24
If you have more than 3 useStates you might as well use reducers
- Distinctive: line 35
Start with reducers which are passed through props
- Distinctive: line 36
If that's too complicated, use React context
- Distinctive: line 44
Use them to update state based on other state.
- Distinctive: line 49
Avoid passing styles to components, or styling your components in views
- Distinctive: line 50
Create components that are pre-styled
- Distinctive: line 51
Create variants - e.g. small, medium, large - rather than size={18}
- Distinctive: line 52
Avoid using styles in views as much as possible
- Distinctive: line 56
Create constants for your theme or use a consistent structure
- Distinctive: line 57
Use the theme fonts and colors
- Distinctive: line 58
Avoid naming fonts and inluding color values directly in views and components
- Distinctive: line 62
Use flexbox for every component
- Distinctive: line 66
Don't pre-add padding or margin to the outside of components, unless there is a specific reason to
- Distinctive: line 67
Use flexbox gap instead
- Distinctive: line 71
Use PascalCase for component names, but kebab case for file-names
- Distinctive: line 76
If using a 3rd party component library, wrap those components then include your wrapped components.
- Distinctive: line 79
Don't create duplicates of components for minor variations.
- Distinctive: line 81
Put your components into a high level components folder
- Distinctive: line 82
Use an aliases or subpath imports "~" to import components from views.
- Distinctive: line 86
Use flexbox and create rules for screen sizes
- Distinctive: line 90
Avoid code that conditionally shows a complex component - this creates janky ui
- Distinctive: line 91
Instead use the display css property to hide or show - this will precalculate everything in the component but not render it
- Distinctive: line 95
Ensure the rules of hooks linting rule is on
- Distinctive: line 96
Check out 0xlint and Biome
- Distinctive: line 100
All views should be routable - meaning you can get to them via a route
- Distinctive: line 101
No view should rely on variables or parameters from another
- Distinctive: line 109
Avoid barrelled imports as much as possible _unless_ you are planning to package that library for others
≈ “Common” is an estimate: at least 1 in 5 of the 6,350 Cursor rule files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
---
description: React best practices and conventions for UI code
globs: *.tsx
alwaysApply: false
---
## 1. Use as little React as possible
- Keep components small - less than 100 lines
- Views reference components
- Remove as much logic as possible from components and views
- Externalize functions rather and keep external functions _vanilla typescript_
- Vanilla typescript is easier to test, and package for other uses
## 2. Avoid using useEffect
- Avoid using useEffect to fetch data or initialise state
- Use hooks, tanstack query, or the new `use` feature in react 19
- use useEffect to update state when something else changes
## 3. Use useState sparingly
- Using a local variable is often more optimal - even if something has to be calculated
- useState uses reducers under the hood
- If you have more than 3 useStates you might as well use reducers
## 4. Use React.FC and expand props
- Expand props so that each parameter is named
- It's easier to know which props are not used
## 5. Avoid globals and global state
- Globals including auth globals, often lead to race conditions
- Global state is only useful in rare cases. SPAs with signifant complexity
- Start with reducers which are passed through props
- If that's too complicated, use React context
- As a last resort for very complicated SPAs - use zustand
## 6. Use reducers
- Reducers are great - read up on them and understand them
- They keep all state update logic in one place
- They are vanilla typescript - keep them that way
- Use them to update state based on other state.
- Note that updating any part of the state returned from a reducer will cause a re-render if the whole state is a parameter - you can pass just parts of it
## 7. Avoid passing style to components
- Avoid passing styles to components, or styling your components in views
- Create components that are pre-styled
- Create variants - e.g. small, medium, large - rather than size={18}
- Avoid using styles in views as much as possible
## 8. Use the theme
- Create constants for your theme or use a consistent structure
- Use the theme fonts and colors
- Avoid naming fonts and inluding color values directly in views and components
## 9. Use flexbox
- Use flexbox for every component
## 10. Avoid margin
- Don't pre-add padding or margin to the outside of components, unless there is a specific reason to
- Use flexbox gap instead
## 11. Use kebab-case for file names
- Use PascalCase for component names, but kebab case for file-names
- PascalCase can often give you issues in git as case sensitive file names is not supported on all platforms
## 12. Create a component library
- If using a 3rd party component library, wrap those components then include your wrapped components. It makes it easier to change libraries
- Shadcn makes this easy - it includes the source in your repo, and imports only primitives from that source.
- You don't need to wrap Shadcn generated components - just edit the component source with your changes
- Don't create duplicates of components for minor variations. Create a variation
- Customise the component if there's a new variation - don't style from the outside
- Put your components into a high level components folder
- Use an aliases or subpath imports "~" to import components from views.
## 13. Avoid hard coding width or height
- Use flexbox and create rules for screen sizes
## 14. Use a show prop if you need to hide something
- Avoid code that conditionally shows a complex component - this creates janky ui
- Instead use the display css property to hide or show - this will precalculate everything in the component but not render it
## 15. Use eslint or equivalent
- Ensure the rules of hooks linting rule is on
- Check out 0xlint and Biome
## 16. Views are routes
- All views should be routable - meaning you can get to them via a route
- No view should rely on variables or parameters from another
- A view can be accessed in any order
- Pass params on the url. You can use url segments for ids, search params should be optional
- Name views with the same name as the route - or place in a folder with that name
## 17. Avoid default exports
- It's more efficient to export the component directly than to import a default
- Avoid barrelled imports as much as possible _unless_ you are planning to package that library for others
Where files are headingNew Cursor rule files have more rules about planning and tracking tasks, and fewer about code style.
Of the Cursor rule files we read, the 3,978 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository15 other files it gives its agents.
- AGENTS.mdAGENTS.md
- .cursor/rules/bun-test.mdcCursor rule
- .cursor/rules/context7-integration.mdcCursor rule
- .cursor/rules/drizzle-patterns.mdcCursor rule
- .cursor/rules/production-review-panel.mdcCursor rule
- .cursor/rules/project-context.mdcCursor rule
- .cursor/rules/tanstack-react-router_api.mdcCursor rule
- .cursor/rules/tanstack-react-router_guide.mdcCursor rule
- .cursor/rules/tanstack-react-router_installation.mdcCursor rule
- .cursor/rules/tanstack-react-router_routing.mdcCursor rule
- .cursor/rules/tanstack-react-router_setup-and-architecture.mdcCursor rule
- .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdcCursor rule
- sd25-peSkill
- react-patternsSkill
- update-model-versionsSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

