Loading...
Loading...
**MUST** use strict TypeScript configuration as defined in tsconfig.json:
---
trigger: always_on
---
# Global Coding Rules
## TypeScript Configuration
**MUST** use strict TypeScript configuration as defined in tsconfig.json:
```json
{
"compilerOptions": {
"target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true
}
}
```
**MUST** enable strict mode with no exceptions:
- Use explicit typing for function parameters
- No `any` types except in rare, documented cases
- Use proper null checks with optional chaining
- Enable strict property initialization checks
## Code Formatting and Linting
**MUST** use ESLint with Next.js configuration:
```json
{
"scripts": {
"lint": "eslint",
"lint:fix": "eslint --fix"
},
"lint-staged": {
"./src/**/*.{ts,js,jsx,tsx}": ["eslint --fix", "prettier --write -u"]
}
}
```
**MUST** follow these ESLint patterns:
- Use `eslint-plugin-simple-import-sort` for import ordering
- Use `eslint-plugin-unused-imports` to remove unused imports
- Follow Next.js ESLint configuration standards
## Import Organization
**MUST** organize imports in this order:
```typescript
// 1. External libraries
import React from "react";
import { NextRequest } from "next/server";
// 2. Internal absolute imports (domain, services, etc.)
import User from "@/domain/entities/User";
import Sessions from "@/services/auth/Sessions";
// 3. Relative imports
import "./Component.css";
```
**MUST** use absolute imports with `@/` for all internal modules:
```typescript
// Good
import db from "@/persistance/db";
import UserRepository from "@/domain/repositories/UserRepository";
// Bad
import db from "../../../persistance/db";
import UserRepository from "../../domain/repositories/UserRepository";
```
## Package Management
**MUST** use Yarn as package manager (as specified in package.json):
```json
{
"packageManager": "[email protected]+sha1.ac34549e6aa8e7ead463a7407e1c7390f61a6610"
}
```
**MUST** specify exact versions for critical dependencies:
```json
{
"dependencies": {
"@trigger.dev/sdk": "4.0.1",
"next": "15.5.0",
"react": "19.1.0"
}
}
```
## Environment Configuration
**MUST** use environment variables for configuration:
```env
# Database
DATABASE_URL=postgres://user:password@host:port/database
# Authentication
JWT_SECRET=your-very-secure-jwt-secret
# External Services
RESEND_API_KEY=re_your_resend_api_key
ELASTICSEARCH_URL=https://your-elasticsearch-cluster.com
```
**MUST** provide env.example with all required variables:
```env
# Copy to .env.local and fill in your values
DATABASE_URL=
JWT_SECRET=
RESEND_API_KEY=
ELASTICSEARCH_URL=
```
## Error Handling Patterns
**MUST** use consistent error handling across layers:
```typescript
// Domain layer - Use domain-specific errors
class UserNotFoundError extends Error {
constructor(id: string) {
super(`User with id ${id} not found`);
this.name = "UserNotFoundError";
}
}
// Service layer - Transform to client errors
try {
const user = await userRepository.findById(id);
} catch (error) {
if (error instanceof UserNotFoundError) {
throw new ActionClientError("USER_NOT_FOUND");
}
throw error;
}
// Frontend - Handle gracefully
try {
await signIn(email, password);
} catch (error) {
setError(error.message);
}
```
## Async/Await Patterns
**MUST** use async/await over Promises for readability:
```typescript
// Good
const processUser = async (id: string) => {
const user = await userRepository.findById(id);
const result = await processData(user);
return result;
};
// Avoid
const processUser = (id: string) => {
return userRepository
.findById(id)
.then((user) => processData(user))
.then((result) => result);
};
```
## Naming Conventions
**MUST** use consistent naming patterns:
**Files and Directories:**
- **PascalCase**: Components, Classes, Types (`UserComponent.tsx`, `UserRepository.ts`)
- **camelCase**: Functions, variables (`getUserById`, `userService.ts`)
- **kebab-case**: Pages, routes (`user-profile.tsx`, `auth-callback.ts`)
- **lowercase**: Configuration (`middleware.ts`, `layout.tsx`)
**Code Elements:**
```typescript
// Interfaces and Types - PascalCase
interface UserProfile {
id: string;
name: string;
}
// Classes - PascalCase
class UserService {
// Methods - camelCase
async getUserById(id: string): Promise<User> {}
}
// Constants - SCREAMING_SNAKE_CASE
const MAX_RETRY_ATTEMPTS = 3;
const API_BASE_URL = "https://api.example.com";
// Variables and functions - camelCase
const userName = "john";
const fetchUserData = async () => {};
```
## Performance Considerations
**MUST** implement performance best practices:
```typescript
// Use React.memo for expensive components
const ExpensiveComponent = React.memo(({ data }) => {
return <ComplexRendering data={data} />;
});
// Use proper dependency arrays in useEffect
useEffect(() => {
fetchData(id);
}, [id]); // Include all dependencies
// Use Next.js Image for optimized images
import Image from "next/image";
const OptimizedImage = () => (
<Image src="/image.jpg" alt="Description" width={500} height={300} />
);
// Implement proper loading states
const [isLoading, setIsLoading] = useState(false);
```
## Security Practices
**MUST** follow security guidelines:
```typescript
// Validate all inputs
const validateEmail = (email: string): boolean => {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
};
// Use secure cookie settings
const cookieOptions = {
httpOnly: true,
secure: process.env.NODE_ENV === "production",
sameSite: "strict" as const,
maxAge: 7 * 24 * 60 * 60,
};
// Sanitize user inputs
const sanitizedInput = input.trim().toLowerCase();
// Use environment variables for secrets
const JWT_SECRET = process.env.JWT_SECRET!;
```
## Git Commit Conventions
**MUST** use Conventional Commits with Commitizen:
```json
{
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
}
}
```
**Commit message format:**
```
type(scope): description
feat(auth): add JWT token refresh functionality
fix(database): resolve connection pool timeout issue
docs(readme): update installation instructions
style(components): format button component code
refactor(services): extract common validation logic
test(auth): add unit tests for password hashing
```
## Git Hooks with Husky
**MUST** use Husky for git hooks:
```json
{
"scripts": {
"prepare": "husky"
},
"lint-staged": {
"./src/**/*.{ts,js,jsx,tsx}": ["eslint --fix", "prettier --write -u"]
}
}
```
## Documentation Standards
**MUST** document complex functions and classes:
```typescript
/**
* Authenticates a user with email and password
* @param email - User's email address
* @param password - Plain text password
* @returns Promise resolving to authenticated user
* @throws ActionClientError when credentials are invalid
*/
const authenticateUser = async (
email: string,
password: string
): Promise<User> => {
// Implementation
};
```
## Testing Patterns
**MUST** follow testing conventions (when tests are added):
```typescript
// Unit tests - test individual functions
describe("PasswordManager", () => {
it("should hash passwords securely", async () => {
const password = "test123";
const hash = await PasswordManager.hash(password);
expect(hash).not.toBe(password);
});
});
// Integration tests - test service interactions
describe("AuthService", () => {
it("should create user and send welcome email", async () => {
const userData = { email: "[email protected]" };
const user = await AuthService.createUser(userData);
expect(user.id).toBeDefined();
// Verify email was sent
});
});
```
## Bundle Analysis and Optimization
**MUST** use Next.js built-in optimization:
```json
{
"scripts": {
"build": "next build --turbopack",
"dev": "next dev --turbopack"
}
}
```
**MUST** implement code splitting:
```typescript
// Dynamic imports for large components
const HeavyComponent = dynamic(() => import("./HeavyComponent"), {
loading: () => <Loading />,
});
// Route-based code splitting (automatic with App Router)
// pages/dashboard/page.tsx automatically creates a chunk
```
## Logging Standards
**MUST** use structured logging:
```typescript
const logger = {
info: (message: string, meta?: Record<string, any>) => {
console.log(
JSON.stringify({
level: "info",
message,
meta,
timestamp: new Date().toISOString(),
})
);
},
error: (message: string, error?: Error) => {
console.error(
JSON.stringify({
level: "error",
message,
error: error?.message,
stack: error?.stack,
timestamp: new Date().toISOString(),
})
);
},
};
```
## Code Review Guidelines
**MUST** ensure code reviews check for:
- TypeScript strict compliance
- Proper error handling
- Security considerations (input validation, secrets)
- Performance implications
- Test coverage for new features
- Documentation for complex logic
- Consistent naming conventions
- Proper import organization
An AI client and API for WordPress to communicate with any generative AI models of various capabilities using a uniform API. Built on top of the [PHP AI Client](https://github.com/WordPress/php-ai-client), it provides a WordPress-native Prompt Builder, an Admin Settings Screen for credentials, automatic credential wiring, a PSR-compliant HTTP client, and a client-side JavaScript API.
> This file provides instructions for AI agents that read AGENTS.md (GitHub Copilot, Cursor, Windsurf, Cline, Aider, OpenCode, and others).
This document collects ideas and instructions for implementing future improvements. Follow these when adding features or refactoring the code.
> This file must stay **in sync** with `CLAUDE.md`. Whenever you change one, mirror the same change in the other so both tools continue to work correctly.