VeztaVezta
Guides

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 to src/* in the backend, @/ maps to the project root in the frontend
  • Enums: Use as const objects instead of TypeScript enums (consistent with Kubb-generated types)

Linting and Formatting

  • ESLint -- run pnpm lint in any subproject before committing
  • Prettier -- run pnpm format in 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 ESLint

Financial 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:

  1. Make your backend changes (new endpoints, modified DTOs)
  2. Run pnpm export:openapi in vezta-be (or rely on auto-export at startup)
  3. Run pnpm generate in vezta-fe
  4. Copy vezta-fe/lib/api/gen/ to vezta-mobile/lib/api/gen/

Branch Strategy

  • main -- production branch, always deployable
  • Feature branches -- created off main for all new work

Branch naming:

feature/copy-trade-filters
fix/order-state-transition
refactor/market-normalizer
chore/upgrade-prisma

Commit 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 endpoints

Include 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 foreground

Pull Request Process

Create a Feature Branch

git checkout main
git pull origin main
git checkout -b feature/your-feature

Make Your Changes

Follow the code standards described above. Run linting and tests locally:

pnpm lint
pnpm test

Push and Open a PR

git push -u origin feature/your-feature

Open 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 @ApiProperty decorators for OpenAPI accuracy
  • Financial calculations use Decimal, not floats
  • Error responses use ApiException with 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.

On this page