

Also from Kynth Studios


Also from Kynth Studios


Also from Kynth Studios
1# CLAUDE.md23This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.45## Standard Worflow67Use this workflow when working on a new task:89### Workflow when working on a new task:10111. First, think through the problem, read the codebase for relevant files, and12 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 changes17 you made and any other relevant information.1819Periodically make sure to commit when it makes sense to do so.2021## Development Commands2223**Important: This project uses yarn, not npm. Always use yarn commands.**2425**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.2627**To activate the correct Node.js version, run these commands first:**28```bash29export NVM_DIR="$HOME/.nvm"30[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"31nvm use32```3334**Note**: These commands load nvm and switch to the project's Node.js version. You need to run them in each new terminal session.3536### Core Development3738- `yarn dev` - Start development server39- `yarn build` - Build for production40- `yarn lint` - Run ESLint41- `yarn type-check` - TypeScript type checking4243### Code Quality4445- `yarn clean` - Fix linting and format code (recommended after changes)46- `yarn lint:fix` - Auto-fix linting issues47- `yarn format:write` - Format code with Prettier4849### Database Operations5051- `yarn db:push` - Push schema changes to database52- `yarn db:generate` - Generate new migrations53- `yarn db:migrate` - Run pending migrations5455## Architecture Overview5657This is a full-stack Next.js application template with the following architecture:5859### Tech Stack6061- **Frontend**: Next.js 15 with App Router, React 19, TypeScript, Tailwind CSS, Shadcn/UI62- **Backend**: PostgreSQL with Supabase, Drizzle ORM, Next.js Server Actions63- **Auth**: Clerk authentication64- **Payments**: Stripe integration65- **Analytics**: PostHog66- **AI**: OpenAI integration6768### Key Architectural Patterns6970#### Route Organization7172- **Route Groups**: `(auth)` for authentication pages, `(marketing)` for public pages73- **Route-specific Components**: Use `_components` folder within routes for one-off components74- **Layouts**: Separate layouts for different route groups7576#### Data Layer7778- **Server Actions**: Located in `/actions/` directory, organized by functionality79- **Services**: Located in `/lib/services/` directory for complex business logic80- **Database Schema**: Drizzle ORM schemas in `/db/schema/`81- **Type Safety**: Use schema-generated types like InsertProfile and SelectProfile from your database schemas8283#### Data Flow Architecture8485Follow this layered architecture pattern:8687- **React Components** → **Server Actions** → **Services** (when complex logic is needed)88- Services handle domain-specific logic, external API integrations, and complex business rules89- Keep Server Actions lightweight and focused on data validation and orchestration9091#### Component Architecture9293- **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/`9697## Important Development Rules9899### Environment Variables100101- Always use centralized config: `serverConfig` and `publicEnv` from `@/lib/config`102- Never use `process.env` directly in application code103- Update `.env.example` when adding new environment variables104105### Import Conventions106107- Use `@/` for all imports from the app root108- Import types from `@/types`109- Import database types from `@/db/schema`110- Import services from `@/lib/services`111112### File Naming113114- Use kebab-case for all files and folders115- Type files: `example-types.ts` in `/types/` directory116- Export all types in `types/index.ts`117118### Code Quality Requirements119120- **Always use the correct Node.js version (20.12.2)** before running any code quality commands121- **Load nvm first**: Run the nvm commands above if you're in a new terminal session122- Run `yarn clean` after making changes to ensure code quality123- Use TypeScript interfaces over type aliases when possible124- Follow the existing patterns in the codebase125126## Coding Standards127128All code must adhere to these strict formatting and quality guidelines:129130### Syntax & Structure131132- File names must be dash-case (word-cloud.service.ts) unless an existing pattern differs133- Group imports: node/standard → npm packages → internal paths. No unused imports134- Use arrow functions everywhere except inside class bodies, where concise method syntax is allowed135- Prefer early returns; nested if/else blocks deeper than two levels are disallowed136- Early returns must use block format with braces (e.g., `if (!value) { return }`) for readability137- 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) instead140- Array combinators (map, reduce, filter) are allowed only when you return their result141- Identifiers must be English142- No commented code allowed143144### Functional Programming Rules145146Each function must:147148- Be ≤ 50 lines (preferably; extract helpers if longer)149- Take ≤ 4 parameters (optional ones last)150- Have a single responsibility151- Be pure unless it is an intentional I/O wrapper (e.g. DB write); such wrappers must be ≤ 15 lines152- Name functions with camelCase imperative verbs (calculateTotals, getUserById)153154### Type Safety & Error Handling155156- Explicitly type all function parameters, return types, and exported constants157- Type all local variables inside a function158- **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 types159- No any; if an external library forces it, wrap and narrow160- 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 block163164### React Component Standards165166- Always define props with interfaces, never inline types167- Place interfaces directly above component definitions168- Use const arrow functions for component definitions169- 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.172173 **Wrong (~50 lines in one handler):**174175```tsx176 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()180181 if (!trimmedName) {182 setErrors({ ...errors, name: "Name is required" })183 toast({184 title: "Error",185 description: "Name is required",186 variant: "destructive"187 })188 return189 }190191 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 return199 }200201 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 return212 }213214 setIsSubmitting(true)215 setErrors({})216217 try {218 const payload: FormPayload = {219 name: trimmedName,220 email: trimmedEmail,221 message: trimmedMessage,222 timestamp: new Date().toISOString()223 }224225 const response: Response = await fetch("/api/contact", {226 method: "POST",227 headers: { "Content-Type": "application/json" },228 body: JSON.stringify(payload)229 })230231 if (!response.ok) {232 throw new Error("Failed to submit")233 }234235 const result: SubmissionResult = await response.json()236237 setFormData({ name: "", email: "", message: "" })238 setSubmissionCount((prev) => prev + 1)239240 toast({ title: "Success", description: "Message sent successfully!" })241242 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```260261 **Good (broken into focused helpers ≤ 20 lines each):**262263```tsx264 const validateForm = (): boolean => {265 const trimmedName: string = formData.name.trim()266 const trimmedEmail: string = formData.email.trim()267 const trimmedMessage: string = formData.message.trim()268269 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 false277 }278279 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 false287 }288289 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 false300 }301302 return true303 }304305 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 }312313 const response: Response = await fetch("/api/contact", {314 method: "POST",315 headers: { "Content-Type": "application/json" },316 body: JSON.stringify(payload)317 })318319 if (!response.ok) {320 throw new Error("Failed to submit")321 }322323 return response.json()324 }325326 const handleSuccess = (result: SubmissionResult): void => {327 setFormData({ name: "", email: "", message: "" })328 setSubmissionCount((prev: number) => prev + 1)329 toast({ title: "Success", description: "Message sent successfully!" })330331 if (onSuccess) {332 onSuccess(result)333 }334 }335336 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 }347348 const handleFormSubmit = async (): Promise<void> => {349 const isValid: boolean = validateForm()350351 if (!isValid) {352 return353 }354355 setIsSubmitting(true)356 setErrors({})357358 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```368369- Example with implicit return:370371```tsx372 interface MyComponentProps {373 title: string374 children: React.ReactNode375 }376377 const MyComponent = ({ title, children }: MyComponentProps) => (378 <div>379 {title}380 {children}381 </div>382 )383384 export default MyComponent385```386387- Example with explicit return (when logic is present):388389```tsx390 interface MyComponentProps {391 title: string392 children: React.ReactNode393 }394395 const MyComponent = ({ title, children }: MyComponentProps) => {396 const processedTitle = title.toUpperCase()397398 return (399 <div>400 {processedTitle}401 {children}402 </div>403 )404 }405406 export default MyComponent407```408409- Normal components that are not Next.js pages/layouts should be exported410 using export const pattern411- Example with implicit return:412413```tsx414 interface NotAPageOrLayoutComponentProps {415 title: string416 children: React.ReactNode417 }418419 export const NotAPageOrLayoutComponent = ({420 title,421 children422 }: NotAPageOrLayoutComponentProps) => (423 <div>424 {title}425 {children}426 </div>427 )428```429430### Component Granularity & Organization431432- Break down large components into smaller, focused components for better maintainability433- When a component contains multiple logical sections (e.g., Card with CardHeader + CardContent), extract each section into separate components434- Create dedicated folders for related component groups:435 - Use kebab-case folder names matching the main component concept436 - Place related sub-components within the same folder using kebab-case file names437 - Example structure: `component-name/component-name-header.tsx`, `component-name/component-name-content.tsx`438- Each sub-component should have a single, clear responsibility439- Maintain the parent component as a composition wrapper that orchestrates child components440- Follow this pattern when refactoring existing components or creating new feature components441442### Advanced Component Architecture Patterns443444#### Pure Functions and Constants Organization445446- **Pure functions** (no side effects, deterministic output) must be extracted outside components:447 - Place above the component definition448 - Examples: `getGreeting()`, `getMembershipBadgeColor()`, `formatDate()`449- **Constants and static data** must be moved outside components:450 - Place after imports and interfaces, before pure functions451 - Use SCREAMING_SNAKE_CASE for naming (e.g., `TEMPLATE_FEATURES`, `TECH_STACK`) constants452 - **Always explicitly type constants** with appropriate type annotations453 - Examples: `const API_URL: string = "..."`, `const MAX_RETRIES: number = 3`454 - Use `as const` for immutable values when type inference is sufficient455 - Group related constants together456457#### Custom Hooks Organization458459- **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 conventions462 - Place hooks in `/hooks/` folder at project root level463 - Export hooks using named exports: `export const useScrollDetection = () => {}`464 - **Always explicitly type hook return values** and parameters465 - Examples: `useScrollDetection(): boolean`, `useLocalStorage<T>(key: string): [T, (value: T) => void]`466 - Group related hooks in the same file only if they're tightly coupled467468#### Whitespace and Formatting Rules469470- **Component variable organization**: Maintain consistent whitespace between different types of declarations:471 - Add a blank line between React state declarations and custom hook calls472 - Add a blank line between custom hook calls and other variable declarations473 - Example:474475```tsx476 const [isMenuOpen, setIsMenuOpen] = useState<boolean>(false)477 const [isVisible, setIsVisible] = useState<boolean>(true)478479 const isScrolled: boolean = useScrollDetection()480 const userData: UserData = useUserData()481482 const processedData: ProcessedData = processUserData(userData)483```484485#### Nested Component Structure for Complex Components486487When a component has multiple distinct sections, create nested folder structure:488489```490dashboard-welcome/491├── dashboard-welcome.tsx // Main orchestrator component492├── greeting.tsx // Self-contained greeting section493├── whats-included/ // Folder for multi-part section494│ ├── whats-included.tsx // Section orchestrator495│ ├── whats-included-title.tsx // Title sub-component496│ └── whats-included-features.tsx // Features list sub-component497├── core-technologies/ // Folder for multi-part section498│ ├── core-technologies.tsx // Section orchestrator499│ ├── core-technologies-title.tsx // Title sub-component500│ └── core-technologies-list.tsx // Tech list sub-component501└── get-started/ // Folder for multi-part section502 ├── get-started.tsx // Section orchestrator503 ├── get-started-title.tsx // Title sub-component504 ├── get-started-features.tsx // Features grid sub-component505 └── get-started-feature-2.tsx // Individual feature card506```507508#### Component Organization Rules5095101. **Main orchestrator**: Composition only, minimal logic, imports and renders sub-components5112. **Section orchestrators**: Handle section-specific logic, render related sub-components5123. **Leaf components**: Single responsibility, pure presentation, accept props only5134. **Shared constants**: Extract to file level, use proper naming conventions5145. **Pure functions**: Extract above component definitions, properly typed5156. **File structure**: Mirror logical component hierarchy in folder structure516517### Application Guidelines5185191. Apply these standards to all new code and when refactoring existing code5202. When making any code changes, ensure they conform to these guidelines5213. If existing code doesn't follow these standards, update it to comply when modifying those files5224. Use these standards as a checklist when reviewing code changes5235. Prefer extracting helper functions over writing long, complex functions5246. Always prioritize code readability and maintainability525526## Database Schema527528### Current Tables529530- **Profiles**: User profiles with Stripe integration and membership tiers531532### Schema Location533534- Schemas: `/db/schema/`535- Migrations: `/db/migrations/`536- Database connection: `/db/db.ts`537538## Testing and Deployment539540- The project uses Vercel for deployment541- No specific test framework is configured - check with user if testing is needed542- Always run `yarn build` and `yarn type-check` before considering work complete543
One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| sportiz91/vibe-template.cursor/rules/auth.mdc · 9 | Cursor rules | securitydo-not | 32/100 | 14 days ago | |
| sportiz91/vibe-template.cursor/rules/storage.mdc · 9 | Cursor rules | archsecuritydo-not | 65/100 | 14 days ago | |
| sportiz91/vibe-template.cursor/rules/backend.mdc · 9 | Cursor rules | do-not | 61/100 | 14 days ago | |
| sportiz91/vibe-template.cursor/rules/coding-standards.mdc · 9 | Cursor rules | styletypesui | 36/100 | 14 days ago | |
| sportiz91/vibe-template.cursor/rules/frontend.mdc · 9 | Cursor rules | do-not | 61/100 | 14 days ago | |
| sportiz91/vibe-template.cursor/rules/general.mdc · 9 | Cursor rules | stylearchsecuritydo-not+1 | 69/100 | 14 days ago | |
| sportiz91/vibe-template.cursorrules · 9 | .cursorrules | stylearchsecuritydo-not+1 | 49/100 | 14 days ago |
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| bagisto/bagistoCLAUDE.md · 28k | CLAUDE.md | setupbuildteststyle+5 | 100/100 | 7 days ago | |
| Adit-Jain-srm/NightmareNetCLAUDE.md · 46 | CLAUDE.md | buildtestlint-formatstyle+6 | 100/100 | 14 days ago | |
| tyrchen/geektime-bootcamp-aiw7/genslides/backend/CLAUDE.md · 230 | CLAUDE.md | testlint-formatstylearch+6 | 100/100 | 9 days ago | |
| nimbalyst/nimbalystpackages/android/CLAUDE.md · 1.5k | CLAUDE.md | setupbuildstylearch+2 | 100/100 | 14 days ago | |
| dotCMS/corecore-web/CLAUDE.md · 949 | CLAUDE.md | teststylearchtesting-strategy+3 | 100/100 | 14 days ago | |
| microsoft/playwrightCLAUDE.md · 95k | CLAUDE.md | buildtestlint-formatstyle+7 | 100/100 | 7 days ago | |
| tphakala/birdnet-goCLAUDE.md · 1.6k | CLAUDE.md | buildtestlint-formatstyle+8 | 100/100 | today | |
| dotCMS/coreCLAUDE.md · 949 | CLAUDE.md | setupbuildteststyle+7 | 99/100 | today |
A badge carrying the measured quality of the strongest agent config file in this repository, out of 100. It reads from this index every time somebody loads your page, so it changes when the measurement changes and there is nothing to keep up to date. Free, no account, and the value is not something you or we can set by hand.
[](https://rulestack.kynth.studio/configs/sportiz91-vibe-template-claude)Would rather not hotlink us? Every badge is also served in shields.io’s endpoint schema, so shields renders the image and your readers never talk to our domain:
Published by Toolproof, the masthead over this index and eight others. The method behind the number is at toolproof.kynth.studio/methodology, and the whole thing is readable as JSON with no key at /api.