Contributing
Guide for contributing to OpenCode Manager.
Getting Started
- Fork the repository
- Clone your fork
- Set up local development (see Local Setup)
- Create a feature branch
- Make changes
- Submit a pull request
Code Style
General Guidelines
- No comments - Code should be self-documenting
- No console.log - Use proper logging
- Strict TypeScript - Proper typing everywhere
- Named imports - No default imports
- DRY principles - Don't repeat yourself
- SOLID design - Follow SOLID principles
Backend (Bun + Hono)
// Route handler
app.get('/api/repos', async (c) => {
const repos = await repoService.listAll()
return c.json(repos)
})
// Service
export const repoService = {
async listAll(): Promise<Repository[]> {
return db.query.repositories.findMany()
}
}
Guidelines:
- Use Zod for validation
- Async/await (no .then() chains)
- Structured error handling
- Follow existing patterns
Frontend (React + Vite)
import { useState } from 'react'
import { Button } from '@/components/ui/button'
import { useRepositories } from '@/hooks/useRepositories'
export function RepoList() {
const { data: repos } = useRepositories()
return (
<div>
{repos?.map(repo => (
<RepoCard key={repo.id} repo={repo} />
))}
</div>
)
}
Guidelines:
- Use
@/alias for imports - React Query for server state
- React Hook Form + Zod for forms
- Radix UI + Tailwind for components
Pull Request Process
Before Submitting
- Run linting:
pnpm lint - Run tests:
pnpm test - Check types:
pnpm typecheck - Test manually: Verify your changes work
PR Guidelines
- Keep PRs focused on a single feature/fix
- Write clear commit messages
- Include tests for new functionality
- Update documentation if needed
- Reference related issues
Commit Messages
Format: type: brief description
Types:
- feat - New feature
- fix - Bug fix
- docs - Documentation
- refactor - Code refactoring
- test - Adding tests
- chore - Maintenance
Examples:
feat: add file upload progress indicator
fix: resolve session expiry on mobile
docs: update installation guide
refactor: extract git service from routes
Testing
Writing Tests
import { expect, test, describe, beforeEach } from 'bun:test'
describe('featureName', () => {
beforeEach(() => {
// Setup
})
test('should do something', async () => {
const result = await doSomething()
expect(result).toBe(expected)
})
})
Coverage Requirements
- Minimum 80% coverage
- Cover edge cases
- Test error conditions
Running Tests
# All tests
pnpm test
# With coverage
cd backend && bun test --coverage
# Single file
cd backend && bun test path/to/test.ts
Architecture Decisions
Why Bun?
- Fast startup and execution
- Built-in TypeScript support
- SQLite driver included
- Modern JavaScript runtime
Why Hono?
- Lightweight and fast
- TypeScript-first
- Works with Bun natively
- Simple, Express-like API
Why React Query?
- Automatic caching and refetching
- Server state management
- Optimistic updates
- SSE support for streaming
Why Radix UI?
- Accessible by default
- Unstyled (pairs with Tailwind)
- Headless components
- Production-ready
Adding Features
New API Endpoint
- Create route in
backend/src/routes/ - Add service logic in
backend/src/services/ - Define types in
shared/ - Add tests
- Update API client in frontend
New UI Component
- Create component in
frontend/src/components/ - Use Radix UI primitives if applicable
- Style with Tailwind
- Add to relevant page
- Test responsiveness
New Feature Flag
- Add to settings schema
- Create migration if needed
- Add UI toggle in settings
- Check flag in relevant code
Getting Help
- Questions: Open a GitHub Discussion
- Bugs: Open a GitHub Issue
- Features: Open a GitHub Issue with
featurelabel
License
By contributing, you agree that your contributions will be licensed under the MIT License.