RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Diff/sportiz91-vibe-template-cursor-rules-coding-standards ↔ sportiz91-vibe-template-claude

Comparison

A · Cursor rules · sportiz91/vibe-templateB · CLAUDE.md · sportiz91/vibe-template
What each file covers, counted
DimensionSharedOnly in AOnly in BOverlap
Sections00270%
Commands00100%
Section tags30827%

What each file covers

Sections

0 shared · 0 only in A · 27 only in B
  • + CLAUDE.md
  • + Standard Worflow
  • + Workflow when working on a new task:
  • + Development Commands
  • + Core Development
  • + Code Quality
  • + Database Operations
  • + Architecture Overview
  • + Tech Stack
  • + Key Architectural Patterns
  • + Important Development Rules
  • + Environment Variables
  • + Import Conventions
  • + File Naming
  • + Code Quality Requirements
  • + Coding Standards
  • + Syntax & Structure
  • + Functional Programming Rules
  • + Type Safety & Error Handling
  • + React Component Standards
  • + Component Granularity & Organization
  • + Advanced Component Architecture Patterns
  • + Application Guidelines
  • + Database Schema
  • + Current Tables
  • + Schema Location
  • + Testing and Deployment

Commands

0 shared · 0 only in A · 10 only in B
  • + yarn dev
  • + yarn build
  • + yarn lint
  • + yarn type-check
  • + yarn clean
  • + yarn lint:fix
  • + yarn format:write
  • + yarn db:push
  • + yarn db:generate
  • + yarn db:migrate

Section tags

3 shared · 0 only in A · 8 only in B
  • + setup
  • + test
  • + lint-format
  • + architecture
  • + security
  • + database
  • + do-not
  • + agent-behaviour
  •   code-style
  •   types
  •   ui

Line diff

+312 added−124 removed231 unchanged42.5% identical
sportiz91/vibe-template · .cursor/rules/coding-standards.mdc
@@ −1 @@
1---
2description:
3globs:
4alwaysApply: false
5---
6Rule Name: coding-standards
7Description:
8This rule defines the coding standards and formatting guidelines that must be followed for all code changes in this project.
9 
10<coding_format>
11 
12A. Syntax & Structure
13- File names must be dash-case (word-cloud.service.ts) unless an existing pattern differs.
14- Group imports: node/standard → npm packages → internal paths. No unused imports.
15- Use arrow functions everywhere except inside class bodies, where concise method syntax is allowed.
16- Prefer early returns; nested if/else blocks deeper than two levels are disallowed.
17- Early returns must use block format with braces (e.g., `if (!value) { return }`) for readability.
18- Extract function call results as scope variables before using in conditions (e.g., `const trimmedText = text.trim(); if (!trimmedText) {...}` instead of `if (!text.trim()) {...}`).
19- Use async/await—never chain .then().
20- No .forEach for side effects; use for (const x of arr) instead.
21- Array combinators (map, reduce, filter) are allowed only when you return their result.
22- Identifiers must be English.
23- No commented code allowed.
24 
25B. Functional-Programming Rules
26- Each function must:
27 * Be ≤ 50 lines (preferably; extract helpers if longer).
28 * Take ≤ 4 parameters (optional ones last).
29 * Have a single responsibility.
30 * Be pure unless it is an intentional I/O wrapper (e.g. DB write); such wrappers must be ≤ 15 lines.
31 * Name functions with camelCase imperative verbs (calculateTotals, getUserById).
32 
33C. Type Safety & Error Handling
34- Explicitly type all function parameters, return types, and exported constants.
35- Type all local variables inside a function.
36- **Special attention for async operations**: Variables from awaited functions (e.g., `const { userId } = await auth()`) must be explicitly typed, especially in Next.js components where auth results should use proper domain types.
37- No any; if an external library forces it, wrap and narrow.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38- Error handling in catch blocks:
39 - If the error variable is not used, use `catch {}` (no parameter).
40 - If the error is used, type it as `unknown` and handle it safely within the catch block.
41 
42D. React Component Standards
43 
44- Always define props with interfaces, never inline types
45- Place interfaces directly above component definitions
@@ −49 @@
49- Handler functions inside components must be ≤ 20 lines and have a single, clear responsibility. Extract helper functions for complex logic.
50 
51 **Wrong (~50 lines in one handler):**
 
52 ```tsx
53 const handleFormSubmit = async (): Promise<void> => {
54 const trimmedName: string = formData.name.trim()
55 const trimmedEmail: string = formData.email.trim()
56 const trimmedMessage: string = formData.message.trim()
57
58 if (!trimmedName) {
59 setErrors({ ...errors, name: "Name is required" })
60 toast({ title: "Error", description: "Name is required", variant: "destructive" })
 
 
 
 
61 return
62 }
63
64 if (!trimmedEmail || !trimmedEmail.includes("@")) {
65 setErrors({ ...errors, email: "Valid email is required" })
66 toast({ title: "Error", description: "Valid email is required", variant: "destructive" })
 
 
 
 
67 return
68 }
69
70 if (!trimmedMessage || trimmedMessage.length < 10) {
71 setErrors({ ...errors, message: "Message must be at least 10 characters" })
72 toast({ title: "Error", description: "Message too short", variant: "destructive" })
 
 
 
 
 
 
 
73 return
74 }
75
76 setIsSubmitting(true)
77 setErrors({})
78
79 try {
80 const payload: FormPayload = {
81 name: trimmedName,
@@ −83 @@
83 message: trimmedMessage,
84 timestamp: new Date().toISOString()
85 }
86
87 const response: Response = await fetch("/api/contact", {
88 method: "POST",
89 headers: { "Content-Type": "application/json" },
90 body: JSON.stringify(payload)
91 })
92
93 if (!response.ok) {
94 throw new Error("Failed to submit")
95 }
96
97 const result: SubmissionResult = await response.json()
98
99 setFormData({ name: "", email: "", message: "" })
100 setSubmissionCount(prev => prev + 1)
101
102 toast({ title: "Success", description: "Message sent successfully!" })
103
104 if (onSuccess) {
105 onSuccess(result)
106 }
107 } catch (error: unknown) {
108 const errorMessage: string = error instanceof Error ? error.message : "Unknown error"
 
109 console.error("Submission error:", errorMessage)
110 setErrors({ submit: "Failed to send message" })
111 toast({ title: "Error", description: "Failed to send message", variant: "destructive" })
 
 
 
 
112 } finally {
113 setIsSubmitting(false)
114 }
@@ −116 @@
116 ```
117 
118 **Good (broken into focused helpers ≤ 20 lines each):**
 
