Documentation Index Fetch the complete documentation index at: https://mintlify.com/egeuysall/ryva-archive/llms.txt
Use this file to discover all available pages before exploring further.
Ryva enforces strict code style guidelines to ensure consistency and maintainability across the codebase.
Overview
Automated Enforcement - Pre-commit hooks and CI/CD validate code style
Language-Specific Tools - golangci-lint for Go, ESLint & Prettier for TypeScript
Zero Tolerance - PRs with style violations cannot be merged
All code must pass linting before being committed. Pre-commit hooks will reject improperly formatted code.
Go (Backend API)
Style Guide
We follow the official Effective Go guidelines.
Go Linting Configuration
Ryva uses golangci-lint with extensive checks enabled:
- errcheck # Check for unchecked errors
- govet # Go vet analysis
- ineffassign # Detect ineffectual assignments
- staticcheck # Staticcheck analysis
- unused # Check for unused code
- errorlint # Error wrapping checks
- errname # Error naming conventions
- bodyclose # HTTP response body closing
- noctx # HTTP requests without context
- goconst # Repeated strings that could be constants
- gocyclo # Cyclomatic complexity
- whitespace # Whitespace issues
- gosec # Security issues
- gocritic # Go code critic
- nilerr # Nil error returns
- nilnil # Returning nil, nil
- dupl # Code duplication
- gomodguard # Module usage restrictions
- revive # Fast, configurable linter
- misspell # Spelling mistakes
- unconvert # Unnecessary type conversions
- unparam # Unused function parameters
- nakedret # Naked returns
- prealloc # Slice preallocation
Go Best Practices
Error Handling
Never ignore errors . Always return and handle them properly.
func getUser ( id string ) ( * User , error ) {
user , err := db . Query ( "SELECT * FROM users WHERE id = ?" , id )
if err != nil {
return nil , fmt . Errorf ( "failed to get user: %w " , err )
}
return user , nil
}
Context Usage
Always use context.Context for database operations, HTTP requests, and cancellable operations.
// ✅ Correct
func ( s * UserService ) GetUser ( ctx context . Context , id string ) ( * User , error ) {
var user User
err := s . db . QueryRowContext ( ctx , "SELECT * FROM users WHERE id = ?" , id ). Scan ( & user )
if err != nil {
return nil , fmt . Errorf ( "failed to get user: %w " , err )
}
return & user , nil
}
Handler Structure
Keep handlers thin. Move business logic to services.
// ✅ Correct - Thin handler
func ( h * UserHandler ) CreateUser ( w http . ResponseWriter , r * http . Request ) {
var req CreateUserRequest
if err := json . NewDecoder ( r . Body ). Decode ( & req ); err != nil {
http . Error ( w , "invalid request" , http . StatusBadRequest )
return
}
// Validate input
if err := req . Validate (); err != nil {
http . Error ( w , err . Error (), http . StatusBadRequest )
return
}
// Delegate to service
user , err := h . userService . CreateUser ( r . Context (), & req )
if err != nil {
http . Error ( w , "failed to create user" , http . StatusInternalServerError )
return
}
respondJSON ( w , http . StatusCreated , user )
}
Naming Conventions
Variables
Constants
Interfaces
// Use camelCase for local variables
userID := "123"
userEmail := "user@example.com"
// Use PascalCase for exported names
type UserService struct {}
func ( s * UserService ) CreateUser () {}
// ✅ Package comments should describe the package purpose
// Package auth provides authentication and authorization functionality.
package auth
// ✅ Exported functions should have comments
// CreateUser creates a new user in the database.
// It returns an error if the email is already taken.
func CreateUser ( ctx context . Context , user * User ) error {
// Implementation
}
// ✅ Complex logic should be explained
func processPayment ( amount float64 ) error {
// Calculate fee based on payment tier
// Tier 1 (0-100): 2%
// Tier 2 (101-1000): 1.5%
// Tier 3 (1001+): 1%
fee := calculateFee ( amount )
// ...
}
Code Organization
// ✅ Correct - Clean architecture
// handler → service → repository
// handlers/user_handler.go
type UserHandler struct {
userService * service . UserService
}
// services/user_service.go
type UserService struct {
userRepo repository . UserRepository
}
// repository/user_repository.go
type UserRepository interface {
Create ( ctx context . Context , user * User ) error
GetByID ( ctx context . Context , id string ) ( * User , error )
}
Linter Settings
Key settings from .golangci.yml:
Cyclomatic complexity : Max 15
Duplicate threshold : 100 lines
Naked returns : Max 30 lines
String constants : Min 3 characters, 3 occurrences
TypeScript/React (Frontend)
Style Guide
We follow TypeScript best practices and React conventions.
Prettier Configuration
{
"semi" : true ,
"trailingComma" : "es5" ,
"singleQuote" : true ,
"printWidth" : 100 ,
"tabWidth" : 2 ,
"useTabs" : false ,
"arrowParens" : "avoid"
}
TypeScript Best Practices
Type Safety
Never use any type . Use proper types or unknown if type is truly unknown.
interface User {
id : string ;
name : string ;
email : string ;
role : 'admin' | 'user' | 'guest' ;
}
function getUser ( id : string ) : Promise < User > {
return fetch ( `/api/users/ ${ id } ` ). then ( res => res . json ());
}
Component Props
Always type component props with interfaces.
// ✅ Correct
interface UserProfileProps {
user : User ;
onUpdate ?: ( user : User ) => void ;
isEditable ?: boolean ;
}
export function UserProfile ({ user , onUpdate , isEditable = false } : UserProfileProps ) {
// Implementation
}
Server vs Client Components
Server Components by default . Only use Client Components when needed.
Server Component (Default)
Client Component (When Needed)
// No 'use client' directive
export function UserList () {
// Can directly fetch data
const users = await getUsers ();
return (
< div >
{ users . map ( user => (
< div key = { user . id } > { user . name } </ div >
)) }
</ div >
);
}
Hooks
// ✅ Custom hooks should start with 'use'
import { useState , useEffect } from 'react' ;
interface UseUserDataResult {
user : User | null ;
isLoading : boolean ;
error : Error | null ;
}
export function useUserData ( userId : string ) : UseUserDataResult {
const [ user , setUser ] = useState < User | null >( null );
const [ isLoading , setIsLoading ] = useState ( true );
const [ error , setError ] = useState < Error | null >( null );
useEffect (() => {
fetchUser ( userId )
. then ( setUser )
. catch ( setError )
. finally (() => setIsLoading ( false ));
}, [ userId ]);
return { user , isLoading , error };
}
State Management
TanStack Query (Server State)
Zustand (Client State)
import { useQuery } from '@tanstack/react-query' ;
export function useUser ( userId : string ) {
return useQuery ({
queryKey: [ 'user' , userId ],
queryFn : () => fetchUser ( userId ),
});
}
Naming Conventions
Components
Functions
Constants
Types/Interfaces
// PascalCase for components
export function UserProfile () {}
export function NavigationMenu () {}
File Organization
components/
├── UserProfile/
│ ├── UserProfile.tsx # Main component
│ ├── UserProfile.test.tsx # Tests
│ ├── UserProfile.types.ts # Type definitions
│ └── index.ts # Exports
Import Order
// 1. React imports
import { useState , useEffect } from 'react' ;
// 2. External libraries
import { useQuery } from '@tanstack/react-query' ;
import { z } from 'zod' ;
// 3. Internal modules
import { fetchUser } from '@/lib/api' ;
import { useAuth } from '@/hooks/useAuth' ;
// 4. Components
import { Button } from '@/components/ui/Button' ;
import { UserAvatar } from '@/components/UserAvatar' ;
// 5. Types
import type { User } from '@/types/user' ;
// 6. Styles (if applicable)
import styles from './UserProfile.module.css' ;
General Principles
Code Quality Standards
Readability First - Code is read more than written
DRY Principle - Don’t Repeat Yourself
KISS Principle - Keep It Simple, Stupid
YAGNI Principle - You Aren’t Gonna Need It
Single Responsibility - One function, one purpose
Explicit over Implicit - Clear code over clever code
Fail Fast - Validate early and return errors immediately
Immutability - Prefer immutable data structures
Pre-commit Hooks
Ryva uses pre-commit hooks to enforce code quality:
Automatic Checks
On every commit, the following run automatically:
Code formatting validation
Linting
Commit message validation (Conventional Commits)
Type checking
Fix Issues
If hooks fail, fix the issues and commit again: # Fix formatting
make format
# Fix linting issues
make lint
# Try commit again
git commit -m "feat(api): add new feature"
You cannot bypass pre-commit hooks. Fix all issues before committing.
CI/CD Checks
All PRs must pass:
✅ ESLint (Web)
✅ golangci-lint (API)
✅ Prettier formatting (Web)
✅ gofmt formatting (API)
✅ TypeScript type checking (Web)
✅ Go vet analysis (API)
✅ Security scans (gosec, npm audit)
Run all checks locally before pushing: make lint
make test
make format