Skip to main content

Environment Variables

The frontend uses environment variables for configuration. Create a .env.local file in packages/nextjs/ with the following variables:

Required Variables

.env.local
# 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

1

Alchemy API Key

  1. Visit Alchemy Dashboard
  2. Create a free account
  3. Create a new app
  4. Copy the API key
Default Development Key: The project includes a default key for quick prototyping, but you should use your own for production.
2

WalletConnect Project ID

  1. Visit WalletConnect Cloud
  2. Create a free account
  3. Create a new project
  4. Copy the Project ID
Default Development ID: A default project ID is provided for development.

Optional Variables

.env.local
# 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:
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

For local development with Hardhat:
targetNetworks: [chains.hardhat]

RPC Configuration

Customize RPC endpoints for specific networks:
scaffold.config.ts
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:
  1. RPC override (if configured)
  2. Alchemy RPC (if API key provided)
  3. Default public RPC

Wagmi Configuration

Web3 connectivity is configured in services/web3/wagmiConfig.tsx:
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:
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:
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.625rem;
  --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

1

Environment Variables

✓ Create .env.local with API keys
2

Network Selection

✓ Set targetNetworks in scaffold.config.ts
3

RPC Configuration

✓ Configure RPC overrides if needed
4

Contract Deployment

✓ Deploy contracts to generate addresses
5

Test Configuration

✓ Run dev server and verify wallet connections

Next Steps

Deployment

Deploy your configured frontend

Smart Contracts

Learn about contract deployment

Build docs developers (and LLMs) love