Thank you for your interest in contributing to HackVillage. This project is open-source at its core — the judging logic and escrow mechanics are public so the developer community can audit, trust, and improve them. Every contribution, from a bug report to a full feature, moves that mission forward.
Please read this document carefully before opening issues or submitting pull requests.
- Code of Conduct
- Ways to Contribute
- Reporting Bugs
- Suggesting Features
- Development Setup
- Project Structure
- Branching Strategy
- Commit Message Convention
- Pull Request Process
- Code Style
- Testing
- Working with the Escrow Layer
- Security Vulnerabilities
- License
By participating in this project you agree to abide by our Code of Conduct. We are committed to maintaining a welcoming and respectful community. Violations can be reported to the maintainers at the contact address listed in that document.
You do not need to write code to contribute meaningfully:
- Bug reports — Found something broken? Open a detailed issue.
- Feature requests — Have an idea that fits the roadmap? Start a discussion.
- Code — Fix a bug, implement a roadmap feature, or improve performance.
- Documentation — Improve the README, this guide, or inline code comments where the why is non-obvious.
- Smart contract audits — The escrow contract logic is public. Review it, flag concerns, and open an issue with findings.
- Design & UX — Propose UI improvements via issues with mockups or wireframes attached.
- Testing — Improve coverage, especially for edge cases in the escrow and payout engine.
Before filing a bug report, search existing issues to avoid duplicates.
When opening a new issue, use the Bug Report template and include:
- Steps to reproduce — Precise, numbered steps.
- Expected behavior — What should have happened.
- Actual behavior — What actually happened, including any error messages or stack traces.
- Environment — OS, Node.js version, browser (if frontend), and relevant environment variables (redact secrets).
- Severity — Does this block a core flow (escrow, payout, judging) or is it cosmetic?
For escrow or payout bugs, always include the transaction reference or smart contract interaction hash if available.
Open a Feature Request issue and describe:
- The problem — What user need or gap does this address?
- The proposed solution — A clear description of the behavior you want.
- Alternatives considered — Other approaches you ruled out and why.
- Roadmap alignment — Does this fit an existing roadmap item or is it a new direction?
Large features (new escrow flows, DAO mechanics, cross-border payment rails) should be discussed in an issue and reach rough consensus before any code is written.
| Requirement | Minimum Version |
|---|---|
| Node.js | 18.x |
| npm | 9.x |
| PostgreSQL | 15.x |
| Git | 2.x |
You will also need:
- A Paystack account — test keys are sufficient for local development.
- An RPC endpoint for the target chain (Polygon Mumbai testnet or Solana Devnet) for escrow contract work.
# 1. Fork the repository on GitHub, then clone your fork
git clone https://github.com/<your-username>/HackVillage.git
cd HackVillage
# 2. Add the upstream remote
git remote add upstream https://github.com/CodeWithEugene/HackVillage.git
# 3. Install dependencies
npm install
# 4. Copy the environment template and fill in your values
cp .env.example .env.local| Variable | Description |
|---|---|
DATABASE_URL |
PostgreSQL connection string |
PAYSTACK_SECRET_KEY |
Paystack secret key (sk_test_... for local) |
NEXT_PUBLIC_PAYSTACK_PUBLIC_KEY |
Paystack public key (pk_test_... for local) |
SMART_CONTRACT_ADDRESS |
Deployed escrow contract address |
RPC_URL |
JSON-RPC endpoint for the target chain |
NEXTAUTH_SECRET |
Random secret for session signing |
NEXTAUTH_URL |
Base URL (http://localhost:3000 locally) |
Never commit .env.local or any file containing real credentials.
# Start the development server
npm run dev
# Run database migrations
npm run db:migrate
# (Optional) Seed demo data
npm run db:seedOpen http://localhost:3000 in your browser.
HackVillage/
├── app/ # Next.js App Router — pages and layouts
├── components/ # Shared React components
├── lib/ # Shared utilities, DB client, API helpers
├── services/
│ ├── escrow/ # Escrow microservice — Paystack + smart contract calls
│ └── payout/ # Split disbursement logic
├── contracts/ # Smart contract source and ABI
├── db/
│ ├── migrations/ # PostgreSQL migrations
│ └── seeds/ # Seed data for development
├── public/ # Static assets
└── tests/ # Unit and integration tests
Changes to services/escrow/ and contracts/ carry the highest risk and require the most thorough review. See Working with the Escrow Layer before touching those areas.
| Branch | Purpose |
|---|---|
main |
Production-ready code. Protected. Merge via PR only. |
develop |
Integration branch for completed features. |
feature/<name> |
New features — branch from develop. |
fix/<name> |
Bug fixes — branch from develop (or main for hotfixes). |
chore/<name> |
Tooling, dependencies, non-functional changes. |
docs/<name> |
Documentation-only changes. |
# Start a feature branch
git checkout develop
git pull upstream develop
git checkout -b feature/your-feature-nameNever commit directly to main or develop.
HackVillage uses Conventional Commits. Every commit message must follow this format:
<type>(<scope>): <short summary>
[optional body]
[optional footer(s)]
| Type | When to use |
|---|---|
feat |
A new feature visible to end users |
fix |
A bug fix |
docs |
Documentation changes only |
style |
Formatting, whitespace — no logic change |
refactor |
Code restructure with no feature or bug change |
test |
Adding or updating tests |
chore |
Build process, dependency updates, tooling |
perf |
Performance improvements |
ci |
CI/CD configuration changes |
Use one of the following scopes where applicable: escrow, payout, profiles, events, auth, db, contracts, ui, api, docs.
feat(escrow): lock prize pool on event publication
fix(payout): prevent duplicate disbursement on retry
docs(contributing): add escrow layer guidance
test(payout): add integration test for M-Pesa payout failure rollback
Breaking changes must include BREAKING CHANGE: in the commit footer.
- Keep PRs focused — One feature or fix per PR. Large PRs are hard to review and slow to merge.
- Fill out the PR template — Every PR must include a summary, the motivation, and a test plan.
- Pass all checks — CI must be green before review is requested: linting, type checks, and tests must all pass.
- Link related issues — Use
Closes #<issue-number>in the PR description to auto-close the issue on merge. - Request a review — Assign at least one maintainer as reviewer. Do not merge your own PR.
- Respond to feedback — Address review comments or explain your reasoning. Unresolved threads block merge.
- Squash on merge — Maintainers will squash commits on merge to keep the
develophistory clean.
Before marking your PR ready for review, confirm:
- Code follows the style guidelines in this document
- New and changed code is covered by tests
- All existing tests pass (
npm test) - No secrets, credentials, or
.envfiles are included - The PR description explains the why, not just the what
- Escrow/payout changes have been manually tested against the Paystack test environment
- Smart contract changes include updated ABI and have been tested on a testnet
- TypeScript everywhere — No plain
.jsfiles inapp/,components/,lib/, orservices/. - Strict mode —
"strict": trueintsconfig.json. Do not disable strict checks. - No
any— Use proper types. If the type is genuinely unknown, useunknownand narrow it. - Named exports — Prefer named exports over default exports for better refactoring support.
The project uses ESLint and Prettier. Run before committing:
npm run lint # ESLint
npm run format # Prettier
npm run typecheck # tsc --noEmitCI will fail on lint or type errors. Do not disable rules with eslint-disable without a comment explaining why.
- Prefer React Server Components. Use
"use client"only when necessary (event handlers, browser APIs, hooks). - Co-locate component-specific styles and helpers with the component file.
- Do not fetch data in client components. Use Server Components or Route Handlers.
- Each service function must have a single responsibility.
- All external API calls (Paystack, RPC) must be wrapped in try/catch with explicit error types.
- Payout and escrow operations must be idempotent — retrying a failed call must never cause a double disbursement.
Tests live in the tests/ directory, mirroring the source structure.
npm test # Run all tests
npm run test:unit # Unit tests only
npm run test:e2e # End-to-end tests (requires running dev server)- Every new function in
services/escrow/andservices/payout/must have unit tests. - Payout failure and rollback paths must be covered — these are the highest-risk code paths.
- Integration tests for Paystack interactions must use Paystack's test mode with recorded fixtures; they must not make live network calls in CI.
- Smart contract tests must run against a local hardhat or anchor test node, not a public testnet.
The escrow and payout engine (services/escrow/, services/payout/, contracts/) is the most sensitive part of the codebase. Bugs here can result in funds being locked permanently or paid out incorrectly. Before contributing to these areas:
- Read the architecture section in the README in full.
- Open an issue first for any non-trivial change, even if it looks like a fix. Describe the current behavior, the desired behavior, and your proposed approach. Wait for maintainer acknowledgment before writing code.
- Never remove or weaken rollback logic. If a Paystack call fails or a network error occurs, funds must remain locked in the vault. This is a hard invariant.
- Smart contract changes require a testnet deployment and a link to the verified contract in the PR description before review will begin.
- Two maintainer approvals are required to merge any PR that touches
services/escrow/,services/payout/, orcontracts/.
Do not open a public GitHub issue for security vulnerabilities.
Report security issues directly to the maintainers by emailing the address listed in SECURITY.md. Include a clear description of the vulnerability, steps to reproduce, and the potential impact. We will acknowledge receipt within 48 hours and aim to release a fix within 14 days for critical issues.
By contributing to HackVillage you agree that your contributions will be licensed under the Apache License 2.0 that covers this project. You retain copyright over your own contributions; by submitting a PR you grant the project a perpetual, irrevocable license to use, modify, and distribute your contribution under those terms.