OpenSpace web3-fullstack-systematic-build
Systematic approach to building full-stack Web3 applications layer by layer
git clone https://github.com/HKUDS/OpenSpace
T=$(mktemp -d) && git clone --depth=1 https://github.com/HKUDS/OpenSpace "$T" && mkdir -p ~/.claude/skills && cp -r "$T/gdpval_bench/skills/web3-fullstack-systematic-build" ~/.claude/skills/hkuds-openspace-web3-fullstack-systematic-build && rm -rf "$T"
gdpval_bench/skills/web3-fullstack-systematic-build/SKILL.mdWeb3 Full-Stack Systematic Build
This skill provides a structured, layer-by-layer approach to building complex full-stack Web3 applications. Follow this sequence to maintain clarity, reduce coupling, and enable incremental testing even when tool failures occur.
Phase 1: Project Structure
First, establish the complete directory structure before writing any code:
project-name/ ├── contracts/ │ ├── interfaces/ │ ├── core/ │ ├── libraries/ │ └── deployment/ ├── frontend/ │ ├── src/ │ │ ├── components/ │ │ ├── hooks/ │ │ ├── config/ │ │ └── utils/ │ └── public/ ├── scripts/ │ ├── deploy/ │ └── test/ ├── zk-circuits/ └── docs/
Action: Create all directories upfront using:
mkdir -p contracts/{interfaces,core,libraries,deployment} mkdir -p frontend/src/{components,hooks,config,utils} mkdir -p frontend/public mkdir -p scripts/{deploy,test} mkdir -p zk-circuits docs
Phase 2: Interface Contracts First
Define all interface contracts before implementing logic. This establishes clear API boundaries.
Example interface structure:
// contracts/interfaces/IToken.sol // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IToken { function transfer(address to, uint256 amount) external returns (bool); function balanceOf(address account) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); }
Actions:
- List all external protocols you'll integrate (e.g., Aave, Connext, Uniswap)
- Create interface files for each protocol's required functions
- Create interfaces for your own contracts' public APIs
- Validate interface completeness before proceeding
Phase 3: Core Contract Implementation
Implement contracts in dependency order, starting with libraries, then core logic.
Order of implementation:
- Libraries - Utility functions with no state dependencies
- Base contracts - Abstract contracts with shared logic
- Core contracts - Main business logic implementing interfaces
- Integration contracts - Contracts that bridge multiple protocols
Example:
// contracts/core/PrivatePool.sol // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../interfaces/IToken.sol"; import "../libraries/SafeMath.sol"; contract PrivatePool { using SafeMath for uint256; IToken public token; mapping(address => uint256) private balances; constructor(address _token) { token = IToken(_token); } function deposit(uint256 amount) external { token.transferFrom(msg.sender, address(this), amount); balances[msg.sender] = balances[msg.sender].add(amount); } }
Actions:
- Implement one contract at a time
- Compile and test each contract before moving to the next
- Keep contracts focused on single responsibilities
- Document all state variables and functions
Phase 4: Frontend Configuration
Set up frontend infrastructure before building components.
Create these config files first:
- Network configuration (
):frontend/src/config/networks.js
export const networks = { mainnet: { chainId: 1, rpcUrl: process.env.REACT_APP_MAINNET_RPC, explorer: 'https://etherscan.io' }, testnet: { chainId: 5, rpcUrl: process.env.REACT_APP_TESTNET_RPC, explorer: 'https://goerli.etherscan.io' } };
- Contract addresses (
):frontend/src/config/contracts.js
export const contractAddresses = { PrivatePool: process.env.REACT_APP_PRIVATE_POOL_ADDRESS, Token: process.env.REACT_APP_TOKEN_ADDRESS };
- ABI imports (
):frontend/src/config/abis/
// Import compiled contract ABIs here import PrivatePoolABI from './PrivatePool.json'; export { PrivatePoolABI };
Actions:
- Create environment variable templates (
).env.example - Set up Web3 provider configuration (ethers.js, web3.js, or wagmi)
- Configure wallet connection logic
- Create utility functions for common operations
Phase 5: Component Development
Build frontend components in this order:
- Utility components - Buttons, inputs, modals (no Web3 logic)
- Web3 wrapper components - Wallet connection, network switcher
- Contract interaction components - Forms that call contract functions
- Data display components - Components showing on-chain data
- Page components - Assembling everything into pages
Example component:
// frontend/src/components/DepositForm.jsx import { useState } from 'react'; import { useContractWrite } from 'wagmi'; import { PrivatePoolABI } from '../config/abis'; export function DepositForm({ contractAddress, tokenAddress }) { const [amount, setAmount] = useState(''); const { write: deposit } = useContractWrite({ address: contractAddress, abi: PrivatePoolABI, functionName: 'deposit', args: [BigInt(amount)] }); return ( <form onSubmit={(e) => { e.preventDefault(); deposit(); }}> <input value={amount} onChange={(e) => setAmount(e.target.value)} placeholder="Amount" /> <button type="submit">Deposit</button> </form> ); }
Actions:
- Create components with clear prop interfaces
- Implement error handling for all Web3 interactions
- Add loading states for pending transactions
- Test each component in isolation
Phase 6: Deployment Scripts
Create deployment scripts last, after all contracts are complete and tested.
Structure:
// scripts/deploy/01_deploy_token.js async function main() { const Token = await ethers.getContractFactory("Token"); const token = await Token.deploy(); await token.deployed(); console.log("Token deployed to:", token.address); // Save address for frontend config fs.writeFileSync( 'frontend/.env', `REACT_APP_TOKEN_ADDRESS=${token.address}\n`, { flag: 'a' } ); }
Actions:
- Create deployment scripts for each contract in dependency order
- Include address saving mechanism for frontend integration
- Create verification scripts for block explorers
- Document deployment parameters and expected outputs
Key Principles
- Interface-first design - Define contracts before implementing
- Layer-by-layer progression - Complete each phase before next
- Incremental testing - Test at each layer, not just at the end
- Configuration before components - Set up infrastructure first
- Documentation at each step - Update docs as you progress
Recovery from Failures
If a tool failure occurs:
- Note which phase completed successfully
- Resume from the last completed phase
- Re-validate interfaces and contracts before continuing
- Use the directory structure as a progress checklist
This systematic approach ensures partial progress is preserved and the overall architecture remains coherent even when interruptions occur.