Local Development
Local Development Workflow
Section titled “Local Development Workflow”The modern way to handle local development is using icp-cli and @ic-reactor/vite-plugin. This setup automates environment variables and proxy configuration.
1. Configure Vite Plugin
Section titled “1. Configure Vite Plugin”If you’re using Vite, add the plugin to your vite.config.ts. It will automatically proxy /api requests to your local replica and inject canister IDs.
import { icReactorPlugin } from "@ic-reactor/vite-plugin"
export default defineConfig({ plugins: [ icReactorPlugin({ canisters: [ { name: "backend", didFile: "src/declarations/backend.did", }, ], }), ],})2. Set Up ClientManager
Section titled “2. Set Up ClientManager”The ClientManager can now automatically detect your environment through the ic_env cookie set by the Vite plugin or an asset canister.
import { ClientManager } from "@ic-reactor/react"import { queryClient } from "./queryClient"
export const clientManager = new ClientManager({ queryClient, // Automatically detects network and canister IDs from ic_env cookie})3. Run Development Cycle
Section titled “3. Run Development Cycle”-
Start the local network:
Terminal window icp network start -d -
Deploy your backend:
Terminal window icp deploy backend -
Start your dev server:
Terminal window npm run dev
Manual Configuration (Optional)
Section titled “Manual Configuration (Optional)”If you’re not using the Vite plugin, you can still configure everything manually.
1. Setup ClientManager with withProcessEnv
Section titled “1. Setup ClientManager with withProcessEnv”export const clientManager = new ClientManager({ // Auto-detects network based on DFX_NETWORK env var withProcessEnv: true,})2. Configure Environment Variables
Section titled “2. Configure Environment Variables”Create .env.local for local development:
DFX_NETWORK=localVITE_BACKEND_CANISTER_ID=bkyz2-fmaaa-aaaaa-qaaaq-caiFetching Root Key
Section titled “Fetching Root Key”When communicating with the IC mainnet, the agent uses a hardcoded public key to verify responses. For a local replica, the agent needs to fetch a different root key during initialization.
import { useEffect } from "react"import { clientManager, useAgentState } from "./reactor"
function App() { const { isInitialized } = useAgentState()
useEffect(() => { clientManager.initialize() }, [])
if (!isInitialized) { return <div>Loading...</div> }
return <YourApp />}Troubleshooting
Section titled “Troubleshooting””Fail to verify certificate”
Section titled “”Fail to verify certificate””This error usually means the agent hasn’t fetched the local root key.
Solution: Ensure you are calling clientManager.initialize() at the root of your application.
”Can’t connect to localhost:4943”
Section titled “”Can’t connect to localhost:4943””Check if your local replica is running and on which port.
-
Run
dfx info webserver-portto verify the port. -
If it’s not
4943, update yourClientManagerconfig:export const clientManager = new ClientManager({port: 8000, // or your specific portwithProcessEnv: true,})
Internet Identity on Localhost
Section titled “Internet Identity on Localhost”To use Internet Identity locally, you need to deploy a local instance of the II canister.
-
Pull the dependency in
dfx.json:{"canisters": {//..."internet_identity": {"type": "custom","candid": "https://github.com/dfinity/internet-identity/releases/latest/download/internet_identity.did","wasm": "https://github.com/dfinity/internet-identity/releases/latest/download/internet_identity_dev.wasm.gz","specified_id": "rdmx6-jaaaa-aaaaa-aaadq-cai"}}} -
Deploy it:
It is recommended to deploy it to the default canister ID:
Terminal window dfx deploy internet_identity --specified-id rdmx6-jaaaa-aaaaa-aaadq-cai -
Login using the local provider URL.
useAuthhandles this automatically ifwithProcessEnvis set correctly!// Auto-detects based on network// Local: http://rdmx6-jaaaa-aaaaa-aaadq-cai.localhost:4943// Mainnet: https://identity.ic0.appconst { login } = useAuth()