Environment Variables
The frontend uses environment variables for configuration. Create a .env.local file in packages/nextjs/ with the following variables:
Required Variables
# Alchemy API Key for blockchain RPC access
NEXT_PUBLIC_ALCHEMY_API_KEY = your_alchemy_api_key
# WalletConnect Project ID for wallet connections
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID = your_walletconnect_project_id
Environment variables prefixed with NEXT_PUBLIC_ are exposed to the browser and can be accessed client-side.
Getting API Keys
Alchemy API Key
Visit Alchemy Dashboard
Create a free account
Create a new app
Copy the API key
Default Development Key : The project includes a default key for quick prototyping, but you should use your own for production.
WalletConnect Project ID
Visit WalletConnect Cloud
Create a free account
Create a new project
Copy the Project ID
Default Development ID : A default project ID is provided for development.
Optional Variables
# Ignore build errors (useful for CI/CD)
NEXT_PUBLIC_IGNORE_BUILD_ERROR = false
# Enable IPFS build mode
NEXT_PUBLIC_IPFS_BUILD = false
Scaffold Configuration
The main application configuration is in scaffold.config.ts:
import * as chains from "viem/chains" ;
const scaffoldConfig = {
// The networks on which your DApp is live
targetNetworks: [ chains . hardhat ],
// Polling interval for RPC servers (in milliseconds)
pollingInterval: 30000 ,
// Alchemy API key
alchemyApiKey: process . env . NEXT_PUBLIC_ALCHEMY_API_KEY || DEFAULT_ALCHEMY_API_KEY ,
// RPC overrides for specific networks
rpcOverrides: {
// Example:
// [chains.mainnet.id]: "https://mainnet.rpc.buidlguidl.com",
},
// WalletConnect Project ID
walletConnectProjectId: process . env . NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID || "3a8170812b534d0ff9d794f19a901d64" ,
// Only show Burner Wallet on local network
onlyLocalBurnerWallet: true ,
} as const satisfies ScaffoldConfig ;
Network Configuration
Local Development
Testnets
Mainnet
Multiple Networks
For local development with Hardhat: targetNetworks : [ chains . hardhat ]
For testnet deployment (e.g., Sepolia): targetNetworks : [ chains . sepolia ]
For mainnet deployment: targetNetworks : [ chains . mainnet ]
Support multiple networks: targetNetworks : [ chains . mainnet , chains . sepolia , chains . base ]
RPC Configuration
Customize RPC endpoints for specific networks:
rpcOverrides : {
[ chains . mainnet . id ]: "https://mainnet.rpc.buidlguidl.com" ,
[ chains . sepolia . id ]: "https://sepolia.rpc.custom.com" ,
}
RPC overrides take precedence over Alchemy URLs. The application uses a fallback strategy:
RPC override (if configured)
Alchemy RPC (if API key provided)
Default public RPC
Wagmi Configuration
Web3 connectivity is configured in services/web3/wagmiConfig.tsx:
import { createConfig } from "wagmi" ;
import { hardhat , mainnet } from "viem/chains" ;
const { targetNetworks } = scaffoldConfig ;
// Mainnet is always enabled for ENS resolution and ETH prices
export const enabledChains = targetNetworks . find (( network ) => network . id === 1 )
? targetNetworks
: ([ ... targetNetworks , mainnet ] as const );
export const wagmiConfig = createConfig ({
chains: enabledChains ,
connectors: wagmiConnectors (),
ssr: true ,
client ({ chain }) {
let rpcFallbacks = [ http ()];
const rpcOverrideUrl = scaffoldConfig . rpcOverrides ?.[ chain . id ];
if ( rpcOverrideUrl ) {
rpcFallbacks = [ http ( rpcOverrideUrl ), http ()];
} else {
const alchemyHttpUrl = getAlchemyHttpUrl ( chain . id );
if ( alchemyHttpUrl ) {
const isUsingDefaultKey = scaffoldConfig . alchemyApiKey === DEFAULT_ALCHEMY_API_KEY ;
// Prioritize default RPC if using default Scaffold-ETH key
rpcFallbacks = isUsingDefaultKey
? [ http (), http ( alchemyHttpUrl )]
: [ http ( alchemyHttpUrl ), http ()];
}
}
return createClient ({
chain ,
transport: fallback ( rpcFallbacks ),
pollingInterval: chain . id !== hardhat . id
? scaffoldConfig . pollingInterval
: undefined ,
});
},
});
Wallet Connectors
The application supports multiple wallet connectors via RainbowKit:
MetaMask
WalletConnect
Coinbase Wallet
Burner Wallet (local development only)
Next.js Configuration
Advanced Next.js settings in next.config.ts:
const nextConfig : NextConfig = {
reactStrictMode: true ,
devIndicators: false ,
typescript: {
// Ignore build errors if env var is set
ignoreBuildErrors: process . env . NEXT_PUBLIC_IGNORE_BUILD_ERROR === "true" ,
},
eslint: {
ignoreDuringBuilds: process . env . NEXT_PUBLIC_IGNORE_BUILD_ERROR === "true" ,
},
webpack : config => {
// Required for Web3 libraries
config . resolve . fallback = { fs: false , net: false , tls: false };
config . externals . push ( "pino-pretty" , "lokijs" , "encoding" );
return config ;
},
};
// IPFS deployment configuration
const isIpfs = process . env . NEXT_PUBLIC_IPFS_BUILD === "true" ;
if ( isIpfs ) {
nextConfig . output = "export" ; // Static export
nextConfig . trailingSlash = true ; // Required for IPFS
nextConfig . images = {
unoptimized: true , // No image optimization
};
}
IPFS Build Mode
When deploying to IPFS, set NEXT_PUBLIC_IPFS_BUILD=true to enable:
Static HTML export
Trailing slashes on all routes
Unoptimized images (IPFS compatible)
Styling Configuration
The application uses Tailwind CSS 4 with custom theming.
Global Styles
Styles are imported in styles/globals.css:
@import "tailwindcss" ;
@import "tw-animate-css" ;
@custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));
@theme {
--shadow-center: 0 0 12px -2px rgb(0 0 0 / 0 .05 );
--animate-pulse-fast: pulse 1s cubic-bezier(0 .4 , 0, 0 .6 , 1) infinite;
}
Theme Variables
Custom CSS variables for light and dark themes:
:root {
--radius : 0.625 rem ;
--background : oklch ( 1 0 0 );
--foreground : oklch ( 0.145 0 0 );
--primary : oklch ( 0.205 0 0 );
--primary-foreground : oklch ( 0.985 0 0 );
/* ... more variables */
}
DaisyUI Configuration
The project uses daisyUI for component styling with custom themes. Theme switching is handled by next-themes.
Component Library
The application includes:
daisyUI : Pre-built components (buttons, cards, modals)
shadcn/ui : Radix UI primitives (dialogs, dropdowns, tooltips)
Custom components : Built on top of the above libraries
Contract Addresses
Contract addresses are auto-generated in contracts/deployedContracts.ts when you deploy contracts:
// Auto-generated - do not edit manually
export const deployedContracts = {
31337 : { // Hardhat local network
AgoraGovernor: {
address: "0x..." ,
abi: [ ... ],
},
AgoraTreasury: {
address: "0x..." ,
abi: [ ... ],
},
// ... other contracts
},
};
These files are automatically generated by the deployment scripts. Don’t edit them manually.
Configuration Checklist
Environment Variables
✓ Create .env.local with API keys
Network Selection
✓ Set targetNetworks in scaffold.config.ts
RPC Configuration
✓ Configure RPC overrides if needed
Contract Deployment
✓ Deploy contracts to generate addresses
Test Configuration
✓ Run dev server and verify wallet connections
Next Steps
Deployment Deploy your configured frontend
Smart Contracts Learn about contract deployment