Contributing
Code standards, branch strategy, and PR process
This guide covers coding conventions, the branching strategy, and the pull request process for contributing to any Vezta subproject.
Code Standards
TypeScript
TypeScript strict mode is enabled across all subprojects. Write typed code throughout -- no any types unless absolutely unavoidable.
- Path aliases:
@/*maps tosrc/*in the backend,@/maps to the project root in the frontend - Enums: Use
as constobjects instead of TypeScript enums (consistent with Kubb-generated types)
Linting and Formatting
- ESLint -- run
pnpm lintin any subproject before committing - Prettier -- run
pnpm formatin the backend for auto-formatting
cd vezta-be && pnpm lint # Backend ESLint
cd vezta-fe && pnpm lint # Frontend ESLint (next lint)
cd vezta-mobile && pnpm lint # Mobile ESLintFinancial Values
Never use JavaScript floating-point numbers for financial values. The backend uses Prisma's Decimal type with specific precisions: @db.Decimal(18, 2) for USD amounts, @db.Decimal(10, 6) for prices, @db.Decimal(5, 4) for rates. On the frontend and mobile, decimal values from the API arrive as strings -- parse them carefully.
Error Response Contract
All backend errors must normalize to this shape:
{
"statusCode": 400,
"code": "VALIDATION_ERROR",
"message": "Field 'amount' must be a positive number"
}The frontend depends on this contract. Use ApiException (not raw HttpException) for domain errors that need machine-readable codes.
Generated Code
Never hand-edit files in lib/api/gen/ in any subproject. This directory is fully regenerated by Kubb. To update the API client:
- Make your backend changes (new endpoints, modified DTOs)
- Run
pnpm export:openapiinvezta-be(or rely on auto-export at startup) - Run
pnpm generateinvezta-fe - Copy
vezta-fe/lib/api/gen/tovezta-mobile/lib/api/gen/
Branch Strategy
main-- production branch, always deployable- Feature branches -- created off
mainfor all new work
Branch naming:
feature/copy-trade-filters
fix/order-state-transition
refactor/market-normalizer
chore/upgrade-prismaCommit Messages
Use Conventional Commits:
feat: add copy trade subscription filters
fix: correct order state machine transition for partial fills
refactor: extract normalizer into standalone service
chore: upgrade Prisma to 6.x
docs: add API client generation guide
test: add E2E tests for trading endpointsInclude the scope when the change is specific to a subproject or module:
feat(trading): add TPSL support to order creation
fix(mobile): reconnect WebSocket on app foregroundPull Request Process
Create a Feature Branch
git checkout main
git pull origin main
git checkout -b feature/your-featureMake Your Changes
Follow the code standards described above. Run linting and tests locally:
pnpm lint
pnpm testPush and Open a PR
git push -u origin feature/your-featureOpen a pull request against main. Include:
- A clear description of what the PR does and why
- Steps to test the changes locally
- Screenshots for UI changes
CI Checks
The test.yml workflow runs automatically on PRs. All checks must pass before merging:
- Linting (ESLint)
- Unit tests with coverage
- E2E tests (frontend via Playwright)
- Type checking (mobile via
pnpm tsc)
Code Review
At least one review approval is required before merging. Reviewers should check:
- Code follows existing patterns and conventions
- DTOs have proper
@ApiPropertydecorators for OpenAPI accuracy - Financial calculations use
Decimal, not floats - Error responses use
ApiExceptionwith appropriate codes - New API endpoints have
@ApiTags,@ApiOperation, and@ApiResponse
Merge and Deploy
Merge the PR into main. This triggers automatic deployment:
- Frontend deploys to Vercel
- Backend deploys to the Docker VM via GitHub Actions
- Mobile triggers EAS Build
Swagger Documentation
Every backend controller must be properly decorated for OpenAPI spec accuracy, since the frontend generates its entire API client from this spec:
@ApiTags('trading')
@ApiBearerAuth('access-token')
@Controller('api/v1/trading')
export class TradingController {
@Post('orders')
@ApiOperation({ summary: 'Place a new order' })
@ApiResponse({ status: 201, type: OrderResponseDto })
@ApiResponse({ status: 400, description: 'Validation error' })
create(@Body() dto: CreateOrderDto) { ... }
}After merging backend API changes, a follow-up commit should regenerate the frontend client (pnpm generate) and sync it to the mobile app. Do not merge frontend PRs that depend on new API endpoints without the regenerated client.