119 ```tsx
120 const validateForm = (): boolean => {
121 const trimmedName: string = formData.name.trim()
122 const trimmedEmail: string = formData.email.trim()
123 const trimmedMessage: string = formData.message.trim()
124
125 if (!trimmedName) {
126 setErrors({ ...errors, name: "Name is required" })
127 toast({ title: "Error", description: "Name is required", variant: "destructive" })
 
 
 
 
128 return false
129 }
130
131 if (!trimmedEmail || !trimmedEmail.includes("@")) {
132 setErrors({ ...errors, email: "Valid email is required" })
133 toast({ title: "Error", description: "Valid email is required", variant: "destructive" })
 
 
 
 
134 return false
135 }
136
137 if (!trimmedMessage || trimmedMessage.length < 10) {
138 setErrors({ ...errors, message: "Message must be at least 10 characters" })
139 toast({ title: "Error", description: "Message too short", variant: "destructive" })
 
 
 
 
 
 
 
140 return false
141 }
142
143 return true
144 }
145
146 const submitForm = async (): Promise<SubmissionResult> => {
147 const payload: FormPayload = {
148 name: formData.name.trim(),
@@ −150 @@
150 message: formData.message.trim(),
151 timestamp: new Date().toISOString()
152 }
153
154 const response: Response = await fetch("/api/contact", {
155 method: "POST",
156 headers: { "Content-Type": "application/json" },
157 body: JSON.stringify(payload)
158 })
159
160 if (!response.ok) {
161 throw new Error("Failed to submit")
162 }
163
164 return response.json()
165 }
166
167 const handleSuccess = (result: SubmissionResult): void => {
168 setFormData({ name: "", email: "", message: "" })
169 setSubmissionCount((prev: number) => prev + 1)
170 toast({ title: "Success", description: "Message sent successfully!" })
171
172 if (onSuccess) {
173 onSuccess(result)
174 }
175 }
176
177 const handleError = (error: unknown): void => {
178 const errorMessage: string = error instanceof Error ? error.message : "Unknown error"
 
179 console.error("Submission error:", errorMessage)
180 setErrors({ submit: "Failed to send message" })
181 toast({ title: "Error", description: "Failed to send message", variant: "destructive" })
 
 
 
 
182 }
183
184 const handleFormSubmit = async (): Promise<void> => {
185 const isValid: boolean = validateForm()
186
187 if (!isValid) {
188 return
189 }
190
191 setIsSubmitting(true)
192 setErrors({})
193
194 try {
195 const result: SubmissionResult = await submitForm()
196 handleSuccess(result)
@@ −201 @@
201 }
202 }
203 ```
 
