Hosting a Project
Register your project on Build Together to create open tasks, attract contributors, and coordinate work onchain.
Prerequisites
- A wallet with ETH for gas (Sepolia testnet or mainnet)
- A Radicle repository for your project's code
- ETH to set reward amounts and fund bounty escrow
1. Connect Your Wallet
Sign in to the Build Together web app with your wallet. The app uses SIWE (Sign-In With Ethereum) — no password required.
2. Create a Project onchain
Click New Project on the projects page. Fill in:
- Radicle ID — your
rad:...identifier from Radicle. This is stored permanently onchain. - Name — human-readable project name.
- Description — brief description of what you're building (optional).
The app calls ProjectRegistry.createProject() onchain. Your wallet must sign and broadcast the transaction. Once mined:
- The indexer picks up the
ProjectCreatedevent and writes the project to the database. - Your project card appears on the projects page within seconds.
The Radicle ID is stored in a string[] array onchain — append-only and immutable. You can add more Radicle IDs later (e.g. if you split the repo) but you cannot remove or change existing entries.
3. Add Team Members
From your project's detail page, you can add two kinds of members:
Maintainers — can create bounties, accept contributions, and cancel bounties. Use this for trusted collaborators.
Allowlisted wallets — can create bounties only. Cannot accept or cancel. Use this for contributors you want to let self-fund bounties.
ProjectRegistry.addMaintainer(projectId, address)
ProjectRegistry.updateAllowlist(projectId, address, true)The indexer syncs these onchain events to the project_member table automatically.
4. Create a Task (Bounty)
Once your project has an onchain ID, click New Task on the project detail page. Only the owner, maintainers, and allowlisted wallets can create tasks.
Fill in:
- Title — short description of the work.
- Description — acceptance criteria, constraints, context (optional but recommended).
- Reward (ETH) — the promised reward amount in ETH. This is recorded onchain but funds are not required upfront — anyone can fund the escrow later.
The app calls BountyEscrow.createBounty(projectId, rewardAmount). Once mined, the indexer creates the bounty record and links it to your project.
5. Fund the Escrow
Anyone — including external contributors who want to see the work done — can fund a bounty:
BountyEscrow.fundBounty(bountyId) // payable, any amountThe bounty status moves from OPEN to FUNDED as soon as any ETH is deposited.
6. Accept Contributions and Pay Out
When a contributor submits a patch, the project owner or any maintainer calls:
BountyEscrow.acceptContribution(bountyId, contributor, patchId)The full escrowed ETH is transferred directly to the contributor's wallet in the same transaction.
Managing Your Project
| Action | Method |
|---|---|
| Add a maintainer | ProjectRegistry.addMaintainer(projectId, address) |
| Remove a maintainer | ProjectRegistry.removeMaintainer(projectId, address) |
| Add/remove allowlisted wallet | ProjectRegistry.updateAllowlist(projectId, address, bool) |
| Add an additional Radicle repo | ProjectRegistry.addRadicleId(projectId, radicleId) |
| Transfer ownership | ProjectRegistry.transferOwnership(projectId, newOwner) |
| Cancel a bounty and reclaim ETH | BountyEscrow.cancelBounty(bountyId) |
- Creating Open Work — writing good task specs
- Core Contracts — full contract reference
- Architecture — how the indexer and API connect onchain state to the UI