@mallardbay/cursor-rules 1.0.28 → 1.0.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,124 @@
1
+ ---
2
+ description: Defines best practices for building consistent, maintainable, and library-agnostic UI in Mallard Bay React Native projects
3
+ globs:
4
+ alwaysApply: true
5
+ ---
6
+
7
+ # UI Development Standards (React Native)
8
+
9
+ ## Component Abstraction Layer
10
+
11
+ The mobile app uses NativeBase under the hood, but **all UI primitives must be accessed through custom wrapper components**. This abstraction enables switching to a different component library (e.g., Gluestack, Tamagui) with minimal churn.
12
+
13
+ ### Import Rules
14
+
15
+ - **Never import directly from `native-base`** in feature code — always use the project's custom wrapper components
16
+ - **Never import from `~components/shared/ui`** — use the abstraction layer instead
17
+ - Wrapper components live in a dedicated directory (e.g., `src/components/primitives/` or the project's established equivalent)
18
+ - Only the wrapper component files themselves may import from `native-base`
19
+
20
+ ### Wrapper Component Guidelines
21
+
22
+ - Each wrapper should expose a **stable, minimal API** — only pass through props the project actually uses
23
+ - Use TypeScript interfaces for wrapper props rather than re-exporting the library's prop types
24
+ - Keep wrappers thin — they should delegate to the underlying library, not add business logic
25
+ - Name wrappers after their semantic purpose (e.g., `AppText`, `AppButton`, `AppBox`) or match the library's naming if there's no ambiguity
26
+ - Document any NativeBase-specific behavior the wrapper intentionally hides or transforms
27
+
28
+ ### Example Pattern
29
+
30
+ ```tsx
31
+ // src/components/primitives/AppButton.tsx — ✅ Correct
32
+ import { Button as NativeBaseButton } from "native-base"
33
+
34
+ export default function AppButton(props: AppButtonProps) {
35
+ return <NativeBaseButton {...props} />
36
+ }
37
+
38
+ // src/features/booking/BookingCard.tsx — ✅ Correct
39
+ import AppButton from "~components/primitives/AppButton"
40
+
41
+ // src/features/booking/BookingCard.tsx — ❌ Wrong
42
+ import { Button } from "native-base"
43
+ import { Button } from "~components/shared/ui"
44
+ ```
45
+
46
+ ## Theme Usage
47
+
48
+ Use theme values consistently across all components:
49
+
50
+ ### Colors
51
+
52
+ - Use theme colors instead of hardcoded values
53
+ - Example: `theme.colors.primary[500]` instead of `'#3B82F6'`
54
+
55
+ ### Spacing
56
+
57
+ - Use theme spacing values for margins and padding
58
+ - Example: `theme.space[4]` instead of numeric literals
59
+
60
+ ### Typography
61
+
62
+ - Use theme typography settings for text styles
63
+ - Example: `theme.fontSizes.md` instead of hardcoded numbers
64
+
65
+ ## Component Structure
66
+
67
+ Maintain clean and consistent component structure:
68
+
69
+ ### Nesting
70
+
71
+ - Limit component nesting to maximum depth of 3
72
+ - Keep component hierarchy readable and maintainable
73
+
74
+ ### Inline Styles
75
+
76
+ - Limit inline styles to maximum of 2 per component
77
+ - Prefer theme-based styling and style props
78
+
79
+ ### Component Library
80
+
81
+ - Use the project's custom wrapper components (abstraction layer) for all UI primitives
82
+ - If a wrapper doesn't exist yet for a NativeBase component you need, create one in the primitives directory following the established pattern
83
+ - Keep wrapper components minimal and focused on API stability
84
+
85
+ ## Platform Considerations
86
+
87
+ ### React Native Specifics
88
+
89
+ - Use `StyleSheet.create` or NativeBase style props — avoid inline object styles
90
+ - Prefer `FlatList` / `SectionList` over mapping arrays for long lists
91
+ - Use platform-specific extensions (`.ios.tsx`, `.android.tsx`) only when behavior genuinely diverges
92
+ - Test on both iOS and Android
93
+
94
+ ### Navigation
95
+
96
+ - Follow the project's established navigation patterns (React Navigation or equivalent)
97
+ - Keep screen components thin — delegate to feature components
98
+
99
+ ### Performance
100
+
101
+ - Use `React.memo` for pure list item components
102
+ - Use `useCallback` for handlers passed to list items
103
+ - Use `useMemo` for expensive computations and filtered/sorted data
104
+ - Avoid anonymous functions in `renderItem` and event handlers
105
+ - Minimize bridge crossings by batching state updates
106
+
107
+ ## Rendering Optimization
108
+
109
+ - Optimize component rendering
110
+ - Avoid unnecessary re-renders
111
+ - Move function definitions outside components or use `useCallback` for event handlers
112
+ - Use `useCallback` for functions passed as props to child components
113
+ - Use `useMemo` for expensive computations and complex data transformations
114
+ - Memoize filtered, sorted, or mapped arrays to avoid recalculation on every render
115
+
116
+ ## File Patterns
117
+
118
+ These rules apply to all TypeScript and TSX files in the project.
119
+
120
+ ## Components
121
+
122
+ - Keep components small and focused on a single responsibility
123
+ - Use functional components with hooks instead of class components
124
+ - Prefer `export default function BookingCard() {` over `function BookingCard(): React.ReactElement | null {` when defining components
@@ -14,7 +14,13 @@ alwaysApply: false
14
14
  - Functions: camelCase
15
15
  - Constants: UPPER_SNAKE_CASE
16
16
  - Types: PascalCase
17
- - Types should be defined at the bottom of files
17
+ - Follow this ordering within files:
18
+ 1. Imports
19
+ 2. Constants
20
+ 3. Exported functions / components
21
+ 4. Helpers and other non-exported definitions
22
+ 5. Types (when not imported)
23
+ - Exported members always come before non-exported members
18
24
  - PropTypes should be defined before component definitions
19
25
  - Prefer using alias for importing components. Only use relative for tests or when there's a direct sibling
20
26
 
@@ -56,13 +56,14 @@ We do not chase 100% coverage for its own sake. If a test doesn’t meaningfully
56
56
 
57
57
  ### Mocking Guidelines
58
58
 
59
- - Use mock helpers instead of inline mocks
60
- - Follow existing patterns for:
59
+ - **Always use mock helpers**—never define mocks inline. All mocks should come from dedicated mock helper files following existing patterns for:
61
60
  - Entity mocks
62
61
  - Apollo mocks
63
62
  - Provider mocks
63
+ - **Mock data through Apollo mocks, not module mocks**—use Apollo mock providers to control query/mutation responses instead of mocking modules or components directly
64
64
  - Keep mocks simple and maintainable
65
65
  - **Do not use variable matchers for Apollo mocks**—match exact variables (e.g. avoid `expect.anything()` or `variables: {}`) so tests fail when the component passes incorrect variables to queries or mutations
66
+ - **Never mock `@mallardbay/lib-react-components`**—if truly unavoidable, stop and ask for approval first
66
67
 
67
68
  ### Test Utilities
68
69
 
@@ -14,7 +14,13 @@ Be as strictly as possible where it delivers clear value—specifically in preve
14
14
 
15
15
  ### File Organization
16
16
 
17
- - Place types at the bottom of files
17
+ - Follow this ordering within files:
18
+ 1. Imports
19
+ 2. Constants
20
+ 3. Exported functions / components
21
+ 4. Helpers and other non-exported definitions
22
+ 5. Types (when not imported)
23
+ - Exported members always come before non-exported members
18
24
  - Define PropTypes before component definitions
19
25
 
20
26
  ## Best Practices
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # setup-cursor.sh — frontend & frontend-lib layering with shared base
2
+ # setup-cursor.sh — frontend, frontend-lib, frontend-mobile & backend layering with shared base
3
3
  # Also generates CLAUDE.md for Claude Code and AGENTS.md for Codex
4
4
 
5
5
  set -e
@@ -65,6 +65,7 @@ fi
65
65
  SHARED_DIR="$SRC_DIR/.cursor/shared/rules"
66
66
  FRONTEND_DIR="$SRC_DIR/.cursor/frontend/rules"
67
67
  FRONTEND_LIB_DIR="$SRC_DIR/.cursor/frontend-lib/rules"
68
+ FRONTEND_MOBILE_DIR="$SRC_DIR/.cursor/frontend-mobile/rules"
68
69
  BACKEND_DIR="$SRC_DIR/.cursor/backend/rules"
69
70
  SHARED_SKILLS_DIR="$SRC_DIR/.cursor/shared/skills"
70
71
 
@@ -215,6 +216,10 @@ case "$ENV_TYPE" in
215
216
  append_to_md_files "$FRONTEND_DIR"
216
217
  append_to_md_files "$FRONTEND_LIB_DIR"
217
218
  ;;
219
+ frontend-mobile)
220
+ copy_rules "$FRONTEND_MOBILE_DIR"
221
+ append_to_md_files "$FRONTEND_MOBILE_DIR"
222
+ ;;
218
223
  *)
219
224
  echo "Unknown environment type: $ENV_TYPE"
220
225
  exit 1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mallardbay/cursor-rules",
3
- "version": "1.0.28",
3
+ "version": "1.0.30",
4
4
  "description": "Mallard Bay shared cursor rules",
5
5
  "main": "bin/setup-cursor.sh",
6
6
  "repository": "git@github.com:mallardbay/cursor-rules.git",