├── .cursor └── rules │ ├── community-projects.mdc │ ├── conventional-commits.mdc │ ├── conversation-style.mdc │ ├── cursor-rules-location.mdc │ ├── file-organization.mdc │ ├── git-commit-workflow.mdc │ ├── naming-conventions.mdc │ └── solid-principles.mdc ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── conversation-style.mdc ├── git-commit-workflow.mdc ├── nextjs ├── async-params.mdc ├── code-review.mdc ├── data-access.mdc ├── naming-conventions.mdc ├── nextjs-15.mdc ├── server-actions.mdc ├── shadcn.mdc ├── solid-principles.mdc └── tailwindcss-4.mdc ├── open-source ├── community-projects.mdc └── conventional-commits.mdc ├── supabase ├── drizzle-migrations.mdc ├── drizzle-queries.mdc ├── supabase-bootstrap-with-auth.mdc ├── supabase-create-functions.mdc ├── supabase-create-migration.mdc ├── supabase-drizzle-bootstrap.mdc ├── supabase-postgres-style-guide.mdc ├── supabase-rls-policies.mdc └── supabase-writing-edge-functions.mdc └── task-master ├── cursor_rules.mdc ├── dev_workflow.mdc └── self_improve.mdc /.cursor/rules/community-projects.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Ensures proper setup of community project files and 3 | globs: 4 | --- 5 | # Community Projects Rule 6 | Standards for initializing and maintaining community-focused open source projects. 7 | 8 | 9 | name: community_projects 10 | description: Ensures proper setup of community project files and documentation 11 | filters: 12 | - type: event 13 | pattern: "project_init|project_validate" 14 | - type: directory 15 | pattern: ".*" 16 | 17 | actions: 18 | - type: validate 19 | description: "Validate required community files" 20 | requirements: 21 | - name: "README.md" 22 | required: true 23 | content: 24 | - "Project title and description" 25 | - "Installation instructions" 26 | - "Usage examples" 27 | - "Contributing guidelines reference" 28 | - "License reference" 29 | - name: "CONTRIBUTING.md" 30 | required: true 31 | content: 32 | - "How to contribute" 33 | - "Development setup" 34 | - "Pull request process" 35 | - "Code style guidelines" 36 | - "Testing requirements" 37 | - name: "LICENSE" 38 | required: true 39 | content: 40 | - "Valid open source license text" 41 | - "Current year" 42 | - "Copyright holder information" 43 | - name: "CODE_OF_CONDUCT.md" 44 | required: true 45 | content: 46 | - "Expected behavior" 47 | - "Unacceptable behavior" 48 | - "Reporting process" 49 | - "Enforcement guidelines" 50 | - "Contact information" 51 | 52 | - type: suggest 53 | message: | 54 | When setting up a community project, ensure: 55 | 56 | 1. README.md contains: 57 | ```markdown 58 | # Project Name 59 | 60 | Brief description of the project. 61 | 62 | ## Installation 63 | 64 | Step-by-step installation instructions. 65 | 66 | ## Usage 67 | 68 | Basic usage examples. 69 | 70 | ## Contributing 71 | 72 | Please read [CONTRIBUTING.md](mdc:CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests. 73 | 74 | ## License 75 | 76 | This project is licensed under the [LICENSE_NAME] - see the [LICENSE](mdc:LICENSE) file for details. 77 | ``` 78 | 79 | 2. CONTRIBUTING.md contains: 80 | ```markdown 81 | # Contributing Guidelines 82 | 83 | ## Development Setup 84 | [Development environment setup instructions] 85 | 86 | ## Pull Request Process 87 | 1. Update documentation 88 | 2. Update tests 89 | 3. Follow code style 90 | 4. Get reviews 91 | 92 | ## Code Style 93 | [Code style guidelines] 94 | 95 | ## Testing 96 | [Testing requirements and instructions] 97 | ``` 98 | 99 | 3. LICENSE file: 100 | - Choose appropriate license (MIT, Apache 2.0, etc.) 101 | - Include current year 102 | - Include copyright holder 103 | 104 | 4. CODE_OF_CONDUCT.md: 105 | - Based on Contributor Covenant 106 | - Include contact information 107 | - Clear enforcement guidelines 108 | 109 | examples: 110 | - input: | 111 | # Bad: Missing required files 112 | my-project/ 113 | ├── src/ 114 | └── README.md 115 | 116 | # Good: Complete community project setup 117 | my-project/ 118 | ├── src/ 119 | ├── README.md 120 | ├── CONTRIBUTING.md 121 | ├── LICENSE 122 | └── CODE_OF_CONDUCT.md 123 | output: "Properly configured community project" 124 | 125 | metadata: 126 | priority: high 127 | version: 1.0 128 | tags: 129 | - community 130 | - documentation 131 | - open-source 132 | 133 | -------------------------------------------------------------------------------- /.cursor/rules/conventional-commits.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Automatically commit changes using conventional commits format 3 | globs: 4 | --- 5 | # Conventional Commits Rule 6 | 7 | ## Description 8 | This rule defines the format and structure for commit messages following the Conventional Commits 1.0.0 specification. It ensures consistent, semantic, and machine-readable commit messages. 9 | 10 | ## Rule Type 11 | workflow 12 | 13 | ## Rule Format 14 | ```json 15 | { 16 | "type": "workflow", 17 | "name": "conventional_commits", 18 | "description": "Enforces Conventional Commits 1.0.0 specification", 19 | "filters": [ 20 | { 21 | "type": "event", 22 | "pattern": "pre_commit" 23 | } 24 | ], 25 | "steps": [ 26 | { 27 | "action": "validate", 28 | "description": "Validate commit message format", 29 | "requirements": [ 30 | "Message MUST be prefixed with a type", 31 | "Type MUST be one of: feat, fix, docs, style, refactor, perf, test, build, ci, chore", 32 | "Scope is OPTIONAL and MUST be in parentheses", 33 | "Description MUST immediately follow the colon and space", 34 | "Description MUST use imperative mood ('add' not 'added')", 35 | "Description MUST be less than 100 characters", 36 | "Breaking changes MUST be indicated by '!' or 'BREAKING CHANGE:' footer", 37 | "Body MUST be separated from description by one blank line", 38 | "Footer MUST be separated from body by one blank line" 39 | ] 40 | }, 41 | { 42 | "action": "execute", 43 | "description": "Format and create commit", 44 | "script": { 45 | "detect_type": { 46 | "feat": ["add", "create", "implement", "introduce"], 47 | "fix": ["fix", "correct", "resolve", "patch"], 48 | "docs": ["document", "comment", "update.*docs"], 49 | "style": ["style", "format", "lint"], 50 | "refactor": ["refactor", "restructure", "reorganize"], 51 | "perf": ["optimize", "performance", "improve.*speed"], 52 | "test": ["test", "spec", "coverage"], 53 | "build": ["build", "dependency", "package"], 54 | "ci": ["ci", "pipeline", "workflow"], 55 | "chore": ["chore", "misc", "task"] 56 | }, 57 | "format_message": { 58 | "template": "${type}${scope}: ${description}\n\n${body}\n\n${footer}", 59 | "variables": { 60 | "type": "Detected from changes or user input", 61 | "scope": "Optional, derived from file paths", 62 | "description": "First line of commit message", 63 | "body": "Detailed explanation of changes", 64 | "footer": "Optional references or breaking changes" 65 | } 66 | }, 67 | "command": [ 68 | "# Extract type from changes or prompt user", 69 | "TYPE=$(detect_change_type \"$CHANGES\" || prompt_user \"Enter commit type:\")", 70 | "", 71 | "# Extract scope from file paths", 72 | "SCOPE=$(get_common_path \"$CHANGED_FILES\")", 73 | "", 74 | "# Format the commit message", 75 | "printf \"%s\\n\\n%s\\n\\n%s\" \"$TYPE${SCOPE:+($SCOPE)}: $DESCRIPTION\" \"$BODY\" \"$FOOTER\" > \"$COMMIT_MSG_FILE\"" 76 | ] 77 | } 78 | } 79 | ] 80 | } 81 | ``` 82 | 83 | ## Manual Commit Syntax 84 | When creating commits manually, always use the printf syntax to properly handle newlines and formatting: 85 | 86 | ```bash 87 | printf "type(scope): description\n\nbody of the commit explaining the changes in detail\n\nfooter information" | git commit -F - 88 | ``` 89 | 90 | For example: 91 | ```bash 92 | printf "feat(auth): add OAuth2 support\n\nAdd Google and GitHub provider integration\nImplement token refresh handling\nAdd user profile synchronization\n\nCloses #123" | git commit -F - 93 | ``` 94 | 95 | This ensures proper formatting and newline handling in the commit message. 96 | 97 | ## Examples 98 | 99 | ### Feature with Scope 100 | ``` 101 | feat(auth): implement OAuth2 support 102 | 103 | - Add Google and GitHub provider integration 104 | - Implement token refresh handling 105 | - Add user profile synchronization 106 | 107 | Closes #123 108 | ``` 109 | 110 | ### Bug Fix with Breaking Change 111 | ``` 112 | fix(api): update user serialization 113 | 114 | - Modify user data structure for better consistency 115 | - Add validation for new fields 116 | 117 | BREAKING CHANGE: user.fullName split into firstName and lastName 118 | ``` 119 | 120 | ### Documentation Update 121 | ``` 122 | docs(readme): add modern package manager instructions 123 | 124 | - Add yarn and pnpm installation methods 125 | - Update minimum Node.js version requirement 126 | ``` 127 | 128 | ### Performance Improvement 129 | ``` 130 | perf(core): optimize database queries 131 | 132 | - Add query result caching 133 | - Implement proper indexing 134 | - Reduce unnecessary joins 135 | 136 | Closes #456 137 | ``` 138 | 139 | ## Integration 140 | This rule should be used in conjunction with the git-commit-workflow rule to ensure changes are properly reviewed before creating the commit message. The workflow should be: 141 | 142 | 1. Review changes (git-commit-workflow) 143 | 2. Format commit message (conventional-commits) 144 | 3. Validate commit message (conventional-commits) 145 | 4. Commit changes 146 | -------------------------------------------------------------------------------- /.cursor/rules/conversation-style.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Enforces consistent conversation patterns and style 3 | globs: 4 | --- 5 | # Conversation Style 6 | Guidelines for maintaining a consistent and engaging conversation style. 7 | 8 | 9 | name: conversation_style 10 | description: Enforces consistent conversation patterns and style 11 | filters: 12 | - type: event 13 | pattern: "conversation_start|message_response" 14 | 15 | actions: 16 | - type: suggest 17 | message: | 18 | When engaging in conversations, follow these rules: 19 | 20 | 1. Unicorn Greeting: 21 | - Start every conversation and response with "🦄" 22 | - Place the emoji at the very beginning of the message 23 | - Add a space after emoji if followed by a sentence 24 | Example: 25 | ``` 26 | // Bad: Missing unicorn or wrong placement 27 | Hello! How can I help you today? 28 | Hi 🦄 there! 29 | 30 | // Good: Proper unicorn placement 31 | 🦄 Hello! How can I help you today? 32 | 🦄 Hi there! 33 | 🦄 I'll help you with that request. 34 | ``` 35 | 36 | 2. Response Structure: 37 | - Emoji followed by greeting (if appropriate) 38 | - Then context or acknowledgment 39 | - Finally, the main response 40 | Example: 41 | ``` 42 | // Bad: Incorrect structure 43 | Let me help you with that. 44 | 🦄 [No context or acknowledgment] 45 | 46 | // Good: Proper structure 47 | 🦄 I understand you want to modify the configuration. 48 | I'll help you make those changes safely. 49 | ``` 50 | 51 | 3. Consistency: 52 | - Use the unicorn emoji consistently 53 | - Don't substitute with other emojis 54 | - Don't skip the emoji even in short responses 55 | Example: 56 | ``` 57 | // Bad: Inconsistent usage 58 | 🌟 Hello there! 59 | Sure, I can help. 60 | 61 | // Good: Consistent usage 62 | 🦄 Hello there! 63 | 🦄 Sure, I can help. 64 | ``` 65 | 66 | examples: 67 | - input: | 68 | User: Can you help me with this code? 69 | Assistant: Let me take a look at that for you. 70 | 71 | User: Thanks! 72 | Assistant: You're welcome! 73 | output: | 74 | User: Can you help me with this code? 75 | Assistant: 🦄 Let me take a look at that for you. 76 | 77 | User: Thanks! 78 | Assistant: 🦄 You're welcome! 79 | 80 | metadata: 81 | priority: medium 82 | version: 1.0 83 | tags: 84 | - conversation 85 | - style 86 | - user-interaction 87 | -------------------------------------------------------------------------------- /.cursor/rules/cursor-rules-location.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Standards for placing Cursor rule files in the correct directory 3 | globs: *.mdc 4 | --- 5 | # Cursor Rules Location 6 | Rules for placing and organizing Cursor rule files in the repository. 7 | 8 | name: cursor_rules_location 9 | description: Standards for placing Cursor rule files in the correct directory 10 | filters: 11 | # Match any .mdc files 12 | - type: file_extension 13 | pattern: "\\.mdc$" 14 | # Match files that look like Cursor rules 15 | - type: content 16 | pattern: "(?s).*?" 17 | # Match file creation events 18 | - type: event 19 | pattern: "file_create" 20 | 21 | actions: 22 | - type: reject 23 | conditions: 24 | - pattern: "^(?!\\.\\/\\.cursor\\/rules\\/.*\\.mdc$)" 25 | message: "Cursor rule files (.mdc) must be placed in the .cursor/rules directory" 26 | 27 | - type: suggest 28 | message: | 29 | When creating Cursor rules: 30 | 31 | 1. Always place rule files in PROJECT_ROOT/.cursor/rules/: 32 | ``` 33 | .cursor/rules/ 34 | ├── your-rule-name.mdc 35 | ├── another-rule.mdc 36 | └── ... 37 | ``` 38 | 39 | 2. Follow the naming convention: 40 | - Use kebab-case for filenames 41 | - Always use .mdc extension 42 | - Make names descriptive of the rule's purpose 43 | 44 | 3. Directory structure: 45 | ``` 46 | PROJECT_ROOT/ 47 | ├── .cursor/ 48 | │ └── rules/ 49 | │ ├── your-rule-name.mdc 50 | │ └── ... 51 | └── ... 52 | ``` 53 | 54 | 4. Never place rule files: 55 | - In the project root 56 | - In subdirectories outside .cursor/rules 57 | - In any other location 58 | 59 | examples: 60 | - input: | 61 | # Bad: Rule file in wrong location 62 | rules/my-rule.mdc 63 | my-rule.mdc 64 | .rules/my-rule.mdc 65 | 66 | # Good: Rule file in correct location 67 | .cursor/rules/my-rule.mdc 68 | output: "Correctly placed Cursor rule file" 69 | 70 | metadata: 71 | priority: high 72 | version: 1.0 73 | -------------------------------------------------------------------------------- /.cursor/rules/file-organization.mdc: -------------------------------------------------------------------------------- 1 | # File Organization 2 | Guidelines for organizing code into files following single responsibility principle. 3 | 4 | 5 | name: file_organization 6 | description: Enforces file-level organization and separation of concerns 7 | filters: 8 | - type: file_extension 9 | pattern: "\\.ts$|\\.js$" 10 | - type: content 11 | pattern: "(?s)(class|interface|type|function).*?\\{" 12 | 13 | actions: 14 | - type: suggest 15 | message: | 16 | When organizing code into files, follow these rules: 17 | 18 | 1. Single Definition Per File: 19 | - Each class should be in its own file 20 | - Each standalone function should be in its own file 21 | - Each complex type/interface (more than one line) should be in its own file 22 | Example: 23 | ```typescript 24 | // Bad: Multiple definitions in one file 25 | // user-types.ts 26 | interface UserCredentials { 27 | username: string; 28 | password: string; 29 | } 30 | interface UserProfile { 31 | id: string; 32 | name: string; 33 | email: string; 34 | } 35 | class UserService { 36 | // ... 37 | } 38 | 39 | // Good: Separate files for each definition 40 | // user-credentials.ts 41 | interface UserCredentials { 42 | username: string; 43 | password: string; 44 | } 45 | 46 | // user-profile.ts 47 | interface UserProfile { 48 | id: string; 49 | name: string; 50 | email: string; 51 | } 52 | 53 | // user-service.ts 54 | class UserService { 55 | // ... 56 | } 57 | ``` 58 | 59 | 2. File Naming Conventions: 60 | - Use kebab-case for filenames 61 | - Name files after their primary export 62 | - Use suffixes to indicate type: `.interface.ts`, `.type.ts`, `.service.ts`, etc. 63 | Example: 64 | ```typescript 65 | // Good file names: 66 | user-credentials.interface.ts 67 | user-profile.interface.ts 68 | user-service.ts 69 | create-user.function.ts 70 | ``` 71 | 72 | 3. Simple Type Exceptions: 73 | - Single-line type aliases and interfaces can be co-located if they're tightly coupled 74 | Example: 75 | ```typescript 76 | // Acceptable in the same file: 77 | type UserId = string; 78 | type UserRole = 'admin' | 'user'; 79 | interface BasicUser { id: string; role: UserRole; } 80 | ``` 81 | 82 | 4. Barrel File Usage: 83 | - Use index.ts files to re-export related components 84 | - Keep barrel files simple - export only, no implementations 85 | Example: 86 | ```typescript 87 | // users/index.ts 88 | export * from './user-credentials.interface'; 89 | export * from './user-profile.interface'; 90 | export * from './user-service'; 91 | ``` 92 | 93 | 5. Directory Structure: 94 | - Group related files in directories 95 | - Use feature-based organization 96 | Example: 97 | ``` 98 | src/ 99 | ├── users/ 100 | │ ├── interfaces/ 101 | │ │ ├── user-credentials.interface.ts 102 | │ │ └── user-profile.interface.ts 103 | │ ├── services/ 104 | │ │ └── user-service.ts 105 | │ └── index.ts 106 | └── ... 107 | ``` 108 | 109 | 6. Import Organization: 110 | - Keep imports organized by type (external, internal, relative) 111 | - Use explicit imports over namespace imports 112 | Example: 113 | ```typescript 114 | // External imports 115 | import { Injectable } from '@nestjs/common'; 116 | import { v4 as uuid } from 'uuid'; 117 | 118 | // Internal imports (from your app) 119 | import { UserProfile } from '@/users/interfaces'; 120 | import { DatabaseService } from '@/database'; 121 | 122 | // Relative imports (same feature) 123 | import { UserCredentials } from './user-credentials.interface'; 124 | ``` 125 | 126 | examples: 127 | - input: | 128 | // Bad: Multiple concerns in one file 129 | interface UserData { 130 | id: string; 131 | name: string; 132 | } 133 | 134 | class UserService { 135 | getUser(id: string) { } 136 | } 137 | 138 | function validateUser(user: UserData) { } 139 | output: | 140 | // user-data.interface.ts 141 | interface UserData { 142 | id: string; 143 | name: string; 144 | } 145 | 146 | // user.service.ts 147 | class UserService { 148 | getUser(id: string) { } 149 | } 150 | 151 | // validate-user.function.ts 152 | function validateUser(user: UserData) { } 153 | 154 | metadata: 155 | priority: high 156 | version: 1.0 157 | tags: 158 | - code-organization 159 | - best-practices 160 | - file-structure 161 | 162 | -------------------------------------------------------------------------------- /.cursor/rules/git-commit-workflow.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Workflow for testing, validating, and committing changes using conventional commits 3 | globs: 4 | --- 5 | # Git Commit Workflow Rule 6 | 7 | ## Description 8 | This rule defines the complete workflow for validating changes, running tests, and creating commits. It ensures that all changes are properly tested and validated before being committed using the conventional commits format. 9 | 10 | ## Rule Type 11 | workflow 12 | 13 | ## Rule Format 14 | ```json 15 | { 16 | "type": "workflow", 17 | "name": "git_commit_workflow", 18 | "description": "Validates changes and creates conventional commits", 19 | "filters": [ 20 | { 21 | "type": "event", 22 | "pattern": "pre_commit" 23 | } 24 | ], 25 | "steps": [ 26 | { 27 | "action": "validate", 28 | "description": "Run tests and type checks", 29 | "requirements": [ 30 | "All tests MUST pass", 31 | "TypeScript compilation MUST succeed", 32 | "Build process MUST complete successfully" 33 | ] 34 | }, 35 | { 36 | "action": "execute", 37 | "description": "Validate and commit changes", 38 | "script": { 39 | "steps": [ 40 | { 41 | "name": "run_tests", 42 | "command": "npm test", 43 | "on_failure": "abort" 44 | }, 45 | { 46 | "name": "type_check", 47 | "command": "npm run type-check", 48 | "on_failure": "abort" 49 | }, 50 | { 51 | "name": "build", 52 | "command": "npm run build", 53 | "on_failure": "abort" 54 | }, 55 | { 56 | "name": "check_changes", 57 | "command": "git status --porcelain", 58 | "store_output": "CHANGED_FILES" 59 | }, 60 | { 61 | "name": "stage_changes", 62 | "command": "git add ." 63 | }, 64 | { 65 | "name": "create_commit", 66 | "use_rule": "conventional-commits" 67 | } 68 | ] 69 | } 70 | } 71 | ] 72 | } 73 | ``` 74 | 75 | ## Workflow Steps 76 | 77 | 1. **Run Tests** 78 | - Execute the test suite using `npm test` 79 | - Abort if any tests fail 80 | - Ensure all new features have corresponding tests 81 | 82 | 2. **Type Checking** 83 | - Run TypeScript type checking 84 | - Verify no type errors exist 85 | - Abort if type checking fails 86 | 87 | 3. **Build Process** 88 | - Run the build process 89 | - Ensure the project builds successfully 90 | - Abort if build fails 91 | 92 | 4. **Check Changes** 93 | - Use `git status` to identify modified files 94 | - Review changes before staging 95 | - Ensure no unintended files are included 96 | 97 | 5. **Stage Changes** 98 | - Stage all relevant files using `git add` 99 | - Review staged changes if needed 100 | 101 | 6. **Create Commit** 102 | - Use conventional-commits rule to format commit message 103 | - Follow proper commit message structure 104 | - Include appropriate type, scope, and description 105 | 106 | ## Integration with Conventional Commits 107 | This workflow automatically integrates with the conventional-commits rule to ensure proper commit message formatting. The workflow will: 108 | 109 | 1. Detect the appropriate commit type based on changes 110 | 2. Generate a properly formatted commit message 111 | 3. Include relevant scope based on changed files 112 | 4. Add detailed body explaining changes 113 | 5. Include footer with issue references if applicable 114 | 115 | ## Examples 116 | 117 | ### Feature Development 118 | ```bash 119 | # 1. Run tests 120 | npm test 121 | 122 | # 2. Type check 123 | npm run type-check 124 | 125 | # 3. Build 126 | npm run build 127 | 128 | # 4. Check changes 129 | git status 130 | 131 | # 5. Stage changes 132 | git add . 133 | 134 | # 6. Create commit (using conventional-commits rule) 135 | printf "feat(auth): implement OAuth2 support\n\nAdd Google and GitHub provider integration\nImplement token refresh handling\n\nCloses #123" | git commit -F - 136 | ``` 137 | 138 | ### Bug Fix 139 | ```bash 140 | # Follow the same workflow 141 | npm test && npm run type-check && npm run build 142 | git status 143 | git add . 144 | printf "fix(api): resolve user data serialization issue\n\nFix incorrect handling of nested user properties\n\nCloses #456" | git commit -F - 145 | ``` 146 | 147 | ## Error Handling 148 | - If any validation step fails, the workflow will abort 149 | - Test failures must be resolved before proceeding 150 | - Type errors must be fixed before commit 151 | - Build errors must be addressed 152 | - Proper error messages will be displayed for each failure 153 | 154 | ## Notes 155 | - Always run this workflow before creating commits 156 | - Ensure all tests are up to date 157 | - Keep commits focused and atomic 158 | - Follow the conventional commits format 159 | - Use meaningful commit messages 160 | -------------------------------------------------------------------------------- /.cursor/rules/naming-conventions.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Enforces consistent naming patterns for files, types, and functions 3 | globs: *.ts, *.js, *.tsx 4 | --- 5 | # Naming Conventions 6 | Standards for naming TypeScript and JavaScript files, types, and functions. 7 | 8 | 9 | name: naming_conventions 10 | description: Enforces consistent naming patterns for files, types, and functions 11 | filters: 12 | # Match TypeScript and JavaScript files 13 | - type: file_extension 14 | pattern: "\\.(ts|js)$" 15 | # Match file creation and modification events 16 | - type: event 17 | pattern: "(file_create|file_modify)" 18 | 19 | actions: 20 | - type: reject 21 | conditions: 22 | # Reject files not in kebab-case 23 | - pattern: "^(?!.*[A-Z])(?!.*\\s)(?!.*_)[a-z0-9-]+\\.(ts|js)$" 24 | message: "File names must be in kebab-case (e.g., my-file-name.ts)" 25 | 26 | - type: suggest 27 | message: | 28 | Follow these naming conventions: 29 | 30 | 1. Files: 31 | - Use kebab-case for all TypeScript and JavaScript files 32 | - Examples: 33 | ✅ user-service.ts 34 | ✅ api-client.js 35 | ❌ UserService.ts 36 | ❌ apiClient.js 37 | 38 | 2. Types (interfaces, types, classes): 39 | - Use PascalCase 40 | - Examples: 41 | ✅ interface UserProfile 42 | ✅ type ApiResponse 43 | ✅ class HttpClient 44 | ❌ interface userProfile 45 | ❌ type api_response 46 | 47 | 3. Functions: 48 | - Use camelCase 49 | - Examples: 50 | ✅ function getUserData() 51 | ✅ const fetchApiResponse = () => {} 52 | ❌ function GetUserData() 53 | ❌ const fetch_api_response = () => {} 54 | 55 | examples: 56 | - input: | 57 | // Bad: Incorrect naming 58 | UserService.ts 59 | API_client.js 60 | 61 | interface user_profile {} 62 | function FetchData() {} 63 | 64 | // Good: Correct naming 65 | user-service.ts 66 | api-client.js 67 | 68 | interface UserProfile {} 69 | function fetchData() {} 70 | output: "Correctly named files, types, and functions" 71 | 72 | metadata: 73 | priority: high 74 | version: 1.0 75 | 76 | -------------------------------------------------------------------------------- /.cursor/rules/solid-principles.mdc: -------------------------------------------------------------------------------- 1 | # SOLID Principles 2 | Guidelines for implementing SOLID principles in the codebase. 3 | 4 | 5 | name: solid_principles 6 | description: Enforces SOLID principles in code design and implementation 7 | filters: 8 | - type: file_extension 9 | pattern: "\\.ts$|\\.js$" 10 | - type: content 11 | pattern: "(?s)class.*?\\{|interface.*?\\{|function.*?\\{" 12 | 13 | actions: 14 | - type: suggest 15 | message: | 16 | When writing code, follow these SOLID principles: 17 | 18 | 1. Single Responsibility Principle (SRP): 19 | - Each class/module should have only one reason to change 20 | - Keep classes focused and cohesive 21 | - Extract separate concerns into their own classes 22 | Example: 23 | ```typescript 24 | // Good: Single responsibility 25 | class UserAuthentication { 26 | authenticate(credentials: Credentials): boolean { ... } 27 | } 28 | class UserProfile { 29 | updateProfile(data: ProfileData): void { ... } 30 | } 31 | 32 | // Bad: Multiple responsibilities 33 | class User { 34 | authenticate(credentials: Credentials): boolean { ... } 35 | updateProfile(data: ProfileData): void { ... } 36 | sendEmail(message: string): void { ... } 37 | } 38 | ``` 39 | 40 | 2. Open/Closed Principle (OCP): 41 | - Classes should be open for extension but closed for modification 42 | - Use interfaces and abstract classes 43 | - Implement new functionality through inheritance/composition 44 | Example: 45 | ```typescript 46 | // Good: Open for extension 47 | interface PaymentProcessor { 48 | process(payment: Payment): void; 49 | } 50 | class CreditCardProcessor implements PaymentProcessor { ... } 51 | class PayPalProcessor implements PaymentProcessor { ... } 52 | 53 | // Bad: Closed for extension 54 | class PaymentProcessor { 55 | process(payment: Payment, type: string): void { 56 | if (type === 'credit') { ... } 57 | else if (type === 'paypal') { ... } 58 | } 59 | } 60 | ``` 61 | 62 | 3. Liskov Substitution Principle (LSP): 63 | - Derived classes must be substitutable for their base classes 64 | - Maintain expected behavior when using inheritance 65 | - Don't violate base class contracts 66 | Example: 67 | ```typescript 68 | // Good: Derived class maintains base contract 69 | class Bird { 70 | fly(): void { ... } 71 | } 72 | class Sparrow extends Bird { 73 | fly(): void { ... } // Implements flying behavior 74 | } 75 | 76 | // Bad: Violates base contract 77 | class Penguin extends Bird { 78 | fly(): void { 79 | throw new Error("Can't fly!"); // Violates base class contract 80 | } 81 | } 82 | ``` 83 | 84 | 4. Interface Segregation Principle (ISP): 85 | - Don't force clients to depend on interfaces they don't use 86 | - Keep interfaces small and focused 87 | - Split large interfaces into smaller ones 88 | Example: 89 | ```typescript 90 | // Good: Segregated interfaces 91 | interface Readable { 92 | read(): void; 93 | } 94 | interface Writable { 95 | write(data: string): void; 96 | } 97 | 98 | // Bad: Fat interface 99 | interface FileSystem { 100 | read(): void; 101 | write(data: string): void; 102 | delete(): void; 103 | create(): void; 104 | modify(): void; 105 | } 106 | ``` 107 | 108 | 5. Dependency Inversion Principle (DIP): 109 | - High-level modules shouldn't depend on low-level modules 110 | - Both should depend on abstractions 111 | - Use dependency injection 112 | Example: 113 | ```typescript 114 | // Good: Depends on abstraction 115 | interface Logger { 116 | log(message: string): void; 117 | } 118 | class UserService { 119 | constructor(private logger: Logger) {} 120 | } 121 | 122 | // Bad: Depends on concrete implementation 123 | class UserService { 124 | private logger = new FileLogger(); 125 | } 126 | ``` 127 | 128 | Additional Guidelines: 129 | - Use interfaces to define contracts 130 | - Implement dependency injection 131 | - Keep classes small and focused 132 | - Use composition over inheritance when possible 133 | - Write unit tests to verify SOLID compliance 134 | 135 | examples: 136 | - input: | 137 | // Bad example - violates SRP and OCP 138 | class OrderProcessor { 139 | processOrder(order: Order) { 140 | // Handles validation 141 | // Handles payment 142 | // Handles shipping 143 | // Handles notification 144 | } 145 | } 146 | output: | 147 | // Good example - follows SOLID principles 148 | interface OrderValidator { 149 | validate(order: Order): boolean; 150 | } 151 | interface PaymentProcessor { 152 | process(order: Order): void; 153 | } 154 | interface ShippingService { 155 | ship(order: Order): void; 156 | } 157 | interface NotificationService { 158 | notify(order: Order): void; 159 | } 160 | 161 | class OrderProcessor { 162 | constructor( 163 | private validator: OrderValidator, 164 | private paymentProcessor: PaymentProcessor, 165 | private shippingService: ShippingService, 166 | private notificationService: NotificationService 167 | ) {} 168 | 169 | processOrder(order: Order) { 170 | if (this.validator.validate(order)) { 171 | this.paymentProcessor.process(order); 172 | this.shippingService.ship(order); 173 | this.notificationService.notify(order); 174 | } 175 | } 176 | } 177 | 178 | metadata: 179 | priority: high 180 | version: 1.0 181 | tags: 182 | - code-quality 183 | - design-patterns 184 | - best-practices 185 | 186 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules/ 3 | .pnpm-store/ 4 | yarn.lock 5 | package-lock.json 6 | pnpm-lock.yaml 7 | 8 | # Build outputs 9 | dist/ 10 | build/ 11 | out/ 12 | .next/ 13 | *.tsbuildinfo 14 | 15 | # IDE and editor files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | !.vscode/settings.json 19 | .idea/ 20 | *.swp 21 | *.swo 22 | .DS_Store 23 | Thumbs.db 24 | 25 | # Environment variables 26 | .env 27 | .env.local 28 | .env.*.local 29 | .env.development 30 | .env.test 31 | .env.production 32 | 33 | # Debug logs 34 | npm-debug.log* 35 | yarn-debug.log* 36 | yarn-error.log* 37 | debug.log 38 | *.log 39 | 40 | # Test coverage 41 | coverage/ 42 | .nyc_output/ 43 | 44 | # Cursor IDE specific 45 | .cursor/temp/ 46 | .cursor/logs/ 47 | !.cursor/rules/ 48 | 49 | # Misc 50 | .cache/ 51 | .temp/ 52 | *.bak 53 | *.tmp 54 | *~ 55 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Cursor Rules 2 | 3 | We love your input! We want to make contributing to Cursor Rules as easy and transparent as possible, whether it's: 4 | 5 | - Reporting a bug 6 | - Discussing the current state of the rules 7 | - Submitting a fix 8 | - Proposing new rules 9 | - Improving documentation 10 | 11 | ## Development Process 12 | 13 | We use GitHub to host code, to track issues and feature requests, as well as accept pull requests. 14 | 15 | 1. Fork the repo and create your branch from `main` 16 | 2. If you've added new rules, make sure they follow our existing format 17 | 3. Update documentation if needed 18 | 4. Issue that pull request! 19 | 20 | ## Rule File Standards 21 | 22 | When creating or modifying rule files: 23 | 24 | 1. Place all rule files in `.cursor/rules/` directory 25 | 2. Use kebab-case for filenames with `.mdc` extension 26 | 3. Follow the standard rule format: 27 | ```markdown 28 | # Rule Name 29 | Description of the rule 30 | 31 | 32 | name: rule_name 33 | description: Detailed description 34 | filters: 35 | # ... filters ... 36 | actions: 37 | # ... actions ... 38 | 39 | ``` 40 | 41 | ## Commit Messages 42 | 43 | We follow the Conventional Commits specification. Each commit message should be structured as follows: 44 | 45 | ``` 46 | type(scope): description 47 | 48 | [optional body] 49 | 50 | [optional footer] 51 | ``` 52 | 53 | Types: 54 | - feat: New feature or rule 55 | - fix: Bug fix 56 | - docs: Documentation changes 57 | - style: Formatting changes 58 | - refactor: Code refactoring 59 | - test: Adding/modifying tests 60 | - chore: Maintenance tasks 61 | 62 | ## Pull Request Process 63 | 64 | 1. Update the README.md with details of changes if needed 65 | 2. Follow the pull request template 66 | 3. You may merge the Pull Request once you have the sign-off of at least one other developer 67 | 68 | ## Any Contributions You Make Will Be Under the MIT Software License 69 | 70 | In short, when you submit code changes, your submissions are understood to be under the same [MIT License](LICENSE) that covers the project. Feel free to contact the maintainers if that's a concern. 71 | 72 | ## Report Bugs Using GitHub's [Issue Tracker](../../issues) 73 | 74 | Report a bug by [opening a new issue](../../issues/new); it's that easy! 75 | 76 | ## Write Bug Reports With Detail, Background, and Sample Code 77 | 78 | **Great Bug Reports** tend to have: 79 | 80 | - A quick summary and/or background 81 | - Steps to reproduce 82 | - Be specific! 83 | - Give sample code if you can 84 | - What you expected would happen 85 | - What actually happens 86 | - Notes (possibly including why you think this might be happening, or stuff you tried that didn't work) 87 | 88 | ## License 89 | 90 | By contributing, you agree that your contributions will be licensed under its MIT License. 91 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Squirrel Software 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cursor Rules 2 | 3 | A collection of standardized rules and guidelines for maintaining high-quality code using Cursor IDE. 4 | 5 | ## Overview 6 | 7 | This repository contains a set of rules that help maintain consistency and quality in codebases using Cursor IDE. These rules cover various aspects of development including: 8 | 9 | - Code organization and file structure 10 | - Naming conventions 11 | - Git commit standards 12 | - SOLID principles implementation 13 | - Conversation style guidelines 14 | - And more... 15 | 16 | ## Rules 17 | 18 | 1. **Conventional Commits** - Standards for commit message formatting 19 | 2. **Community Projects** - Standards for initializing and maintaining community-focused open source projects 20 | 3. **Conversation Style** - Guidelines for AI-human interaction in Cursor 21 | 4. **Cursor Rules Location** - Standards for rule file placement 22 | 5. **File Organization** - Guidelines for code organization 23 | 6. **Git Commit Workflow** - Process for validating and committing changes 24 | 7. **Naming Conventions** - Standards for naming files and code elements 25 | 8. **SOLID Principles** - Implementation of SOLID design principles 26 | 27 | ## Installation 28 | 29 | 1. Create a `.cursor/rules` directory in your project root: 30 | ```bash 31 | mkdir -p .cursor/rules 32 | ``` 33 | 34 | 2. Copy the desired rule files into the `.cursor/rules` directory: 35 | ```bash 36 | cp path/to/rules/*.mdc .cursor/rules/ 37 | ``` 38 | 39 | ## Usage 40 | In the event that the rules do not load automatically, I have found that the best way to load them is to open the agent composer and say: 41 | ``` 42 | For the remainder of this session, remember the following @rules 43 | ``` 44 | 45 | It will then respond with: 46 | ``` 47 | 🦄 Let me fetch the rules 48 | 49 | 🦄 I understand and will follow all the provided rules for our session. Here's a summary of how I'll incorporate them: 50 | 51 | 1. Conversation Style: I'll start each message with 🦄 and maintain a structured response format. 52 | 53 | 2. Naming Conventions: I'll ensure all files, types, and functions follow the specified patterns: 54 | - Files in kebab-case 55 | - Types in PascalCase 56 | - Functions in camelCase 57 | 58 | 3. SOLID Principles: Follow: 59 | - Single Responsibility: One reason to change 60 | - Open/Closed: Open for extension, closed for modification 61 | - Liskov Substitution: Derived classes must be substitutable 62 | - Interface Segregation: Keep interfaces focused 63 | - Dependency Inversion: Depend on abstractions 64 | 65 | 4. Conventional Commits: Format commits as `type(scope): description` with proper body and footer. Types include feat, fix, docs, style, refactor, perf, test, build, ci, chore. 66 | 67 | 5. Cursor Rules Location: Place all `.mdc` rule files in `.cursor/rules/` directory using kebab-case naming. 68 | 69 | 6. File Organization: One definition per file, use kebab-case filenames with appropriate suffixes (`.interface.ts`, `.service.ts`), group related files in feature-based directories, organize imports (external/internal/relative). 70 | 71 | 7. Git Commit Workflow: Run tests, type checks, and build before committing. Follow sequence: validate → test → type-check → build → check changes → stage → commit. 72 | 73 | 8. Community Projects: I'll ensure any project work follows the community standards with proper README.md, CONTRIBUTING.md, LICENSE, and CODE_OF_CONDUCT.md files. 74 | 75 | ``` 76 | Once installed, these rules will be automatically applied when using Cursor IDE. The rules provide guidance for: 77 | 78 | - File naming and organization 79 | - Code structure and design 80 | - Git commit messages 81 | - Development workflows 82 | - And more... 83 | 84 | ## Contributing 85 | 86 | We welcome contributions! Please see our [Contributing Guidelines](CONTRIBUTING.md) for details. 87 | 88 | ## Code of Conduct 89 | 90 | This project follows a [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. 91 | 92 | ## License 93 | 94 | This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. 95 | -------------------------------------------------------------------------------- /conversation-style.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Enforces consistent conversation patterns and style 3 | globs: 4 | --- 5 | # Conversation Style 6 | Guidelines for maintaining a consistent and engaging conversation style. 7 | 8 | 9 | name: conversation_style 10 | description: Enforces consistent conversation patterns and style 11 | filters: 12 | - type: event 13 | pattern: "conversation_start|message_response" 14 | 15 | actions: 16 | - type: suggest 17 | message: | 18 | When engaging in conversations, follow these rules: 19 | 20 | 1. Unicorn Greeting: 21 | - Start every conversation and response with "🦄" 22 | - Place the emoji at the very beginning of the message 23 | - Add a space after emoji if followed by a sentence 24 | Example: 25 | ``` 26 | // Bad: Missing unicorn or wrong placement 27 | Hello! How can I help you today? 28 | Hi 🦄 there! 29 | 30 | // Good: Proper unicorn placement 31 | 🦄 Hello! How can I help you today? 32 | 🦄 Hi there! 33 | 🦄 I'll help you with that request. 34 | ``` 35 | 36 | 2. Response Structure: 37 | - Emoji followed by greeting (if appropriate) 38 | - Then context or acknowledgment 39 | - Finally, the main response 40 | Example: 41 | ``` 42 | // Bad: Incorrect structure 43 | Let me help you with that. 44 | 🦄 [No context or acknowledgment] 45 | 46 | // Good: Proper structure 47 | 🦄 I understand you want to modify the configuration. 48 | I'll help you make those changes safely. 49 | ``` 50 | 51 | 3. Consistency: 52 | - Use the unicorn emoji consistently 53 | - Don't substitute with other emojis 54 | - Don't skip the emoji even in short responses 55 | Example: 56 | ``` 57 | // Bad: Inconsistent usage 58 | 🌟 Hello there! 59 | Sure, I can help. 60 | 61 | // Good: Consistent usage 62 | 🦄 Hello there! 63 | 🦄 Sure, I can help. 64 | ``` 65 | 66 | examples: 67 | - input: | 68 | User: Can you help me with this code? 69 | Assistant: Let me take a look at that for you. 70 | 71 | User: Thanks! 72 | Assistant: You're welcome! 73 | output: | 74 | User: Can you help me with this code? 75 | Assistant: 🦄 Let me take a look at that for you. 76 | 77 | User: Thanks! 78 | Assistant: 🦄 You're welcome! 79 | 80 | metadata: 81 | priority: medium 82 | version: 1.0 83 | tags: 84 | - conversation 85 | - style 86 | - user-interaction 87 | -------------------------------------------------------------------------------- /git-commit-workflow.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Workflow for testing, validating, and committing changes using conventional commits 3 | globs: 4 | --- 5 | # Git Commit Workflow Rule 6 | 7 | ## Description 8 | This rule defines the complete workflow for validating changes, running tests, and creating commits. It ensures that all changes are properly tested and validated before being committed using the conventional commits format. 9 | 10 | ## Rule Type 11 | workflow 12 | 13 | ## Rule Format 14 | ```json 15 | { 16 | "type": "workflow", 17 | "name": "git_commit_workflow", 18 | "description": "Validates changes and creates conventional commits", 19 | "filters": [ 20 | { 21 | "type": "event", 22 | "pattern": "pre_commit" 23 | } 24 | ], 25 | "steps": [ 26 | { 27 | "action": "validate", 28 | "description": "Run tests and type checks", 29 | "requirements": [ 30 | "All tests MUST pass", 31 | "TypeScript compilation MUST succeed", 32 | "Build process MUST complete successfully" 33 | ] 34 | }, 35 | { 36 | "action": "execute", 37 | "description": "Validate and commit changes", 38 | "script": { 39 | "steps": [ 40 | { 41 | "name": "run_tests", 42 | "command": "npm test", 43 | "on_failure": "abort" 44 | }, 45 | { 46 | "name": "type_check", 47 | "command": "npm run type-check", 48 | "on_failure": "abort" 49 | }, 50 | { 51 | "name": "build", 52 | "command": "npm run build", 53 | "on_failure": "abort" 54 | }, 55 | { 56 | "name": "check_changes", 57 | "command": "git status --porcelain", 58 | "store_output": "CHANGED_FILES" 59 | }, 60 | { 61 | "name": "stage_changes", 62 | "command": "git add ." 63 | }, 64 | { 65 | "name": "create_commit", 66 | "use_rule": "conventional-commits" 67 | } 68 | ] 69 | } 70 | } 71 | ] 72 | } 73 | ``` 74 | 75 | ## Workflow Steps 76 | 77 | 1. **Run Tests** 78 | - Execute the test suite using `npm test` 79 | - Abort if any tests fail 80 | - Ensure all new features have corresponding tests 81 | 82 | 2. **Type Checking** 83 | - Run TypeScript type checking 84 | - Verify no type errors exist 85 | - Abort if type checking fails 86 | 87 | 3. **Build Process** 88 | - Run the build process 89 | - Ensure the project builds successfully 90 | - Abort if build fails 91 | 92 | 4. **Check Changes** 93 | - Use `git status` to identify modified files 94 | - Review changes before staging 95 | - Ensure no unintended files are included 96 | 97 | 5. **Stage Changes** 98 | - Stage all relevant files using `git add` 99 | - Review staged changes if needed 100 | 101 | 6. **Create Commit** 102 | - Use conventional-commits rule to format commit message 103 | - Follow proper commit message structure 104 | - Include appropriate type, scope, and description 105 | 106 | ## Integration with Conventional Commits 107 | This workflow automatically integrates with the conventional-commits rule to ensure proper commit message formatting. The workflow will: 108 | 109 | 1. Detect the appropriate commit type based on changes 110 | 2. Generate a properly formatted commit message 111 | 3. Include relevant scope based on changed files 112 | 4. Add detailed body explaining changes 113 | 5. Include footer with issue references if applicable 114 | 115 | ## Examples 116 | 117 | ### Feature Development 118 | ```bash 119 | # 1. Run tests 120 | npm test 121 | 122 | # 2. Type check 123 | npm run type-check 124 | 125 | # 3. Build 126 | npm run build 127 | 128 | # 4. Check changes 129 | git status 130 | 131 | # 5. Stage changes 132 | git add . 133 | 134 | # 6. Create commit (using conventional-commits rule) 135 | printf "feat(auth): implement OAuth2 support\n\nAdd Google and GitHub provider integration\nImplement token refresh handling\n\nCloses #123" | git commit -F - 136 | ``` 137 | 138 | ### Bug Fix 139 | ```bash 140 | # Follow the same workflow 141 | npm test && npm run type-check && npm run build 142 | git status 143 | git add . 144 | printf "fix(api): resolve user data serialization issue\n\nFix incorrect handling of nested user properties\n\nCloses #456" | git commit -F - 145 | ``` 146 | 147 | ## Error Handling 148 | - If any validation step fails, the workflow will abort 149 | - Test failures must be resolved before proceeding 150 | - Type errors must be fixed before commit 151 | - Build errors must be addressed 152 | - Proper error messages will be displayed for each failure 153 | 154 | ## Notes 155 | - Always run this workflow before creating commits 156 | - Ensure all tests are up to date 157 | - Keep commits focused and atomic 158 | - Follow the conventional commits format 159 | - Use meaningful commit messages 160 | -------------------------------------------------------------------------------- /nextjs/async-params.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: 3 | globs: 4 | alwaysApply: false 5 | --- 6 | # Async Params and SearchParams in Next.js 15 7 | 8 | name: async_params 9 | description: Guidelines for handling async params and searchParams in Next.js 15 page components 10 | filters: 11 | - type: file_extension 12 | pattern: ".tsx?$" 13 | - type: path 14 | pattern: "app/.*page.tsx$" 15 | 16 | actions: 17 | - type: reject 18 | conditions: 19 | - pattern: "params\\s*:\\s*\\{\\s*[a-zA-Z_][a-zA-Z0-9_]*\\s*:\\s*string\\s*\\}" 20 | message: "Page params must be typed as a Promise and awaited" 21 | 22 | - pattern: "searchParams\\s*:\\s*\\{[^}]*\\}" 23 | message: "Page searchParams must be typed as a Promise and awaited" 24 | 25 | - pattern: "const\\s+\\{\\s*[a-zA-Z_][a-zA-Z0-9_]*\\s*\\}\\s*=\\s*params" 26 | message: "Page params must be awaited before destructuring" 27 | 28 | - pattern: "const\\s+\\{\\s*[a-zA-Z_][a-zA-Z0-9_]*\\s*\\}\\s*=\\s*searchParams" 29 | message: "Page searchParams must be awaited before destructuring" 30 | 31 | - type: suggest 32 | message: | 33 | # Async Params and SearchParams 34 | 35 | In Next.js 15, page components that use `params` or `searchParams` must: 36 | 1. Be async functions 37 | 2. Type params/searchParams as Promises 38 | 3. Await the params/searchParams before use 39 | 40 | ## Params Example 41 | ```typescript 42 | // ✅ DO: Properly type and await params 43 | interface PageProps { 44 | params: Promise<{ slug: string }> 45 | } 46 | 47 | export default async function Page({ params }: PageProps) { 48 | const { slug } = await params 49 | return
Post: {slug}
50 | } 51 | 52 | // ❌ DON'T: Use params without Promise type and await 53 | interface PageProps { 54 | params: { slug: string } // Wrong! Should be Promise 55 | } 56 | 57 | export default function Page({ params }: PageProps) { 58 | const { slug } = params // Wrong! Should await params 59 | return
Post: {slug}
60 | } 61 | ``` 62 | 63 | ## SearchParams Example 64 | ```typescript 65 | // ✅ DO: Properly type and await searchParams 66 | interface PageProps { 67 | searchParams: Promise<{ q?: string }> 68 | } 69 | 70 | export default async function Page({ searchParams }: PageProps) { 71 | const { q } = await searchParams 72 | return
Search: {q}
73 | } 74 | 75 | // ❌ DON'T: Use searchParams without Promise type and await 76 | interface PageProps { 77 | searchParams: { q?: string } // Wrong! Should be Promise 78 | } 79 | 80 | export default function Page({ searchParams }: PageProps) { 81 | const { q } = searchParams // Wrong! Should await searchParams 82 | return
Search: {q}
83 | } 84 | ``` 85 | 86 | ## Best Practices 87 | 1. Always make page components async when using params/searchParams 88 | 2. Always type params/searchParams as Promises 89 | 3. Always await params/searchParams before destructuring 90 | 4. Consider handling loading states while params are being resolved 91 | 5. Use TypeScript for better type safety 92 | 93 | ## Common Patterns 94 | ```typescript 95 | // Multiple params 96 | interface PageProps { 97 | params: Promise<{ 98 | slug: string 99 | id: string 100 | }> 101 | } 102 | 103 | // Both params and searchParams 104 | interface PageProps { 105 | params: Promise<{ slug: string }> 106 | searchParams: Promise<{ page?: string }> 107 | } 108 | 109 | // With error handling 110 | export default async function Page({ params }: PageProps) { 111 | try { 112 | const { slug } = await params 113 | // Use slug 114 | } catch (error) { 115 | notFound() 116 | } 117 | } 118 | ``` 119 | 120 | metadata: 121 | priority: high 122 | version: 1.0 123 | framework: next.js 124 | frameworkVersion: "15.0.0" 125 |
126 | -------------------------------------------------------------------------------- /nextjs/code-review.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Comprehensive checklist and guidelines for conducting code reviews 3 | globs: ["**/*"] 4 | alwaysApply: true 5 | --- 6 | 7 | # Code Review Guidelines 8 | 9 | ## Review Process 10 | - **Before Starting Review:** 11 | - Check task requirements and acceptance criteria 12 | - Review related tasks and dependencies 13 | - Understand the context of the changes 14 | 15 | - **During Review:** 16 | - Follow checklist systematically 17 | - Document findings clearly 18 | - Provide constructive feedback 19 | - Reference specific rules when applicable 20 | 21 | - **After Review:** 22 | - Verify fixes address all comments 23 | - Check if changes require task updates 24 | - Update documentation if needed 25 | 26 | ## Review Checklist 27 | 28 | ### Architecture & Structure 29 | ```typescript 30 | // ✅ DO: Proper server action structure 31 | // app/actions/organization/create.ts 32 | 'use server' 33 | import { createOrganization } from '@/lib/data/mutations/organizations' 34 | 35 | // ❌ DON'T: Mix concerns 36 | 'use server' 37 | import { db } from '@/db' 38 | // Direct database operations in server action 39 | ``` 40 | 41 | - [ ] Next.js 15 app directory structure 42 | - [ ] Server actions in `app/actions/` 43 | - [ ] Database operations in `lib/data/{queries,mutations}/` 44 | - [ ] shadcn/ui component patterns 45 | - [ ] SOLID principles adherence 46 | - [ ] Clean data access patterns 47 | 48 | ### Database & Data Layer 49 | ```typescript 50 | // ✅ DO: Use Drizzle migrations 51 | // db/migrations/0001_initial.ts 52 | import { sql } from 'drizzle-orm' 53 | 54 | // ❌ DON'T: Manual SQL files 55 | // migrations/manual.sql 56 | CREATE TABLE users... 57 | ``` 58 | 59 | - [ ] Generated Drizzle migrations 60 | - [ ] Proper RLS policies 61 | - [ ] Edge function security 62 | - [ ] PostgreSQL style compliance 63 | - [ ] Type-safe database operations 64 | - [ ] Query optimization 65 | 66 | ### Server Actions & API 67 | ```typescript 68 | // ✅ DO: Proper server action 69 | export async function createUser(input: CreateUserInput) { 70 | const result = await createUserMutation(input); 71 | if (result.error) { 72 | return { error: result.error }; 73 | } 74 | return { data: result.data }; 75 | } 76 | 77 | // ❌ DON'T: Skip validation/typing 78 | export async function createUser(formData: any) { 79 | const user = await db.users.create(formData); 80 | return user; 81 | } 82 | ``` 83 | 84 | - [ ] 'use server' directive present 85 | - [ ] Abstracted database operations 86 | - [ ] Comprehensive error handling 87 | - [ ] Zod schema validation 88 | - [ ] Proper async patterns 89 | - [ ] Appropriate response handling 90 | 91 | ### Security 92 | ```typescript 93 | // ✅ DO: Proper RLS policy 94 | CREATE POLICY "users can only access their own data" 95 | ON public.users 96 | FOR SELECT 97 | USING (auth.uid() = user_id); 98 | 99 | // ❌ DON'T: Skip RLS 100 | CREATE POLICY "allow all" 101 | ON public.users 102 | FOR ALL 103 | USING (true); 104 | ``` 105 | 106 | - [ ] RLS policy implementation 107 | - [ ] Client-side data security 108 | - [ ] Authentication checks 109 | - [ ] Secret management 110 | - [ ] Proper access scoping 111 | 112 | ### Component Structure 113 | ```typescript 114 | // ✅ DO: Proper component structure 115 | import { Button } from '@/components/ui/button' 116 | import { cn } from '@/lib/utils' 117 | 118 | export function CustomButton({ className, ...props }) { 119 | return 29 | 30 | 31 | 32 | Card Title 33 | Card Description 34 | 35 | 36 |

