-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path.cursorrules
More file actions
251 lines (182 loc) · 11.3 KB
/
.cursorrules
File metadata and controls
251 lines (182 loc) · 11.3 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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
We use Sentry for watching for errors in our deployed application, as well as for instrumentation of our application.
## Error collection
Error collection is automatic and configured in `src/router.tsx`.
## Instrumentation
We want our server functions instrumented. So if you see a function name like `createServerFn`, you can instrument it with Sentry. You'll need to import `Sentry`:
```tsx
import * as Sentry from '@sentry/tanstackstart-react'
```
And then wrap the implementation of the server function with `Sentry.startSpan`, like so:
```tsx
Sentry.startSpan({ name: 'Requesting all the pokemon' }, async () => {
// Some lengthy operation here
await fetch('https://api.pokemon.com/data/')
})
```
# Type Alias Rule
- **Never use `interface` for type definitions.**
Always use `type` (type aliases) instead of `interface` to declare all object and function shapes in TypeScript.
# shadcn instructions
Use the latest version of Shadcn to install new components, like this command to add a button component:
```bash
pnpx shadcn@latest add button
```
## ⚠️ TanStack/React-Start/React-Router Only
> **Note:** These UI and architecture guidelines are intended for use with [TanStack Router](https://tanstack.com/router), [TanStack Start](https://tanstack.com/start), or similar React (non-Next.js) setups only.
>
> **Do not use Next.js or Next.js-specific patterns** (such as `app/` or `pages/` directories, server components, or Next-specific routing hooks) in UI or features
>
> All interfaces and components in should presume a TanStack-based (NOT Next.js) architecture for organization, routing, and rendering concerns.
---
## Tailwind UI Guidelines
- **Spacing:** Always use `flex` and `gap-*` Tailwind classes for layout and spatial separation of child elements. Avoid adding manual margin or padding for spacing between immediate children inside a flex container. **Never use `space-y-*`, `space-x-*`, or other `space-*` utilities**—always use `flex` with `gap-*` instead.
- **Margin Classes:** **STRONGLY AVOID** using margin classes (`m-*`, `mt-*`, `mb-*`, `ml-*`, `mr-*`, `mx-*`, `my-*`) for spacing between elements. Instead, use `flex` with `gap-*` for spacing between siblings, or `padding` on parent containers when appropriate. Margin classes should only be used for edge cases like centering elements or creating space from viewport edges, not for spacing between related UI elements.
- **Sizing:** Prefer explicit `size`, `width`, or `height` attributes on elements (for example, `width={64}` or `height={32}`) instead of applying Tailwind's `w-*` or `h-*` classes, unless absolutely necessary for utility.
- **Lucide Icons:** Always size Lucide icons by passing the `size` prop directly (e.g., `<SearchIcon size={24} />`)—never attempt to size Lucide icons using Tailwind classes like `w-6 h-6`.
- **Consistency:** Comments in UI code should not be rewritten or removed unless new, meaningful explanations are added.
- **No Inline Styles:** Do **not** use inline CSS via `style` attributes or add `<style>` tags anywhere in your code. All styling must be handled using Tailwind utility classes, component props, or external/static CSS files when necessary.
---
## Ternary Operator Rendering Rule
When conditionally rendering React components or JSX elements, **always use ternary operators (e.g. `cond ? <Component /> : null`) instead of logical AND (`cond && <Component />`)**. This prevents unexpected rendering of `"0"` as a string if the left operand is `0` rather than `false`.
**Bad:**
```tsx
{count && <Badge>{count}</Badge>} // Will render "0" if count is 0
```
**Good:**
```tsx
{count > 0 ? <Badge>{count}</Badge> : null}
```
- Never use logical `&&` for conditional rendering if the left value is potentially a number, string, or other non-boolean.
- Always explicitly check your condition and use the ternary operator with a fallback of `null` to avoid accidental `"0"` or similar outputs in the render tree.
---
## Examples
```tsx
<div className="flex gap-4 items-center">
<input className="flex-1" type="text" size={40} />
<button className="px-4 py-2">Search</button>
{/* Lucide icon usage example */}
<SearchIcon size={24} />
</div>
```
---
All new UI interfaces and extensions must adhere to these standards to ensure consistency, maintainability, and a cohesive user experience.
## Component Organization Guideline
When implementing larger or complex UI components, split them into separate files for maintainability and clarity. Use a top-level folder (e.g., `features/` or `components/feature/`) and group related UI, logic, or subcomponents as needed. This modular approach helps prevent large, unwieldy files and improves reusability.
**Component Size Rule:**
- **Components should ideally be a maximum of 100 lines of code.** If a component exceeds 100 lines, it should be broken down into smaller subcomponents or extract logic into custom hook/util functions to ensure maintainability.
**Example:**
```
components/chat/
├── ChatBox.tsx
├── SearchInput.tsx
├── SuggestionList.tsx
└── index.ts
```
Import composite and shared components via their respective file paths, and keep the main screen or feature file focused on layout and composition, not internal UI logic or presentation.
This approach is strongly encouraged for all new UI
## File Naming Conventions
Files should follow the pattern `FILE.TYPE.EXTENSION` where the type suffix indicates the file's purpose or characteristics.
**Type Suffixes:**
- **`.client.tsx`** - Files containing client-side interactivity (React components with hooks, event handlers, or browser APIs)
- **`.server.ts`** - Server functions and server-side logic (TanStack Start server functions, API handlers)
- **`.types.ts`** - TypeScript type definitions, interfaces, and type exports
**Examples:**
```
features/search/
├── components/
│ ├── search-landing.tsx # Standard React component (no client suffix needed if no interactivity)
│ ├── search-input.client.tsx # Component with client interactivity
│ └── search-results-list.tsx # Standard component
├── server/
│ └── search.server.ts # Server functions
└── types.ts # Type definitions for search feature
```
**Guidelines:**
- Use `.client.tsx` when a component uses React hooks (`useState`, `useEffect`, etc.), event handlers, or browser APIs
- Use `.server.ts` for all TanStack Start server functions and server-side utilities
- Use `.types.ts` for shared type definitions within a feature or module
- Standard React components without client-side interactivity don't need a type suffix
## UI Implementation Guidance
- **Component Reuse:** When building user experiences, prefer to reuse and compose existing [shadcn/ui](https://ui.shadcn.com/) components (such as Button, Input, Avatar, etc.) whenever possible. This ensures visual and interactive consistency and minimizes duplicated UI logic.
- **Custom Extensions:** If you require custom states (e.g. loading, thinking, chat bubble), extend shadcn/ui components using recommended composition patterns (such as `asChild` or via Tailwind overrides) instead of rewriting fundamental UI elements.
- **Interactivity:** Leverage shadcn/ui form, modal, and list components for search bars, chat interfaces, suggestion pickers, and feedback overlays.
**Example (chat input):**
```tsx
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { SendIcon } from "lucide-react";
function ChatInput() {
return (
<form className="flex gap-2 items-center">
<Input className="flex-1" placeholder="Type your message..." />
<Button type="submit" size="icon">
<SendIcon size={20} />
<span className="sr-only">Send</span>
</Button>
</form>
);
}
```
**Guidelines Recap:**
- Always build on shadcn/ui when possible.
- Compose and override instead of duplicating.
- Tailwind spacing, shadcn/ui sizing conventions, and Lucide icon rules (see above) still apply.
- **Never use inline CSS (`style` attributes or `<style>` tags); use Tailwind or external CSS only.**
> **Note:** If shadcn/ui does not provide a required component out-of-the-box, consider extending relevant primitives _before_ custom-building new UI from scratch.
## Import Path Aliases
- **Use Path Aliases:** Always import project files using configured alias paths (e.g., `@components/Header`) rather than relative paths like `../components/Header`.
- This applies to all internal modules, components, utilities, and assets.
- Example:
- ✅ `import Header from "@components/Header"`
- ❌ `import Header from "../components/Header"`
> This ensures code is easier to refactor and maintain, and helps prevent brittle or ambiguous import paths, especially as folder structures change.
When importing types (such as SteamApp) from the database, use the path alias `@/database` (i.e., `import type { SteamApp } from "@/utils/database"`) instead of deeper or legacy paths like `@/utils/database`.
- **Environment Variables:**
- Always import environment variables from the correct environment-specific modules:
- Use `@/env/env.client` when accessing variables in code that runs on the client/browser.
- Use `@/env/env.server` for server-side-only code.
- **Never import environment variables directly from `.env` files or from any other location.**
- This ensures the correct exposure and security of sensitive information according to runtime context.
## TypeScript Switch Statement Exhaustiveness
When using switch statements with explicit union types or known values, always include a `default` case with `x satisfies never` to ensure exhaustive type checking:
```tsx
type Platform = "windows" | "mac" | "linux";
switch (platform) {
case "windows":
return <WindowsLogo />;
case "mac":
return <AppleLogo />;
case "linux":
return <LinuxLogo />;
default:
platform satisfies never;
return null;
}
```
**Guidelines:**
- Use `x satisfies never` in the `default` case when all possible values are explicitly handled
- This pattern ensures TypeScript will error if new values are added to the union type but not handled in the switch
- The `satisfies never` assertion provides compile-time exhaustiveness checking
- Always return a fallback value (like `null` or a default component) after the `satisfies never` assertion
## Sitemap Route Registration
**When adding a new route, always add it to the sitemap configuration.**
- **Location:** Add the route to `src/utils/sitemap.ts` in the `routes` object
- **Static Routes:** Add the route path with priority and changeFrequency configuration
- **Dynamic Routes:** Use a function that returns an array of route configurations
- **Priority Guidelines:**
- Homepage and main search: `1.0` (highest)
- Primary category pages (popular-games, free-games, etc.): `0.8-0.9`
- Secondary pages (tags, platforms): `0.7`
- Individual game/item pages: `0.6`
- Lower priority pages: `0.5` or below
- **Change Frequency:** Use `"daily"` for frequently updated pages, `"weekly"` for less frequently updated content
**Example:**
```ts
routes: {
"/new-route": {
priority: 0.8,
changeFrequency: "daily",
},
}
```
**Important:** Forgetting to add a route to the sitemap will prevent it from being discovered by search engines and included in the generated `public/sitemap.xml` file.