Systematic approach to building full-stack Web3 applications layer by layer
52
57%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Medium
Suggest reviewing before use
Fix and improve this skill with Tessl
tessl review fix ./benchmarks/gdpval/skills/web3-fullstack-systematic-build/SKILL.mdThis 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.
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 docsDefine 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:
Implement contracts in dependency order, starting with libraries, then core logic.
Order of implementation:
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:
Set up frontend infrastructure before building components.
Create these config files first:
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'
}
};frontend/src/config/contracts.js):export const contractAddresses = {
PrivatePool: process.env.REACT_APP_PRIVATE_POOL_ADDRESS,
Token: process.env.REACT_APP_TOKEN_ADDRESS
};frontend/src/config/abis/):// Import compiled contract ABIs here
import PrivatePoolABI from './PrivatePool.json';
export { PrivatePoolABI };Actions:
.env.example)Build frontend components in this order:
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 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:
If a tool failure occurs:
This systematic approach ensures partial progress is preserved and the overall architecture remains coherent even when interruptions occur.
c5a9c4b
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.