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-storage ↔ 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
Sections015270%
Commands00100%
Section tags30827%

What each file covers

Sections

0 shared · 15 only in A · 27 only in B
  • − Storage Rules
  • − General Rules
  • − Organization
  • − Buckets
  • − File Structure
  • − Actions
  • − File Handling
  • − Upload Rules
  • − Download Rules
  • − Delete Rules
  • − Security
  • − Bucket Policies
  • − Access Control
  • − Error Handling
  • − Optimization
  • + 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
  • + code-style
  • + types
  • + database
  • + ui
  • + agent-behaviour
  •   architecture
  •   security
  •   do-not

Line diff

+500 added−120 removed43 unchanged7.9% identical
sportiz91/vibe-template · .cursor/rules/storage.mdc
@@ −1 @@
1---
2description: Follow these rules when working on file storage.
3globs:
4---
5# Storage Rules
6 
7Follow these rules when working with Supabase Storage.
8 
9It uses Supabase Storage for file uploads, downloads, and management.
10 
11## General Rules
12 
13- Always use environment variables for bucket names to maintain consistency across environments
14- Never hardcode bucket names in the application code
15- Always handle file size limits and allowed file types at the application level
16- Use the `upsert` method instead of `upload` when you want to replace existing files
17- Always implement proper error handling for storage operations
18- Use content-type headers when uploading files to ensure proper file handling
19 
20## Organization
 
 
 
 
 
 
21 
22### Buckets
23 
24- Name buckets in kebab-case: `user-uploads`, `profile-images`
25- Create separate buckets for different types of files (e.g., `profile-images`, `documents`, `attachments`)
26- Document bucket purposes in a central location
27- Set appropriate bucket policies (public/private) based on access requirements
28- Implement RLS (Row Level Security) policies for buckets that need user-specific access
29- Make sure to let me know instructions for setting up RLS policies on Supabase since you can't do this yourself, including the SQL scripts I need to run in the editor
30 
31### File Structure
32 
33- Organize files in folders based on their purpose and ownership
34- Use predictable, collision-resistant naming patterns
35- Structure: `{bucket}/{userId}/{purpose}/{filename}`
36- Example: `profile-images/123e4567-e89b/avatar/profile.jpg`
37- Include timestamps in filenames when version history is important
38- Example: `documents/123e4567-e89b/contracts/2024-02-13-contract.pdf`
39 
40## Actions
 
 
 
 
 
41 
42- When importing storage actions, use `@/actions/storage`
43- Name files like `example-storage-actions.ts`
44- Include Storage at the end of function names `Ex: uploadFile -> uploadFileStorage`
45- Follow the same ActionState pattern as DB actions
46 
47Example of a storage action:
48 
49```ts
50"use server"
 
 
51 
52import { createClientComponentClient } from "@supabase/auth-helpers-nextjs"
53import { ActionState } from "@/types"
54 
55export async function uploadFileStorage(
56 bucket: string,
57 path: string,
58 file: File
59): Promise<ActionState<{ path: string }>> {
60 try {
61 const supabase = createClientComponentClient()
62
63 const { data, error } = await supabase
64 .storage
65 .from(bucket)
66 .upload(path, file, {
67 upsert: false,
68 contentType: file.type
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69 })
 
 
70 
71 if (error) throw error
 
 
 
 
 
 
 
 
72 
73 return {
74 isSuccess: true,
75 message: "File uploaded successfully",
76 data: { path: data.path }
 
 
 
 
 
 
 
77 }
78 } catch (error) {
79 console.error("Error uploading file:", error)
80 return { isSuccess: false, message: "Failed to upload file" }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81 }
82}
83```
84 
85## File Handling
86 
87### Upload Rules
 
 
 
 
88 
89- Always validate file size before upload
90- Implement file type validation using both extension and MIME type
91- Generate unique filenames to prevent collisions
92- Set appropriate content-type headers
93- Handle existing files appropriately (error or upsert)
 
 
 
 
94 
95Example validation:
 
 
 
 
 
 
 
 
96 
97```ts
98const MAX_FILE_SIZE = 10 * 1024 * 1024 // 10MB
99const ALLOWED_TYPES = ["image/jpeg", "image/png", "image/webp"]
 
 
 
 
 
 
 
 
 
100 
101function validateFile(file: File): boolean {
102 if (file.size > MAX_FILE_SIZE) {
103 throw new Error("File size exceeds limit")
104 }
105
106 if (!ALLOWED_TYPES.includes(file.type)) {
107 throw new Error("File type not allowed")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108 }
109
110 return true
111}
112```
113 
114### Download Rules
 
 
 
