This file provides instructions and guidelines for working with OpenCode on this project.
- Available Agents
- Agent Usage Guidelines
- Coding Style
- Security Requirements
- Testing Requirements
- Common Patterns
- Performance Guidelines
- Git Workflow
| Agent | Purpose | When to Use |
|---|---|---|
| planner | Implementation planning | Complex features, refactoring |
| architect | System design | Architectural decisions |
| tdd-guide | Test-driven development | New features, bug fixes |
| code-reviewer | Code review | After writing code |
| security-reviewer | Security analysis | Before commits |
| build-error-resolver | Fix build errors | When build fails |
| e2e-runner | E2E testing | Critical user flows |
| refactor-cleaner | Dead code cleanup | Code maintenance |
| doc-updater | Documentation | Updating docs |
ALWAYS invoke these agents proactively:
- planner: When request involves multiple files or complex logic
- tdd-guide: When writing new code or fixing bugs
- code-reviewer: Immediately after any code modification
- security-reviewer: When touching auth, APIs, or sensitive data
- build-error-resolver: When build or type errors occur
For complex decisions, run agents in parallel:
User: "Add user authentication"
Invoke simultaneously:
- planner: Break down implementation steps
- architect: Design authentication system
- security-reviewer: Identify security requirements
- tdd-guide: Define test requirements
- MANY SMALL FILES - Keep files between 200-400 lines (800 max)
- Immutability - ALWAYS use spread operator, NEVER mutate directly
- Comprehensive Error Handling - Every async operation wrapped in try/catch
- Input Validation - All inputs validated at system boundaries
// CORRECT: Immutability
function updateUser(user, name) {
return {
...user,
name
}
}
// WRONG: Mutation
function updateUser(user, name) {
user.name = name // NEVER DO THIS
return user
}src/
├── app/ # Next.js App Router
│ ├── api/ # API routes
│ └── (pages)/ # Page components
├── components/ # React components
│ ├── ui/ # Generic UI components
│ └── forms/ # Form components
├── hooks/ # Custom React hooks
├── lib/ # Utilities and configs
├── types/ # TypeScript types
└── styles/ # Global styles
- Files:
kebab-case.tsfor utilities,PascalCase.tsxfor components - Functions:
camelCase, verb-noun pattern (e.g.,fetchMarkets,calculateTotal) - Constants:
SCREAMING_SNAKE_CASE - Types/Interfaces:
PascalCase
BEFORE any code change, verify:
-
No Hardcoded Secrets
- API keys in environment variables
- No credentials in source code
.env.localin.gitignore
-
Input Validation
- All user inputs validated with schemas (Zod)
- File uploads restricted (size, type)
- SQL injection prevention (parameterized queries)
-
Authentication/Authorization
- Tokens in httpOnly cookies
- Authorization checks on every route
- Row Level Security in Supabase
// ALWAYS: Environment variables
const apiKey = process.env.OPENAI_API_KEY
if (!apiKey) {
throw new Error('OPENAI_API_KEY not configured')
}
// NEVER: Hardcoded secrets
const apiKey = "sk-abc123..." // PROHIBITEDIf security vulnerability found:
- STOP current implementation
- DOCUMENT the vulnerability
- FIX before proceeding
- VERIFY fix is complete
- REVIEW with security-reviewer agent
Test Types (ALL required):
- Unit Tests - Individual functions, utilities, components
- Integration Tests - API endpoints, database operations
- E2E Tests - Critical user flows (Playwright)
1. Write test first (RED)
2. Run test - it should FAIL
3. Write minimal implementation (GREEN)
4. Run test - it should PASS
5. Refactor (IMPROVE)
6. Verify coverage (80%+)
test('calculates similarity correctly', () => {
// Arrange
const vector1 = [1, 0, 0]
const vector2 = [0, 1, 0]
// Act
const similarity = calculateCosineSimilarity(vector1, vector2)
// Assert
expect(similarity).toBe(0)
})interface ApiResponse<T> {
success: boolean
data?: T
error?: string
meta?: {
total: number
page: number
limit: number
}
}export function useDebounce<T>(value: T, delay: number): T {
const [debouncedValue, setDebouncedValue] = useState<T>(value)
useEffect(() => {
const handler = setTimeout(() => setDebouncedValue(value), delay)
return () => clearTimeout(handler)
}, [value, delay])
return debouncedValue
}async function fetchData(url: string) {
try {
const response = await fetch(url)
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`)
}
return await response.json()
} catch (error) {
console.error('Fetch failed:', error)
throw new Error('Failed to fetch data')
}
}- Fast tasks: Use faster models for simple operations
- Complex tasks: Use advanced models for architecture, planning
- Code generation: Balance speed and quality
Avoid large context windows for:
- Large-scale refactoring
- Feature implementation spanning multiple files
- Debugging complex interactions
Good for lower context:
- Single-file edits
- Independent utility creation
- Documentation updates
- Simple bug fixes
If build fails:
- Use build-error-resolver agent
- Analyze error messages
- Fix incrementally
- Verify after each fix
<type>(<scope>): <description>
[optional body]
[optional footer]
Types:
feat: New featurefix: Bug fixdocs: Documentationstyle: Formattingrefactor: Code refactoringtest: Testschore: Maintenance
<type>/<short-description>
Examples:
feat/add-google-authfix/handle-null-responsesdocs/update-readme
main(ormaster): Production-ready code- Direct commits NOT allowed
- All changes through Pull Requests
/plan- Create implementation plan/tdd- Test-driven development workflow/code-review- Review uncommitted changes/build-fix- Fix build errors/e2e- Run end-to-end tests/verify- Run verification checks
backend-patterns- API and database patternsfrontend-patterns- React and Next.js patternstdd-workflow- Test-driven developmentsecurity-review- Security best practicescoding-standards- General coding guidelines
Remember: Quality over speed. Test before implementation. Security is not optional.