Thank you for considering contributing to PayD! We're building a decentralized payroll platform on Stellar, and we value contributions from developers, designers, and documentation experts alike.
- Code of Conduct
- Getting Started
- Development Environment Setup
- Coding Standards
- Database Migrations
- Making Changes
- Testing
- Commit Conventions
- Submitting a Pull Request
- Rewards Program
- Getting Recognized
We are committed to providing a welcoming and inclusive environment for all contributors. Please read and follow our CODE_OF_CONDUCT.md.
- Node.js 18+ (for frontend and backend)
- Rust 1.70+ (for Soroban contracts)
- Docker & Docker Compose (recommended for local development)
- Git (for version control)
- PostgreSQL 15+ (if running backend without Docker)
- Redis 7+ (if running backend without Docker)
- Fork the repository on GitHub
- Clone your fork locally:
git clone https://github.com/YOUR_USERNAME/PayD.git cd PayD - Create a feature branch:
git checkout -b feature/your-feature-name
- Install dependencies (see Development Environment Setup)
- Run the development server (see Development Environment Setup)
The easiest way to get started is using Docker Compose, which sets up the entire stack (API, PostgreSQL, Redis).
# Navigate to backend directory
cd backend
# Copy environment file
cp .env.example .env
# Start all services
docker-compose up
# In another terminal, verify services are healthy
./scripts/docker-health-check.sh
# View logs
docker-compose logs -f apiTroubleshooting Docker issues? See DOCKER_TROUBLESHOOTING.md.
cd backend
# Install Node.js dependencies
npm install
# Copy and configure environment
cp .env.example .env
# Edit .env with your local database credentials
# Install PostgreSQL (macOS with Homebrew)
brew install postgresql@15
brew services start postgresql@15
# Install Redis (macOS with Homebrew)
brew install redis
brew services start redis
# Create database and run migrations
npm run db:migrate
# Start development server
npm run dev# From root directory
npm install
# Start development server (includes contract watching)
npm start# Install Rust (if not already installed)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Build all contracts
cd contracts/bulk_payment
cargo build --release
# Or build all at once from root
cargo build --release --workspaceWindows users should use WSL 2 (Windows Subsystem for Linux) with Docker Desktop:
# Enable WSL 2 and install Docker Desktop for Windows
# Then follow the Linux instructions above in your WSL terminal- Formatter: Prettier (configured in
.prettierrc) - Linter: ESLint (configured in
.eslintrc.json) - Style: Follow existing code patterns in the codebase
# Format code
npm run format
# Lint code
npm run lint
# Fix linting issues
npm run lint -- --fixKey conventions:
- Use
constby default,letwhen reassignment is needed - Prefer arrow functions for callbacks
- Use TypeScript strict mode (no
anywithout justification) - Add JSDoc comments for public functions and exports
- Use meaningful variable names (avoid single letters except in loops)
- Formatter:
rustfmt(automatic viacargo fmt) - Linter:
clippy(automatic viacargo clippy) - Style: Follow Rust API guidelines
# Format Rust code
cargo fmt
# Lint Rust code
cargo clippy --all-targets --all-featuresKey conventions:
- Use
#[derive(...)]for common traits - Document public functions with
///doc comments - Use meaningful error types (avoid generic
Stringerrors) - Optimize for gas efficiency in contracts (see GAS_OPTIMIZATION_CHECKLIST.md)
- Naming:
NNN_description.sql(e.g.,001_create_tables.sql) - Style: Use uppercase for SQL keywords, lowercase for identifiers
- Comments: Add migration purpose and design decisions at the top
- Idempotency: Use
IF NOT EXISTS/IF NOT EXISTSclauses
-- Migration 001: Create core tables
-- Purpose: Establish base schema for organizations, employees, and transactions
-- Design: Uses SERIAL for IDs, TIMESTAMPTZ for timezone safety
CREATE TABLE IF NOT EXISTS organizations (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);- React components: Use
PascalCasefilenames such asPayrollScheduler.tsx - Hooks and TypeScript implementation files: Use
camelCasefilenames such asusePayrollData.tsandpayrollAuditService.ts - Static assets and path-oriented docs: Use
kebab-casefilenames such aspayroll-summary-icon.svg - SQL migrations: Use
NNN_snake_case.sqlfilenames such as025_add_metadata_to_payroll_items.sql - Legacy areas: Preserve the existing directory pattern unless the change is a dedicated rename/refactor
See docs/FILENAMING_CONVENTIONS.md for the full naming matrix and migration guidance.
- Markdown: Use clear headings, code blocks, and examples
- Links: Use relative paths for internal docs
- Code examples: Include language identifier in fenced code blocks
- Accessibility: Use descriptive alt text for diagrams
This section is mandatory reading before submitting any PR that modifies the database schema.
Migration files are immutable once merged to main. The migration runner
(backend/src/db/migrate.ts) stores a SHA-256 checksum of every file it applies.
If the file's bytes change later — even a single space or comment — the runner
detects the mismatch and aborts:
[migrate] DRIFT DETECTED: "017_create_schema_migrations.sql" was previously
applied with checksum abc123... but the file now has checksum def456...
Aborted to protect database integrity.
This is the most common cause of CI/CD pipeline failures in this project.
Need to add a column? Fix a constraint? Add an index? Create a new migration. Never edit an existing one.
# 1. Find the next available number
ls backend/src/db/migrations/*.sql | sed 's/.*\///' | grep -oP '^\d+' | sort -n | tail -1
# 2. Create your migration (increment the number by 1)
# Example: if the result was 038, create:
touch backend/src/db/migrations/039_add_tax_region_to_employees.sql
# 3. Create the matching rollback (required — PRs without it will be rejected)
touch backend/src/db/rollbacks/039_add_tax_region_to_employees.sql- [ ] Migration file named correctly: NNN_short_description.sql
- [ ] Migration number is unique (no duplicates with existing files)
- [ ] Migration uses IF NOT EXISTS / IF EXISTS for idempotency
- [ ] Matching rollback file created in backend/src/db/rollbacks/
- [ ] npm run db:migrate:dry-run passes locally
- [ ] Running npm run db:migrate twice gives Applied: 0 on the second run
- [ ] No existing migration file was modified| Error | Fix |
|---|---|
DRIFT DETECTED |
Restore the original file content; create a new migration for your changes |
Duplicate migration prefix(es) detected |
Run node scripts/resequence-migrations.mjs from the repo root |
Missing rollback file |
Create backend/src/db/rollbacks/NNN_your_migration.sql |
See backend/src/db/MIGRATION_GUIDE.md for:
- Complete workflow with examples
- How the checksum guard works
- How to use the re-sequencing script
- Troubleshooting guide
- Full PR checklist
- Check existing issues to avoid duplicate work
- Comment on the issue to let others know you're working on it
- Discuss major changes in the issue before starting implementation
- Keep commits atomic: Each commit should represent a single logical change
- Write descriptive commit messages (see Commit Conventions)
- Update documentation as you make changes
- Test your changes thoroughly (see Testing)
- Keep PRs focused: Avoid mixing unrelated changes
Before submitting a PR, ensure:
- Code follows project style guidelines
- All tests pass locally
- New tests added for new functionality
- Documentation updated (README, inline comments, etc.)
- No console.log or debug code left behind
- Accessibility considerations addressed (if UI changes)
- No secrets or sensitive data committed
- Commit messages follow conventions
# Run all tests
npm run test
# Run tests in watch mode
npm run test -- --watch
# Run tests with coverage
npm run test -- --coveragecd backend
# Run all tests
npm run test
# Run specific test file
npm run test -- src/services/__tests__/payroll.test.ts
# Run with coverage
npm run test -- --coveragecd contracts/bulk_payment
# Run contract tests
cargo test
# Run with output
cargo test -- --nocapture# Verify documentation examples
npm run test:docs- Unit tests: Required for all new functions and utilities
- Integration tests: Required for API endpoints and contract interactions
- Coverage target: Aim for 80%+ coverage on critical paths
- E2E tests: Recommended for major user workflows
We follow a simplified version of Conventional Commits:
<type>(<scope>): <subject>
<body>
<footer>
feat: A new featurefix: A bug fixdocs: Documentation changesstyle: Code style changes (formatting, missing semicolons, etc.)refactor: Code refactoring without feature changesperf: Performance improvementstest: Adding or updating testschore: Build, dependency, or tooling changes
Optional but recommended. Examples: backend, frontend, contracts, db, api
# Good commits
git commit -m "feat(backend): add payroll batch processing endpoint"
git commit -m "fix(frontend): resolve wallet balance display bug"
git commit -m "docs(contracts): document storage layout for bulk payment"
git commit -m "refactor(db): optimize employee search query"
git commit -m "test(backend): add integration tests for payroll service"-
Rebase on main: Ensure your branch is up-to-date
git fetch origin git rebase origin/main
-
Run all checks locally:
npm run lint npm run format npm run test npm run test:docs -
Push your branch:
git push origin feature/your-feature-name
- Open a Pull Request on GitHub against the
mainbranch - Use the PR template from
.github/pull_request_template.md(automatically provided by GitHub) - Fill in all sections with tests, docs, and accessibility considerations:
- Summary: What does this PR do?
- What Changed: Detailed description of changes
- Related Issues: Link to issue(s) it resolves (e.g.,
Closes #123) - Testing: How was this tested?
- Documentation: What documentation was updated?
- Accessibility / Responsiveness: Any accessibility considerations?
- Checklist: Verify all items are complete (tests, docs, accessibility)
- Automated checks: CI/CD pipeline runs automatically
- Code review: At least one maintainer will review
- Feedback: Address any requested changes
- Approval: PR is approved and ready to merge
- Merge: Maintainer merges to
main
Use the same format as commit messages:
feat(backend): add payroll batch processing endpoint
fix(frontend): resolve wallet balance display bug
docs(contracts): document storage layout for bulk payment
We reward contributions to high-priority issues! Check the issue labels:
bounty: Eligible for XLM/USDC rewardsgood-first-issue: Great for newcomershelp-wanted: Community contributions needed
- Work on a bounty-eligible issue
- Submit a PR that resolves the issue
- Comment on the issue with your PR link and claim the bounty
- Wait for approval: Maintainers review and approve
- Receive payment: Rewards paid in XLM or USDC within 7 business days
See BOUNTY.md and CONTRIBUTION_REWARD.md for details.
When your PR is merged, add yourself to CONTRIBUTORS.md:
- **[Your Name](https://github.com/your-username)** - Frontend / Bug Fixes / Documentation- Bronze: 1-5 contributions
- Silver: 6-15 contributions
- Gold: 16+ contributions
- Questions? Open a discussion on GitHub
- Found a bug? Open an issue with the bug report template
- Have an idea? Open an issue with the feature request template
- Need support? Check DOCKER_TROUBLESHOOTING.md or existing documentation
- Architecture Diagram
- Database Schema
- Contract Storage Layout
- Gas Optimization Guide
- Deployment Guide
Thank you for contributing to PayD! 🚀
Thank you for contributing!