From Zero to dApp Hero: Building a Full-Stack Web3 Project with AI (Aider + Gemini)
Video
Loading video player...
Can AI Really Build a Web3 App from Scratch?
Ever felt overwhelmed by the sheer complexity of building a full-stack decentralized application? Smart contracts, frontend frameworks, wallet integration, deployment scripts⦠itās a lot! Youāve probably heard the hype about AI coding assistants like GitHub Copilot, but what about tools specifically designed for iterative development across your entire codebase?
What if you could have an AI pair programmer, powered by a cutting-edge model like Googleās Gemini 2.5 Pro, sitting right in your terminal, ready to refactor your Solidity, build your Next.js frontend, write tests, and even manage your Git commits? Sounds like science fiction?
Itās not. Meet Aider.
Aider is an AI coding assistant that works directly with your local Git repository. Unlike simple autocompletion tools, Aider understands your entire project context, allowing you to prompt complex changes across multiple files. Combined with a powerful LLM like Gemini 2.5 Pro, it becomes a formidable tool for accelerating Web3 development.
But is it all hype? Can you really trust AI to build secure smart contracts and functional frontends? Does it eliminate the need for developer expertise, or just change the workflow?
In this tutorial, weāre putting it to the test.
Weāll embark on a journey, mirroring a real development session, to build a complete ERC20 token sale dApp from the ground up, relying heavily on Aider and Gemini 2.5 Pro. Weāll start with an empty directory and prompt our way through:
- Setting up a Foundry project for our smart contracts.
- Developing an ERC20 token (
AIDER
/AID
) using OpenZeppelin v5. - Implementing a token sale mechanism (buy 1 AID for 0.1 ETH).
- Writing tests and deployment scripts.
- Debugging AI-generated code (because yes, AI makes mistakes!).
- Building a sleek Next.js 15 frontend with Tailwind CSS and Shadcn UI.
- Integrating RainbowKit for wallet connections.
- Deploying locally to Anvil and interacting with the dApp.
This isnāt just about the final code; itās about the process. Youāll witness the prompts, the AIās responses, the inevitable errors, and the debugging steps required. Weāll explore the strengths and weaknesses of using AI for Web3 development, giving you a realistic perspective on how these tools can augment, but not entirely replace, your skills.
What Youāll Learn:
- How to set up and use Aider with Gemini 2.5 Pro in a Docker environment.
- Structuring a full-stack Web3 project (Next.js + Foundry).
- Prompting Aider for smart contract development (ERC20, token sale logic).
- Debugging Solidity code generated by AI.
- Using Foundry for testing, building, and local deployment (Anvil).
- Prompting Aider for Next.js frontend development with RainbowKit integration.
- Connecting a frontend to a locally deployed smart contract.
- The practical workflow, benefits, and pitfalls of AI-assisted Web3 development.
Ready to see if AI can live up to the promise and build a working dApp? Letās fire up Aider and start coding!
1. Setting the Stage: Project Setup and Tools
Before we unleash the AI, we need to prepare our development environment. Weāll structure our project with the smart contracts nested inside the main Next.js application directory. This allows us to easily share ABIs and deployment information later.
Prerequisites:
- Node.js & npm/yarn: For the Next.js frontend. (Download Node.jsā)
- Foundry: For Solidity development. (Installation Guideā)
- Docker: To run Aider in an isolated environment. (Install Dockerā)
- Git: For version control, essential for Aider. (Install Gitā)
- Google AI API Key: Youāll need an API key for Gemini 2.5 Pro. (Get API Keyā)
Step 1: Project Structure & Git Initialization
First, create your main project directory and initialize Git:
mkdir aider-gemini-dapp
cd aider-gemini-dapp
git init
Step 2: Foundry Setup for Contracts
Now, create a subdirectory for the smart contracts and initialize a Foundry project within it.
mkdir contracts
cd contracts
forge init --no-commit
cd ..
forge init
creates the basic Foundry structure (src
,test
,script
,lib
,foundry.toml
).--no-commit
preventsforge init
from creating its own Git commit, as we want the main project directory to be the single Git repository. Foundry will automatically addforge-std
as a Git submodule.
Your structure should look like this:
aider-gemini-dapp/
āāā .git/
āāā contracts/
ā āāā lib/
ā ā āāā forge-std/
ā āāā script/
ā ā āāā Counter.s.sol
ā āāā src/
ā ā āāā Counter.sol
ā āāā test/
ā ā āāā Counter.t.sol
ā āāā .gitignore
ā āāā foundry.toml
āāā .gitmodules
Foundry uses Git submodules to manage dependencies like forge-std
and, later, OpenZeppelin. The .gitmodules
file in your root directory tracks these submodules.
Step 3: Setting up Aider with Docker and Gemini
Weāll run Aider inside a Docker container to keep things clean. Aiderās documentation provides the necessary Docker commands.
-
Pull the Aider Docker Image:
docker pull paulgauthier/aider-full
-
Prepare API Key: Create a file named
.env
in your projectās root directory (aider-gemini-dapp
) and add your Google AI API key:# .env GEMINI_API_KEY=YOUR_GOOGLE_AI_API_KEY_HERE
Important: Add
.env
to your root.gitignore
file to avoid committing your API key!echo ".env" >> .gitignore git add .gitignore git commit -m "Add .env to gitignore"
-
Run Aider: Execute the following command from your projectās root directory (
aider-gemini-dapp
). This mounts your current directory into the containerās/app
directory and configures Aider to use Gemini 2.5 Pro.docker run --rm -it \ -v $(pwd):/app \ -e GEMINI_API_KEY \ --env-file .env \ paulgauthier/aider-full \ --model gemini/gemini-2.5-pro
--rm
: Removes the container when it exits.-it
: Runs in interactive mode.-v $(pwd):/app
: Mounts your project directory.--env-file .env
: Loads the API key from the.env
file.--model gemini/gemini-2.5-pro-latest
: Specifies the Gemini model (ensure you have access). Here you would put sonnet or other models if you have access ()
Aider should start, potentially asking to add its cache files to
.gitignore
. Typey
and press Enter.Added .aider* to .gitignore. Added the change to git. Continue? [y/N/a] y
You are now inside the Aider chat interface, ready to give instructions!
2. Prompting the Smart Contract: From Counter to Token Sale
Our Foundry project starts with a default Counter
contract. We need to tell Aider to replace this with our desired AiderToken
ERC20 contract and its sale logic.
Step 1: Adding Initial Files to Aider Chat
First, we need to make Aider aware of the existing contract files. Use the /add
command within the Aider chat:
/add contracts/src/Counter.sol contracts/script/Counter.s.sol contracts/test/Counter.t.sol contracts/README.md
Aider will confirm the files have been added to the chat context.
Step 2: The Core Smart Contract Prompt
Now, letās give Aider the main instruction. We want it to:
- Replace the
Counter
contract with an ERC20 token named āAIDERā (symbol āAIDā). - Use OpenZeppelin Contracts v5.
- Implement a
buyTokens
function where 1 AID costs 0.1 ETH. - Make the contract
Ownable
. - Update the deployment script (
Counter.s.sol
->AiderToken.s.sol
). - Update the tests (
Counter.t.sol
->AiderToken.t.sol
). - Update the
contracts/README.md
to describe the new token.
Hereās the prompt (similar to the one used in the video):
I'm working on this new token project and I just set up an empty foundry project using `forge init`. The goal is to change this default Counter contract to an OpenZeppelin Contracts v5 ERC20 token.
The token should be named "AIDER" with the symbol "AID" and use the standard 18 decimals. It should be Ownable.
We also want to sell the token directly from the contract. Add a payable function `buyTokens` where users can send ETH to buy tokens at a fixed price of 0.1 ETH per 1 AID token.
Your task is to:
1. Replace the contents of `contracts/src/Counter.sol` with the new `AiderToken.sol` contract implementing the ERC20 token and the `buyTokens` functionality.
2. Rename `contracts/src/Counter.sol` to `contracts/src/AiderToken.sol`.
3. Update the deployment script `contracts/script/Counter.s.sol` to deploy the `AiderToken` instead. Rename it to `contracts/script/AiderToken.s.sol`.
4. Update the tests in `contracts/test/Counter.t.sol` to properly test the `AiderToken` (name, symbol, decimals, ownership, and the `buyTokens` function). Rename it to `contracts/test/AiderToken.t.sol`.
5. Update the `contracts/README.md` file to describe this new AiderToken project and its features, removing the Counter information.
6. Make sure to include OpenZeppelin v5 contracts as a dependency.
Aider will analyze the request, plan the changes, and likely ask for confirmation before proceeding. It might also ask to run commands, like installing OpenZeppelin.
Step 3: Handling Dependencies (OpenZeppelin)
Aider might suggest running forge install @openzeppelin/contracts
. However, running commands directly inside the Aider Docker container might fail if Foundry isnāt installed within the container image.
Itās often better to run Foundry commands in a separate terminal on your host machine (where Foundry is installed).
-
Aider: When Aider asks to run
forge install
, tell it no. -
Your Terminal (Host): Navigate to the
contracts
directory and run the install command yourself:cd contracts forge install OpenZeppelin/openzeppelin-contracts@v5.0.2 --no-commit # Add forge-std if it wasn't added automatically or you need a specific version # forge install foundry-rs/forge-std --no-commit cd ..
--no-commit
prevents Forge from creating a commit for the dependency installation.- Specify the version (
@v5.0.2
) for consistency.
-
Aider: After installing manually, tell Aider youāve handled the dependency. You might need to re-add the
foundry.toml
file or tell Aider to/update-repo-map
if it seems unaware of the new library files incontracts/lib
.
Aider will then proceed to generate the code changes based on your prompt. Review the proposed changes carefully.
3. Debugging the AI: Refining the Smart Contract
AI code generation is rarely perfect on the first try, especially with the nuances of Solidity. Expect to iterate and debug.
Common Issues & Refinements (Based on Video):
-
Initial
buyTokens
Logic: Aiderās first version might have flaws:- Incorrect Payment Handling: It might initially require the exact payment amount instead of accepting more and refunding.
- Dependency Issues: It might try to use external libraries unnecessarily (like
foundry-devops-tools
mentioned in the video) for deployment scripts. - Visibility: It might mark
buyTokens
asexternal
when it needs to bepublic
to be called by thereceive
function later.
-
Adding
receive()
: The initial prompt didnāt explicitly ask for areceive
function to allow direct ETH transfers. We need to add this. -
Decimal Calculation Bug: A critical error often made by AI is forgetting to handle token decimals correctly when calculating how many tokens to mint based on ETH received.
msg.value / TOKEN_PRICE
gives the number of tokens, but_mint
expects the amount in the base unit (amount * 10^decimals). -
Test Failures: Tests written by AI might fail due to:
- Incorrect setup (using
sender
instead ofvm.prank
). - Incorrect assertions (especially around balances after refunds, due to gas costs).
- Not covering edge cases introduced by refinements.
- Incorrect setup (using
The Debugging Loop with Aider:
This is where Aider shines. Instead of manually fixing everything, you can feed the compiler errors or test failures back to Aider.
-
Compiler Errors: If
forge build
fails in your terminal, copy the error message and paste it into the Aider chat.I ran `forge build` in the contracts directory and got this error: <paste compiler error here> Can you fix this?
-
Refining Logic: Ask Aider to modify the contract based on your requirements.
Please change the `buyTokens` function in `AiderToken.sol`: 1. It should accept any `msg.value` as long as it's greater than or equal to `TOKEN_PRICE`. 2. Calculate the number of tokens to mint based on `msg.value / TOKEN_PRICE`. 3. Calculate any `refundAmount = msg.value % TOKEN_PRICE`. 4. Mint the correct amount of tokens in base units (considering 18 decimals). 5. If `refundAmount` is greater than 0, send it back to `msg.sender`. 6. Add necessary error handling (e.g., for insufficient payment or failed refund). Also, add a `receive() external payable` function that simply calls `buyTokens()`. Update the tests accordingly.
-
Test Failures: If
forge test
fails, provide the failure output.The tests are failing with this message: <paste test failure output here> It seems like the token amount calculation or assertion is wrong. Can you fix the `AiderToken.sol` contract and the `AiderToken.t.sol` test?
Aider might identify the decimal issue or problems with assertions. For gas-related assertion failures (like checking exact ETH balance after refund), you might need to adjust tests to check for ranges (
>=
or<=
) instead of exact equality.
Key Fixes Applied (Based on Video Outcome):
- Visibility:
buyTokens
changed fromexternal
topublic
. - Refund Logic: Implemented correct calculation and refund transfer.
- Decimal Calculation: Correctly multiplied
tokensToMint
by10**decimals()
before calling_mint
. receive()
Added: Included thereceive
function.- Tests Updated: Adjusted tests to use
vm.prank
and handle refund assertions more robustly.
Final AiderToken.sol
(Example):
// SPDX-License-Identifier: MIT
// Compatible with OpenZeppelin Contracts v5.0.2
pragma solidity ^0.8.20;
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
contract AiderToken is ERC20, Ownable {
uint256 public constant TOKEN_PRICE = 0.1 ether; // Price per token in ETH (wei)
error AiderToken__InsufficientPayment();
error AiderToken__TransferFailed();
constructor(address initialOwner) ERC20("AIDER", "AID") Ownable(initialOwner) {
// No initial supply is minted upon deployment in this version.
// Tokens are only created when purchased via buyTokens.
}
/**
* @notice Allows users to buy tokens by sending ETH.
* @dev Mints new tokens to the sender based on the ETH sent and the TOKEN_PRICE.
* Requires msg.value to be at least TOKEN_PRICE.
* Refunds any ETH sent in excess of the cost of whole tokens.
*/
function buyTokens() public payable { // Changed from external to public
if (msg.value < TOKEN_PRICE) {
revert AiderToken__InsufficientPayment();
}
uint256 tokensToMint = msg.value / TOKEN_PRICE; // Number of tokens (e.g., 5)
// *** Critical Fix: Calculate amount in base units ***
uint256 amountToMint = tokensToMint * (10**decimals()); // Amount in base units (e.g., 5 * 10**18)
uint256 refundAmount = msg.value % TOKEN_PRICE;
_mint(msg.sender, amountToMint); // Mint the correct amount in base units
// Refund excess ETH if any
if (refundAmount > 0) {
(bool success, ) = msg.sender.call{value: refundAmount}("");
if (!success) {
revert AiderToken__TransferFailed();
// Note: In a real-world scenario, consider the implications
// if the refund fails (e.g., user contract cannot receive ETH).
// The tokens are already minted at this point.
}
}
}
/**
* @notice Allows direct ETH transfers to the contract to buy tokens.
* @dev Calls the buyTokens function internally.
*/
receive() external payable {
buyTokens();
}
/**
* @notice Allows the owner to withdraw the accumulated ETH balance from the contract.
*/
function withdraw() external onlyOwner {
(bool success, ) = owner().call{value: address(this).balance}("");
if (!success) {
revert AiderToken__TransferFailed();
}
}
// The decimals function is inherited from ERC20 and defaults to 18.
}
Keep iterating with forge build
and forge test
in your terminal and feeding results back to Aider until the contract compiles cleanly and all tests pass. Remember to commit the changes using Aider (y
when prompted) or manually.
4. Building the Frontend with AI
With the smart contract ready, letās build the user interface using Next.js, Tailwind, Shadcn UI, and RainbowKit.
Step 1: Initialize Next.js Project
In your root project directory (aider-gemini-dapp
), run the Next.js setup command:
npx create-next-app@latest . --ts --eslint --tailwind --no-src-dir --app --import-alias "@/*"
.
: Installs in the current directory.--ts
: TypeScript.--eslint
: ESLint setup.--tailwind
: Tailwind CSS setup.--no-src-dir
: Doesnāt use a separatesrc
directory.--app
: Uses the App Router.--import-alias "@/*"
: Configures path alias.
This will create the necessary Next.js files (app
, public
, package.json
, config files, etc.) alongside your existing contracts
directory.
Step 2: Install Shadcn UI
Initialize Shadcn UI for pre-built components:
npx shadcn-ui@latest init
Accept the defaults (or customize as needed). This will create components.json
and potentially components/ui
and lib/utils.ts
.
Step 3: Install Web3 Dependencies
Install RainbowKit, Wagmi, and Viem:
npm install @rainbow-me/rainbowkit wagmi viem@2.x @tanstack/react-query
Step 4: Configure RainbowKit/Wagmi Providers
We need to wrap our application with the necessary Web3 providers. Aider can help create this wrapper.
-
Add Files to Aider: Make Aider aware of the new frontend structure.
/add app/layout.tsx app/page.tsx package.json tsconfig.json next.config.ts tailwind.config.ts postcss.config.mjs globals.css
-
Prompt for Provider Setup:
I have installed Next.js, Tailwind, Shadcn UI, RainbowKit, Wagmi, Viem, and @tanstack/react-query. Please create a new provider component file, `app/providers.tsx`, that sets up the Wagmi config and wraps children with `WagmiProvider`, `QueryClientProvider`, and `RainbowKitProvider`. Configure it for the Anvil local development network (chain id 31337) and potentially Sepolia for later use. Use a placeholder WalletConnect Project ID for now. Then, update `app/layout.tsx` to import and use this `Providers` component to wrap the main content. Make sure the layout includes the necessary RainbowKit CSS import.
Aider should generate app/providers.tsx
and modify app/layout.tsx
. Youāll need to replace 'YOUR_PROJECT_ID'
in providers.tsx
with your actual WalletConnect Project ID if you plan to use WalletConnect features.
Step 5: Prompting the Main Page UI
Now, letās ask Aider to create the main token sale interface in app/page.tsx
.
Okay, the providers are set up. Now, please modify the main page component in `app/page.tsx`.
Create a visually appealing token sale page using Tailwind CSS and Shadcn UI components (like `Button` and `Alert`).
The page should:
1. Display a title like "AIDER Token Sale".
2. Show the price (0.1 ETH per AID).
3. Include a RainbowKit `<ConnectButton />`.
4. If the wallet is connected:
- Show a "Buy 1 AID Token for 0.1 ETH" button (use Shadcn Button).
- When clicked, this button should trigger a transaction using Wagmi's `useWriteContract` hook to call the `buyTokens` function on our deployed `AiderToken` contract. Remember to send 0.1 ETH as the `value`.
- Use the contract address deployed locally (we'll paste the actual address later, use a placeholder like "0x5FbDB2315678afecb367f032d93F642f64180aa3" for now). Define the minimal ABI needed for `buyTokens`.
- Disable the button while the transaction is pending or confirming.
- Use `useWaitForTransactionReceipt` to track the transaction status.
- Display status messages using Shadcn `Alert` components:
- Show the transaction hash while waiting for confirmation.
- Show a success message upon confirmation.
- Show an error message if the transaction fails (display `error.shortMessage`).
5. If the wallet is not connected, display a message prompting the user to connect.
Make the overall page look cool and web3-like, maybe with a gradient background. Include a simple footer mentioning the tech stack.
Aider will generate the code for app/page.tsx
. Review it carefully.
Step 6: Add Required UI Components
Aider might use Shadcn components like Button
and Alert
that havenāt been explicitly added to your project yet. Add them using the Shadcn CLI in your terminal:
npx shadcn-ui@latest add button alert
5. Deployment and Interaction
Now, letās deploy the contract locally and interact with the frontend.
Step 1: Start Local Blockchain (Anvil)
Open a new terminal window, navigate to your project root, and start Anvil:
anvil
Anvil will start, displaying available accounts and private keys. Keep this terminal running.
Step 2: Deploy the Smart Contract
-
Set Private Key: In another terminal window, set the
PRIVATE_KEY
environment variable using one of the keys provided by Anvil.# Example for Linux/macOS/WSL export PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 # Example for Windows Command Prompt # set PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 # Example for Windows PowerShell # $env:PRIVATE_KEY = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
-
Run Deployment Script: Navigate to the
contracts
directory and run the Foundry deployment script:cd contracts forge script script/AiderToken.s.sol:DeployScript --rpc-url http://127.0.0.1:8545 --private-key $PRIVATE_KEY --broadcast cd ..
- Replace
AiderToken.s.sol:DeployScript
if Aider named the script or contract differently. - Foundry will compile the contract and execute the script, deploying
AiderToken
. - Copy the deployed contract address from the output.
- Replace
Step 3: Update Frontend Contract Address
Paste the deployed contract address into app/page.tsx
, replacing the placeholder:
// app/page.tsx
// ...
// --- Contract Configuration ---
const contractAddress = "YOUR_DEPLOYED_CONTRACT_ADDRESS_HERE"; // <-- PASTE ADDRESS HERE
// ...
You can even ask Aider to do this:
/edit app/page.tsx
Then provide the instruction:
Please replace the placeholder contract address "0x5FbDB2315678afecb367f032d93F642f64180aa3" with the actual deployed address: YOUR_DEPLOYED_CONTRACT_ADDRESS_HERE
Step 4: Configure MetaMask
- Add Anvil as a custom network in MetaMask (RPC URL:
http://127.0.0.1:8545
, Chain ID:31337
). - Import one of the Anvil accounts into MetaMask using its private key. Ensure this account has ETH (Anvil accounts start with 10000 ETH).
Step 5: Run the Frontend
Start the Next.js development server from your project root:
npm run dev
Open your browser to http://localhost:3000
.
Step 6: Interact!
- Connect your MetaMask wallet (ensure youāre on the Anvil network and using the imported Anvil account).
- Click the āBuy 1 AID Tokenā button.
- MetaMask will pop up asking you to confirm the transaction (sending 0.1 ETH).
- Confirm the transaction.
- The frontend should display the transaction hash and then a success message once confirmed on Anvil (which is usually instant).
Youāve successfully built and interacted with a full-stack dApp using AI assistance!
6. Reflections: AI as a Web3 Co-Pilot
This journey demonstrates the potential and the current reality of using AI tools like Aider and Gemini for Web3 development:
Strengths:
- Speed: AI significantly accelerates boilerplate setup, frontend generation, and implementing standard patterns.
- Context Awareness: Aiderās ability to work across the whole repo is powerful for refactoring and feature implementation.
- Frontend Proficiency: LLMs trained on vast amounts of web data excel at generating React/Next.js code, integrating libraries like RainbowKit, and styling with Tailwind.
- Debugging Assistance: Feeding errors back to the AI can often lead to quick fixes, especially for common syntax or logic errors.
Weaknesses/Challenges:
- Solidity Nuances: AI can struggle with subtle Solidity concepts like decimal handling, gas optimization, security patterns (reentrancy), and the exact behavior of EVM features. Human oversight is critical.
- Hallucinations/Incorrect Assumptions: AI might invent libraries (like
foundry-devops-tools
) or make incorrect assumptions about function visibility or testing setups (sender
vsprank
). - Over-Reliance Risk: Blindly accepting AI code without understanding and testing is dangerous, especially for smart contracts holding value.
- Debugging Still Required: You still need strong debugging skills to identify why AI code fails and guide the AI towards the correct solution. AI is a powerful assistant, not a replacement for understanding.
- Prompt Engineering: The quality of the output heavily depends on the clarity and detail of your prompts.
Conclusion:
AI tools like Aider + Gemini are transformative co-pilots for Web3 development. They can handle much of the heavy lifting, especially on the frontend, allowing developers to focus on core logic, security, and architecture. However, they are not magic wands. Deep understanding of Solidity, security best practices, and the underlying blockchain principles remains essential. Use AI to accelerate, augment, and learn, but always verify, test rigorously, and remain the captain of your ship. Happy building!