Thank you for your interest in contributing to Payego! We welcome contributions from everyone and appreciate your help in making this project better.
- Code of Conduct
- Getting Started
- Development Workflow
- Testing Requirements
- Code Quality Standards
- Pull Request Process
- Commit Message Guidelines
- Architecture Overview
- Security Guidelines
- Documentation Standards
- Getting Help
We are committed to providing a welcoming and inclusive environment for all contributors, regardless of experience level, background, or identity.
- Be respectful and considerate
- Use welcoming and inclusive language
- Accept constructive criticism gracefully
- Focus on what's best for the project
- Show empathy towards other contributors
- Harassment, trolling, or discriminatory comments
- Personal attacks or insults
- Publishing others' private information
- Any conduct that would be inappropriate in a professional setting
Ensure you have the following installed:
- Rust: v1.75+ (
rustup update) - Node.js: v18+
- PostgreSQL: v15+
- Diesel CLI:
cargo install diesel_cli --no-default-features --features postgres - Git: Latest version
-
Fork the Repository
# Click "Fork" on GitHub, then clone your fork git clone https://github.com/YOUR_USERNAME/payego.git cd payego
-
Add Upstream Remote
git remote add upstream https://github.com/intelliDean/payego.git
-
Environment Configuration
cp .env.example .env
Edit
.envand configure:- Database credentials
- JWT secret (32+ characters)
- Payment provider keys (Stripe, PayPal, Paystack)
- CORS origins
-
Database Setup
# Create database diesel setup # Run migrations diesel migration run
-
Install Dependencies
Backend:
cargo build
Frontend:
cd payego_ui npm install -
Verify Setup
Backend:
cargo test --workspace cargo runFrontend:
cd payego_ui npm test npm run dev
Always create a new branch for your work:
git checkout -b feature/your-feature-name
# or
git checkout -b fix/bug-descriptionBranch naming conventions:
feature/- New featuresfix/- Bug fixesdocs/- Documentation changesrefactor/- Code refactoringtest/- Adding or updating testschore/- Maintenance tasks
Backend Development:
- Code location:
crates/api,crates/core,crates/primitives - Run tests:
cargo test --workspace - Check linting:
cargo clippy --workspace --tests -- -D warnings - Format code:
cargo fmt --all
Frontend Development:
- Code location:
payego_ui/src - Run dev server:
npm run dev - Run tests:
npm test - Run linting:
npm run lint - Build:
npm run build
Regularly sync with upstream:
git fetch upstream
git rebase upstream/mainFollow our commit message guidelines:
git add .
git commit -m "feat: add user profile endpoint"git push origin feature/your-feature-nameThen create a Pull Request on GitHub.
Required:
- Write integration tests for new API endpoints
- Write unit tests for service layer logic
- Ensure all existing tests pass
Running tests:
# All tests
cargo test --workspace
# Specific test file
cargo test --test auth_tests
# With output
cargo test -- --nocaptureTest categories:
bin/payego/tests/- Integration tests- Service unit tests - In service modules
Example test:
#[tokio::test]
async fn test_user_registration() {
let app = setup_test_app().await;
let response = app.register_user("test@example.com", "password123").await;
assert_eq!(response.status(), StatusCode::CREATED);
}Required:
- Write tests for new components
- Test error handling scenarios
- Ensure all existing tests pass
Running tests:
cd payego_ui
npm test
# With coverage
npm test -- --coverage
# Watch mode
npm test -- --watchTest utilities:
Use test-utils.tsx for component tests:
import { render, screen } from '../utils/test-utils';
test('renders login form', () => {
render(<LoginForm />);
expect(screen.getByLabelText(/email/i)).toBeInTheDocument();
});- Backend: Maintain 70%+ coverage for service layer
- Frontend: Aim for 60%+ coverage for components
- Critical paths: 100% coverage (auth, payments, transfers)
1. Run Clippy (Required)
cargo clippy --workspace --tests -- -D warningsAll Clippy warnings must be resolved before PR approval.
2. Format Code (Required)
cargo fmt --all3. Follow Rust Conventions
- Use
snake_casefor functions and variables - Use
PascalCasefor types and traits - Add doc comments for public APIs
- Avoid
unwrap()- use proper error handling
4. Error Handling
- Use
Result<T, ApiError>for all fallible operations - Never use
panic!in production code - Log errors appropriately (WARN for expected, ERROR for unexpected)
5. Security
- Wrap secrets in
secrecy::Secret<T> - Never log sensitive data
- Validate all user input
1. Run Linter (Required)
npm run lint2. TypeScript
- Enable strict mode
- Avoid
anytypes - Use proper type definitions
3. Component Standards
- Use functional components with hooks
- Extract reusable logic into custom hooks
- Keep components focused and small
4. Error Handling
- Use centralized error handler (
errorHandler.ts) - Display user-friendly error messages
- Log errors for debugging
Checklist:
- All tests pass (
cargo test,npm test) - Code is formatted (
cargo fmt,npm run lint) - No Clippy warnings (
cargo clippy) - Added tests for new functionality
- Updated documentation if needed
- Commit messages follow conventions
- Branch is up-to-date with
main
## Description
Brief description of changes
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Testing
How was this tested?
## Checklist
- [ ] Tests added/updated
- [ ] Documentation updated
- [ ] No breaking changes (or documented)- Automated Checks: CI runs tests and linting
- Code Review: Maintainer reviews code
- Feedback: Address review comments
- Approval: PR approved by maintainer
- Merge: Squash and merge to main
Expected timeline: 2-5 business days for initial review
We follow Conventional Commits.
<type>(<scope>): <subject>
<body>
<footer>
feat: New featurefix: Bug fixdocs: Documentation changesstyle: Code style changes (formatting)refactor: Code refactoringtest: Adding or updating testschore: Maintenance tasks
Good:
feat(auth): add email verification flow
Implements email verification with expiring tokens.
Users receive verification emails upon registration.
Closes #123
Bad:
updated stuff
- Use present tense ("add" not "added")
- Use imperative mood ("move" not "moves")
- Keep subject line under 72 characters
- Reference issues in footer
payego/
├── bin/payego/ # Main binary
├── crates/
│ ├── api/ # HTTP handlers
│ ├── core/ # Business logic
│ └── primitives/ # Shared types
└── payego_ui/ # React frontend
1. API Layer (crates/api)
- HTTP handlers
- Request/response parsing
- Route definitions
- OpenAPI documentation
2. Core Layer (crates/core)
- Business logic services
- External API clients
- Database operations
- Email service
3. Primitives Layer (crates/primitives)
- Database entities
- DTOs (Data Transfer Objects)
- Error types
- Shared utilities
Service Layer Pattern:
pub struct TransferService {
db: Arc<DatabaseConnection>,
}
impl TransferService {
pub async fn transfer_internal(
&self,
request: TransferRequest,
) -> Result<Transaction, ApiError> {
// Business logic here
}
}Entity vs DTO Separation:
- Entities: Database models (internal only)
- DTOs: API contracts (public-facing)
- Never expose entities directly in API responses
Error Handling:
pub enum ApiError {
NotFound(String),
Unauthorized,
ValidationError(Vec<String>),
// ...
}Component Structure:
- Keep components small and focused
- Extract business logic into hooks
- Use React Query for server state
- Use Context API for auth state
Error Handling:
import { getErrorMessage } from '../utils/errorHandler';
try {
await api.login(credentials);
} catch (err) {
setError(getErrorMessage(err));
}DO:
- Use
secrecy::Secret<String>for sensitive data - Store secrets in environment variables
- Use
.envfile locally (never commit!)
DON'T:
- Hardcode secrets in code
- Log sensitive information
- Commit
.envfiles
If you discover a security vulnerability:
- DO NOT open a public issue
- Email the maintainer directly
- Include detailed description and reproduction steps
- Allow time for fix before public disclosure
- Validate all user input
- Use parameterized queries (Diesel handles this)
- Implement rate limiting
- Use HTTPS in production
- Keep dependencies updated
Rust:
/// Transfers funds between internal Payego users
///
/// # Arguments
/// * `from_user_id` - Source user ID
/// * `to_username` - Destination username
/// * `amount` - Transfer amount
///
/// # Returns
/// Transaction record on success
///
/// # Errors
/// Returns `ApiError::InsufficientBalance` if sender lacks funds
pub async fn transfer_internal(
&self,
from_user_id: Uuid,
to_username: &str,
amount: Decimal,
) -> Result<Transaction, ApiError> {
// Implementation
}TypeScript:
/**
* Extracts user-friendly error message from API error
* @param error - Axios error or generic error object
* @returns User-friendly error message string
*/
export function getErrorMessage(error: any): string {
// Implementation
}OpenAPI/Swagger:
- Document all endpoints with
#[utoipa::path] - Include request/response examples
- Document all status codes
- Add parameter descriptions
Example:
#[utoipa::path(
post,
path = "/api/auth/login",
request_body = LoginRequest,
responses(
(status = 200, description = "Login successful", body = AuthResponse),
(status = 401, description = "Invalid credentials"),
),
tag = "Authentication"
)]
pub async fn login(/* ... */) -> Result<Json<AuthResponse>, ApiError> {
// Implementation
}If your changes affect:
- Setup process → Update README.md
- Docker deployment → Update README.Docker.md
- Contributing process → Update CONTRIBUTING.md
- Main README: README.md
- Docker Guide: README.Docker.md
- API Docs: http://localhost:8080/swagger-ui/ (when running)
- Open a GitHub Discussion for general questions
- Open an issue for bug reports
- Check existing issues before creating new ones
Debugging Backend:
# Enable debug logging
RUST_LOG=debug cargo run
# View database queries
RUST_LOG=diesel=debug cargo runDebugging Frontend:
# Check React Query cache
# Install React Query DevTools (already configured)Database Inspection:
# Connect to database
diesel database reset # Careful: drops all data!
psql -U postgres -d payegoYour contributions make Payego better for everyone. We appreciate your time and effort!
Happy Coding! 🚀
By contributing to Payego, you agree that your contributions will be licensed under the MIT License.