--- description: globs: alwaysApply: false --- # Coding Standards ## Code Quality ### TypeScript Requirements - All new code must use TypeScript - Enable strict type checking - Avoid using `any` type, prefer specific types - Define interfaces or type aliases for complex objects ```typescript // ✅ Good practice interface LinkData { slug: string url: string createdAt: Date expiresAt?: Date } // ❌ Avoid const linkData: any = { ... } ``` ### Function and Variable Naming - Use descriptive names - Function names should start with verbs - Boolean variables use `is`, `has`, `should` prefixes - Constants use UPPER_SNAKE_CASE ```typescript // ✅ Good practice const isValidUrl = (url: string): boolean => { ... } const hasExpired = computed(() => { ... }) const MAX_SLUG_LENGTH = 50 // ❌ Avoid const check = (u: string) => { ... } const expired = computed(() => { ... }) const maxLen = 50 ``` ## Security Requirements ### Input Validation - All user input must be validated using Zod - API endpoints must validate request parameters - Frontend forms use vee-validate + Zod ```typescript // API input validation import { z } from 'zod' const createLinkSchema = z.object({ url: z.string().url(), slug: z.string().min(1).max(50).optional(), expiresAt: z.string().datetime().optional() }) export default defineEventHandler(async (event) => { const body = await readBody(event) const validatedData = createLinkSchema.parse(body) // ... }) ``` ### Authentication - Use Site Token for authentication - Sensitive operations require permission verification - Don't store sensitive information on the client ### Data Sanitization - Sanitize user-input HTML content - Validate URL format and security - Prevent XSS and injection attacks ## Performance Best Practices ### Reactive Data - Use `ref` and `reactive` appropriately - Avoid unnecessary reactive wrapping - Use `readonly` to protect data ```typescript // ✅ Good practice const { data: links, pending } = await $fetch('/api/links') const filteredLinks = computed(() => links.value.filter(link => link.isActive) ) // ❌ Avoid const links = ref([]) const filteredLinks = ref([]) watch(links, () => { filteredLinks.value = links.value.filter(link => link.isActive) }) ``` ### Async Operations - Use `async/await` instead of Promise chains - Handle errors and loading states properly - Avoid blocking UI operations ```typescript // ✅ Good practice const { data, error, pending } = await useFetch('/api/links') // Error handling try { const result = await $fetch('/api/link/create', { ... }) } catch (error) { // Handle error } ``` ## Code Organization ### File Structure - Each file should export only one main functionality - Group related functionality in the same directory - Use `index.ts` as directory entry point ### Import/Export - Use ES6 module syntax - Organize imports alphabetically - Separate third-party and local imports ```typescript // Third-party libraries import { ref, computed } from 'vue' import { z } from 'zod' // Local imports import type { LinkData } from '~/types' import { validateUrl } from '~/utils/validation' ``` ### Comments and Documentation - Add comments for complex logic - Use JSDoc comments for public APIs - Keep comments in sync with code ```typescript /** * Create a new short link * @param url - Original URL * @param slug - Custom slug (optional) * @returns Created link data */ export async function createLink(url: string, slug?: string): Promise { // Implementation logic } ``` ## Testing Standards ### Unit Testing Requirements - **Mandatory for all `server/api` endpoints** - Every API route must have comprehensive unit tests - Use Vitest as the primary testing framework with Nuxt Test Utils - Follow the Test-Driven Development (TDD) approach when possible - Maintain test coverage above 80% for API endpoints ### Testing Scope and Strategy - **API Layer**: Test all endpoints in [server/api/](mdc:server/api/) directory - **Validation Logic**: Test Zod schemas and input validation - **Error Handling**: Verify error responses and status codes - **Authentication**: Test token validation and authorization flows - **Business Logic**: Cover edge cases and critical functionality ### Test File Organization ```typescript // File naming convention tests/api/link/create.test.ts // Unit tests for API endpoints tests/api/helpers/fixtures.ts // Shared test data tests/sink.spec.ts // Integration/E2E tests ``` ### Testing Best Practices - **Write descriptive test names** that explain the behavior being tested - **Test both happy path and error scenarios** - **Use meaningful assertions** that validate expected behavior - **Keep tests independent** - no test should depend on another test's state - **Mock external dependencies** to ensure test reliability ```typescript // ✅ Good test structure describe('POST /api/link/create', () => { it('should create a new link with valid URL and custom slug', async () => { const response = await $fetch('/api/link/create', { method: 'POST', body: { url: 'https://example.com', slug: 'my-link' } }) expect(response.success).toBe(true) expect(response.data.slug).toBe('my-link') expect(response.data.url).toBe('https://example.com') }) it('should reject requests with invalid URL format', async () => { await expect($fetch('/api/link/create', { method: 'POST', body: { url: 'not-a-valid-url' } })).rejects.toThrow() }) }) ``` ### Test Data Management - Use factory functions for creating test data - Store common test fixtures in `tests/api/helpers/fixtures.ts` - Avoid hardcoded values in tests; use constants and variables ```typescript // ✅ Good test data management const validLinkPayload = { url: 'https://example.com', slug: 'test-slug', expiresAt: new Date(Date.now() + 86400000).toISOString() } const invalidUrlPayload = { url: 'invalid-url-format', slug: 'test-slug' } ``` ### Running and Maintaining Tests - Run tests locally before pushing changes: `npm run test` - Use watch mode during development: `npm run test:watch` - Generate coverage reports: `npm run test:coverage` - Tests must pass in CI/CD pipeline before merging ## Git Commit Conventions ### Commit Message Format Follow the conventional commit specification: ``` type(scope): brief description Optional body explaining what and why vs how Optional footer with issue references ``` ### Commit Types - **feat**: New feature implementation - **fix**: Bug fix or issue resolution - **docs**: Documentation updates only - **style**: Code formatting changes (no functional impact) - **refactor**: Code restructuring without changing functionality - **perf**: Performance optimization - **test**: Adding or modifying tests - **chore**: Build process, dependency updates, or auxiliary tool changes - **ci**: Continuous integration configuration changes ### Scope Examples - **api**: Changes to server/api endpoints - **ui**: Frontend components or styling - **auth**: Authentication related changes - **db**: Database or data storage changes - **config**: Configuration file updates ### Writing Good Commit Messages #### Good Examples ```bash feat(api): add AI-powered slug generation endpoint Integrate Cloudflare AI Workers to automatically generate meaningful slugs based on URL content and page titles. - Add new /api/link/ai endpoint - Implement content analysis logic - Update link creation flow to support AI suggestions - Add comprehensive test coverage Closes #123 ``` ```bash fix(auth): resolve token validation edge case Handle expired tokens more gracefully by returning proper 401 status code instead of throwing unhandled exceptions. Fixes #456 ``` ```bash test(api): add comprehensive coverage for link endpoints - Add unit tests for create, edit, delete operations - Include validation error scenarios - Test authentication requirements - Achieve 85% coverage for link management APIs ``` #### Avoid These Patterns ```bash # ❌ Too vague fix: stuff # ❌ Not descriptive update code # ❌ Multiple concerns in one commit feat: add new API endpoint and fix UI bug and update docs # ❌ All caps or inconsistent formatting FIX: BROKEN AUTH SYSTEM ``` ### Commit Best Practices #### Single Responsibility Each commit should represent one logical change: - One feature addition - One bug fix - One refactoring operation - One documentation update #### Atomic Commits Commits should be complete and functional: - Code compiles without errors - Tests pass - No broken functionality introduced #### Meaningful Descriptions - Use imperative mood ("add feature" not "added feature") - Capitalize the first letter - No period at the end of the subject line - Keep subject line under 50 characters - Use body for detailed explanations when needed ### Branch Naming Conventions ```bash # Feature branches feature/ai-slug-generation feature/link-expiration # Bug fix branches fix/auth-token-validation fix/mobile-responsive-layout # Documentation branches docs/api-endpoint-guide docs/deployment-instructions # Hotfix branches hotfix/security-vulnerability hotfix/production-crash ``` ### Pull Request Guidelines #### PR Title Format Use the same format as commit messages: ``` feat(api): add AI-powered slug generation fix(auth): resolve token validation edge case docs(readme): update installation instructions ``` #### PR Description Template ```markdown ## Summary Brief description of changes made ## Type of Change - [ ] Bug fix - [ ] New feature - [ ] Documentation update - [ ] Refactoring - [ ] Performance improvement ## Testing - [ ] Unit tests added/updated - [ ] Integration tests pass - [ ] Manual testing completed ## Checklist - [ ] Code follows project style guidelines - [ ] Self-review completed - [ ] Documentation updated if needed - [ ] Tests cover new functionality - [ ] No breaking changes introduced ``` This standardized approach ensures clean, readable commit history and makes it easier to track changes, generate changelogs, and collaborate effectively with team members.