115 
116- Always handle missing files gracefully
117- Implement proper error handling for failed downloads
118- Use signed URLs for private files
 
119 
120### Delete Rules
 
 
 
 
 
 
 
 
 
 
121 
122- Implement soft deletes when appropriate
123- Clean up related database records when deleting files
124- Handle bulk deletions carefully
125- Verify ownership before deletion
126- Always delete all versions/transforms of a file
127 
128## Security
 
 
129 
130### Bucket Policies
 
131 
132- Make buckets private by default
133- Only make buckets public when absolutely necessary
134- Use RLS policies to restrict access to authorized users
135- Example RLS policy:
 
 
 
 
 
 
136 
137```sql
138CREATE POLICY "Users can only access their own files"
139ON storage.objects
140FOR ALL
141USING (auth.uid()::text = (storage.foldername(name))[1]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143 
144### Access Control
145 
146- Generate short-lived signed URLs for private files
147- Implement proper CORS policies
148- Use separate buckets for public and private files
149- Never expose internal file paths
150- Validate user permissions before any operation
 
151 
152## Error Handling
153 
154- Implement specific error types for common storage issues
155- Always provide meaningful error messages
156- Implement retry logic for transient failures
157- Log storage errors separately for monitoring
 
 
158 
159## Optimization
160 
161- Implement progressive upload for large files
162- Clean up temporary files and failed uploads
163- Use batch operations when handling multiple files
 
 
 
 
 
 
 
 
 
 
 
 
 
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
168- Use const arrow functions for component definitions
169- Use implicit return syntax when components only return JSX (no logic before return)
170- Export components using export default pattern (required for Next.js pages/layouts)
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,
220 email: trimmedEmail,
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 }
258 }
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(),
308 email: formData.email.trim(),
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)
361 } catch (error: unknown) {
362 handleError(error)
363 } finally {
364 setIsSubmitting(false)
365 }
366 }
367 ```
368 
369- Example with implicit return:
370 
371 ```tsx
372 interface MyComponentProps {
373 title: string
374 children: React.ReactNode
375 }
376 
377 const MyComponent = ({ title, children }: MyComponentProps) => (
378 <div>
379 {title}
380 {children}
381 </div>
382 )
383 
384 export default MyComponent
385 ```
386 
387- Example with explicit return (when logic is present):
388 
389 ```tsx
390 interface MyComponentProps {
391 title: string
392 children: React.ReactNode
393 }
394 
395 const MyComponent = ({ title, children }: MyComponentProps) => {
396 const processedTitle = title.toUpperCase()
397 
398 return (
399 <div>
400 {processedTitle}
401 {children}
402 </div>
403 )
404 }
405 
406 export default MyComponent
407 ```
408 
409- Normal components that are not Next.js pages/layouts should be exported
410 using export const pattern
411- Example with implicit return:
412 
413 ```tsx
414 interface NotAPageOrLayoutComponentProps {
415 title: string
416 children: React.ReactNode
417 }
418 
419 export const NotAPageOrLayoutComponent = ({
420 title,
421 children
422 }: NotAPageOrLayoutComponentProps) => (
423 <div>
424 {title}
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: Follow these rules when working on file storage.
3−globs:
4−---
5−# Storage Rules
1+# CLAUDE.md
62  
7−Follow these rules when working with Supabase Storage.
3+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
84  
9−It uses Supabase Storage for file uploads, downloads, and management.
5+## Standard Worflow
106  
11−## General Rules
7+Use this workflow when working on a new task:
128  
13−- Always use environment variables for bucket names to maintain consistency across environments
14−- Never hardcode bucket names in the application code
15−- Always handle file size limits and allowed file types at the application level
16−- Use the `upsert` method instead of `upload` when you want to replace existing files
17−- Always implement proper error handling for storage operations
18−- Use content-type headers when uploading files to ensure proper file handling
9+### Workflow when working on a new task:
1910  
20−## Organization
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.
2118  
22−### Buckets
19+Periodically make sure to commit when it makes sense to do so.
2320  
24−- Name buckets in kebab-case: `user-uploads`, `profile-images`
25−- Create separate buckets for different types of files (e.g., `profile-images`, `documents`, `attachments`)
26−- Document bucket purposes in a central location
27−- Set appropriate bucket policies (public/private) based on access requirements
28−- Implement RLS (Row Level Security) policies for buckets that need user-specific access
29−- Make sure to let me know instructions for setting up RLS policies on Supabase since you can't do this yourself, including the SQL scripts I need to run in the editor
21+## Development Commands
3022  
31−### File Structure
23+**Important: This project uses yarn, not npm. Always use yarn commands.**
3224  
33−- Organize files in folders based on their purpose and ownership
34−- Use predictable, collision-resistant naming patterns
35−- Structure: `{bucket}/{userId}/{purpose}/{filename}`
36−- Example: `profile-images/123e4567-e89b/avatar/profile.jpg`
37−- Include timestamps in filenames when version history is important
38−- Example: `documents/123e4567-e89b/contracts/2024-02-13-contract.pdf`
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.
3926  
40−## Actions
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+```
4133  
42−- When importing storage actions, use `@/actions/storage`
43−- Name files like `example-storage-actions.ts`
44−- Include Storage at the end of function names `Ex: uploadFile -> uploadFileStorage`
45−- Follow the same ActionState pattern as DB actions
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.
4635  
47−Example of a storage action:
36+### Core Development
4837  
49−```ts
50−"use server"
38+- `yarn dev` - Start development server
39+- `yarn build` - Build for production
40+- `yarn lint` - Run ESLint
41+- `yarn type-check` - TypeScript type checking
5142  
52−import { createClientComponentClient } from "@supabase/auth-helpers-nextjs"
53−import { ActionState } from "@/types"
43+### Code Quality
5444  
55−export async function uploadFileStorage(
56− bucket: string,
57− path: string,
58− file: File
59−): Promise<ActionState<{ path: string }>> {
60− try {
61− const supabase = createClientComponentClient()
62−
63− const { data, error } = await supabase
64− .storage
65− .from(bucket)
66− .upload(path, file, {
67− upsert: false,
68− contentType: file.type
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
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
168+- Use const arrow functions for component definitions
169+- Use implicit return syntax when components only return JSX (no logic before return)
170+- Export components using export default pattern (required for Next.js pages/layouts)
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"
69187 })
188+ return
189+ }
70190  
71− if (error) throw error
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+ }
72200  
73− return {
74− isSuccess: true,
75− message: "File uploaded successfully",
76− data: { path: data.path }
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
77212 }
78− } catch (error) {
79− console.error("Error uploading file:", error)
80− return { isSuccess: false, message: "Failed to upload file" }
213+ 
214+ setIsSubmitting(true)
215+ setErrors({})
216+ 
217+ try {
218+ const payload: FormPayload = {
219+ name: trimmedName,
220+ email: trimmedEmail,
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+ }
81258 }
82−}
83−```
259+ ```
84260  
85−## File Handling
261+ **Good (broken into focused helpers ≤ 20 lines each):**
86262  
87−### Upload Rules
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()
88268  
89−- Always validate file size before upload
90−- Implement file type validation using both extension and MIME type
91−- Generate unique filenames to prevent collisions
92−- Set appropriate content-type headers
93−- Handle existing files appropriately (error or upsert)
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+ }
94278  
95−Example validation:
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+ }
96288  
97−```ts
98−const MAX_FILE_SIZE = 10 * 1024 * 1024 // 10MB
99−const ALLOWED_TYPES = ["image/jpeg", "image/png", "image/webp"]
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+ }
100301  
101−function validateFile(file: File): boolean {
102− if (file.size > MAX_FILE_SIZE) {
103− throw new Error("File size exceeds limit")
302+ return true
104303 }
105−
106− if (!ALLOWED_TYPES.includes(file.type)) {
107− throw new Error("File type not allowed")
304+ 
305+ const submitForm = async (): Promise<SubmissionResult> => {
306+ const payload: FormPayload = {
307+ name: formData.name.trim(),
308+ email: formData.email.trim(),
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()
108324 }
109−
110− return true
111−}
112−```
113325  
114−### Download Rules
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!" })
115330  
116−- Always handle missing files gracefully
117−- Implement proper error handling for failed downloads
118−- Use signed URLs for private files
331+ if (onSuccess) {
332+ onSuccess(result)
333+ }
334+ }
119335  
120−### Delete Rules
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+ }
121347  
122−- Implement soft deletes when appropriate
123−- Clean up related database records when deleting files
124−- Handle bulk deletions carefully
125−- Verify ownership before deletion
126−- Always delete all versions/transforms of a file
348+ const handleFormSubmit = async (): Promise<void> => {
349+ const isValid: boolean = validateForm()
127350  
128−## Security
351+ if (!isValid) {
352+ return
353+ }
129354  
130−### Bucket Policies
355+ setIsSubmitting(true)
356+ setErrors({})
131357  
132−- Make buckets private by default
133−- Only make buckets public when absolutely necessary
134−- Use RLS policies to restrict access to authorized users
135−- Example RLS policy:
358+ try {
359+ const result: SubmissionResult = await submitForm()
360+ handleSuccess(result)
361+ } catch (error: unknown) {
362+ handleError(error)
363+ } finally {
364+ setIsSubmitting(false)
365+ }
366+ }
367+ ```
136368  
137−```sql
138−CREATE POLICY "Users can only access their own files"
139−ON storage.objects
140−FOR ALL
141−USING (auth.uid()::text = (storage.foldername(name))[1]);
369+- Example with implicit return:
370+ 
371+ ```tsx
372+ interface MyComponentProps {
373+ title: string
374+ children: React.ReactNode
375+ }
376+ 
377+ const MyComponent = ({ title, children }: MyComponentProps) => (
378+ <div>
379+ {title}
380+ {children}
381+ </div>
382+ )
383+ 
384+ export default MyComponent
385+ ```
386+ 
387+- Example with explicit return (when logic is present):
388+ 
389+ ```tsx
390+ interface MyComponentProps {
391+ title: string
392+ children: React.ReactNode
393+ }
394+ 
395+ const MyComponent = ({ title, children }: MyComponentProps) => {
396+ const processedTitle = title.toUpperCase()
397+ 
398+ return (
399+ <div>
400+ {processedTitle}
401+ {children}
402+ </div>
403+ )
404+ }
405+ 
406+ export default MyComponent
407+ ```
408+ 
409+- Normal components that are not Next.js pages/layouts should be exported
410+ using export const pattern
411+- Example with implicit return:
412+ 
413+ ```tsx
414+ interface NotAPageOrLayoutComponentProps {
415+ title: string
416+ children: React.ReactNode
417+ }
418+ 
419+ export const NotAPageOrLayoutComponent = ({
420+ title,
421+ children
422+ }: NotAPageOrLayoutComponentProps) => (
423+ <div>
424+ {title}
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+ 
487+When a component has multiple distinct sections, create nested folder structure:
488+ 
142489 ```
490+dashboard-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+```
143507  
144−### Access Control
508+#### Component Organization Rules
145509  
146−- Generate short-lived signed URLs for private files
147−- Implement proper CORS policies
148−- Use separate buckets for public and private files
149−- Never expose internal file paths
150−- Validate user permissions before any operation
510+1. **Main orchestrator**: Composition only, minimal logic, imports and renders sub-components
511+2. **Section orchestrators**: Handle section-specific logic, render related sub-components
512+3. **Leaf components**: Single responsibility, pure presentation, accept props only
513+4. **Shared constants**: Extract to file level, use proper naming conventions
514+5. **Pure functions**: Extract above component definitions, properly typed
515+6. **File structure**: Mirror logical component hierarchy in folder structure
151516  
152−## Error Handling
517+### Application Guidelines
153518  
154−- Implement specific error types for common storage issues
155−- Always provide meaningful error messages
156−- Implement retry logic for transient failures
157−- Log storage errors separately for monitoring
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
158525  
159−## Optimization
526+## Database Schema
160527  
161−- Implement progressive upload for large files
162−- Clean up temporary files and failed uploads
163−- Use batch operations when handling multiple files
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