-
Notifications
You must be signed in to change notification settings - Fork 42
Expand file tree
/
Copy path.cursorrules
More file actions
133 lines (117 loc) · 6.68 KB
/
Copy path.cursorrules
File metadata and controls
133 lines (117 loc) · 6.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# Cursor Project Rules for Frontman
## Project Overview
This is a multi-language project with ReScript, TypeScript, and JavaScript components. The main client library is being converted from TypeScript to ReScript.
## ReScript Guidelines
### Core Patterns
1. **Use `@react.component`** instead of `@genType` for React components
2. **Labelled Arguments**: Use `~paramName=?` syntax for optional parameters, `~paramName` for required
3. **Minimal Type Annotations**: Only specify types when compilation requires it - let ReScript infer types
4. **JSX v4 Style**: Use record syntax for styles with unquoted keys: `{padding: "20px", color: "white"}`
### Event Handling
5. **Event Property Access**: Use `e->ReactEvent.Keyboard.shiftKey` not `ReactEvent.Keyboard.shiftKey`
6. **Function Call Syntax**: Use `ReactEvent.Keyboard.preventDefault(e)` not `e->ReactEvent.Keyboard.preventDefault()`
7. **Complex Expressions**: Wrap in parentheses: `!(e->ReactEvent.Keyboard.shiftKey)`
8. **Form Target Access**: Use `target["value"]` instead of `target##value` for JavaScript object properties
### JSX Patterns
9. **Text Content**: Always use `React.string("text")` for text content
10. **Conditional Rendering**: Use `condition ? <Component /> : React.null`
11. **Optional Rendering**: Use `Option.mapOr(optionalValue, React.null, value => <Component value />)`
12. **Unused Parameters**: Prefix with `_` (e.g., `~_onClearSelection=?`)
### Type System
13. **Variant Types**: Use proper variant syntax: `type status = | Pending | Completed | Error`
14. **Module Prefixes**: Use `Client__Types.Status` for accessing types from other modules
15. **Type Annotations**: Add explicit types when needed: `~messages: option<array<Client__Types.chatMessage>>=?`
### String and Array Operations (ReScript v12+)
16. **String Concatenation**: Use `++` operator: `"Hello " ++ name`
17. **String Interpolation**: Use backticks for Unicode support and interpolation: `` `Hello ${name}` ``
18. **Array Operations**: Use `Array.mapWithIndex`, `Array.join` (not Belt.Array)
19. **Option Handling**: Use `Option.getOr`, `Option.forEach`, `Option.mapOr` (not Belt.Option)
- `getOr` instead of `getWithDefault`
- `mapOr` instead of `mapWithDefault`
20. **String Operations**: Use `String.length`, `String.trim`, `String.split` (not Js.String)
21. **Array Functions**: Use `Array.reduce`, `Array.filter`, `Array.slice` (not Belt.Array)
22. **Array.slice Parameters**: Use `~start` and `~end` parameters: `Array.slice(~start=0, ~end=3)`
### JavaScript Interop
23. **Raw Functions**: Use `%raw` with template literals for complex JavaScript:
let myFunction: (string, int) => bool = %raw(`function(str, num) {
// JavaScript code here
return str.length > num;
}`)
24. **External Bindings**: Use `@val external` for simple JavaScript functions:
@val external myFunction: (string, int) => bool = "myFunction"
25. **Avoid Unused Variable Warnings**: Use the template literal approach for complex functions to avoid warnings
### Common Pitfalls
26. **Unicode Characters**: Use backticks for Unicode support: `` `🎯 Click element` `` instead of `"🎯 Click element"`
27. **String Interpolation**: Use backticks for interpolation: `` `Hello ${name}` `` instead of `"Hello " ++ name`
28. **JSX Syntax**: Ensure proper closing tags and use `React.string()` for all text content
29. **Boolean Expressions**: Wrap complex boolean expressions in parentheses for proper evaluation
30. **Passing Optional Props**: When passing optional props between components:
- Parent: `~onReload: option<unit => unit>=?`
- Child accepting it: `~onReload: option<unit => unit>` (no `=?`)
- Pass directly: `onReload={onReload}` (don't unwrap)
31. **React Hooks**: Use `React.useState(() => initialValue)` and `React.useEffect1(() => effect, [deps])`
32. **useEffect Return**: Must return `option<unit => unit>` - use `None` for no cleanup, `Some(() => cleanup)` for cleanup
33. **Component Props with Underscores**: Some components use `_propName` for unused props - match the exact prop names
34. **Variant Types in Switch**: Use `switch` expressions for variant types: `switch variant { | Case1 => ... | Case2 => ... }`
35. **Optional Style Props**: Handle optional style props with `style={style->Option.getOr({})}`
36. **Module Exports**: Update `Client.res` to export new components without `@genType` unless needed
### File Structure
- Components: `Client__ComponentName.res`
- Types: `Client__Types.res`
- Main export: `Client.res` with module exports
- Use flat folder structure with ReScript namespacing convention
- Bindings: `Client__Bindings__LibraryName.res`
### Example Component Structure
@react.component
let make = (
~title=?,
~subtitle=?,
~onClick=?,
) => {
let title = title->Option.getOr("Default Title")
<div
style={
padding: "20px",
backgroundColor: "#111827",
}>
<h2>
{React.string(title)}
</h2>
{onClick->Option.mapOr(
React.null,
onClick => <button onClick={_ => onClick()}>
{React.string("Click me")}
</button>
)}
</div>
}
### Conversion Checklist
- [ ] Replace `@genType` with `@react.component`
- [ ] Convert props to labelled arguments with `~`
- [ ] Add `=?` for optional parameters
- [ ] Remove explicit type annotations unless required
- [ ] Convert inline styles to record syntax
- [ ] Use `React.string()` for all text content
- [ ] Fix event handlers with proper ReScript syntax
- [ ] Update module exports in `Client.res`
- [ ] Test compilation with `make build`
## Code Style Guidelines
- **ReScript**: Never use mutable - use `ref` instead. Functional programming style.
- **TypeScript**: Strict mode enabled. Use React.FC with interfaces. Inline styles preferred.
- **Imports**: Group by external libs, then internal modules. Use absolute imports.
- **Naming**: camelCase for variables/functions, PascalCase for components/types.
- **Folder structure**: keep a flat folder structure, use rescript namespacing convention when needed
- **Error handling**: Use Result types in ReScript, try/catch in TypeScript.
- **Testing**: Vitest with Node environment. Test files: `*.test.res.mjs`
- **Task runner**: Makefiles only - never use yarn/npm scripts directly.
## Project Structure
- `libs/client/` - ReScript client library (main focus)
- `libs/agent/` - ReScript agent library
- `libs/bindings/` - ReScript bindings for Node.js APIs
- `libs/nextjs/` - ReScript Next.js utilities
- `test/sites/` - Test sites for development
## Development Workflow
1. Make changes to ReScript files in `libs/client/src/`
2. Run `cd libs/client && make build` to compile
3. Use `make build` from project root to build all ReScript libraries
4. Follow the conversion checklist when converting TypeScript components to ReScript