Card Content

37 |
38 | 39 |

Card Footer

40 |
41 |
42 | ``` 43 | 44 | ## Installing Additional Components 45 | 46 | Many more components are available but not currently installed. You can view the complete list at https://ui.shadcn.com/r 47 | 48 | To install additional components, use the Shadcn CLI: 49 | 50 | 51 | ```bash 52 | npx shadcn@latest add [component-name] 53 | ``` 54 | 55 | For example, to add the Accordion component: 56 | 57 | ```bash 58 | npx shadcn@latest add accordion 59 | ``` 60 | 61 | Note: `npx shadcn-ui@latest` is deprecated, use `npx shadcn@latest` instead 62 | 63 | Some commonly used components are 64 | 65 | - Accordion 66 | - Alert 67 | - AlertDialog 68 | - AspectRatio 69 | - Avatar 70 | - Calendar 71 | - Checkbox 72 | - Collapsible 73 | - Command 74 | - ContextMenu 75 | - DataTable 76 | - DatePicker 77 | - Dropdown Menu 78 | - Form 79 | - Hover Card 80 | - Menubar 81 | - Navigation Menu 82 | - Popover 83 | - Progress 84 | - Radio Group 85 | - ScrollArea 86 | - Select 87 | - Separator 88 | - Sheet 89 | - Skeleton 90 | - Slider 91 | - Switch 92 | - Table 93 | - Textarea 94 | - Toast 95 | - Toggle 96 | - Tooltip 97 | 98 | ## Component Styling 99 | 100 | This project uses the "new-york" style variant with the "neutral" base color and CSS variables for theming, as configured in `components.json`. -------------------------------------------------------------------------------- /nextjs/solid-principles.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: 3 | globs: 4 | alwaysApply: false 5 | --- 6 | # SOLID Principles 7 | Guidelines for implementing SOLID principles in the codebase. 8 | 9 | 10 | name: solid_principles 11 | description: Enforces SOLID principles in code design and implementation 12 | filters: 13 | - type: file_extension 14 | pattern: "\\.ts$|\\.js$" 15 | - type: content 16 | pattern: "(?s)class.*?\\{|interface.*?\\{|function.*?\\{" 17 | 18 | actions: 19 | - type: suggest 20 | message: | 21 | When writing code, follow these SOLID principles: 22 | 23 | 1. Single Responsibility Principle (SRP): 24 | - Each class/module should have only one reason to change 25 | - Keep classes focused and cohesive 26 | - Extract separate concerns into their own classes 27 | Example: 28 | ```typescript 29 | // Good: Single responsibility 30 | class UserAuthentication { 31 | authenticate(credentials: Credentials): boolean { ... } 32 | } 33 | class UserProfile { 34 | updateProfile(data: ProfileData): void { ... } 35 | } 36 | 37 | // Bad: Multiple responsibilities 38 | class User { 39 | authenticate(credentials: Credentials): boolean { ... } 40 | updateProfile(data: ProfileData): void { ... } 41 | sendEmail(message: string): void { ... } 42 | } 43 | ``` 44 | 45 | 2. Open/Closed Principle (OCP): 46 | - Classes should be open for extension but closed for modification 47 | - Use interfaces and abstract classes 48 | - Implement new functionality through inheritance/composition 49 | Example: 50 | ```typescript 51 | // Good: Open for extension 52 | interface PaymentProcessor { 53 | process(payment: Payment): void; 54 | } 55 | class CreditCardProcessor implements PaymentProcessor { ... } 56 | class PayPalProcessor implements PaymentProcessor { ... } 57 | 58 | // Bad: Closed for extension 59 | class PaymentProcessor { 60 | process(payment: Payment, type: string): void { 61 | if (type === 'credit') { ... } 62 | else if (type === 'paypal') { ... } 63 | } 64 | } 65 | ``` 66 | 67 | 3. Liskov Substitution Principle (LSP): 68 | - Derived classes must be substitutable for their base classes 69 | - Maintain expected behavior when using inheritance 70 | - Don't violate base class contracts 71 | Example: 72 | ```typescript 73 | // Good: Derived class maintains base contract 74 | class Bird { 75 | fly(): void { ... } 76 | } 77 | class Sparrow extends Bird { 78 | fly(): void { ... } // Implements flying behavior 79 | } 80 | 81 | // Bad: Violates base contract 82 | class Penguin extends Bird { 83 | fly(): void { 84 | throw new Error("Can't fly!"); // Violates base class contract 85 | } 86 | } 87 | ``` 88 | 89 | 4. Interface Segregation Principle (ISP): 90 | - Don't force clients to depend on interfaces they don't use 91 | - Keep interfaces small and focused 92 | - Split large interfaces into smaller ones 93 | Example: 94 | ```typescript 95 | // Good: Segregated interfaces 96 | interface Readable { 97 | read(): void; 98 | } 99 | interface Writable { 100 | write(data: string): void; 101 | } 102 | 103 | // Bad: Fat interface 104 | interface FileSystem { 105 | read(): void; 106 | write(data: string): void; 107 | delete(): void; 108 | create(): void; 109 | modify(): void; 110 | } 111 | ``` 112 | 113 | 5. Dependency Inversion Principle (DIP): 114 | - High-level modules shouldn't depend on low-level modules 115 | - Both should depend on abstractions 116 | - Use dependency injection 117 | Example: 118 | ```typescript 119 | // Good: Depends on abstraction 120 | interface Logger { 121 | log(message: string): void; 122 | } 123 | class UserService { 124 | constructor(private logger: Logger) {} 125 | } 126 | 127 | // Bad: Depends on concrete implementation 128 | class UserService { 129 | private logger = new FileLogger(); 130 | } 131 | ``` 132 | 133 | Additional Guidelines: 134 | - Use interfaces to define contracts 135 | - Implement dependency injection 136 | - Keep classes small and focused 137 | - Use composition over inheritance when possible 138 | - Write unit tests to verify SOLID compliance 139 | 140 | examples: 141 | - input: | 142 | // Bad example - violates SRP and OCP 143 | class OrderProcessor { 144 | processOrder(order: Order) { 145 | // Handles validation 146 | // Handles payment 147 | // Handles shipping 148 | // Handles notification 149 | } 150 | } 151 | output: | 152 | // Good example - follows SOLID principles 153 | interface OrderValidator { 154 | validate(order: Order): boolean; 155 | } 156 | interface PaymentProcessor { 157 | process(order: Order): void; 158 | } 159 | interface ShippingService { 160 | ship(order: Order): void; 161 | } 162 | interface NotificationService { 163 | notify(order: Order): void; 164 | } 165 | 166 | class OrderProcessor { 167 | constructor( 168 | private validator: OrderValidator, 169 | private paymentProcessor: PaymentProcessor, 170 | private shippingService: ShippingService, 171 | private notificationService: NotificationService 172 | ) {} 173 | 174 | processOrder(order: Order) { 175 | if (this.validator.validate(order)) { 176 | this.paymentProcessor.process(order); 177 | this.shippingService.ship(order); 178 | this.notificationService.notify(order); 179 | } 180 | } 181 | } 182 | 183 | metadata: 184 | priority: high 185 | version: 1.0 186 | tags: 187 | - code-quality 188 | - design-patterns 189 | - best-practices 190 | 191 | -------------------------------------------------------------------------------- /nextjs/tailwindcss-4.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Guide for using Tailwind CSS v4 instead of v3.x 3 | globs: **/*.{js,ts,jsx,tsx,mdx,css} 4 | alwaysApply: false 5 | --- 6 | 7 | 8 | # Tailwind CSS v4 9 | 10 | ## Core Changes 11 | 12 | - **CSS-first configuration**: Configuration is now done in CSS instead of JavaScript 13 | - Use `@theme` directive in CSS instead of `tailwind.config.js` 14 | - Example: 15 | ```css 16 | @import "tailwindcss"; 17 | 18 | @theme { 19 | --font-display: "Satoshi", "sans-serif"; 20 | --breakpoint-3xl: 1920px; 21 | --color-avocado-500: oklch(0.84 0.18 117.33); 22 | --ease-fluid: cubic-bezier(0.3, 0, 0, 1); 23 | } 24 | ``` 25 | - Legacy `tailwind.config.js` files can still be imported using the `@config` directive: 26 | ```css 27 | @import "tailwindcss"; 28 | @config "../../tailwind.config.js"; 29 | ``` 30 | - **CSS import syntax**: Use `@import "tailwindcss"` instead of `@tailwind` directives 31 | - Old: `@tailwind base; @tailwind components; @tailwind utilities;` 32 | - New: `@import "tailwindcss";` 33 | 34 | - **Package changes**: 35 | - PostCSS plugin is now `@tailwindcss/postcss` (not `tailwindcss`) 36 | - CLI is now `@tailwindcss/cli` 37 | - Vite plugin is `@tailwindcss/vite` 38 | - No need for `postcss-import` or `autoprefixer` anymore 39 | 40 | - **Native CSS cascade layers**: Uses real CSS `@layer` instead of Tailwind's custom implementation 41 | 42 | ## Theme Configuration 43 | 44 | - **CSS theme variables**: All design tokens are available as CSS variables 45 | - Namespace format: `--category-name` (e.g., `--color-blue-500`, `--font-sans`) 46 | - Access in CSS: `var(--color-blue-500)` 47 | - Available namespaces: 48 | - `--color-*` : Color utilities like `bg-red-500` and `text-sky-300` 49 | - `--font-*` : Font family utilities like `font-sans` 50 | - `--text-*` : Font size utilities like `text-xl` 51 | - `--font-weight-*` : Font weight utilities like `font-bold` 52 | - `--tracking-*` : Letter spacing utilities like `tracking-wide` 53 | - `--leading-*` : Line height utilities like `leading-tight` 54 | - `--breakpoint-*` : Responsive breakpoint variants like `sm:*` 55 | - `--container-*` : Container query variants like `@sm:*` and size utilities like `max-w-md` 56 | - `--spacing-*` : Spacing and sizing utilities like `px-4` and `max-h-16` 57 | - `--radius-*` : Border radius utilities like `rounded-sm` 58 | - `--shadow-*` : Box shadow utilities like `shadow-md` 59 | - `--inset-shadow-*` : Inset box shadow utilities like `inset-shadow-xs` 60 | - `--drop-shadow-*` : Drop shadow filter utilities like `drop-shadow-md` 61 | - `--blur-*` : Blur filter utilities like `blur-md` 62 | - `--perspective-*` : Perspective utilities like `perspective-near` 63 | - `--aspect-*` : Aspect ratio utilities like `aspect-video` 64 | - `--ease-*` : Transition timing function utilities like `ease-out` 65 | - `--animate-*` : Animation utilities like `animate-spin` 66 | 67 | 68 | - **Simplified theme configuration**: Many utilities no longer need theme configuration 69 | - Utilities like `grid-cols-12`, `z-40`, and `opacity-70` work without configuration 70 | - Data attributes like `data-selected:opacity-100` don't need configuration 71 | 72 | - **Dynamic spacing scale**: Derived from a single spacing value 73 | - Default: `--spacing: 0.25rem` 74 | - Every multiple of the base value is available (e.g., `mt-21` works automatically) 75 | 76 | - **Overriding theme namespaces**: 77 | - Override entire namespace: `--font-*: initial;` 78 | - Override entire theme: `--*: initial;` 79 | 80 | 81 | ## New Features 82 | 83 | - **Container query support**: Built-in now, no plugin needed 84 | - `@container` for container context 85 | - `@sm:`, `@md:`, etc. for container-based breakpoints 86 | - `@max-md:` for max-width container queries 87 | - Combine with `@min-md:@max-xl:hidden` for ranges 88 | 89 | - **3D transforms**: 90 | - `transform-3d` enables 3D transforms 91 | - `rotate-x-*`, `rotate-y-*`, `rotate-z-*` for 3D rotation 92 | - `scale-z-*` for z-axis scaling 93 | - `translate-z-*` for z-axis translation 94 | - `perspective-*` utilities (`perspective-near`, `perspective-distant`, etc.) 95 | - `perspective-origin-*` utilities 96 | - `backface-visible` and `backface-hidden` 97 | 98 | - **Gradient enhancements**: 99 | - Linear gradient angles: `bg-linear-45` (renamed from `bg-gradient-*`) 100 | - Gradient interpolation: `bg-linear-to-r/oklch`, `bg-linear-to-r/srgb` 101 | - Conic and radial gradients: `bg-conic`, `bg-radial-[at_25%_25%]` 102 | 103 | - **Shadow enhancements**: 104 | - `inset-shadow-*` and `inset-ring-*` utilities 105 | - Can be composed with regular `shadow-*` and `ring-*` 106 | 107 | - **New CSS property utilities**: 108 | - `field-sizing-content` for auto-resizing textareas 109 | - `scheme-light`, `scheme-dark` for `color-scheme` property 110 | - `font-stretch-*` utilities for variable fonts 111 | 112 | ## New Variants 113 | 114 | - **Composable variants**: Chain variants together 115 | - Example: `group-has-data-potato:opacity-100` 116 | 117 | - **New variants**: 118 | - `starting` variant for `@starting-style` transitions 119 | - `not-*` variant for `:not()` pseudo-class 120 | - `inert` variant for `inert` attribute 121 | - `nth-*` variants (`nth-3:`, `nth-last-5:`, `nth-of-type-4:`, `nth-last-of-type-6:`) 122 | - `in-*` variant (like `group-*` but without adding `group` class) 123 | - `open` variant now supports `:popover-open` 124 | - `**` variant for targeting all descendants 125 | 126 | ## Custom Extensions 127 | 128 | - **Custom utilities**: Use `@utility` directive 129 | ```css 130 | @utility tab-4 { 131 | tab-size: 4; 132 | } 133 | ``` 134 | 135 | - **Custom variants**: Use `@variant` directive 136 | ```css 137 | @variant pointer-coarse (@media (pointer: coarse)); 138 | @variant theme-midnight (&:where([data-theme="midnight"] *)); 139 | ``` 140 | 141 | - **Plugins**: Use `@plugin` directive 142 | ```css 143 | @plugin "@tailwindcss/typography"; 144 | ``` 145 | 146 | ## Breaking Changes 147 | 148 | - **Removed deprecated utilities**: 149 | - `bg-opacity-*` → Use `bg-black/50` instead 150 | - `text-opacity-*` → Use `text-black/50` instead 151 | - And others: `border-opacity-*`, `divide-opacity-*`, etc. 152 | 153 | - **Renamed utilities**: 154 | - `shadow-sm` → `shadow-xs` (and `shadow` → `shadow-sm`) 155 | - `drop-shadow-sm` → `drop-shadow-xs` (and `drop-shadow` → `drop-shadow-sm`) 156 | - `blur-sm` → `blur-xs` (and `blur` → `blur-sm`) 157 | - `rounded-sm` → `rounded-xs` (and `rounded` → `rounded-sm`) 158 | - `outline-none` → `outline-hidden` (for the old behavior) 159 | 160 | - **Default style changes**: 161 | - Default border color is now `currentColor` (was `gray-200`) 162 | - Default `ring` width is now 1px (was 3px) 163 | - Placeholder text now uses current color at 50% opacity (was `gray-400`) 164 | - Hover styles only apply on devices that support hover (`@media (hover: hover)`) 165 | 166 | - **Syntax changes**: 167 | - CSS variables in arbitrary values: `bg-(--brand-color)` instead of `bg-[--brand-color]` 168 | - Stacked variants now apply left-to-right (not right-to-left) 169 | - Use CSS variables instead of `theme()` function 170 | 171 | ## Advanced Configuration 172 | 173 | - **Using a prefix**: 174 | ```css 175 | @import "tailwindcss" prefix(tw); 176 | ``` 177 | - Results in classes like `tw:flex`, `tw:bg-red-500`, `tw:hover:bg-red-600` 178 | 179 | - **Source detection**: 180 | - Automatic by default (ignores `.gitignore` files and binary files) 181 | - Add sources: `@source "../node_modules/@my-company/ui-lib";` 182 | - Disable automatic detection: `@import "tailwindcss" source(none);` 183 | 184 | - **Legacy config files**: 185 | ```css 186 | @import "tailwindcss"; 187 | @config "../../tailwind.config.js"; 188 | ``` 189 | 190 | - **Dark mode configuration**: 191 | ```css 192 | @import "tailwindcss"; 193 | @variant dark (&:where(.dark, .dark *)); 194 | ``` 195 | 196 | - **Container customization**: Extend with `@utility` 197 | ```css 198 | @utility container { 199 | margin-inline: auto; 200 | padding-inline: 2rem; 201 | } 202 | ``` 203 | 204 | - **Using `@apply` in Vue/Svelte**: 205 | ```html 206 | 215 | ``` -------------------------------------------------------------------------------- /open-source/community-projects.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Ensures proper setup of community project files and 3 | globs: 4 | --- 5 | # Community Projects Rule 6 | Standards for initializing and maintaining community-focused open source projects. 7 | 8 | 9 | name: community_projects 10 | description: Ensures proper setup of community project files and documentation 11 | filters: 12 | - type: event 13 | pattern: "project_init|project_validate" 14 | - type: directory 15 | pattern: ".*" 16 | 17 | actions: 18 | - type: validate 19 | description: "Validate required community files" 20 | requirements: 21 | - name: "README.md" 22 | required: true 23 | content: 24 | - "Project title and description" 25 | - "Installation instructions" 26 | - "Usage examples" 27 | - "Contributing guidelines reference" 28 | - "License reference" 29 | - name: "CONTRIBUTING.md" 30 | required: true 31 | content: 32 | - "How to contribute" 33 | - "Development setup" 34 | - "Pull request process" 35 | - "Code style guidelines" 36 | - "Testing requirements" 37 | - name: "LICENSE" 38 | required: true 39 | content: 40 | - "Valid open source license text" 41 | - "Current year" 42 | - "Copyright holder information" 43 | - name: "CODE_OF_CONDUCT.md" 44 | required: true 45 | content: 46 | - "Expected behavior" 47 | - "Unacceptable behavior" 48 | - "Reporting process" 49 | - "Enforcement guidelines" 50 | - "Contact information" 51 | 52 | - type: suggest 53 | message: | 54 | When setting up a community project, ensure: 55 | 56 | 1. README.md contains: 57 | ```markdown 58 | # Project Name 59 | 60 | Brief description of the project. 61 | 62 | ## Installation 63 | 64 | Step-by-step installation instructions. 65 | 66 | ## Usage 67 | 68 | Basic usage examples. 69 | 70 | ## Contributing 71 | 72 | Please read [CONTRIBUTING.md](mdc:CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests. 73 | 74 | ## License 75 | 76 | This project is licensed under the [LICENSE_NAME] - see the [LICENSE](mdc:LICENSE) file for details. 77 | ``` 78 | 79 | 2. CONTRIBUTING.md contains: 80 | ```markdown 81 | # Contributing Guidelines 82 | 83 | ## Development Setup 84 | [Development environment setup instructions] 85 | 86 | ## Pull Request Process 87 | 1. Update documentation 88 | 2. Update tests 89 | 3. Follow code style 90 | 4. Get reviews 91 | 92 | ## Code Style 93 | [Code style guidelines] 94 | 95 | ## Testing 96 | [Testing requirements and instructions] 97 | ``` 98 | 99 | 3. LICENSE file: 100 | - Choose appropriate license (MIT, Apache 2.0, etc.) 101 | - Include current year 102 | - Include copyright holder 103 | 104 | 4. CODE_OF_CONDUCT.md: 105 | - Based on Contributor Covenant 106 | - Include contact information 107 | - Clear enforcement guidelines 108 | 109 | examples: 110 | - input: | 111 | # Bad: Missing required files 112 | my-project/ 113 | ├── src/ 114 | └── README.md 115 | 116 | # Good: Complete community project setup 117 | my-project/ 118 | ├── src/ 119 | ├── README.md 120 | ├── CONTRIBUTING.md 121 | ├── LICENSE 122 | └── CODE_OF_CONDUCT.md 123 | output: "Properly configured community project" 124 | 125 | metadata: 126 | priority: high 127 | version: 1.0 128 | tags: 129 | - community 130 | - documentation 131 | - open-source 132 | 133 | -------------------------------------------------------------------------------- /open-source/conventional-commits.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Automatically commit changes using conventional commits format 3 | globs: 4 | --- 5 | # Conventional Commits Rule 6 | 7 | ## Description 8 | This rule defines the format and structure for commit messages following the Conventional Commits 1.0.0 specification. It ensures consistent, semantic, and machine-readable commit messages. 9 | 10 | ## Rule Type 11 | workflow 12 | 13 | ## Rule Format 14 | ```json 15 | { 16 | "type": "workflow", 17 | "name": "conventional_commits", 18 | "description": "Enforces Conventional Commits 1.0.0 specification", 19 | "filters": [ 20 | { 21 | "type": "event", 22 | "pattern": "pre_commit" 23 | } 24 | ], 25 | "steps": [ 26 | { 27 | "action": "validate", 28 | "description": "Validate commit message format", 29 | "requirements": [ 30 | "Message MUST be prefixed with a type", 31 | "Type MUST be one of: feat, fix, docs, style, refactor, perf, test, build, ci, chore", 32 | "Scope is OPTIONAL and MUST be in parentheses", 33 | "Description MUST immediately follow the colon and space", 34 | "Description MUST use imperative mood ('add' not 'added')", 35 | "Description MUST be less than 100 characters", 36 | "Breaking changes MUST be indicated by '!' or 'BREAKING CHANGE:' footer", 37 | "Body MUST be separated from description by one blank line", 38 | "Footer MUST be separated from body by one blank line" 39 | ] 40 | }, 41 | { 42 | "action": "execute", 43 | "description": "Format and create commit", 44 | "script": { 45 | "detect_type": { 46 | "feat": ["add", "create", "implement", "introduce"], 47 | "fix": ["fix", "correct", "resolve", "patch"], 48 | "docs": ["document", "comment", "update.*docs"], 49 | "style": ["style", "format", "lint"], 50 | "refactor": ["refactor", "restructure", "reorganize"], 51 | "perf": ["optimize", "performance", "improve.*speed"], 52 | "test": ["test", "spec", "coverage"], 53 | "build": ["build", "dependency", "package"], 54 | "ci": ["ci", "pipeline", "workflow"], 55 | "chore": ["chore", "misc", "task"] 56 | }, 57 | "format_message": { 58 | "template": "${type}${scope}: ${description}\n\n${body}\n\n${footer}", 59 | "variables": { 60 | "type": "Detected from changes or user input", 61 | "scope": "Optional, derived from file paths", 62 | "description": "First line of commit message", 63 | "body": "Detailed explanation of changes", 64 | "footer": "Optional references or breaking changes" 65 | } 66 | }, 67 | "command": [ 68 | "# Extract type from changes or prompt user", 69 | "TYPE=$(detect_change_type \"$CHANGES\" || prompt_user \"Enter commit type:\")", 70 | "", 71 | "# Extract scope from file paths", 72 | "SCOPE=$(get_common_path \"$CHANGED_FILES\")", 73 | "", 74 | "# Format the commit message", 75 | "printf \"%s\\n\\n%s\\n\\n%s\" \"$TYPE${SCOPE:+($SCOPE)}: $DESCRIPTION\" \"$BODY\" \"$FOOTER\" > \"$COMMIT_MSG_FILE\"" 76 | ] 77 | } 78 | } 79 | ] 80 | } 81 | ``` 82 | 83 | ## Manual Commit Syntax 84 | When creating commits manually, always use the printf syntax to properly handle newlines and formatting: 85 | 86 | ```bash 87 | printf "type(scope): description\n\nbody of the commit explaining the changes in detail\n\nfooter information" | git commit -F - 88 | ``` 89 | 90 | For example: 91 | ```bash 92 | printf "feat(auth): add OAuth2 support\n\nAdd Google and GitHub provider integration\nImplement token refresh handling\nAdd user profile synchronization\n\nCloses #123" | git commit -F - 93 | ``` 94 | 95 | This ensures proper formatting and newline handling in the commit message. 96 | 97 | ## Examples 98 | 99 | ### Feature with Scope 100 | ``` 101 | feat(auth): implement OAuth2 support 102 | 103 | - Add Google and GitHub provider integration 104 | - Implement token refresh handling 105 | - Add user profile synchronization 106 | 107 | Closes #123 108 | ``` 109 | 110 | ### Bug Fix with Breaking Change 111 | ``` 112 | fix(api): update user serialization 113 | 114 | - Modify user data structure for better consistency 115 | - Add validation for new fields 116 | 117 | BREAKING CHANGE: user.fullName split into firstName and lastName 118 | ``` 119 | 120 | ### Documentation Update 121 | ``` 122 | docs(readme): add modern package manager instructions 123 | 124 | - Add yarn and pnpm installation methods 125 | - Update minimum Node.js version requirement 126 | ``` 127 | 128 | ### Performance Improvement 129 | ``` 130 | perf(core): optimize database queries 131 | 132 | - Add query result caching 133 | - Implement proper indexing 134 | - Reduce unnecessary joins 135 | 136 | Closes #456 137 | ``` 138 | 139 | ## Integration 140 | This rule should be used in conjunction with the git-commit-workflow rule to ensure changes are properly reviewed before creating the commit message. The workflow should be: 141 | 142 | 1. Review changes (git-commit-workflow) 143 | 2. Format commit message (conventional-commits) 144 | 3. Validate commit message (conventional-commits) 145 | 4. Commit changes 146 | -------------------------------------------------------------------------------- /supabase/drizzle-migrations.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Guidelines for generating and managing database migrations using drizzle-kit 3 | globs: ["db/migrations/*.sql"] 4 | alwaysApply: true 5 | --- 6 | 7 | # Drizzle Migration Guidelines 8 | 9 | ## Migration Generation 10 | - **ALWAYS use `npm run generate` to create migrations** 11 | - Never create migration files manually 12 | - This ensures consistent migration file naming and structure 13 | - Drizzle-kit will automatically detect schema changes 14 | - Example: `npm run generate` will execute drizzle-kit generate command 15 | 16 | ## Migration Best Practices 17 | - **Review Generated Migrations** 18 | ```sql 19 | -- ✅ DO: Review and verify generated migrations 20 | ALTER TABLE "customers" ADD COLUMN "status" text DEFAULT 'new_customer'; 21 | 22 | -- ❌ DON'T: Manually modify generated migration files 23 | -- Let drizzle-kit handle the migration generation 24 | ``` 25 | 26 | - **Version Control** 27 | - Commit migration files along with schema changes 28 | - Never modify committed migrations 29 | - Create new migrations for additional changes 30 | 31 | ## Migration Commands 32 | - `npm run generate` - Generate new migrations 33 | - `npm run migrate` - Apply pending migrations 34 | - `npm run studio` - Open Drizzle Studio for database inspection 35 | 36 | ## Migration Workflow 37 | 1. Make changes to schema files in `db/schema/` 38 | 2. Run `npm run generate` to create migration 39 | 3. Review generated migration file 40 | 4. Run `npm run migrate` to apply changes 41 | 5. Commit both schema and migration files 42 | 43 | ## References 44 | - [Drizzle Kit Documentation](mdc:https:/orm.drizzle.team/kit-docs/overview) 45 | - See also: [supabase-drizzle-bootstrap.mdc](mdc:.cursor/rules/supabase-drizzle-bootstrap.mdc) 46 | -------------------------------------------------------------------------------- /supabase/drizzle-queries.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: 3 | globs: 4 | alwaysApply: false 5 | --- 6 | # Drizzle Query Patterns 7 | Guidelines for writing consistent and secure Drizzle ORM queries with RLS. 8 | 9 | ## Overview 10 | This rule defines patterns for writing Drizzle ORM queries and mutations that respect Row Level Security (RLS) policies. 11 | 12 | 13 | name: drizzle_queries 14 | description: Guidelines for writing Drizzle ORM queries with RLS 15 | filters: 16 | - type: file_extension 17 | pattern: "\\.(ts|js)$" 18 | - type: content 19 | pattern: "drizzle-orm|createDrizzleSupabaseClient" 20 | 21 | actions: 22 | - type: suggest 23 | message: | 24 | When writing Drizzle queries: 25 | 26 | 1. Query Structure: 27 | ```typescript 28 | // ✅ DO: Use simple, direct queries with RLS 29 | export async function getItems() { 30 | const db = await createDrizzleSupabaseClient() 31 | const result = await db.rls(async (tx) => { 32 | return await tx.select().from(items) 33 | }) 34 | return result 35 | } 36 | 37 | // ❌ DON'T: Add unnecessary complexity or manual auth checks 38 | export async function getItems() { 39 | const supabase = await createClient() // ❌ Don't use Supabase client directly 40 | const { data: { user } } = await supabase.auth.getUser() 41 | if (!user) throw new Error('Not authenticated') 42 | // ... more unnecessary checks 43 | } 44 | ``` 45 | 46 | 2. Mutations: 47 | ```typescript 48 | // ✅ DO: Return the mutated record when possible 49 | export async function createItem(data: NewItem) { 50 | const db = await createDrizzleSupabaseClient() 51 | const result = await db.rls(async (tx) => { 52 | const [item] = await tx.insert(items) 53 | .values(data) 54 | .returning() 55 | return item 56 | }) 57 | return result 58 | } 59 | 60 | // ❌ DON'T: Return void or boolean when you can return the record 61 | export async function createItem(data: NewItem) { 62 | const db = await createDrizzleSupabaseClient() 63 | await db.rls(async (tx) => { 64 | await tx.insert(items).values(data) 65 | }) 66 | return true // ❌ Less useful than returning the record 67 | } 68 | ``` 69 | 70 | 3. Type Safety: 71 | ```typescript 72 | // ✅ DO: Use schema types and type assertions 73 | export async function updateItem(id: string, data: Partial) { 74 | const db = await createDrizzleSupabaseClient() 75 | const result = await db.rls(async (tx) => { 76 | const [item] = await tx.update(items) 77 | .set(data) 78 | .where(eq(items.id, id)) 79 | .returning() 80 | return item 81 | }) 82 | return result 83 | } 84 | 85 | // ❌ DON'T: Use any or unknown types 86 | export async function updateItem(id: string, data: any) { 87 | // ... 88 | } 89 | ``` 90 | 91 | 4. Single Record Queries: 92 | ```typescript 93 | // ✅ DO: Use limit(1) and array destructuring 94 | export async function getItemById(id: string) { 95 | const db = await createDrizzleSupabaseClient() 96 | const result = await db.rls(async (tx) => { 97 | const [item] = await tx.select() 98 | .from(items) 99 | .where(eq(items.id, id)) 100 | .limit(1) 101 | return item 102 | }) 103 | return result 104 | } 105 | 106 | // ❌ DON'T: Return array for single record queries 107 | export async function getItemById(id: string) { 108 | const db = await createDrizzleSupabaseClient() 109 | const result = await db.rls(async (tx) => { 110 | return await tx.select() 111 | .from(items) 112 | .where(eq(items.id, id)) 113 | }) 114 | return result[0] // ❌ Less explicit than using limit(1) 115 | } 116 | ``` 117 | 118 | 5. Error Handling: 119 | ```typescript 120 | // ✅ DO: Let RLS handle authorization 121 | export async function deleteItem(id: string) { 122 | const db = await createDrizzleSupabaseClient() 123 | await db.rls(async (tx) => { 124 | await tx.delete(items) 125 | .where(eq(items.id, id)) 126 | }) 127 | return true 128 | } 129 | 130 | // ❌ DON'T: Add manual auth checks 131 | export async function deleteItem(id: string) { 132 | const db = await createDrizzleSupabaseClient() 133 | // ❌ Don't check auth manually, RLS handles this 134 | const user = await getCurrentUser() 135 | if (!user.canDelete) throw new Error('Not authorized') 136 | // ... 137 | } 138 | ``` 139 | 140 | 6. Query Organization: 141 | - Keep queries in `lib/data/queries` directory 142 | - Keep mutations in `lib/data/mutations` directory 143 | - Name files after the primary table they operate on 144 | - Export functions with clear, action-based names 145 | 146 | 7. Cache Invalidation: 147 | ```typescript 148 | // ✅ DO: Use revalidatePath after mutations when needed 149 | export async function updateItem(id: string, data: Partial) { 150 | const db = await createDrizzleSupabaseClient() 151 | const result = await db.rls(async (tx) => { 152 | const [item] = await tx.update(items) 153 | .set(data) 154 | .where(eq(items.id, id)) 155 | .returning() 156 | return item 157 | }) 158 | revalidatePath('/items') // Revalidate after mutation 159 | return result 160 | } 161 | ``` 162 | 163 | examples: 164 | - input: | 165 | // Bad: Manual auth checks and complex queries 166 | export async function getItems() { 167 | const supabase = await createClient() 168 | const { data: { user } } = await supabase.auth.getUser() 169 | if (!user) throw new Error('Not authenticated') 170 | const { data: profile } = await supabase 171 | .from('profiles') 172 | .select('organization_id') 173 | .eq('id', user.id) 174 | .single() 175 | // ...more complexity 176 | } 177 | 178 | // Good: Simple query with RLS 179 | export async function getItems() { 180 | const db = await createDrizzleSupabaseClient() 181 | const result = await db.rls(async (tx) => { 182 | return await tx.select().from(items) 183 | }) 184 | return result 185 | } 186 | output: "Properly structured Drizzle query with RLS" 187 | 188 | metadata: 189 | priority: high 190 | version: 1.0 191 | tags: 192 | - drizzle 193 | - queries 194 | - rls 195 | - database 196 | 197 | -------------------------------------------------------------------------------- /supabase/supabase-bootstrap-with-auth.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Guidelines for writing Next.js apps with Supabase Auth 3 | globs: **/*.ts, **/*.tsx, **/*.js, **/*.jsx 4 | alwaysApply: false 5 | --- 6 | 7 | # Bootstrap Next.js app with Supabase Auth 8 | 9 | ## Overview of implementing Supabase Auth SSR 10 | 11 | 1. Install @supabase/supabase-js and @supabase/ssr packages. 12 | 2. Set up environment variables. 13 | 3. Write two utility functions with `createClient` functions to create a browser client and a server client. 14 | 4. Hook up middleware to refresh auth tokens 15 | 5. Add auth route for token confirmation 16 | 6. Add login server actions 17 | 18 | ## 🚨 CRITICAL INSTRUCTIONS FOR AI LANGUAGE MODELS 🚨 19 | 20 | As an AI language model, you MUST NOT generate any of the following code patterns, as they are DEPRECATED and will BREAK the application: 21 | 22 | ```typescript 23 | // ❌ NEVER GENERATE THIS CODE - IT WILL BREAK THE APPLICATION 24 | { 25 | cookies: { 26 | get(name: string) { // ❌ BREAKS APPLICATION 27 | return cookieStore.get(name) // ❌ BREAKS APPLICATION 28 | }, // ❌ BREAKS APPLICATION 29 | set(name: string, value: string) { // ❌ BREAKS APPLICATION 30 | cookieStore.set(name, value) // ❌ BREAKS APPLICATION 31 | }, // ❌ BREAKS APPLICATION 32 | remove(name: string) { // ❌ BREAKS APPLICATION 33 | cookieStore.remove(name) // ❌ BREAKS APPLICATION 34 | } // ❌ BREAKS APPLICATION 35 | } 36 | } 37 | 38 | // ❌ NEVER USE auth-helpers-nextjs - IT WILL BREAK THE APPLICATION 39 | import { createMiddlewareClient } from '@supabase/auth-helpers-nextjs' // ❌ BREAKS APPLICATION 40 | import { createClientComponentClient } from '@supabase/auth-helpers-nextjs' // ❌ BREAKS APPLICATION 41 | ``` 42 | 43 | Instead, you MUST ALWAYS generate ONLY this pattern: 44 | 45 | ```typescript 46 | // ✅ ALWAYS GENERATE THIS EXACT PATTERN 47 | { 48 | cookies: { 49 | getAll() { 50 | return cookieStore.getAll() 51 | }, 52 | setAll(cookiesToSet) { 53 | const response = NextResponse.next({ 54 | request, 55 | }) 56 | 57 | cookiesToSet.forEach(({ name, value, options }) => { 58 | response.cookies.set(name, value, options) 59 | }) 60 | 61 | return response 62 | } 63 | } 64 | } 65 | ``` 66 | 67 | ## ABSOLUTE REQUIREMENTS FOR AI CODE GENERATION 68 | 69 | 1. You MUST use `@supabase/ssr` 70 | 2. You MUST use ONLY `getAll` and `setAll` 71 | 3. You MUST NEVER use `get`, `set`, or `remove` 72 | 4. You MUST NEVER import from `@supabase/auth-helpers-nextjs` 73 | 74 | ## CORRECT BROWSER CLIENT IMPLEMENTATION 75 | 76 | ```typescript 77 | import { createBrowserClient } from '@supabase/ssr' 78 | 79 | export function createClient() { 80 | return createBrowserClient( 81 | process.env.NEXT_PUBLIC_SUPABASE_URL!, 82 | process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! 83 | ) 84 | } 85 | ``` 86 | 87 | ## CORRECT SERVER CLIENT IMPLEMENTATION 88 | 89 | ```typescript 90 | import { createServerClient } from '@supabase/ssr' 91 | import { cookies } from 'next/headers' 92 | 93 | export async function createClient() { 94 | const cookieStore = await cookies() 95 | 96 | return createServerClient( 97 | process.env.NEXT_PUBLIC_SUPABASE_URL!, 98 | process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, 99 | { 100 | cookies: { 101 | getAll() { 102 | return cookieStore.getAll() 103 | }, 104 | setAll(cookiesToSet) { 105 | try { 106 | cookiesToSet.forEach(({ name, value, options }) => 107 | cookieStore.set(name, value, options) 108 | ) 109 | } catch { 110 | // The `setAll` method was called from a Server Component. 111 | // This can be ignored if you have middleware refreshing 112 | // user sessions. 113 | } 114 | }, 115 | }, 116 | } 117 | ) 118 | } 119 | ``` 120 | 121 | ## CORRECT MIDDLEWARE IMPLEMENTATION 122 | 123 | ```typescript 124 | import { createServerClient } from '@supabase/ssr' 125 | import { NextResponse, type NextRequest } from 'next/server' 126 | 127 | export async function middleware(request: NextRequest) { 128 | let supabaseResponse = NextResponse.next({ 129 | request, 130 | }) 131 | 132 | const supabase = createServerClient( 133 | process.env.NEXT_PUBLIC_SUPABASE_URL!, 134 | process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, 135 | { 136 | cookies: { 137 | getAll() { 138 | return request.cookies.getAll() 139 | }, 140 | setAll(cookiesToSet) { 141 | cookiesToSet.forEach(({ name, value, options }) => request.cookies.set(name, value)) 142 | supabaseResponse = NextResponse.next({ 143 | request, 144 | }) 145 | cookiesToSet.forEach(({ name, value, options }) => 146 | supabaseResponse.cookies.set(name, value, options) 147 | ) 148 | }, 149 | }, 150 | } 151 | ) 152 | 153 | // Do not run code between createServerClient and 154 | // supabase.auth.getUser(). A simple mistake could make it very hard to debug 155 | // issues with users being randomly logged out. 156 | 157 | // IMPORTANT: DO NOT REMOVE auth.getUser() 158 | 159 | const { 160 | data: { user }, 161 | } = await supabase.auth.getUser() 162 | 163 | if ( 164 | !user && 165 | !request.nextUrl.pathname.startsWith('/login') && 166 | !request.nextUrl.pathname.startsWith('/auth') 167 | ) { 168 | // no user, potentially respond by redirecting the user to the login page 169 | const url = request.nextUrl.clone() 170 | url.pathname = '/login' 171 | return NextResponse.redirect(url) 172 | } 173 | 174 | // IMPORTANT: You *must* return the supabaseResponse object as it is. 175 | // If you're creating a new response object with NextResponse.next() make sure to: 176 | // 1. Pass the request in it, like so: 177 | // const myNewResponse = NextResponse.next({ request }) 178 | // 2. Copy over the cookies, like so: 179 | // myNewResponse.cookies.setAll(supabaseResponse.cookies.getAll()) 180 | // 3. Change the myNewResponse object to fit your needs, but avoid changing 181 | // the cookies! 182 | // 4. Finally: 183 | // return myNewResponse 184 | // If this is not done, you may be causing the browser and server to go out 185 | // of sync and terminate the user's session prematurely! 186 | 187 | return supabaseResponse 188 | } 189 | ``` 190 | 191 | ## CORRECT ROOT MIDDLEWARE IMPLEMENTATION 192 | ```typescript 193 | import { type NextRequest } from "next/server" 194 | import { updateSession } from "@/utils/supabase/middleware" 195 | 196 | export async function middleware(request: NextRequest) { 197 | return await updateSession(request) 198 | } 199 | 200 | // Specify which routes should be protected by the middleware 201 | export const config = { 202 | matcher: [ 203 | /* 204 | * Match all request paths except: 205 | * - _next/static (static files) 206 | * - _next/image (image optimization files) 207 | * - favicon.ico (favicon file) 208 | * - public folder 209 | * - public files 210 | */ 211 | "/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)", 212 | ], 213 | } 214 | ``` 215 | 216 | ## AUTH ROUTE FOR TOKEN VERIFICATION to @/app/auth/confirm/route.ts 217 | ```typescript 218 | import { type EmailOtpType } from "@supabase/supabase-js" 219 | import { type NextRequest, NextResponse } from "next/server" 220 | 221 | import { createClient } from "@/utils/supabase/server" 222 | 223 | // Creating a handler to a GET request to route /auth/confirm 224 | export async function GET(request: NextRequest) { 225 | const { searchParams } = new URL(request.url) 226 | const token_hash = searchParams.get("token_hash") 227 | const type = searchParams.get("type") as EmailOtpType | null 228 | const next = "/" 229 | 230 | // Create redirect link without the secret token 231 | const redirectTo = request.nextUrl.clone() 232 | redirectTo.pathname = next 233 | redirectTo.searchParams.delete("token_hash") 234 | redirectTo.searchParams.delete("type") 235 | 236 | if (token_hash && type) { 237 | const supabase = await createClient() 238 | 239 | const { error } = await supabase.auth.verifyOtp({ 240 | type, 241 | token_hash, 242 | }) 243 | if (!error) { 244 | redirectTo.searchParams.delete("next") 245 | return NextResponse.redirect(redirectTo) 246 | } 247 | } 248 | 249 | // return the user to an error page with some instructions 250 | redirectTo.pathname = "/error" 251 | return NextResponse.redirect(redirectTo) 252 | } 253 | ``` 254 | 255 | ## LOGIN SERVER ACTIONS IN @/app/actions/login.ts 256 | ```typescript 257 | "use server" 258 | import { createClient } from "@/utils/supabase/server" 259 | import { redirect } from "next/navigation" 260 | 261 | export async function signIn(formData: FormData) { 262 | const email = formData.get("email") as string 263 | const password = formData.get("password") as string 264 | 265 | const supabase = await createClient() 266 | 267 | const { 268 | error, 269 | data: { user }, 270 | } = await supabase.auth.signInWithPassword({ 271 | email, 272 | password, 273 | }) 274 | console.log("attempting to login", user) 275 | if (error) { 276 | return redirect("/login?error=Invalid credentials") 277 | } 278 | console.log("logged in", user) 279 | const { error: profileError, data } = await supabase 280 | .from("profiles") 281 | .select("*") 282 | .eq("id", user?.id) 283 | console.log("profile", data, profileError) 284 | if (profileError) { 285 | return redirect("/login?error=Could not get profile") 286 | } 287 | console.log("profile", data) 288 | if (data[0].avatar_url === null) { 289 | return redirect("/login/avatar") 290 | } 291 | 292 | return redirect("/") 293 | } 294 | 295 | export async function signUp(formData: FormData) { 296 | const name = formData.get("name") as string 297 | const email = formData.get("email") as string 298 | const password = formData.get("password") as string 299 | 300 | const supabase = await createClient() 301 | 302 | const { 303 | error, 304 | data: { user }, 305 | } = await supabase.auth.signUp({ 306 | email, 307 | password, 308 | options: { 309 | emailRedirectTo: `${process.env.NEXT_PUBLIC_SITE_URL}/auth/callback`, 310 | }, 311 | }) 312 | 313 | if (error) { 314 | return redirect("/login?error=Could not sign up") 315 | } 316 | 317 | await supabase 318 | .from("profiles") 319 | .update({ 320 | full_name: name, 321 | }) 322 | .eq("id", user?.id) 323 | 324 | return redirect("/login?message=Check email to continue sign in process") 325 | } 326 | 327 | export async function signOut() { 328 | const supabase = await createClient() 329 | await supabase.auth.signOut() 330 | return redirect("/login") 331 | } 332 | 333 | ``` 334 | 335 | ## AI MODEL VERIFICATION STEPS 336 | 337 | Before generating any code, you MUST verify: 338 | 339 | 1. Are you using ONLY `getAll` and `setAll`? If not, STOP and FIX. 340 | 2. Are you importing from `@supabase/ssr`? If not, STOP and FIX. 341 | 3. Do you see ANY instance of `get`, `set`, or `remove`? If yes, STOP and FIX. 342 | 4. Are you importing from `auth-helpers-nextjs`? If yes, STOP and FIX. 343 | 5. Did you place the `client.ts`, `server.ts` and `middleware.ts` in the location `@/utils/supabase`? If not, STOP and FIX. 344 | 6. Did you place the auth confirmation `route.ts` in the location `@/app/auth/confirm`? If not, STOP and FIX. 345 | 7. Did you place the login server actions `login.ts` in the location `@/app/actions`? If not, STOP and FIX. 346 | 347 | ## CONSEQUENCES OF INCORRECT IMPLEMENTATION 348 | 349 | If you generate code using: 350 | - Individual cookie methods (`get`/`set`/`remove`) 351 | - `auth-helpers-nextjs` package 352 | 353 | The implementation will: 354 | 1. Break in production 355 | 2. Fail to maintain session state 356 | 3. Cause authentication loops 357 | 4. Result in security vulnerabilities 358 | 359 | ## AI MODEL RESPONSE TEMPLATE 360 | 361 | When asked about Supabase Auth SSR implementation, you MUST: 362 | 1. ONLY use code from this guide 363 | 2. NEVER suggest deprecated approaches 364 | 3. ALWAYS use the exact cookie handling shown above 365 | 4. VERIFY your response against the patterns shown here 366 | 367 | Remember: There are NO EXCEPTIONS to these rules. 368 | -------------------------------------------------------------------------------- /supabase/supabase-create-functions.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Guidelines for writing Supabase database functions 3 | globs: **/*.sql 4 | alwaysApply: false 5 | --- 6 | 7 | # Database: Create functions 8 | 9 | You're a Supabase Postgres expert in writing database functions. Generate **high-quality PostgreSQL functions** that adhere to the following best practices: 10 | 11 | ## General Guidelines 12 | 13 | 1. **Default to `SECURITY INVOKER`:** 14 | 15 | - Functions should run with the permissions of the user invoking the function, ensuring safer access control. 16 | - Use `SECURITY DEFINER` only when explicitly required and explain the rationale. 17 | 18 | 2. **Set the `search_path` Configuration Parameter:** 19 | 20 | - Always set `search_path` to an empty string (`set search_path = '';`). 21 | - This avoids unexpected behavior and security risks caused by resolving object references in untrusted or unintended schemas. 22 | - Use fully qualified names (e.g., `schema_name.table_name`) for all database objects referenced within the function. 23 | 24 | 3. **Adhere to SQL Standards and Validation:** 25 | - Ensure all queries within the function are valid PostgreSQL SQL queries and compatible with the specified context (ie. Supabase). 26 | 27 | ## Best Practices 28 | 29 | 1. **Minimize Side Effects:** 30 | 31 | - Prefer functions that return results over those that modify data unless they serve a specific purpose (e.g., triggers). 32 | 33 | 2. **Use Explicit Typing:** 34 | 35 | - Clearly specify input and output types, avoiding ambiguous or loosely typed parameters. 36 | 37 | 3. **Default to Immutable or Stable Functions:** 38 | 39 | - Where possible, declare functions as `IMMUTABLE` or `STABLE` to allow better optimization by PostgreSQL. Use `VOLATILE` only if the function modifies data or has side effects. 40 | 41 | 4. **Triggers (if Applicable):** 42 | - If the function is used as a trigger, include a valid `CREATE TRIGGER` statement that attaches the function to the desired table and event (e.g., `BEFORE INSERT`). 43 | 44 | ## Example Templates 45 | 46 | ### Simple Function with `SECURITY INVOKER` 47 | 48 | ```sql 49 | create or replace function my_schema.hello_world() 50 | returns text 51 | language plpgsql 52 | security invoker 53 | set search_path = '' 54 | as $$ 55 | begin 56 | return 'hello world'; 57 | end; 58 | $$; 59 | ``` 60 | 61 | ### Function with Parameters and Fully Qualified Object Names 62 | 63 | ```sql 64 | create or replace function public.calculate_total_price(order_id bigint) 65 | returns numeric 66 | language plpgsql 67 | security invoker 68 | set search_path = '' 69 | as $$ 70 | declare 71 | total numeric; 72 | begin 73 | select sum(price * quantity) 74 | into total 75 | from public.order_items 76 | where order_id = calculate_total_price.order_id; 77 | 78 | return total; 79 | end; 80 | $$; 81 | ``` 82 | 83 | ### Function as a Trigger 84 | 85 | ```sql 86 | create or replace function my_schema.update_updated_at() 87 | returns trigger 88 | language plpgsql 89 | security invoker 90 | set search_path = '' 91 | as $$ 92 | begin 93 | -- Update the "updated_at" column on row modification 94 | new.updated_at := now(); 95 | return new; 96 | end; 97 | $$; 98 | 99 | create trigger update_updated_at_trigger 100 | before update on my_schema.my_table 101 | for each row 102 | execute function my_schema.update_updated_at(); 103 | ``` 104 | 105 | ### Function with Error Handling 106 | 107 | ```sql 108 | create or replace function my_schema.safe_divide(numerator numeric, denominator numeric) 109 | returns numeric 110 | language plpgsql 111 | security invoker 112 | set search_path = '' 113 | as $$ 114 | begin 115 | if denominator = 0 then 116 | raise exception 'Division by zero is not allowed'; 117 | end if; 118 | 119 | return numerator / denominator; 120 | end; 121 | $$; 122 | ``` 123 | 124 | ### Immutable Function for Better Optimization 125 | 126 | ```sql 127 | create or replace function my_schema.full_name(first_name text, last_name text) 128 | returns text 129 | language sql 130 | security invoker 131 | set search_path = '' 132 | immutable 133 | as $$ 134 | select first_name || ' ' || last_name; 135 | $$; 136 | ``` 137 | -------------------------------------------------------------------------------- /supabase/supabase-create-migration.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Guidelines for writing Postgres migrations 3 | globs: supabase/migrations/**/*.sql 4 | alwaysApply: false 5 | --- 6 | 7 | # Database: Create migration 8 | 9 | You are a Postgres Expert who loves creating secure database schemas. 10 | 11 | This project uses the migrations provided by the Supabase CLI. 12 | 13 | ## Creating a migration file 14 | 15 | Given the context of the user's message, create a database migration file inside the folder `supabase/migrations/`. 16 | 17 | The file MUST following this naming convention: 18 | 19 | The file MUST be named in the format `YYYYMMDDHHmmss_short_description.sql` with proper casing for months, minutes, and seconds in UTC time: 20 | 21 | 1. `YYYY` - Four digits for the year (e.g., `2024`). 22 | 2. `MM` - Two digits for the month (01 to 12). 23 | 3. `DD` - Two digits for the day of the month (01 to 31). 24 | 4. `HH` - Two digits for the hour in 24-hour format (00 to 23). 25 | 5. `mm` - Two digits for the minute (00 to 59). 26 | 6. `ss` - Two digits for the second (00 to 59). 27 | 7. Add an appropriate description for the migration. 28 | 29 | For example: 30 | 31 | ``` 32 | 20240906123045_create_profiles.sql 33 | ``` 34 | 35 | 36 | ## SQL Guidelines 37 | 38 | Write Postgres-compatible SQL code for Supabase migration files that: 39 | 40 | - Includes a header comment with metadata about the migration, such as the purpose, affected tables/columns, and any special considerations. 41 | - Includes thorough comments explaining the purpose and expected behavior of each migration step. 42 | - Write all SQL in lowercase. 43 | - Add copious comments for any destructive SQL commands, including truncating, dropping, or column alterations. 44 | - When creating a new table, you MUST enable Row Level Security (RLS) even if the table is intended for public access. 45 | - When creating RLS Policies 46 | - Ensure the policies cover all relevant access scenarios (e.g. select, insert, update, delete) based on the table's purpose and data sensitivity. 47 | - If the table is intended for public access the policy can simply return `true`. 48 | - RLS Policies should be granular: one policy for `select`, one for `insert` etc) and for each supabase role (`anon` and `authenticated`). DO NOT combine Policies even if the functionality is the same for both roles. 49 | - Include comments explaining the rationale and intended behavior of each security policy 50 | 51 | The generated SQL code should be production-ready, well-documented, and aligned with Supabase's best practices. 52 | -------------------------------------------------------------------------------- /supabase/supabase-drizzle-bootstrap.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Guidelines for setting up and using Drizzle ORM with Supabase PostgreSQL 3 | globs: *.ts, *.js 4 | alwaysApply: false 5 | --- 6 | # Bootstrap Drizzle with Supabase 7 | 8 | ## Overview 9 | Guidelines for setting up and using Drizzle ORM with Supabase PostgreSQL. 10 | 11 | 12 | name: supabase_drizzle_bootstrap 13 | description: Guidelines for setting up and using Drizzle ORM with Supabase PostgreSQL 14 | filters: 15 | - type: file_extension 16 | pattern: "\\.(ts|js)$" 17 | - type: content 18 | pattern: "drizzle-orm|@supabase/supabase-js" 19 | 20 | actions: 21 | - type: suggest 22 | message: | 23 | When setting up Drizzle with Supabase: 24 | 25 | 1. Install required dependencies: 26 | ```bash 27 | npm install drizzle-orm pg @types/pg postgres jwt-decode 28 | npm install -D drizzle-kit 29 | ``` 30 | 31 | 2. Create a drizzle config file (drizzle.config.ts): 32 | ```typescript 33 | import { config } from 'dotenv'; 34 | import { defineConfig } from 'drizzle-kit'; 35 | 36 | config({ path: '.env' }); 37 | 38 | export default defineConfig({ 39 | schema: './db/schema/index.ts', 40 | out: './supabase/migrations', 41 | dialect: 'postgresql', 42 | dbCredentials: { 43 | url: process.env.DATABASE_URL!, 44 | }, 45 | }); 46 | ``` 47 | 48 | 3. Schema files should be organized as: 49 | ``` 50 | src/ 51 | └── db/ 52 | ├── schema/ 53 | │ ├── index.ts // exports all schema definitions. 54 | │ ├── auth.ts 55 | │ ├── todos.ts 56 | │ └── ... 57 | ├── drizzle.ts 58 | ├── index.ts 59 | └── jwt.ts 60 | ``` 61 | 62 | 4. Example schema structure: 63 | ```typescript 64 | import { eq } from 'drizzle-orm' 65 | import { pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core' 66 | import { authUid, authUsers, authenticatedRole } from 'drizzle-orm/supabase' 67 | 68 | export const todos = pgTable('todos', { 69 | id: uuid('id').defaultRandom().primaryKey(), 70 | title: text('title').notNull(), 71 | completed: boolean('completed').notNull().default(false), 72 | created_at: timestamp('created_at').defaultNow().notNull(), 73 | user_id: uuid('user_id').notNull().references(() => authUsers.id, { onDelete: "cascade" }) 74 | }, (table) => [ 75 | 76 | // Row Level Security is defined here 77 | pgPolicy("users can insert their own todos", { 78 | for: "insert", 79 | to: authenticatedRole, 80 | withCheck: eq(table.id, authUid) 81 | }), 82 | pgPolicy("users can update their own todos", { 83 | for: "update", 84 | to: authenticatedRole, 85 | using: eq(table.id, authUid), 86 | withCheck: eq(table.id, authUid), 87 | }), 88 | ]) 89 | ``` 90 | 91 | 5. Database client setup: 92 | ```typescript 93 | import postgres from "postgres" 94 | import { DrizzleConfig } from "drizzle-orm" 95 | import { drizzle } from "drizzle-orm/postgres-js" 96 | 97 | import { createClient } from "@/utils/supabase/server" 98 | 99 | import { createDrizzle } from "./drizzle" 100 | import * as schema from "./schema" 101 | import { decode } from "./jwt" 102 | 103 | const config = { 104 | casing: "snake_case", 105 | schema, 106 | } satisfies DrizzleConfig 107 | 108 | // ByPass RLS 109 | const admin = drizzle({ 110 | client: postgres(process.env.SUPABASE_DATABASE_URL!, { prepare: false }), 111 | ...config, 112 | }) 113 | 114 | // Protected by RLS 115 | const client = drizzle({ 116 | client: postgres(process.env.SUPABASE_DATABASE_URL!, { prepare: false }), 117 | ...config, 118 | }) 119 | 120 | // https://github.com/orgs/supabase/discussions/23224 121 | // Should be secure because we use the access token that is signed, and not the data read directly from the storage 122 | export async function createDrizzleSupabaseClient() { 123 | const { 124 | data: { session }, 125 | } = await (await createClient()).auth.getSession() 126 | return createDrizzle(decode(session?.access_token ?? ""), { admin, client }) 127 | } 128 | 129 | ``` 130 | 131 | 6. Add createDrizzle to drizzle.ts 132 | ```typescript 133 | import { sql } from "drizzle-orm" 134 | import { PgDatabase } from "drizzle-orm/pg-core" 135 | 136 | type SupabaseToken = { 137 | iss?: string 138 | sub?: string 139 | aud?: string[] | string 140 | exp?: number 141 | nbf?: number 142 | iat?: number 143 | jti?: string 144 | role?: string 145 | } 146 | 147 | export function createDrizzle, 148 | Token extends SupabaseToken = SupabaseToken>(token: Token, { admin, client }: { admin: Database; client: Database }) 149 | { 150 | return { 151 | admin, 152 | rls: (async (transaction, ...rest) => { 153 | return await client.transaction(async (tx) => { 154 | // Supabase exposes auth.uid() and auth.jwt() 155 | // https://supabase.com/docs/guides/database/postgres/row-level-security#helper-functions 156 | try { 157 | await tx.execute(sql` 158 | -- auth.jwt() 159 | select set_config('request.jwt.claims', '${sql.raw( 160 | JSON.stringify(token) 161 | )}', TRUE); 162 | -- auth.uid() 163 | select set_config('request.jwt.claim.sub', '${sql.raw( 164 | token.sub ?? "" 165 | )}', TRUE); 166 | -- set local role 167 | set local role ${sql.raw(token.role ?? "anon")}; 168 | `) 169 | return await transaction(tx) 170 | } finally { 171 | await tx.execute(sql` 172 | -- reset 173 | select set_config('request.jwt.claims', NULL, TRUE); 174 | select set_config('request.jwt.claim.sub', NULL, TRUE); 175 | reset role; 176 | `) 177 | } 178 | }, ...rest) 179 | }) as typeof client.transaction, 180 | } 181 | } 182 | ``` 183 | 184 | 7. Add jwt decode to jwt.ts: 185 | ```typescript 186 | import { jwtDecode, JwtPayload } from "jwt-decode" 187 | 188 | export function decode(accessToken: string) { 189 | try { 190 | return jwtDecode(accessToken) 191 | } catch (error) { 192 | console.error(error) 193 | return { role: "anon" } as JwtPayload & { role: string } 194 | } 195 | } 196 | ``` 197 | 8. Add migration scripts to package.json: 198 | ```json 199 | { 200 | "scripts": { 201 | "generate": "drizzle-kit generate:pg", 202 | "migrate": "drizzle-kit push:pg" 203 | } 204 | } 205 | ``` 206 | 207 | 208 | 8. Best practices: 209 | - Always use TypeScript for type safety 210 | - Define explicit table relationships 211 | - Use migrations for schema changes 212 | - Enable RLS for all tables 213 | - Use UUIDs for primary keys 214 | - Include created_at/updated_at timestamps 215 | - Add user_id foreign keys for RLS 216 | 217 | examples: 218 | - input: | 219 | // Bad: No type safety 220 | const todos = pgTable('todos', { 221 | id: serial('id'), 222 | title: text('title') 223 | }) 224 | 225 | // Good: Type-safe with proper structure 226 | const todos = pgTable('todos', { 227 | id: uuid('id').defaultRandom().primaryKey(), 228 | title: text('title').notNull(), 229 | user_id: uuid('user_id').notNull(), 230 | created_at: timestamp('created_at').defaultNow().notNull() 231 | }) 232 | output: "Properly structured Drizzle schema with types and RLS support" 233 | 234 | metadata: 235 | priority: high 236 | version: 1.0 237 | tags: 238 | - drizzle 239 | - supabase 240 | - database 241 | - orm 242 | 243 | -------------------------------------------------------------------------------- /supabase/supabase-postgres-style-guide.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Guidelines for writing Postgres SQL 3 | globs: **/*.sql 4 | alwaysApply: false 5 | --- 6 | 7 | 8 | # Postgres SQL Style Guide 9 | 10 | ## General 11 | 12 | - Use lowercase for SQL reserved words to maintain consistency and readability. 13 | - Employ consistent, descriptive identifiers for tables, columns, and other database objects. 14 | - Use white space and indentation to enhance the readability of your code. 15 | - Store dates in ISO 8601 format (`yyyy-mm-ddThh:mm:ss.sssss`). 16 | - Include comments for complex logic, using '/* ... */' for block comments and '--' for line comments. 17 | 18 | ## Naming Conventions 19 | 20 | - Avoid SQL reserved words and ensure names are unique and under 63 characters. 21 | - Use snake_case for tables and columns. 22 | - Prefer plurals for table names 23 | - Prefer singular names for columns. 24 | 25 | ## Tables 26 | 27 | - Avoid prefixes like 'tbl_' and ensure no table name matches any of its column names. 28 | - Always add an `id` column of type `identity generated always` unless otherwise specified. 29 | - Create all tables in the `public` schema unless otherwise specified. 30 | - Always add the schema to SQL queries for clarity. 31 | - Always add a comment to describe what the table does. The comment can be up to 1024 characters. 32 | 33 | ## Columns 34 | 35 | - Use singular names and avoid generic names like 'id'. 36 | - For references to foreign tables, use the singular of the table name with the `_id` suffix. For example `user_id` to reference the `users` table 37 | - Always use lowercase except in cases involving acronyms or when readability would be enhanced by an exception. 38 | 39 | #### Examples: 40 | 41 | ```sql 42 | create table books ( 43 | id bigint generated always as identity primary key, 44 | title text not null, 45 | author_id bigint references authors (id) 46 | ); 47 | comment on table books is 'A list of all the books in the library.'; 48 | ``` 49 | 50 | 51 | ## Queries 52 | 53 | - When the query is shorter keep it on just a few lines. As it gets larger start adding newlines for readability 54 | - Add spaces for readability. 55 | 56 | Smaller queries: 57 | 58 | 59 | ```sql 60 | select * 61 | from employees 62 | where end_date is null; 63 | 64 | update employees 65 | set end_date = '2023-12-31' 66 | where employee_id = 1001; 67 | ``` 68 | 69 | Larger queries: 70 | 71 | ```sql 72 | select 73 | first_name, 74 | last_name 75 | from 76 | employees 77 | where 78 | start_date between '2021-01-01' and '2021-12-31' 79 | and 80 | status = 'employed'; 81 | ``` 82 | 83 | 84 | ### Joins and Subqueries 85 | 86 | - Format joins and subqueries for clarity, aligning them with related SQL clauses. 87 | - Prefer full table names when referencing tables. This helps for readability. 88 | 89 | ```sql 90 | select 91 | employees.employee_name, 92 | departments.department_name 93 | from 94 | employees 95 | join 96 | departments on employees.department_id = departments.department_id 97 | where 98 | employees.start_date > '2022-01-01'; 99 | ``` 100 | 101 | ## Aliases 102 | 103 | - Use meaningful aliases that reflect the data or transformation applied, and always include the 'as' keyword for clarity. 104 | 105 | ```sql 106 | select count(*) as total_employees 107 | from employees 108 | where end_date is null; 109 | ``` 110 | 111 | 112 | ## Complex queries and CTEs 113 | 114 | - If a query is extremely complex, prefer a CTE. 115 | - Make sure the CTE is clear and linear. Prefer readability over performance. 116 | - Add comments to each block. 117 | 118 | ```sql 119 | with department_employees as ( 120 | -- Get all employees and their departments 121 | select 122 | employees.department_id, 123 | employees.first_name, 124 | employees.last_name, 125 | departments.department_name 126 | from 127 | employees 128 | join 129 | departments on employees.department_id = departments.department_id 130 | ), 131 | employee_counts as ( 132 | -- Count how many employees in each department 133 | select 134 | department_name, 135 | count(*) as num_employees 136 | from 137 | department_employees 138 | group by 139 | department_name 140 | ) 141 | select 142 | department_name, 143 | num_employees 144 | from 145 | employee_counts 146 | order by 147 | department_name; 148 | ``` 149 | -------------------------------------------------------------------------------- /supabase/supabase-rls-policies.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Guidelines for writing Postgres Row Level Security policies 3 | globs: **/*.sql 4 | alwaysApply: false 5 | --- 6 | # Database: Create RLS policies 7 | 8 | You're a Supabase Postgres expert in writing row level security policies. Your purpose is to generate a policy with the constraints given by the user. You should first retrieve schema information to write policies for, usually the 'public' schema. 9 | 10 | The output should use the following instructions: 11 | 12 | - The generated SQL must be valid SQL. 13 | - You can use only CREATE POLICY or ALTER POLICY queries, no other queries are allowed. 14 | - Always use double apostrophe in SQL strings (eg. 'Night''s watch') 15 | - You can add short explanations to your messages. 16 | - The result should be a valid markdown. The SQL code should be wrapped in ``` (including sql language tag). 17 | - Always use "auth.uid()" instead of "current_user". 18 | - SELECT policies should always have USING but not WITH CHECK 19 | - INSERT policies should always have WITH CHECK but not USING 20 | - UPDATE policies should always have WITH CHECK and most often have USING 21 | - DELETE policies should always have USING but not WITH CHECK 22 | - Don't use `FOR ALL`. Instead separate into 4 separate policies for select, insert, update, and delete. 23 | - The policy name should be short but detailed text explaining the policy, enclosed in double quotes. 24 | - Always put explanations as separate text. Never use inline SQL comments. 25 | - If the user asks for something that's not related to SQL policies, explain to the user 26 | that you can only help with policies. 27 | - Discourage `RESTRICTIVE` policies and encourage `PERMISSIVE` policies, and explain why. 28 | 29 | The output should look like this: 30 | 31 | ```sql 32 | CREATE POLICY "My descriptive policy." ON books FOR INSERT to authenticated USING ( (select auth.uid()) = author_id ) WITH ( true ); 33 | ``` 34 | 35 | Since you are running in a Supabase environment, take note of these Supabase-specific additions below. 36 | 37 | ## Authenticated and unauthenticated roles 38 | 39 | Supabase maps every request to one of the roles: 40 | 41 | - `anon`: an unauthenticated request (the user is not logged in) 42 | - `authenticated`: an authenticated request (the user is logged in) 43 | 44 | These are actually [Postgres Roles](mdc:docs/guides/database/postgres/roles). You can use these roles within your Policies using the `TO` clause: 45 | 46 | ```sql 47 | create policy "Profiles are viewable by everyone" 48 | on profiles 49 | for select 50 | to authenticated, anon 51 | using ( true ); 52 | 53 | -- OR 54 | 55 | create policy "Public profiles are viewable only by authenticated users" 56 | on profiles 57 | for select 58 | to authenticated 59 | using ( true ); 60 | ``` 61 | 62 | Note that `for ...` must be added after the table but before the roles. `to ...` must be added after `for ...`: 63 | 64 | ### Incorrect 65 | 66 | ```sql 67 | create policy "Public profiles are viewable only by authenticated users" 68 | on profiles 69 | to authenticated 70 | for select 71 | using ( true ); 72 | ``` 73 | 74 | ### Correct 75 | 76 | ```sql 77 | create policy "Public profiles are viewable only by authenticated users" 78 | on profiles 79 | for select 80 | to authenticated 81 | using ( true ); 82 | ``` 83 | 84 | ## Multiple operations 85 | 86 | PostgreSQL policies do not support specifying multiple operations in a single FOR clause. You need to create separate policies for each operation. 87 | 88 | ### Incorrect 89 | 90 | ```sql 91 | create policy "Profiles can be created and deleted by any user" 92 | on profiles 93 | for insert, delete -- cannot create a policy on multiple operators 94 | to authenticated 95 | with check ( true ) 96 | using ( true ); 97 | ``` 98 | 99 | ### Correct 100 | 101 | ```sql 102 | create policy "Profiles can be created by any user" 103 | on profiles 104 | for insert 105 | to authenticated 106 | with check ( true ); 107 | 108 | create policy "Profiles can be deleted by any user" 109 | on profiles 110 | for delete 111 | to authenticated 112 | using ( true ); 113 | ``` 114 | 115 | ## Helper functions 116 | 117 | Supabase provides some helper functions that make it easier to write Policies. 118 | 119 | ### `auth.uid()` 120 | 121 | Returns the ID of the user making the request. 122 | 123 | ### `auth.jwt()` 124 | 125 | Returns the JWT of the user making the request. Anything that you store in the user's `raw_app_meta_data` column or the `raw_user_meta_data` column will be accessible using this function. It's important to know the distinction between these two: 126 | 127 | - `raw_user_meta_data` - can be updated by the authenticated user using the `supabase.auth.update()` function. It is not a good place to store authorization data. 128 | - `raw_app_meta_data` - cannot be updated by the user, so it's a good place to store authorization data. 129 | 130 | The `auth.jwt()` function is extremely versatile. For example, if you store some team data inside `app_metadata`, you can use it to determine whether a particular user belongs to a team. For example, if this was an array of IDs: 131 | 132 | ```sql 133 | create policy "User is in team" 134 | on my_table 135 | to authenticated 136 | using ( team_id in (select auth.jwt() -> 'app_metadata' -> 'teams')); 137 | ``` 138 | 139 | ### MFA 140 | 141 | The `auth.jwt()` function can be used to check for [Multi-Factor Authentication](mdc:docs/guides/auth/auth-mfa#enforce-rules-for-mfa-logins). For example, you could restrict a user from updating their profile unless they have at least 2 levels of authentication (Assurance Level 2): 142 | 143 | ```sql 144 | create policy "Restrict updates." 145 | on profiles 146 | as restrictive 147 | for update 148 | to authenticated using ( 149 | (select auth.jwt()->>'aal') = 'aal2' 150 | ); 151 | ``` 152 | 153 | ## RLS performance recommendations 154 | 155 | Every authorization system has an impact on performance. While row level security is powerful, the performance impact is important to keep in mind. This is especially true for queries that scan every row in a table - like many `select` operations, including those using limit, offset, and ordering. 156 | 157 | Based on a series of [tests](mdc:https:/github.com/GaryAustin1/RLS-Performance), we have a few recommendations for RLS: 158 | 159 | ### Add indexes 160 | 161 | Make sure you've added [indexes](mdc:docs/guides/database/postgres/indexes) on any columns used within the Policies which are not already indexed (or primary keys). For a Policy like this: 162 | 163 | ```sql 164 | create policy "Users can access their own records" on test_table 165 | to authenticated 166 | using ( (select auth.uid()) = user_id ); 167 | ``` 168 | 169 | You can add an index like: 170 | 171 | ```sql 172 | create index userid 173 | on test_table 174 | using btree (user_id); 175 | ``` 176 | 177 | ### Call functions with `select` 178 | 179 | You can use `select` statement to improve policies that use functions. For example, instead of this: 180 | 181 | ```sql 182 | create policy "Users can access their own records" on test_table 183 | to authenticated 184 | using ( auth.uid() = user_id ); 185 | ``` 186 | 187 | You can do: 188 | 189 | ```sql 190 | create policy "Users can access their own records" on test_table 191 | to authenticated 192 | using ( (select auth.uid()) = user_id ); 193 | ``` 194 | 195 | This method works well for JWT functions like `auth.uid()` and `auth.jwt()` as well as `security definer` Functions. Wrapping the function causes an `initPlan` to be run by the Postgres optimizer, which allows it to "cache" the results per-statement, rather than calling the function on each row. 196 | 197 | Caution: You can only use this technique if the results of the query or function do not change based on the row data. 198 | 199 | ### Minimize joins 200 | 201 | You can often rewrite your Policies to avoid joins between the source and the target table. Instead, try to organize your policy to fetch all the relevant data from the target table into an array or set, then you can use an `IN` or `ANY` operation in your filter. 202 | 203 | For example, this is an example of a slow policy which joins the source `test_table` to the target `team_user`: 204 | 205 | ```sql 206 | create policy "Users can access records belonging to their teams" on test_table 207 | to authenticated 208 | using ( 209 | (select auth.uid()) in ( 210 | select user_id 211 | from team_user 212 | where team_user.team_id = team_id -- joins to the source "test_table.team_id" 213 | ) 214 | ); 215 | ``` 216 | 217 | We can rewrite this to avoid this join, and instead select the filter criteria into a set: 218 | 219 | ```sql 220 | create policy "Users can access records belonging to their teams" on test_table 221 | to authenticated 222 | using ( 223 | team_id in ( 224 | select team_id 225 | from team_user 226 | where user_id = (select auth.uid()) -- no join 227 | ) 228 | ); 229 | ``` 230 | 231 | ### Specify roles in your policies 232 | 233 | Always use the Role of inside your policies, specified by the `TO` operator. For example, instead of this query: 234 | 235 | ```sql 236 | create policy "Users can access their own records" on rls_test 237 | using ( auth.uid() = user_id ); 238 | ``` 239 | 240 | Use: 241 | 242 | ```sql 243 | create policy "Users can access their own records" on rls_test 244 | to authenticated 245 | using ( (select auth.uid()) = user_id ); 246 | ``` 247 | 248 | This prevents the policy `( (select auth.uid()) = user_id )` from running for any `anon` users, since the execution stops at the `to authenticated` step. 249 | -------------------------------------------------------------------------------- /supabase/supabase-writing-edge-functions.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Coding rules for Supabase Edge Functions 3 | globs: supabase/functions/**/*.ts 4 | alwaysApply: false 5 | --- 6 | # Writing Supabase Edge Functions 7 | 8 | You're an expert in writing TypeScript and Deno JavaScript runtime. Generate **high-quality Supabase Edge Functions** that adhere to the following best practices: 9 | 10 | ## Guidelines 11 | 12 | 1. Try to use Web APIs and Deno’s core APIs instead of external dependencies (eg: use fetch instead of Axios, use WebSockets API instead of node-ws) 13 | 2. If you are reusing utility methods between Edge Functions, add them to `supabase/functions/_shared` and import using a relative path. Do NOT have cross dependencies between Edge Functions. 14 | 3. Do NOT use bare specifiers when importing dependecnies. If you need to use an external dependency, make sure it's prefixed with either `npm:` or `jsr:`. For example, `@supabase/supabase-js` should be written as `npm:@supabase/supabase-js`. 15 | 4. For external imports, always define a version. For example, `npm:@express` should be written as `npm:express@4.18.2`. 16 | 5. For external dependencies, importing via `npm:` and `jsr:` is preferred. Minimize the use of imports from @`deno.land/x` , `esm.sh` and @`unpkg.com` . If you have a package from one of those CDNs, you can replace the CDN hostname with `npm:` specifier. 17 | 6. You can also use Node built-in APIs. You will need to import them using `node:` specifier. For example, to import Node process: `import process from "node:process". Use Node APIs when you find gaps in Deno APIs. 18 | 7. Do NOT use `import { serve } from "https://deno.land/std@0.168.0/http/server.ts"`. Instead use the built-in `Deno.serve`. 19 | 8. Following environment variables (ie. secrets) are pre-populated in both local and hosted Supabase environments. Users don't need to manually set them: 20 | * SUPABASE_URL 21 | * SUPABASE_ANON_KEY 22 | * SUPABASE_SERVICE_ROLE_KEY 23 | * SUPABASE_DB_URL 24 | 9. To set other environment variables (ie. secrets) users can put them in a env file and run the `supabase secrets set --env-file path/to/env-file` 25 | 10. A single Edge Function can handle multiple routes. It is recommended to use a library like Express or Hono to handle the routes as it's easier for developer to understand and maintain. Each route must be prefixed with `/function-name` so they are routed correctly. 26 | 11. File write operations are ONLY permitted on `/tmp` directory. You can use either Deno or Node File APIs. 27 | 12. Use `EdgeRuntime.waitUntil(promise)` static method to run long-running tasks in the background without blocking response to a request. Do NOT assume it is available in the request / execution context. 28 | 29 | ## Example Templates 30 | 31 | ### Simple Hello World Function 32 | 33 | ```tsx 34 | interface reqPayload { 35 | name: string; 36 | } 37 | 38 | console.info('server started'); 39 | 40 | Deno.serve(async (req: Request) => { 41 | const { name }: reqPayload = await req.json(); 42 | const data = { 43 | message: `Hello ${name} from foo!`, 44 | }; 45 | 46 | return new Response( 47 | JSON.stringify(data), 48 | { headers: { 'Content-Type': 'application/json', 'Connection': 'keep-alive' }} 49 | ); 50 | }); 51 | 52 | ``` 53 | 54 | ### Example Function using Node built-in API 55 | 56 | ```tsx 57 | import { randomBytes } from "node:crypto"; 58 | import { createServer } from "node:http"; 59 | import process from "node:process"; 60 | 61 | const generateRandomString = (length) => { 62 | const buffer = randomBytes(length); 63 | return buffer.toString('hex'); 64 | }; 65 | 66 | const randomString = generateRandomString(10); 67 | console.log(randomString); 68 | 69 | const server = createServer((req, res) => { 70 | const message = `Hello`; 71 | res.end(message); 72 | }); 73 | 74 | server.listen(9999); 75 | ``` 76 | 77 | ### Using npm packages in Functions 78 | 79 | ```tsx 80 | import express from "npm:express@4.18.2"; 81 | 82 | const app = express(); 83 | 84 | app.get(/(.*)/, (req, res) => { 85 | res.send("Welcome to Supabase"); 86 | }); 87 | 88 | app.listen(8000); 89 | 90 | ``` 91 | 92 | ### Generate embeddings using built-in @Supabase.ai API 93 | 94 | ```tsx 95 | const model = new Supabase.ai.Session('gte-small'); 96 | 97 | Deno.serve(async (req: Request) => { 98 | const params = new URL(req.url).searchParams; 99 | const input = params.get('text'); 100 | const output = await model.run(input, { mean_pool: true, normalize: true }); 101 | return new Response( 102 | JSON.stringify( 103 | output, 104 | ), 105 | { 106 | headers: { 107 | 'Content-Type': 'application/json', 108 | 'Connection': 'keep-alive', 109 | }, 110 | }, 111 | ); 112 | }); 113 | 114 | ``` 115 | -------------------------------------------------------------------------------- /task-master/cursor_rules.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Guidelines for creating and maintaining Cursor rules to ensure consistency and effectiveness. 3 | globs: .cursor/rules/*.mdc 4 | alwaysApply: true 5 | --- 6 | 7 | - **Required Rule Structure:** 8 | ```markdown 9 | --- 10 | description: Clear, one-line description of what the rule enforces 11 | globs: path/to/files/*.ext, other/path/**/* 12 | alwaysApply: boolean 13 | --- 14 | 15 | - **Main Points in Bold** 16 | - Sub-points with details 17 | - Examples and explanations 18 | ``` 19 | 20 | - **File References:** 21 | - Use `[filename](mdc:path/to/file)` ([filename](mdc:filename)) to reference files 22 | - Example: [prisma.mdc](mdc:.cursor/rules/prisma.mdc) for rule references 23 | - Example: [schema.prisma](mdc:prisma/schema.prisma) for code references 24 | 25 | - **Code Examples:** 26 | - Use language-specific code blocks 27 | ```typescript 28 | // ✅ DO: Show good examples 29 | const goodExample = true; 30 | 31 | // ❌ DON'T: Show anti-patterns 32 | const badExample = false; 33 | ``` 34 | 35 | - **Rule Content Guidelines:** 36 | - Start with high-level overview 37 | - Include specific, actionable requirements 38 | - Show examples of correct implementation 39 | - Reference existing code when possible 40 | - Keep rules DRY by referencing other rules 41 | 42 | - **Rule Maintenance:** 43 | - Update rules when new patterns emerge 44 | - Add examples from actual codebase 45 | - Remove outdated patterns 46 | - Cross-reference related rules 47 | 48 | - **Best Practices:** 49 | - Use bullet points for clarity 50 | - Keep descriptions concise 51 | - Include both DO and DON'T examples 52 | - Reference actual code over theoretical examples 53 | - Use consistent formatting across rules -------------------------------------------------------------------------------- /task-master/dev_workflow.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Guide for using meta-development script (scripts/dev.js) to manage task-driven development workflows 3 | globs: **/* 4 | alwaysApply: true 5 | --- 6 | 7 | - **Global CLI Commands** 8 | - Task Master now provides a global CLI through the `task-master` command 9 | - All functionality from `scripts/dev.js` is available through this interface 10 | - Install globally with `npm install -g claude-task-master` or use locally via `npx` 11 | - Use `task-master ` instead of `node scripts/dev.js ` 12 | - Examples: 13 | - `task-master list` instead of `node scripts/dev.js list` 14 | - `task-master next` instead of `node scripts/dev.js next` 15 | - `task-master expand --id=3` instead of `node scripts/dev.js expand --id=3` 16 | - All commands accept the same options as their script equivalents 17 | - The CLI provides additional commands like `task-master init` for project setup 18 | 19 | - **Development Workflow Process** 20 | - Start new projects by running `task-master init` or `node scripts/dev.js parse-prd --input=` to generate initial tasks.json 21 | - Begin coding sessions with `task-master list` to see current tasks, status, and IDs 22 | - Analyze task complexity with `task-master analyze-complexity --research` before breaking down tasks 23 | - Select tasks based on dependencies (all marked 'done'), priority level, and ID order 24 | - Clarify tasks by checking task files in tasks/ directory or asking for user input 25 | - View specific task details using `task-master show ` to understand implementation requirements 26 | - Break down complex tasks using `task-master expand --id=` with appropriate flags 27 | - Clear existing subtasks if needed using `task-master clear-subtasks --id=` before regenerating 28 | - Implement code following task details, dependencies, and project standards 29 | - Verify tasks according to test strategies before marking as complete 30 | - Mark completed tasks with `task-master set-status --id= --status=done` 31 | - Update dependent tasks when implementation differs from original plan 32 | - Generate task files with `task-master generate` after updating tasks.json 33 | - Maintain valid dependency structure with `task-master fix-dependencies` when needed 34 | - Respect dependency chains and task priorities when selecting work 35 | - Report progress regularly using the list command 36 | 37 | - **Task Complexity Analysis** 38 | - Run `node scripts/dev.js analyze-complexity --research` for comprehensive analysis 39 | - Review complexity report in scripts/task-complexity-report.json 40 | - Or use `node scripts/dev.js complexity-report` for a formatted, readable version of the report 41 | - Focus on tasks with highest complexity scores (8-10) for detailed breakdown 42 | - Use analysis results to determine appropriate subtask allocation 43 | - Note that reports are automatically used by the expand command 44 | 45 | - **Task Breakdown Process** 46 | - For tasks with complexity analysis, use `node scripts/dev.js expand --id=` 47 | - Otherwise use `node scripts/dev.js expand --id= --subtasks=` 48 | - Add `--research` flag to leverage Perplexity AI for research-backed expansion 49 | - Use `--prompt=""` to provide additional context when needed 50 | - Review and adjust generated subtasks as necessary 51 | - Use `--all` flag to expand multiple pending tasks at once 52 | - If subtasks need regeneration, clear them first with `clear-subtasks` command 53 | 54 | - **Implementation Drift Handling** 55 | - When implementation differs significantly from planned approach 56 | - When future tasks need modification due to current implementation choices 57 | - When new dependencies or requirements emerge 58 | - Call `node scripts/dev.js update --from= --prompt=""` to update tasks.json 59 | 60 | - **Task Status Management** 61 | - Use 'pending' for tasks ready to be worked on 62 | - Use 'done' for completed and verified tasks 63 | - Use 'deferred' for postponed tasks 64 | - Add custom status values as needed for project-specific workflows 65 | 66 | - **Task File Format Reference** 67 | ``` 68 | # Task ID: 69 | # Title: 70 | # Status: <status> 71 | # Dependencies: <comma-separated list of dependency IDs> 72 | # Priority: <priority> 73 | # Description: <brief description> 74 | # Details: 75 | <detailed implementation notes> 76 | 77 | # Test Strategy: 78 | <verification approach> 79 | ``` 80 | 81 | - **Command Reference: parse-prd** 82 | - Legacy Syntax: `node scripts/dev.js parse-prd --input=<prd-file.txt>` 83 | - CLI Syntax: `task-master parse-prd --input=<prd-file.txt>` 84 | - Description: Parses a PRD document and generates a tasks.json file with structured tasks 85 | - Parameters: 86 | - `--input=<file>`: Path to the PRD text file (default: sample-prd.txt) 87 | - Example: `task-master parse-prd --input=requirements.txt` 88 | - Notes: Will overwrite existing tasks.json file. Use with caution. 89 | 90 | - **Command Reference: update** 91 | - Legacy Syntax: `node scripts/dev.js update --from=<id> --prompt="<prompt>"` 92 | - CLI Syntax: `task-master update --from=<id> --prompt="<prompt>"` 93 | - Description: Updates tasks with ID >= specified ID based on the provided prompt 94 | - Parameters: 95 | - `--from=<id>`: Task ID from which to start updating (required) 96 | - `--prompt="<text>"`: Explanation of changes or new context (required) 97 | - Example: `task-master update --from=4 --prompt="Now we are using Express instead of Fastify."` 98 | - Notes: Only updates tasks not marked as 'done'. Completed tasks remain unchanged. 99 | 100 | - **Command Reference: generate** 101 | - Legacy Syntax: `node scripts/dev.js generate` 102 | - CLI Syntax: `task-master generate` 103 | - Description: Generates individual task files in tasks/ directory based on tasks.json 104 | - Parameters: 105 | - `--file=<path>, -f`: Use alternative tasks.json file (default: 'tasks/tasks.json') 106 | - `--output=<dir>, -o`: Output directory (default: 'tasks') 107 | - Example: `task-master generate` 108 | - Notes: Overwrites existing task files. Creates tasks/ directory if needed. 109 | 110 | - **Command Reference: set-status** 111 | - Legacy Syntax: `node scripts/dev.js set-status --id=<id> --status=<status>` 112 | - CLI Syntax: `task-master set-status --id=<id> --status=<status>` 113 | - Description: Updates the status of a specific task in tasks.json 114 | - Parameters: 115 | - `--id=<id>`: ID of the task to update (required) 116 | - `--status=<status>`: New status value (required) 117 | - Example: `task-master set-status --id=3 --status=done` 118 | - Notes: Common values are 'done', 'pending', and 'deferred', but any string is accepted. 119 | 120 | - **Command Reference: list** 121 | - Legacy Syntax: `node scripts/dev.js list` 122 | - CLI Syntax: `task-master list` 123 | - Description: Lists all tasks in tasks.json with IDs, titles, and status 124 | - Parameters: 125 | - `--status=<status>, -s`: Filter by status 126 | - `--with-subtasks`: Show subtasks for each task 127 | - `--file=<path>, -f`: Use alternative tasks.json file (default: 'tasks/tasks.json') 128 | - Example: `task-master list` 129 | - Notes: Provides quick overview of project progress. Use at start of sessions. 130 | 131 | - **Command Reference: expand** 132 | - Legacy Syntax: `node scripts/dev.js expand --id=<id> [--num=<number>] [--research] [--prompt="<context>"]` 133 | - CLI Syntax: `task-master expand --id=<id> [--num=<number>] [--research] [--prompt="<context>"]` 134 | - Description: Expands a task with subtasks for detailed implementation 135 | - Parameters: 136 | - `--id=<id>`: ID of task to expand (required unless using --all) 137 | - `--all`: Expand all pending tasks, prioritized by complexity 138 | - `--num=<number>`: Number of subtasks to generate (default: from complexity report) 139 | - `--research`: Use Perplexity AI for research-backed generation 140 | - `--prompt="<text>"`: Additional context for subtask generation 141 | - `--force`: Regenerate subtasks even for tasks that already have them 142 | - Example: `task-master expand --id=3 --num=5 --research --prompt="Focus on security aspects"` 143 | - Notes: Uses complexity report recommendations if available. 144 | 145 | - **Command Reference: analyze-complexity** 146 | - Legacy Syntax: `node scripts/dev.js analyze-complexity [options]` 147 | - CLI Syntax: `task-master analyze-complexity [options]` 148 | - Description: Analyzes task complexity and generates expansion recommendations 149 | - Parameters: 150 | - `--output=<file>, -o`: Output file path (default: scripts/task-complexity-report.json) 151 | - `--model=<model>, -m`: Override LLM model to use 152 | - `--threshold=<number>, -t`: Minimum score for expansion recommendation (default: 5) 153 | - `--file=<path>, -f`: Use alternative tasks.json file 154 | - `--research, -r`: Use Perplexity AI for research-backed analysis 155 | - Example: `task-master analyze-complexity --research` 156 | - Notes: Report includes complexity scores, recommended subtasks, and tailored prompts. 157 | 158 | - **Command Reference: clear-subtasks** 159 | - Legacy Syntax: `node scripts/dev.js clear-subtasks --id=<id>` 160 | - CLI Syntax: `task-master clear-subtasks --id=<id>` 161 | - Description: Removes subtasks from specified tasks to allow regeneration 162 | - Parameters: 163 | - `--id=<id>`: ID or comma-separated IDs of tasks to clear subtasks from 164 | - `--all`: Clear subtasks from all tasks 165 | - Examples: 166 | - `task-master clear-subtasks --id=3` 167 | - `task-master clear-subtasks --id=1,2,3` 168 | - `task-master clear-subtasks --all` 169 | - Notes: 170 | - Task files are automatically regenerated after clearing subtasks 171 | - Can be combined with expand command to immediately generate new subtasks 172 | - Works with both parent tasks and individual subtasks 173 | 174 | - **Task Structure Fields** 175 | - **id**: Unique identifier for the task (Example: `1`) 176 | - **title**: Brief, descriptive title (Example: `"Initialize Repo"`) 177 | - **description**: Concise summary of what the task involves (Example: `"Create a new repository, set up initial structure."`) 178 | - **status**: Current state of the task (Example: `"pending"`, `"done"`, `"deferred"`) 179 | - **dependencies**: IDs of prerequisite tasks (Example: `[1, 2]`) 180 | - Dependencies are displayed with status indicators (✅ for completed, ⏱️ for pending) 181 | - This helps quickly identify which prerequisite tasks are blocking work 182 | - **priority**: Importance level (Example: `"high"`, `"medium"`, `"low"`) 183 | - **details**: In-depth implementation instructions (Example: `"Use GitHub client ID/secret, handle callback, set session token."`) 184 | - **testStrategy**: Verification approach (Example: `"Deploy and call endpoint to confirm 'Hello World' response."`) 185 | - **subtasks**: List of smaller, more specific tasks (Example: `[{"id": 1, "title": "Configure OAuth", ...}]`) 186 | 187 | - **Environment Variables Configuration** 188 | - **ANTHROPIC_API_KEY** (Required): Your Anthropic API key for Claude (Example: `ANTHROPIC_API_KEY=sk-ant-api03-...`) 189 | - **MODEL** (Default: `"claude-3-7-sonnet-20250219"`): Claude model to use (Example: `MODEL=claude-3-opus-20240229`) 190 | - **MAX_TOKENS** (Default: `"4000"`): Maximum tokens for responses (Example: `MAX_TOKENS=8000`) 191 | - **TEMPERATURE** (Default: `"0.7"`): Temperature for model responses (Example: `TEMPERATURE=0.5`) 192 | - **DEBUG** (Default: `"false"`): Enable debug logging (Example: `DEBUG=true`) 193 | - **LOG_LEVEL** (Default: `"info"`): Console output level (Example: `LOG_LEVEL=debug`) 194 | - **DEFAULT_SUBTASKS** (Default: `"3"`): Default subtask count (Example: `DEFAULT_SUBTASKS=5`) 195 | - **DEFAULT_PRIORITY** (Default: `"medium"`): Default priority (Example: `DEFAULT_PRIORITY=high`) 196 | - **PROJECT_NAME** (Default: `"MCP SaaS MVP"`): Project name in metadata (Example: `PROJECT_NAME=My Awesome Project`) 197 | - **PROJECT_VERSION** (Default: `"1.0.0"`): Version in metadata (Example: `PROJECT_VERSION=2.1.0`) 198 | - **PERPLEXITY_API_KEY**: For research-backed features (Example: `PERPLEXITY_API_KEY=pplx-...`) 199 | - **PERPLEXITY_MODEL** (Default: `"sonar-medium-online"`): Perplexity model (Example: `PERPLEXITY_MODEL=sonar-large-online`) 200 | 201 | - **Determining the Next Task** 202 | - Run `task-master next` to show the next task to work on 203 | - The next command identifies tasks with all dependencies satisfied 204 | - Tasks are prioritized by priority level, dependency count, and ID 205 | - The command shows comprehensive task information including: 206 | - Basic task details and description 207 | - Implementation details 208 | - Subtasks (if they exist) 209 | - Contextual suggested actions 210 | - Recommended before starting any new development work 211 | - Respects your project's dependency structure 212 | - Ensures tasks are completed in the appropriate sequence 213 | - Provides ready-to-use commands for common task actions 214 | 215 | - **Viewing Specific Task Details** 216 | - Run `task-master show <id>` or `task-master show --id=<id>` to view a specific task 217 | - Use dot notation for subtasks: `task-master show 1.2` (shows subtask 2 of task 1) 218 | - Displays comprehensive information similar to the next command, but for a specific task 219 | - For parent tasks, shows all subtasks and their current status 220 | - For subtasks, shows parent task information and relationship 221 | - Provides contextual suggested actions appropriate for the specific task 222 | - Useful for examining task details before implementation or checking status 223 | 224 | - **Managing Task Dependencies** 225 | - Use `task-master add-dependency --id=<id> --depends-on=<id>` to add a dependency 226 | - Use `task-master remove-dependency --id=<id> --depends-on=<id>` to remove a dependency 227 | - The system prevents circular dependencies and duplicate dependency entries 228 | - Dependencies are checked for existence before being added or removed 229 | - Task files are automatically regenerated after dependency changes 230 | - Dependencies are visualized with status indicators in task listings and files 231 | 232 | - **Command Reference: add-dependency** 233 | - Legacy Syntax: `node scripts/dev.js add-dependency --id=<id> --depends-on=<id>` 234 | - CLI Syntax: `task-master add-dependency --id=<id> --depends-on=<id>` 235 | - Description: Adds a dependency relationship between two tasks 236 | - Parameters: 237 | - `--id=<id>`: ID of task that will depend on another task (required) 238 | - `--depends-on=<id>`: ID of task that will become a dependency (required) 239 | - Example: `task-master add-dependency --id=22 --depends-on=21` 240 | - Notes: Prevents circular dependencies and duplicates; updates task files automatically 241 | 242 | - **Command Reference: remove-dependency** 243 | - Legacy Syntax: `node scripts/dev.js remove-dependency --id=<id> --depends-on=<id>` 244 | - CLI Syntax: `task-master remove-dependency --id=<id> --depends-on=<id>` 245 | - Description: Removes a dependency relationship between two tasks 246 | - Parameters: 247 | - `--id=<id>`: ID of task to remove dependency from (required) 248 | - `--depends-on=<id>`: ID of task to remove as a dependency (required) 249 | - Example: `task-master remove-dependency --id=22 --depends-on=21` 250 | - Notes: Checks if dependency actually exists; updates task files automatically 251 | 252 | - **Command Reference: validate-dependencies** 253 | - Legacy Syntax: `node scripts/dev.js validate-dependencies [options]` 254 | - CLI Syntax: `task-master validate-dependencies [options]` 255 | - Description: Checks for and identifies invalid dependencies in tasks.json and task files 256 | - Parameters: 257 | - `--file=<path>, -f`: Use alternative tasks.json file (default: 'tasks/tasks.json') 258 | - Example: `task-master validate-dependencies` 259 | - Notes: 260 | - Reports all non-existent dependencies and self-dependencies without modifying files 261 | - Provides detailed statistics on task dependency state 262 | - Use before fix-dependencies to audit your task structure 263 | 264 | - **Command Reference: fix-dependencies** 265 | - Legacy Syntax: `node scripts/dev.js fix-dependencies [options]` 266 | - CLI Syntax: `task-master fix-dependencies [options]` 267 | - Description: Finds and fixes all invalid dependencies in tasks.json and task files 268 | - Parameters: 269 | - `--file=<path>, -f`: Use alternative tasks.json file (default: 'tasks/tasks.json') 270 | - Example: `task-master fix-dependencies` 271 | - Notes: 272 | - Removes references to non-existent tasks and subtasks 273 | - Eliminates self-dependencies (tasks depending on themselves) 274 | - Regenerates task files with corrected dependencies 275 | - Provides detailed report of all fixes made 276 | 277 | - **Command Reference: complexity-report** 278 | - Legacy Syntax: `node scripts/dev.js complexity-report [options]` 279 | - CLI Syntax: `task-master complexity-report [options]` 280 | - Description: Displays the task complexity analysis report in a formatted, easy-to-read way 281 | - Parameters: 282 | - `--file=<path>, -f`: Path to the complexity report file (default: 'scripts/task-complexity-report.json') 283 | - Example: `task-master complexity-report` 284 | - Notes: 285 | - Shows tasks organized by complexity score with recommended actions 286 | - Provides complexity distribution statistics 287 | - Displays ready-to-use expansion commands for complex tasks 288 | - If no report exists, offers to generate one interactively 289 | 290 | - **Command Reference: add-task** 291 | - CLI Syntax: `task-master add-task [options]` 292 | - Description: Add a new task to tasks.json using AI 293 | - Parameters: 294 | - `--file=<path>, -f`: Path to the tasks file (default: 'tasks/tasks.json') 295 | - `--prompt=<text>, -p`: Description of the task to add (required) 296 | - `--dependencies=<ids>, -d`: Comma-separated list of task IDs this task depends on 297 | - `--priority=<priority>`: Task priority (high, medium, low) (default: 'medium') 298 | - Example: `task-master add-task --prompt="Create user authentication using Auth0"` 299 | - Notes: Uses AI to convert description into structured task with appropriate details 300 | 301 | - **Command Reference: init** 302 | - CLI Syntax: `task-master init` 303 | - Description: Initialize a new project with Task Master structure 304 | - Parameters: None 305 | - Example: `task-master init` 306 | - Notes: 307 | - Creates initial project structure with required files 308 | - Prompts for project settings if not provided 309 | - Merges with existing files when appropriate 310 | - Can be used to bootstrap a new Task Master project quickly 311 | 312 | - **Code Analysis & Refactoring Techniques** 313 | - **Top-Level Function Search** 314 | - Use grep pattern matching to find all exported functions across the codebase 315 | - Command: `grep -E "export (function|const) \w+|function \w+\(|const \w+ = \(|module\.exports" --include="*.js" -r ./` 316 | - Benefits: 317 | - Quickly identify all public API functions without reading implementation details 318 | - Compare functions between files during refactoring (e.g., monolithic to modular structure) 319 | - Verify all expected functions exist in refactored modules 320 | - Identify duplicate functionality or naming conflicts 321 | - Usage examples: 322 | - When migrating from `scripts/dev.js` to modular structure: `grep -E "function \w+\(" scripts/dev.js` 323 | - Check function exports in a directory: `grep -E "export (function|const)" scripts/modules/` 324 | - Find potential naming conflicts: `grep -E "function (get|set|create|update)\w+\(" -r ./` 325 | - Variations: 326 | - Add `-n` flag to include line numbers 327 | - Add `--include="*.ts"` to filter by file extension 328 | - Use with `| sort` to alphabetize results 329 | - Integration with refactoring workflow: 330 | - Start by mapping all functions in the source file 331 | - Create target module files based on function grouping 332 | - Verify all functions were properly migrated 333 | - Check for any unintentional duplications or omissions 334 | -------------------------------------------------------------------------------- /task-master/self_improve.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Guidelines for continuously improving Cursor rules based on emerging code patterns and best practices. 3 | globs: **/* 4 | alwaysApply: true 5 | --- 6 | 7 | - **Rule Improvement Triggers:** 8 | - New code patterns not covered by existing rules 9 | - Repeated similar implementations across files 10 | - Common error patterns that could be prevented 11 | - New libraries or tools being used consistently 12 | - Emerging best practices in the codebase 13 | 14 | - **Analysis Process:** 15 | - Compare new code with existing rules 16 | - Identify patterns that should be standardized 17 | - Look for references to external documentation 18 | - Check for consistent error handling patterns 19 | - Monitor test patterns and coverage 20 | 21 | - **Rule Updates:** 22 | - **Add New Rules When:** 23 | - A new technology/pattern is used in 3+ files 24 | - Common bugs could be prevented by a rule 25 | - Code reviews repeatedly mention the same feedback 26 | - New security or performance patterns emerge 27 | 28 | - **Modify Existing Rules When:** 29 | - Better examples exist in the codebase 30 | - Additional edge cases are discovered 31 | - Related rules have been updated 32 | - Implementation details have changed 33 | 34 | - **Example Pattern Recognition:** 35 | ```typescript 36 | // If you see repeated patterns like: 37 | const data = await prisma.user.findMany({ 38 | select: { id: true, email: true }, 39 | where: { status: 'ACTIVE' } 40 | }); 41 | 42 | // Consider adding to [prisma.mdc](mdc:.cursor/rules/prisma.mdc): 43 | // - Standard select fields 44 | // - Common where conditions 45 | // - Performance optimization patterns 46 | ``` 47 | 48 | - **Rule Quality Checks:** 49 | - Rules should be actionable and specific 50 | - Examples should come from actual code 51 | - References should be up to date 52 | - Patterns should be consistently enforced 53 | 54 | - **Continuous Improvement:** 55 | - Monitor code review comments 56 | - Track common development questions 57 | - Update rules after major refactors 58 | - Add links to relevant documentation 59 | - Cross-reference related rules 60 | 61 | - **Rule Deprecation:** 62 | - Mark outdated patterns as deprecated 63 | - Remove rules that no longer apply 64 | - Update references to deprecated rules 65 | - Document migration paths for old patterns 66 | 67 | - **Documentation Updates:** 68 | - Keep examples synchronized with code 69 | - Update references to external docs 70 | - Maintain links between related rules 71 | - Document breaking changes 72 | 73 | Follow [cursor_rules.mdc](mdc:.cursor/rules/cursor_rules.mdc) for proper rule formatting and structure. --------------------------------------------------------------------------------