204- Example with implicit return:
205 
206 ```tsx
@@ −229 @@
229 
230 const MyComponent = ({ title, children }: MyComponentProps) => {
231 const processedTitle = title.toUpperCase()
232
233 return (
234 <div>
235 {processedTitle}
@@ −260 @@
260 {children}
261 </div>
262 )
 
263 
264E. Component Granularity & Organization
265- Break down large components into smaller, focused components for better maintainability.
266- When a component contains multiple logical sections (e.g., Card with CardHeader + CardContent), extract each section into separate components.
 
267- Create dedicated folders for related component groups:
268 * Use kebab-case folder names matching the main component concept
269 * Place related sub-components within the same folder using kebab-case file names
270 * Example structure: `component-name/component-name-header.tsx`, `component-name/component-name-content.tsx`
271- Each sub-component should have a single, clear responsibility.
272- Maintain the parent component as a composition wrapper that orchestrates child components.
273- Follow this pattern when refactoring existing components or creating new feature components.
274 
275F. Advanced Component Architecture Patterns
276 
277F.1. Pure Functions and Constants Organization
 
278- **Pure functions** (no side effects, deterministic output) must be extracted outside components:
279 * Place above the component definition
280 * Examples: `getGreeting()`, `getMembershipBadgeColor()`, `formatDate()`
281- **Constants and static data** must be moved outside components:
282 * Place after imports and interfaces, before pure functions
283 * Use SCREAMING_SNAKE_CASE for naming (e.g., `TEMPLATE_FEATURES`, `TECH_STACK`)
284 * **Always explicitly type constants** with appropriate type annotations
285 * Examples: `const API_URL: string = "..."`, `const MAX_RETRIES: number = 3`
286 * Use `as const` for immutable values when type inference is sufficient
287 * Group related constants together
288 
289F.1.1. Custom Hooks Organization
 
290- **Custom hooks** must be extracted to separate files in the `/hooks/` directory:
291 * Use kebab-case file naming: `use-scroll-detection.ts`, `use-local-storage.ts`
292 * Start hook names with `use` prefix following React conventions
293 * Place hooks in `/hooks/` folder at project root level
294 * Export hooks using named exports: `export const useScrollDetection = () => {}`
295 * **Always explicitly type hook return values** and parameters
296 * Examples: `useScrollDetection(): boolean`, `useLocalStorage<T>(key: string): [T, (value: T) => void]`
297 * Group related hooks in the same file only if they're tightly coupled
298 
299F.1.2. Whitespace and Formatting Rules
 
300- **Component variable organization**: Maintain consistent whitespace between different types of declarations:
301 * Add a blank line between React state declarations and custom hook calls
302 * Add a blank line between custom hook calls and other variable declarations
303 * Example:
 
304 ```tsx
305 const [isMenuOpen, setIsMenuOpen] = useState<boolean>(false)
306 const [isVisible, setIsVisible] = useState<boolean>(true)
307
308 const isScrolled: boolean = useScrollDetection()
309 const userData: UserData = useUserData()
310
311 const processedData: ProcessedData = processUserData(userData)
312 ```
313 
314F.2. Nested Component Structure for Complex Components
 
315When a component has multiple distinct sections, create nested folder structure:
316 
317```
318dashboard-welcome/
319├── dashboard-welcome.tsx // Main orchestrator component
320├── greeting.tsx // Self-contained greeting section
321├── whats-included/ // Folder for multi-part section
322│ ├── whats-included.tsx // Section orchestrator
323│ ├── whats-included-title.tsx // Title sub-component
324│ └── whats-included-features.tsx // Features list sub-component
325├── core-technologies/ // Folder for multi-part section
326│ ├── core-technologies.tsx // Section orchestrator
327│ ├── core-technologies-title.tsx // Title sub-component
328│ └── core-technologies-list.tsx // Tech list sub-component
329└── get-started/ // Folder for multi-part section
330 ├── get-started.tsx // Section orchestrator
331 ├── get-started-title.tsx // Title sub-component
332 ├── get-started-features.tsx // Features grid sub-component
333 └── get-started-feature-2.tsx // Individual feature card
334```
335 
336F.3. Component Organization Rules
 
3371. **Main orchestrator**: Composition only, minimal logic, imports and renders sub-components
3382. **Section orchestrators**: Handle section-specific logic, render related sub-components
3393. **Leaf components**: Single responsibility, pure presentation, accept props only
3404. **Shared constants**: Extract to file level, use proper naming conventions
3415. **Pure functions**: Extract above component definitions, properly typed
3426. **File structure**: Mirror logical component hierarchy in folder structure
343 
344</coding_format>
345 
346<usage_guidelines>
 
 
 
 
 
347 
3481. Apply these standards to all new code and when refactoring existing code.
3492. When making any code changes, ensure they conform to these guidelines.
3503. If existing code doesn't follow these standards, update it to comply when modifying those files.
3514. Use these standards as a checklist when reviewing code changes.
3525. Prefer extracting helper functions over writing long, complex functions.
3536. Always prioritize code readability and maintainability.
354 
355</usage_guidelines>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
sportiz91/vibe-template · CLAUDE.md
@@ +1 @@
1# CLAUDE.md
 
 
 
 
 
 
 
2 
3This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4 
5## Standard Worflow
 
 
 
 
 
 
 
 
 
 
 
6 
7Use this workflow when working on a new task:
 
 
 
 
 
 
8 
9### Workflow when working on a new task:
10 
111. First, think through the problem, read the codebase for relevant files, and
12 write a plan to tasks/todo.md.
132. The plan should have a list of todo items that you can check off as you complete them.
143. Before you begin to work, check in with me and I verify the plan.
154. Then, begin working on the todo items, marking them as complete as you go.
165. Finally, add a review section to the todo.md file with a summary of the changes
17 you made and any other relevant information.
18 
19Periodically make sure to commit when it makes sense to do so.
20 
21## Development Commands
22 
23**Important: This project uses yarn, not npm. Always use yarn commands.**
24 
25**Node.js Version**: This project uses Node.js version 20.12.2 (see .nvmrc). Always ensure you're using the correct Node.js version before running any commands, especially linting and code quality tools.
26 
27**To activate the correct Node.js version, run these commands first:**
28```bash
29export NVM_DIR="$HOME/.nvm"
30[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
31nvm use
32```
33 
34**Note**: These commands load nvm and switch to the project's Node.js version. You need to run them in each new terminal session.
35 
36### Core Development
37 
38- `yarn dev` - Start development server
39- `yarn build` - Build for production
40- `yarn lint` - Run ESLint
41- `yarn type-check` - TypeScript type checking
42 
43### Code Quality
44 
45- `yarn clean` - Fix linting and format code (recommended after changes)
46- `yarn lint:fix` - Auto-fix linting issues
47- `yarn format:write` - Format code with Prettier
48 
49### Database Operations
50 
51- `yarn db:push` - Push schema changes to database
52- `yarn db:generate` - Generate new migrations
53- `yarn db:migrate` - Run pending migrations
54 
55## Architecture Overview
56 
57This is a full-stack Next.js application template with the following architecture:
58 
59### Tech Stack
60 
61- **Frontend**: Next.js 15 with App Router, React 19, TypeScript, Tailwind CSS, Shadcn/UI
62- **Backend**: PostgreSQL with Supabase, Drizzle ORM, Next.js Server Actions
63- **Auth**: Clerk authentication
64- **Payments**: Stripe integration
65- **Analytics**: PostHog
66- **AI**: OpenAI integration
67 
68### Key Architectural Patterns
69 
70#### Route Organization
71 
72- **Route Groups**: `(auth)` for authentication pages, `(marketing)` for public pages
73- **Route-specific Components**: Use `_components` folder within routes for one-off components
74- **Layouts**: Separate layouts for different route groups
75 
76#### Data Layer
77 
78- **Server Actions**: Located in `/actions/` directory, organized by functionality
79- **Services**: Located in `/lib/services/` directory for complex business logic
80- **Database Schema**: Drizzle ORM schemas in `/db/schema/`
81- **Type Safety**: Use schema-generated types like InsertProfile and SelectProfile from your database schemas
82 
83#### Data Flow Architecture
84 
85Follow this layered architecture pattern:
86 
87- **React Components** → **Server Actions** → **Services** (when complex logic is needed)
88- Services handle domain-specific logic, external API integrations, and complex business rules
89- Keep Server Actions lightweight and focused on data validation and orchestration
90 
91#### Component Architecture
92 
93- **UI Components**: Shadcn/UI components in `/components/ui/` (don't modify unless specified)
94- **Shared Components**: Reusable components in `/components/`
95- **Route-specific**: Components in `app/route/_components/`
96 
97## Important Development Rules
98 
99### Environment Variables
100 
101- Always use centralized config: `serverConfig` and `publicEnv` from `@/lib/config`
102- Never use `process.env` directly in application code
103- Update `.env.example` when adding new environment variables
104 
105### Import Conventions
106 
107- Use `@/` for all imports from the app root
108- Import types from `@/types`
109- Import database types from `@/db/schema`
110- Import services from `@/lib/services`
111 
112### File Naming
113 
114- Use kebab-case for all files and folders
115- Type files: `example-types.ts` in `/types/` directory
116- Export all types in `types/index.ts`
117 
118### Code Quality Requirements
119 
120- **Always use the correct Node.js version (20.12.2)** before running any code quality commands
121- **Load nvm first**: Run the nvm commands above if you're in a new terminal session
122- Run `yarn clean` after making changes to ensure code quality
123- Use TypeScript interfaces over type aliases when possible
124- Follow the existing patterns in the codebase
125 
126## Coding Standards
127 
128All code must adhere to these strict formatting and quality guidelines:
129 
130### Syntax & Structure
131 
132- File names must be dash-case (word-cloud.service.ts) unless an existing pattern differs
133- Group imports: node/standard → npm packages → internal paths. No unused imports
134- Use arrow functions everywhere except inside class bodies, where concise method syntax is allowed
135- Prefer early returns; nested if/else blocks deeper than two levels are disallowed
136- Early returns must use block format with braces (e.g., `if (!value) { return }`) for readability
137- Extract function call results as scope variables before using in conditions (e.g., `const trimmedText = text.trim(); if (!trimmedText) {...}` instead of `if (!text.trim()) {...}`)
138- Use async/await—never chain .then()
139- No .forEach for side effects; use for (const x of arr) instead
140- Array combinators (map, reduce, filter) are allowed only when you return their result
141- Identifiers must be English
142- No commented code allowed
143 
144### Functional Programming Rules
145 
146Each function must:
147 
148- Be ≤ 50 lines (preferably; extract helpers if longer)
149- Take ≤ 4 parameters (optional ones last)
150- Have a single responsibility
151- Be pure unless it is an intentional I/O wrapper (e.g. DB write); such wrappers must be ≤ 15 lines
152- Name functions with camelCase imperative verbs (calculateTotals, getUserById)
153 
154### Type Safety & Error Handling
155 
156- Explicitly type all function parameters, return types, and exported constants
157- Type all local variables inside a function
158- **Special attention for async operations**: Variables from awaited functions (e.g., `const { userId } = await auth()`) must be explicitly typed, especially in Next.js components where auth results should use proper domain types
159- No any; if an external library forces it, wrap and narrow
160- Error handling in catch blocks:
161 - If the error variable is not used, use `catch {}` (no parameter)
162 - If the error is used, type it as `unknown` and handle it safely within the catch block
163 
164### React Component Standards
165 
166- Always define props with interfaces, never inline types
167- Place interfaces directly above component definitions
@@ +171 @@
171- Handler functions inside components must be ≤ 20 lines and have a single, clear responsibility. Extract helper functions for complex logic.
172 
173 **Wrong (~50 lines in one handler):**
174 
175 ```tsx
176 const handleFormSubmit = async (): Promise<void> => {
177 const trimmedName: string = formData.name.trim()
178 const trimmedEmail: string = formData.email.trim()
179 const trimmedMessage: string = formData.message.trim()
180 
181 if (!trimmedName) {
182 setErrors({ ...errors, name: "Name is required" })
183 toast({
184 title: "Error",
185 description: "Name is required",
186 variant: "destructive"
187 })
188 return
189 }
190 
191 if (!trimmedEmail || !trimmedEmail.includes("@")) {
192 setErrors({ ...errors, email: "Valid email is required" })
193 toast({
194 title: "Error",
195 description: "Valid email is required",
196 variant: "destructive"
197 })
198 return
199 }
200 
201 if (!trimmedMessage || trimmedMessage.length < 10) {
202 setErrors({
203 ...errors,
204 message: "Message must be at least 10 characters"
205 })
206 toast({
207 title: "Error",
208 description: "Message too short",
209 variant: "destructive"
210 })
211 return
212 }
213 
214 setIsSubmitting(true)
215 setErrors({})
216 
217 try {
218 const payload: FormPayload = {
219 name: trimmedName,
@@ +221 @@
221 message: trimmedMessage,
222 timestamp: new Date().toISOString()
223 }
224 
225 const response: Response = await fetch("/api/contact", {
226 method: "POST",
227 headers: { "Content-Type": "application/json" },
228 body: JSON.stringify(payload)
229 })
230 
231 if (!response.ok) {
232 throw new Error("Failed to submit")
233 }
234 
235 const result: SubmissionResult = await response.json()
236 
237 setFormData({ name: "", email: "", message: "" })
238 setSubmissionCount((prev) => prev + 1)
239 
240 toast({ title: "Success", description: "Message sent successfully!" })
241 
242 if (onSuccess) {
243 onSuccess(result)
244 }
245 } catch (error: unknown) {
246 const errorMessage: string =
247 error instanceof Error ? error.message : "Unknown error"
248 console.error("Submission error:", errorMessage)
249 setErrors({ submit: "Failed to send message" })
250 toast({
251 title: "Error",
252 description: "Failed to send message",
253 variant: "destructive"
254 })
255 } finally {
256 setIsSubmitting(false)
257 }
@@ +259 @@
259 ```
260 
261 **Good (broken into focused helpers ≤ 20 lines each):**
262 
263 ```tsx
264 const validateForm = (): boolean => {
265 const trimmedName: string = formData.name.trim()
266 const trimmedEmail: string = formData.email.trim()
267 const trimmedMessage: string = formData.message.trim()
268 
269 if (!trimmedName) {
270 setErrors({ ...errors, name: "Name is required" })
271 toast({
272 title: "Error",
273 description: "Name is required",
274 variant: "destructive"
275 })
276 return false
277 }
278 
279 if (!trimmedEmail || !trimmedEmail.includes("@")) {
280 setErrors({ ...errors, email: "Valid email is required" })
281 toast({
282 title: "Error",
283 description: "Valid email is required",
284 variant: "destructive"
285 })
286 return false
287 }
288 
289 if (!trimmedMessage || trimmedMessage.length < 10) {
290 setErrors({
291 ...errors,
292 message: "Message must be at least 10 characters"
293 })
294 toast({
295 title: "Error",
296 description: "Message too short",
297 variant: "destructive"
298 })
299 return false
300 }
301 
302 return true
303 }
304 
305 const submitForm = async (): Promise<SubmissionResult> => {
306 const payload: FormPayload = {
307 name: formData.name.trim(),
@@ +309 @@
309 message: formData.message.trim(),
310 timestamp: new Date().toISOString()
311 }
312 
313 const response: Response = await fetch("/api/contact", {
314 method: "POST",
315 headers: { "Content-Type": "application/json" },
316 body: JSON.stringify(payload)
317 })
318 
319 if (!response.ok) {
320 throw new Error("Failed to submit")
321 }
322 
323 return response.json()
324 }
325 
326 const handleSuccess = (result: SubmissionResult): void => {
327 setFormData({ name: "", email: "", message: "" })
328 setSubmissionCount((prev: number) => prev + 1)
329 toast({ title: "Success", description: "Message sent successfully!" })
330 
331 if (onSuccess) {
332 onSuccess(result)
333 }
334 }
335 
336 const handleError = (error: unknown): void => {
337 const errorMessage: string =
338 error instanceof Error ? error.message : "Unknown error"
339 console.error("Submission error:", errorMessage)
340 setErrors({ submit: "Failed to send message" })
341 toast({
342 title: "Error",
343 description: "Failed to send message",
344 variant: "destructive"
345 })
346 }
347 
348 const handleFormSubmit = async (): Promise<void> => {
349 const isValid: boolean = validateForm()
350 
351 if (!isValid) {
352 return
353 }
354 
355 setIsSubmitting(true)
356 setErrors({})
357 
358 try {
359 const result: SubmissionResult = await submitForm()
360 handleSuccess(result)
@@ +365 @@
365 }
366 }
367 ```
368 
369- Example with implicit return:
370 
371 ```tsx
@@ +394 @@
394 
395 const MyComponent = ({ title, children }: MyComponentProps) => {
396 const processedTitle = title.toUpperCase()
397 
398 return (
399 <div>
400 {processedTitle}
@@ +425 @@
425 {children}
426 </div>
427 )
428 ```
429 
430### Component Granularity & Organization
431 
432- Break down large components into smaller, focused components for better maintainability
433- When a component contains multiple logical sections (e.g., Card with CardHeader + CardContent), extract each section into separate components
434- Create dedicated folders for related component groups:
435 - Use kebab-case folder names matching the main component concept
436 - Place related sub-components within the same folder using kebab-case file names
437 - Example structure: `component-name/component-name-header.tsx`, `component-name/component-name-content.tsx`
438- Each sub-component should have a single, clear responsibility
439- Maintain the parent component as a composition wrapper that orchestrates child components
440- Follow this pattern when refactoring existing components or creating new feature components
441 
442### Advanced Component Architecture Patterns
443 
444#### Pure Functions and Constants Organization
445 
446- **Pure functions** (no side effects, deterministic output) must be extracted outside components:
447 - Place above the component definition
448 - Examples: `getGreeting()`, `getMembershipBadgeColor()`, `formatDate()`
449- **Constants and static data** must be moved outside components:
450 - Place after imports and interfaces, before pure functions
451 - Use SCREAMING_SNAKE_CASE for naming (e.g., `TEMPLATE_FEATURES`, `TECH_STACK`) constants
452 - **Always explicitly type constants** with appropriate type annotations
453 - Examples: `const API_URL: string = "..."`, `const MAX_RETRIES: number = 3`
454 - Use `as const` for immutable values when type inference is sufficient
455 - Group related constants together
456 
457#### Custom Hooks Organization
458 
459- **Custom hooks** must be extracted to separate files in the `/hooks/` directory:
460 - Use kebab-case file naming: `use-scroll-detection.ts`, `use-local-storage.ts`
461 - Start hook names with `use` prefix following React conventions
462 - Place hooks in `/hooks/` folder at project root level
463 - Export hooks using named exports: `export const useScrollDetection = () => {}`
464 - **Always explicitly type hook return values** and parameters
465 - Examples: `useScrollDetection(): boolean`, `useLocalStorage<T>(key: string): [T, (value: T) => void]`
466 - Group related hooks in the same file only if they're tightly coupled
467 
468#### Whitespace and Formatting Rules
469 
470- **Component variable organization**: Maintain consistent whitespace between different types of declarations:
471 - Add a blank line between React state declarations and custom hook calls
472 - Add a blank line between custom hook calls and other variable declarations
473 - Example:
474 
475 ```tsx
476 const [isMenuOpen, setIsMenuOpen] = useState<boolean>(false)
477 const [isVisible, setIsVisible] = useState<boolean>(true)
478 
479 const isScrolled: boolean = useScrollDetection()
480 const userData: UserData = useUserData()
481 
482 const processedData: ProcessedData = processUserData(userData)
483 ```
484 
485#### Nested Component Structure for Complex Components
486 
487When a component has multiple distinct sections, create nested folder structure:
488 
489```
490dashboard-welcome/
491├── dashboard-welcome.tsx // Main orchestrator component
492├── greeting.tsx // Self-contained greeting section
493├── whats-included/ // Folder for multi-part section
494│ ├── whats-included.tsx // Section orchestrator
495│ ├── whats-included-title.tsx // Title sub-component
496│ └── whats-included-features.tsx // Features list sub-component
497├── core-technologies/ // Folder for multi-part section
498│ ├── core-technologies.tsx // Section orchestrator
499│ ├── core-technologies-title.tsx // Title sub-component
500│ └── core-technologies-list.tsx // Tech list sub-component
501└── get-started/ // Folder for multi-part section
502 ├── get-started.tsx // Section orchestrator
503 ├── get-started-title.tsx // Title sub-component
504 ├── get-started-features.tsx // Features grid sub-component
505 └── get-started-feature-2.tsx // Individual feature card
506```
507 
508#### Component Organization Rules
509 
5101. **Main orchestrator**: Composition only, minimal logic, imports and renders sub-components
5112. **Section orchestrators**: Handle section-specific logic, render related sub-components
5123. **Leaf components**: Single responsibility, pure presentation, accept props only
5134. **Shared constants**: Extract to file level, use proper naming conventions
5145. **Pure functions**: Extract above component definitions, properly typed
5156. **File structure**: Mirror logical component hierarchy in folder structure
516 
517### Application Guidelines
518 
5191. Apply these standards to all new code and when refactoring existing code
5202. When making any code changes, ensure they conform to these guidelines
5213. If existing code doesn't follow these standards, update it to comply when modifying those files
5224. Use these standards as a checklist when reviewing code changes
5235. Prefer extracting helper functions over writing long, complex functions
5246. Always prioritize code readability and maintainability
525 
526## Database Schema
 
 
 
 
 
527 
528### Current Tables
529 
530- **Profiles**: User profiles with Stripe integration and membership tiers
531 
532### Schema Location
533 
534- Schemas: `/db/schema/`
535- Migrations: `/db/migrations/`
536- Database connection: `/db/db.ts`
537 
538## Testing and Deployment
539 
540- The project uses Vercel for deployment
541- No specific test framework is configured - check with user if testing is needed
542- Always run `yarn build` and `yarn type-check` before considering work complete
543 
@@ −1 +1 @@
1−---
2−description:
3−globs:
4−alwaysApply: false
5−---
6−Rule Name: coding-standards
7−Description:
8−This rule defines the coding standards and formatting guidelines that must be followed for all code changes in this project.
1+# CLAUDE.md
92  
10−<coding_format>
3+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
114  
12−A. Syntax & Structure
13−- File names must be dash-case (word-cloud.service.ts) unless an existing pattern differs.
14−- Group imports: node/standard → npm packages → internal paths. No unused imports.
15−- Use arrow functions everywhere except inside class bodies, where concise method syntax is allowed.
16−- Prefer early returns; nested if/else blocks deeper than two levels are disallowed.
17−- Early returns must use block format with braces (e.g., `if (!value) { return }`) for readability.
18−- Extract function call results as scope variables before using in conditions (e.g., `const trimmedText = text.trim(); if (!trimmedText) {...}` instead of `if (!text.trim()) {...}`).
19−- Use async/await—never chain .then().
20−- No .forEach for side effects; use for (const x of arr) instead.
21−- Array combinators (map, reduce, filter) are allowed only when you return their result.
22−- Identifiers must be English.
23−- No commented code allowed.
5+## Standard Worflow
246  
25−B. Functional-Programming Rules
26−- Each function must:
27− * Be ≤ 50 lines (preferably; extract helpers if longer).
28− * Take ≤ 4 parameters (optional ones last).
29− * Have a single responsibility.
30− * Be pure unless it is an intentional I/O wrapper (e.g. DB write); such wrappers must be ≤ 15 lines.
31− * Name functions with camelCase imperative verbs (calculateTotals, getUserById).
7+Use this workflow when working on a new task:
328  
33−C. Type Safety & Error Handling
34−- Explicitly type all function parameters, return types, and exported constants.
35−- Type all local variables inside a function.
36−- **Special attention for async operations**: Variables from awaited functions (e.g., `const { userId } = await auth()`) must be explicitly typed, especially in Next.js components where auth results should use proper domain types.
37−- No any; if an external library forces it, wrap and narrow.
9+### Workflow when working on a new task:
10+ 
11+1. First, think through the problem, read the codebase for relevant files, and
12+ write a plan to tasks/todo.md.
13+2. The plan should have a list of todo items that you can check off as you complete them.
14+3. Before you begin to work, check in with me and I verify the plan.
15+4. Then, begin working on the todo items, marking them as complete as you go.
16+5. Finally, add a review section to the todo.md file with a summary of the changes
17+ you made and any other relevant information.
18+ 
19+Periodically make sure to commit when it makes sense to do so.
20+ 
21+## Development Commands
22+ 
23+**Important: This project uses yarn, not npm. Always use yarn commands.**
24+ 
25+**Node.js Version**: This project uses Node.js version 20.12.2 (see .nvmrc). Always ensure you're using the correct Node.js version before running any commands, especially linting and code quality tools.
26+ 
27+**To activate the correct Node.js version, run these commands first:**
28+```bash
29+export NVM_DIR="$HOME/.nvm"
30+[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
31+nvm use
32+```
33+ 
34+**Note**: These commands load nvm and switch to the project's Node.js version. You need to run them in each new terminal session.
35+ 
36+### Core Development
37+ 
38+- `yarn dev` - Start development server
39+- `yarn build` - Build for production
40+- `yarn lint` - Run ESLint
41+- `yarn type-check` - TypeScript type checking
42+ 
43+### Code Quality
44+ 
45+- `yarn clean` - Fix linting and format code (recommended after changes)
46+- `yarn lint:fix` - Auto-fix linting issues
47+- `yarn format:write` - Format code with Prettier
48+ 
49+### Database Operations
50+ 
51+- `yarn db:push` - Push schema changes to database
52+- `yarn db:generate` - Generate new migrations
53+- `yarn db:migrate` - Run pending migrations
54+ 
55+## Architecture Overview
56+ 
57+This is a full-stack Next.js application template with the following architecture:
58+ 
59+### Tech Stack
60+ 
61+- **Frontend**: Next.js 15 with App Router, React 19, TypeScript, Tailwind CSS, Shadcn/UI
62+- **Backend**: PostgreSQL with Supabase, Drizzle ORM, Next.js Server Actions
63+- **Auth**: Clerk authentication
64+- **Payments**: Stripe integration
65+- **Analytics**: PostHog
66+- **AI**: OpenAI integration
67+ 
68+### Key Architectural Patterns
69+ 
70+#### Route Organization
71+ 
72+- **Route Groups**: `(auth)` for authentication pages, `(marketing)` for public pages
73+- **Route-specific Components**: Use `_components` folder within routes for one-off components
74+- **Layouts**: Separate layouts for different route groups
75+ 
76+#### Data Layer
77+ 
78+- **Server Actions**: Located in `/actions/` directory, organized by functionality
79+- **Services**: Located in `/lib/services/` directory for complex business logic
80+- **Database Schema**: Drizzle ORM schemas in `/db/schema/`
81+- **Type Safety**: Use schema-generated types like InsertProfile and SelectProfile from your database schemas
82+ 
83+#### Data Flow Architecture
84+ 
85+Follow this layered architecture pattern:
86+ 
87+- **React Components** → **Server Actions** → **Services** (when complex logic is needed)
88+- Services handle domain-specific logic, external API integrations, and complex business rules
89+- Keep Server Actions lightweight and focused on data validation and orchestration
90+ 
91+#### Component Architecture
92+ 
93+- **UI Components**: Shadcn/UI components in `/components/ui/` (don't modify unless specified)
94+- **Shared Components**: Reusable components in `/components/`
95+- **Route-specific**: Components in `app/route/_components/`
96+ 
97+## Important Development Rules
98+ 
99+### Environment Variables
100+ 
101+- Always use centralized config: `serverConfig` and `publicEnv` from `@/lib/config`
102+- Never use `process.env` directly in application code
103+- Update `.env.example` when adding new environment variables
104+ 
105+### Import Conventions
106+ 
107+- Use `@/` for all imports from the app root
108+- Import types from `@/types`
109+- Import database types from `@/db/schema`
110+- Import services from `@/lib/services`
111+ 
112+### File Naming
113+ 
114+- Use kebab-case for all files and folders
115+- Type files: `example-types.ts` in `/types/` directory
116+- Export all types in `types/index.ts`
117+ 
118+### Code Quality Requirements
119+ 
120+- **Always use the correct Node.js version (20.12.2)** before running any code quality commands
121+- **Load nvm first**: Run the nvm commands above if you're in a new terminal session
122+- Run `yarn clean` after making changes to ensure code quality
123+- Use TypeScript interfaces over type aliases when possible
124+- Follow the existing patterns in the codebase
125+ 
126+## Coding Standards
127+ 
128+All code must adhere to these strict formatting and quality guidelines:
129+ 
130+### Syntax & Structure
131+ 
132+- File names must be dash-case (word-cloud.service.ts) unless an existing pattern differs
133+- Group imports: node/standard → npm packages → internal paths. No unused imports
134+- Use arrow functions everywhere except inside class bodies, where concise method syntax is allowed
135+- Prefer early returns; nested if/else blocks deeper than two levels are disallowed
136+- Early returns must use block format with braces (e.g., `if (!value) { return }`) for readability
137+- Extract function call results as scope variables before using in conditions (e.g., `const trimmedText = text.trim(); if (!trimmedText) {...}` instead of `if (!text.trim()) {...}`)
138+- Use async/await—never chain .then()
139+- No .forEach for side effects; use for (const x of arr) instead
140+- Array combinators (map, reduce, filter) are allowed only when you return their result
141+- Identifiers must be English
142+- No commented code allowed
143+ 
144+### Functional Programming Rules
145+ 
146+Each function must:
147+ 
148+- Be ≤ 50 lines (preferably; extract helpers if longer)
149+- Take ≤ 4 parameters (optional ones last)
150+- Have a single responsibility
151+- Be pure unless it is an intentional I/O wrapper (e.g. DB write); such wrappers must be ≤ 15 lines
152+- Name functions with camelCase imperative verbs (calculateTotals, getUserById)
153+ 
154+### Type Safety & Error Handling
155+ 
156+- Explicitly type all function parameters, return types, and exported constants
157+- Type all local variables inside a function
158+- **Special attention for async operations**: Variables from awaited functions (e.g., `const { userId } = await auth()`) must be explicitly typed, especially in Next.js components where auth results should use proper domain types
159+- No any; if an external library forces it, wrap and narrow
38160 - Error handling in catch blocks:
39− - If the error variable is not used, use `catch {}` (no parameter).
40− - If the error is used, type it as `unknown` and handle it safely within the catch block.
161+ - If the error variable is not used, use `catch {}` (no parameter)
162+ - If the error is used, type it as `unknown` and handle it safely within the catch block
41163  
42−D. React Component Standards
164+### React Component Standards
43165  
44166 - Always define props with interfaces, never inline types
45167 - Place interfaces directly above component definitions
@@ −49 +171 @@
49171 - Handler functions inside components must be ≤ 20 lines and have a single, clear responsibility. Extract helper functions for complex logic.
50172  
51173 **Wrong (~50 lines in one handler):**
174+ 
52175 ```tsx
53176 const handleFormSubmit = async (): Promise<void> => {
54177 const trimmedName: string = formData.name.trim()
55178 const trimmedEmail: string = formData.email.trim()
56179 const trimmedMessage: string = formData.message.trim()
57−
180+ 
58181 if (!trimmedName) {
59182 setErrors({ ...errors, name: "Name is required" })
60− toast({ title: "Error", description: "Name is required", variant: "destructive" })
183+ toast({
184+ title: "Error",
185+ description: "Name is required",
186+ variant: "destructive"
187+ })
61188 return
62189 }
63−
190+ 
64191 if (!trimmedEmail || !trimmedEmail.includes("@")) {
65192 setErrors({ ...errors, email: "Valid email is required" })
66− toast({ title: "Error", description: "Valid email is required", variant: "destructive" })
193+ toast({
194+ title: "Error",
195+ description: "Valid email is required",
196+ variant: "destructive"
197+ })
67198 return
68199 }
69−
200+ 
70201 if (!trimmedMessage || trimmedMessage.length < 10) {
71− setErrors({ ...errors, message: "Message must be at least 10 characters" })
72− toast({ title: "Error", description: "Message too short", variant: "destructive" })
202+ setErrors({
203+ ...errors,
204+ message: "Message must be at least 10 characters"
205+ })
206+ toast({
207+ title: "Error",
208+ description: "Message too short",
209+ variant: "destructive"
210+ })
73211 return
74212 }
75−
213+ 
76214 setIsSubmitting(true)
77215 setErrors({})
78−
216+ 
79217 try {
80218 const payload: FormPayload = {
81219 name: trimmedName,
@@ −83 +221 @@
83221 message: trimmedMessage,
84222 timestamp: new Date().toISOString()
85223 }
86−
224+ 
87225 const response: Response = await fetch("/api/contact", {
88226 method: "POST",
89227 headers: { "Content-Type": "application/json" },
90228 body: JSON.stringify(payload)
91229 })
92−
230+ 
93231 if (!response.ok) {
94232 throw new Error("Failed to submit")
95233 }
96−
234+ 
97235 const result: SubmissionResult = await response.json()
98−
236+ 
99237 setFormData({ name: "", email: "", message: "" })
100− setSubmissionCount(prev => prev + 1)
101−
238+ setSubmissionCount((prev) => prev + 1)
239+ 
102240 toast({ title: "Success", description: "Message sent successfully!" })
103−
241+ 
104242 if (onSuccess) {
105243 onSuccess(result)
106244 }
107245 } catch (error: unknown) {
108− const errorMessage: string = error instanceof Error ? error.message : "Unknown error"
246+ const errorMessage: string =
247+ error instanceof Error ? error.message : "Unknown error"
109248 console.error("Submission error:", errorMessage)
110249 setErrors({ submit: "Failed to send message" })
111− toast({ title: "Error", description: "Failed to send message", variant: "destructive" })
250+ toast({
251+ title: "Error",
252+ description: "Failed to send message",
253+ variant: "destructive"
254+ })
112255 } finally {
113256 setIsSubmitting(false)
114257 }
@@ −116 +259 @@
116259 ```
117260  
118261 **Good (broken into focused helpers ≤ 20 lines each):**
262+ 
119263 ```tsx
120264 const validateForm = (): boolean => {
121265 const trimmedName: string = formData.name.trim()
122266 const trimmedEmail: string = formData.email.trim()
123267 const trimmedMessage: string = formData.message.trim()
124−
268+ 
125269 if (!trimmedName) {
126270 setErrors({ ...errors, name: "Name is required" })
127− toast({ title: "Error", description: "Name is required", variant: "destructive" })
271+ toast({
272+ title: "Error",
273+ description: "Name is required",
274+ variant: "destructive"
275+ })
128276 return false
129277 }
130−
278+ 
131279 if (!trimmedEmail || !trimmedEmail.includes("@")) {
132280 setErrors({ ...errors, email: "Valid email is required" })
133− toast({ title: "Error", description: "Valid email is required", variant: "destructive" })
281+ toast({
282+ title: "Error",
283+ description: "Valid email is required",
284+ variant: "destructive"
285+ })
134286 return false
135287 }
136−
288+ 
137289 if (!trimmedMessage || trimmedMessage.length < 10) {
138− setErrors({ ...errors, message: "Message must be at least 10 characters" })
139− toast({ title: "Error", description: "Message too short", variant: "destructive" })
290+ setErrors({
291+ ...errors,
292+ message: "Message must be at least 10 characters"
293+ })
294+ toast({
295+ title: "Error",
296+ description: "Message too short",
297+ variant: "destructive"
298+ })
140299 return false
141300 }
142−
301+ 
143302 return true
144303 }
145−
304+ 
146305 const submitForm = async (): Promise<SubmissionResult> => {
147306 const payload: FormPayload = {
148307 name: formData.name.trim(),
@@ −150 +309 @@
150309 message: formData.message.trim(),
151310 timestamp: new Date().toISOString()
152311 }
153−
312+ 
154313 const response: Response = await fetch("/api/contact", {
155314 method: "POST",
156315 headers: { "Content-Type": "application/json" },
157316 body: JSON.stringify(payload)
158317 })
159−
318+ 
160319 if (!response.ok) {
161320 throw new Error("Failed to submit")
162321 }
163−
322+ 
164323 return response.json()
165324 }
166−
325+ 
167326 const handleSuccess = (result: SubmissionResult): void => {
168327 setFormData({ name: "", email: "", message: "" })
169328 setSubmissionCount((prev: number) => prev + 1)
170329 toast({ title: "Success", description: "Message sent successfully!" })
171−
330+ 
172331 if (onSuccess) {
173332 onSuccess(result)
174333 }
175334 }
176−
335+ 
177336 const handleError = (error: unknown): void => {
178− const errorMessage: string = error instanceof Error ? error.message : "Unknown error"
337+ const errorMessage: string =
338+ error instanceof Error ? error.message : "Unknown error"
179339 console.error("Submission error:", errorMessage)
180340 setErrors({ submit: "Failed to send message" })
181− toast({ title: "Error", description: "Failed to send message", variant: "destructive" })
341+ toast({
342+ title: "Error",
343+ description: "Failed to send message",
344+ variant: "destructive"
345+ })
182346 }
183−
347+ 
184348 const handleFormSubmit = async (): Promise<void> => {
185349 const isValid: boolean = validateForm()
186−
350+ 
187351 if (!isValid) {
188352 return
189353 }
190−
354+ 
191355 setIsSubmitting(true)
192356 setErrors({})
193−
357+ 
194358 try {
195359 const result: SubmissionResult = await submitForm()
196360 handleSuccess(result)
@@ −201 +365 @@
201365 }
202366 }
203367 ```
368+ 
204369 - Example with implicit return:
205370  
206371 ```tsx
@@ −229 +394 @@
229394  
230395 const MyComponent = ({ title, children }: MyComponentProps) => {
231396 const processedTitle = title.toUpperCase()
232−
397+ 
233398 return (
234399 <div>
235400 {processedTitle}
@@ −260 +425 @@
260425 {children}
261426 </div>
262427 )
428+ ```
263429  
264−E. Component Granularity & Organization
265−- Break down large components into smaller, focused components for better maintainability.
266−- When a component contains multiple logical sections (e.g., Card with CardHeader + CardContent), extract each section into separate components.
430+### Component Granularity & Organization
431+ 
432+- Break down large components into smaller, focused components for better maintainability
433+- When a component contains multiple logical sections (e.g., Card with CardHeader + CardContent), extract each section into separate components
267434 - Create dedicated folders for related component groups:
268− * Use kebab-case folder names matching the main component concept
269− * Place related sub-components within the same folder using kebab-case file names
270− * Example structure: `component-name/component-name-header.tsx`, `component-name/component-name-content.tsx`
271−- Each sub-component should have a single, clear responsibility.
272−- Maintain the parent component as a composition wrapper that orchestrates child components.
273−- Follow this pattern when refactoring existing components or creating new feature components.
435+ - Use kebab-case folder names matching the main component concept
436+ - Place related sub-components within the same folder using kebab-case file names
437+ - Example structure: `component-name/component-name-header.tsx`, `component-name/component-name-content.tsx`
438+- Each sub-component should have a single, clear responsibility
439+- Maintain the parent component as a composition wrapper that orchestrates child components
440+- Follow this pattern when refactoring existing components or creating new feature components
274441  
275−F. Advanced Component Architecture Patterns
442+### Advanced Component Architecture Patterns
276443  
277−F.1. Pure Functions and Constants Organization
444+#### Pure Functions and Constants Organization
445+ 
278446 - **Pure functions** (no side effects, deterministic output) must be extracted outside components:
279− * Place above the component definition
280− * Examples: `getGreeting()`, `getMembershipBadgeColor()`, `formatDate()`
447+ - Place above the component definition
448+ - Examples: `getGreeting()`, `getMembershipBadgeColor()`, `formatDate()`
281449 - **Constants and static data** must be moved outside components:
282− * Place after imports and interfaces, before pure functions
283− * Use SCREAMING_SNAKE_CASE for naming (e.g., `TEMPLATE_FEATURES`, `TECH_STACK`)
284− * **Always explicitly type constants** with appropriate type annotations
285− * Examples: `const API_URL: string = "..."`, `const MAX_RETRIES: number = 3`
286− * Use `as const` for immutable values when type inference is sufficient
287− * Group related constants together
450+ - Place after imports and interfaces, before pure functions
451+ - Use SCREAMING_SNAKE_CASE for naming (e.g., `TEMPLATE_FEATURES`, `TECH_STACK`) constants
452+ - **Always explicitly type constants** with appropriate type annotations
453+ - Examples: `const API_URL: string = "..."`, `const MAX_RETRIES: number = 3`
454+ - Use `as const` for immutable values when type inference is sufficient
455+ - Group related constants together
288456  
289−F.1.1. Custom Hooks Organization
457+#### Custom Hooks Organization
458+ 
290459 - **Custom hooks** must be extracted to separate files in the `/hooks/` directory:
291− * Use kebab-case file naming: `use-scroll-detection.ts`, `use-local-storage.ts`
292− * Start hook names with `use` prefix following React conventions
293− * Place hooks in `/hooks/` folder at project root level
294− * Export hooks using named exports: `export const useScrollDetection = () => {}`
295− * **Always explicitly type hook return values** and parameters
296− * Examples: `useScrollDetection(): boolean`, `useLocalStorage<T>(key: string): [T, (value: T) => void]`
297− * Group related hooks in the same file only if they're tightly coupled
460+ - Use kebab-case file naming: `use-scroll-detection.ts`, `use-local-storage.ts`
461+ - Start hook names with `use` prefix following React conventions
462+ - Place hooks in `/hooks/` folder at project root level
463+ - Export hooks using named exports: `export const useScrollDetection = () => {}`
464+ - **Always explicitly type hook return values** and parameters
465+ - Examples: `useScrollDetection(): boolean`, `useLocalStorage<T>(key: string): [T, (value: T) => void]`
466+ - Group related hooks in the same file only if they're tightly coupled
298467  
299−F.1.2. Whitespace and Formatting Rules
468+#### Whitespace and Formatting Rules
469+ 
300470 - **Component variable organization**: Maintain consistent whitespace between different types of declarations:
301− * Add a blank line between React state declarations and custom hook calls
302− * Add a blank line between custom hook calls and other variable declarations
303− * Example:
471+ - Add a blank line between React state declarations and custom hook calls
472+ - Add a blank line between custom hook calls and other variable declarations
473+ - Example:
474+ 
304475 ```tsx
305476 const [isMenuOpen, setIsMenuOpen] = useState<boolean>(false)
306477 const [isVisible, setIsVisible] = useState<boolean>(true)
307−
478+ 
308479 const isScrolled: boolean = useScrollDetection()
309480 const userData: UserData = useUserData()
310−
481+ 
311482 const processedData: ProcessedData = processUserData(userData)
312483 ```
313484  
314−F.2. Nested Component Structure for Complex Components
485+#### Nested Component Structure for Complex Components
486+ 
315487 When a component has multiple distinct sections, create nested folder structure:
316488  
317489 ```
318490 dashboard-welcome/
319−├── dashboard-welcome.tsx // Main orchestrator component
491+├── dashboard-welcome.tsx // Main orchestrator component
320492 ├── greeting.tsx // Self-contained greeting section
321493 ├── whats-included/ // Folder for multi-part section
322494 │ ├── whats-included.tsx // Section orchestrator
323−│ ├── whats-included-title.tsx // Title sub-component
495+│ ├── whats-included-title.tsx // Title sub-component
324496 │ └── whats-included-features.tsx // Features list sub-component
325497 ├── core-technologies/ // Folder for multi-part section
326498 │ ├── core-technologies.tsx // Section orchestrator
327499 │ ├── core-technologies-title.tsx // Title sub-component
328500 │ └── core-technologies-list.tsx // Tech list sub-component
329501 └── get-started/ // Folder for multi-part section
330− ├── get-started.tsx // Section orchestrator
502+ ├── get-started.tsx // Section orchestrator
331503 ├── get-started-title.tsx // Title sub-component
332504 ├── get-started-features.tsx // Features grid sub-component
333505 └── get-started-feature-2.tsx // Individual feature card
334506 ```
335507  
336−F.3. Component Organization Rules
508+#### Component Organization Rules
509+ 
337510 1. **Main orchestrator**: Composition only, minimal logic, imports and renders sub-components
338−2. **Section orchestrators**: Handle section-specific logic, render related sub-components
511+2. **Section orchestrators**: Handle section-specific logic, render related sub-components
339512 3. **Leaf components**: Single responsibility, pure presentation, accept props only
340513 4. **Shared constants**: Extract to file level, use proper naming conventions
341514 5. **Pure functions**: Extract above component definitions, properly typed
342515 6. **File structure**: Mirror logical component hierarchy in folder structure
343516  
344−</coding_format>
517+### Application Guidelines
345518  
346−<usage_guidelines>
519+1. Apply these standards to all new code and when refactoring existing code
520+2. When making any code changes, ensure they conform to these guidelines
521+3. If existing code doesn't follow these standards, update it to comply when modifying those files
522+4. Use these standards as a checklist when reviewing code changes
523+5. Prefer extracting helper functions over writing long, complex functions
524+6. Always prioritize code readability and maintainability
347525  
348−1. Apply these standards to all new code and when refactoring existing code.
349−2. When making any code changes, ensure they conform to these guidelines.
350−3. If existing code doesn't follow these standards, update it to comply when modifying those files.
351−4. Use these standards as a checklist when reviewing code changes.
352−5. Prefer extracting helper functions over writing long, complex functions.
353−6. Always prioritize code readability and maintainability.
526+## Database Schema
354527  
355−</usage_guidelines>
528+### Current Tables
529+ 
530+- **Profiles**: User profiles with Stripe integration and membership tiers
531+ 
532+### Schema Location
533+ 
534+- Schemas: `/db/schema/`
535+- Migrations: `/db/migrations/`
536+- Database connection: `/db/db.ts`
537+ 
538+## Testing and Deployment
539+ 
540+- The project uses Vercel for deployment
541+- No specific test framework is configured - check with user if testing is needed
542+- Always run `yarn build` and `yarn type-check` before considering work complete
543+ 
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